|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/2] Add vlapic timer checks
Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
tests/vlapic-timer/Makefile | 9 +++
tests/vlapic-timer/main.c | 131 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
create mode 100644 tests/vlapic-timer/Makefile
create mode 100644 tests/vlapic-timer/main.c
diff --git a/tests/vlapic-timer/Makefile b/tests/vlapic-timer/Makefile
new file mode 100644
index 0000000..01fa4ea
--- /dev/null
+++ b/tests/vlapic-timer/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME := vlapic-timer
+CATEGORY := functional
+TEST-ENVS := $(HVM_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/vlapic-timer/main.c b/tests/vlapic-timer/main.c
new file mode 100644
index 0000000..b081661
--- /dev/null
+++ b/tests/vlapic-timer/main.c
@@ -0,0 +1,131 @@
+/**
+ * @file tests/vlapic-timer/main.c
+ * @ref test-vlapic-timer - LAPIC Timer Emulation
+ *
+ * @page test-vlapic-timer LAPIC Timer Emulation
+ *
+ * Tests the behavior of the vlapic timer emulation by Xen.
+ *
+ * This tests should work on baremetal.
+ *
+ * It is testing switch between different mode, one-shot and periodic.
+ *
+ * @see tests/vlapic-timer/main.c
+ */
+#include <stdbool.h>
+#include <xtf.h>
+#include <arch/apicdef.h>
+
+const char test_title[] = "Test vlapic-timer";
+
+static inline void apic_write(unsigned long reg, uint32_t v)
+{
+ *((volatile uint32_t *)(APIC_BASE + reg)) = v;
+}
+
+static inline uint32_t apic_read(unsigned long reg)
+{
+ return *((volatile uint32_t *)(APIC_BASE + reg));
+}
+
+static inline void change_mode(unsigned long new_mode)
+{
+ uint32_t lvtt;
+
+ lvtt = apic_read(APIC_LVTT);
+ apic_write(APIC_LVTT, (lvtt & ~APIC_TIMER_MODE_MASK) | new_mode);
+}
+
+void wait_until_tmcct_is_zero(uint32_t initial_count, bool stop_when_half)
+{
+ uint32_t tmcct = apic_read(APIC_TMCCT);
+
+ if ( tmcct )
+ {
+ while ( tmcct > (initial_count / 2) )
+ tmcct = apic_read(APIC_TMCCT);
+
+ if ( stop_when_half )
+ return;
+
+ /* Wait until the counter reach 0 or wrap-around */
+ while ( tmcct <= (initial_count / 2) && tmcct > 0 )
+ tmcct = apic_read(APIC_TMCCT);
+ }
+}
+
+void test_main(void)
+{
+ uint32_t tmict = 0x999999;
+
+ apic_write(APIC_TMICT, tmict);
+ /*
+ * Assuming that the initial mode is one-shot, change it to periodic. TMICT
+ * should not be reset.
+ */
+ change_mode(APIC_TIMER_MODE_PERIODIC);
+ if ( apic_read(APIC_TMICT) != tmict )
+ xtf_failure("Fail: TMICT value reset\n");
+
+ /* Testing one-shot */
+ printk("Testing one-shot mode\n");
+ change_mode(APIC_TIMER_MODE_ONESHOT);
+ apic_write(APIC_TMICT, tmict);
+ if ( !apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should have a non-zero value\n");
+ wait_until_tmcct_is_zero(tmict, false);
+ if ( apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should have reached 0\n");
+
+ /*
+ * Write TMICT before changing mode from one-shot to periodic TMCCT should
+ * be reset to TMICT periodicly
+ */
+ apic_write(APIC_TMICT, tmict);
+ wait_until_tmcct_is_zero(tmict, true);
+ printk("Testing periodic mode\n");
+ change_mode(APIC_TIMER_MODE_PERIODIC);
+ if ( !apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should have a non-zero value\n");
+ /*
+ * After the change of mode, the counter should not be reset and continue
+ * counting down from where it was
+ */
+ if ( apic_read(APIC_TMCCT) > (tmict / 2) )
+ xtf_failure("Fail: TMCCT should not be reset to TMICT value\n");
+ wait_until_tmcct_is_zero(tmict, false);
+ if ( apic_read(APIC_TMCCT) < (tmict / 2) )
+ xtf_failure("Fail: TMCCT should be reset to the initial-count\n");
+
+ wait_until_tmcct_is_zero(tmict, true);
+ /*
+ * Keep the same TMICT and change timer mode to one-shot
+ * TMCCT should be > 0 and count-down to 0
+ */
+ printk("Testing one-shot after periodic (no tmict reset)\n");
+ change_mode(APIC_TIMER_MODE_ONESHOT);
+ if ( !apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should have a non-zero value\n");
+ if ( apic_read(APIC_TMCCT) > (tmict / 2) )
+ xtf_failure("Fail: TMCCT should not be reset to init\n");
+ wait_until_tmcct_is_zero(tmict, false);
+ if ( apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should have reach zero\n");
+
+ /* now tmcct == 0 and tmict != 0 */
+ change_mode(APIC_TIMER_MODE_PERIODIC);
+ if ( apic_read(APIC_TMCCT) )
+ xtf_failure("Fail: TMCCT should stay at zero\n");
+
+ xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
Anthony PERARD
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |