[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [XTF PATCH v2 1/3] vlapic-timer: Introduce vLAPIC Timer tests
Start by testing one-shot and periodic timer modes. The behavior of TMICT and TMCCT while switching between periodic and one-shot timer modes check in this test is mostly base on observation of baremetal. Intel SDM gives little details about it. Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> --- arch/x86/include/arch/apic.h | 8 +++ tests/vlapic-timer/Makefile | 9 +++ tests/vlapic-timer/main.c | 151 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 tests/vlapic-timer/Makefile create mode 100644 tests/vlapic-timer/main.c diff --git a/arch/x86/include/arch/apic.h b/arch/x86/include/arch/apic.h index 1389f70..4cb262d 100644 --- a/arch/x86/include/arch/apic.h +++ b/arch/x86/include/arch/apic.h @@ -24,6 +24,14 @@ #define APIC_DEST_SELF 0x40000 #define APIC_ICR2 0x310 +#define APIC_LVTT 0x320 +#define APIC_TIMER_MODE_MASK (0x3<<17) +#define APIC_TIMER_MODE_ONESHOT (0x0<<17) +#define APIC_TIMER_MODE_PERIODIC (0x1<<17) + +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 + #define APIC_DEFAULT_BASE 0xfee00000ul diff --git a/tests/vlapic-timer/Makefile b/tests/vlapic-timer/Makefile new file mode 100644 index 0000000..f2a61cb --- /dev/null +++ b/tests/vlapic-timer/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME := vlapic-timer +CATEGORY := functional +TEST-ENVS := hvm64 + +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..47836a8 --- /dev/null +++ b/tests/vlapic-timer/main.c @@ -0,0 +1,151 @@ +/** + * @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. + * + * These tests are mostly base on observation made on baremetal, Intel SDM does + * not describe everything. + * + * It is testing switch between different mode, one-shot and periodic, as well + * a the TSC-Deadline mode. + * + * @see tests/vlapic-timer/main.c + */ +#include <xtf.h> +#include <arch/apic.h> + +const char test_title[] = "Test vlapic-timer"; + +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_tmcct_count_down(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); + } +} + +static inline void wait_until_tmcct_is_zero(uint32_t initial_count) +{ + wait_tmcct_count_down(initial_count, false); +} +static inline void wait_until_tmcct_is_half_down(uint32_t initial_count) +{ + wait_tmcct_count_down(initial_count, true); +} + +void testing_oneshot_and_periodic_mode(void) +{ + uint32_t tmict = 0x9999999; + + /* Start in one-shot mode */ + change_mode(APIC_TIMER_MODE_ONESHOT); + + apic_write(APIC_TMICT, tmict); + + /* On mode change one-shot -> periodic, TMICT is not reset on baremetal */ + 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); + + /* Testing TMCCT after setting TMICT */ + 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); + if ( apic_read(APIC_TMCCT) ) + xtf_failure("Fail: TMCCT should have reached 0\n"); + + /* + * Testing periodic timer mode + * + * Write TMICT before changing mode one-shot -> periodic, + * check that TMCCT keeps counting down after this mode change + */ + apic_write(APIC_TMICT, tmict); + wait_until_tmcct_is_half_down(tmict); + + 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"); + + if ( apic_read(APIC_TMCCT) > (tmict / 2) ) + xtf_failure("Fail: TMCCT should not be reset to TMICT value\n"); + + /* Check that the TMCCT is reset to TMICT */ + wait_until_tmcct_is_zero(tmict); + if ( apic_read(APIC_TMCCT) < (tmict / 2) ) + xtf_failure("Fail: TMCCT should be reset to TMICT periodically\n"); + + wait_until_tmcct_is_half_down(tmict); + + /* + * Keep the same TMICT and change timer mode periodic -> one-shot + * Check that TMCCT keeps counting down and is not reset. + */ + printk("Testing one-shot after periodic (with same tmict)\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); + 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"); +} + +void test_main(void) +{ + if ( apic_init(APIC_MODE_XAPIC) ) + return xtf_skip("No APIC support"); + + testing_oneshot_and_periodic_mode(); + + 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 |