@@ -31,6 +31,9 @@
#define APIC_TMICT 0x380
#define APIC_TMCCT 0x390
+#define APIC_TDCR 0x3e0
+#define APIC_TDR_DIV_1 0xb
+#define APIC_TDR_DIV_16 0x3
#define APIC_DEFAULT_BASE 0xfee00000ul
@@ -130,6 +130,44 @@ void testing_oneshot_and_periodic_mode(void)
xtf_failure("Fail: TMCCT should stay at zero\n");
}
+/*
+ * Testing change of divide configuration
+ */
+void testing_divide_configuration(void)
+{
+ uint32_t tmict = 0x49999999;
+
+ printk("Testing change of divide configuration register\n");
+
+ change_mode(APIC_TIMER_MODE_PERIODIC);
+
+ apic_write(APIC_TDCR, APIC_TDR_DIV_16);
+ apic_write(APIC_TMICT, tmict);
+
+ wait_until_tmcct_is_half_down(tmict);
+
+ apic_write(APIC_TDCR, APIC_TDR_DIV_1);
+
+ /*
+ * Checking that changing divide configuration value does not cause the
+ * current counter register to have a different value, it should continue
+ * to count down, but at a different rate.
+ */
+
+ if ( apic_read(APIC_TMCCT) > (tmict / 2) )
+ xtf_failure("Fail: TMCCT may have gone back in time\n");
+ if ( apic_read(APIC_TMCCT) == 0 )
+ xtf_failure("Fail: TMCCT should not be 0\n");
+
+ wait_until_tmcct_is_half_down(tmict);
+
+ apic_write(APIC_TDCR, APIC_TDR_DIV_16);
+ if ( apic_read(APIC_TMCCT) > (tmict / 2) )
+ xtf_failure("Fail: TMCCT may have gone back in time\n");
+ if ( apic_read(APIC_TMCCT) == 0 )
+ xtf_failure("Fail: TMCCT should not be 0\n");
+}
+
void test_main(void)
{
if ( apic_init(APIC_MODE_XAPIC) )
@@ -137,6 +175,8 @@ void test_main(void)
testing_oneshot_and_periodic_mode();
+ testing_divide_configuration();
+
xtf_success(NULL);
}
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- arch/x86/include/arch/apic.h | 3 +++ tests/vlapic-timer/main.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+)