Message ID | 1474357762-24136-1-git-send-email-peterx@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Sep 20, 2016 at 03:49:22PM +0800, Peter Xu wrote: > This is fairly basic, and guest codes of this part are rarely changed. > However maybe it's something good to have to make APIC tests more > complete. > > Signed-off-by: Peter Xu <peterx@redhat.com> > --- > > I wrote this for fun, in case we want to have this... so I posted. :) Thanks for having fun :-) > > x86/apic.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > diff --git a/x86/apic.c b/x86/apic.c > index 5fc83c6..4125ce2 100644 > --- a/x86/apic.c > +++ b/x86/apic.c > @@ -350,6 +350,46 @@ static void test_multiple_nmi(void) > report("multiple nmi", ok); > } > > +static volatile int lvtt_counter = 0; > + > +static void lvtt_handler(isr_regs_t *regs) > +{ > + lvtt_counter++; > +} > + > +static void test_apic_timer_one_shot(void) > +{ > + uint64_t tsc1, tsc2; > + static const uint32_t interval = 0x10000; > + > +#define APIC_LVT_TIMER_VECTOR (0xee) > +#define APIC_LVT_TIMER_ONE_SHOT (0) > + > + handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); > + irq_enable(); > + > + /* One shot mode */ > + apic_write(APIC_LVTT, APIC_LVT_TIMER_ONE_SHOT | > + APIC_LVT_TIMER_VECTOR); > + /* Divider == 1 */ > + apic_write(APIC_TDCR, 0x0000000b); > + > + tsc1 = rdtsc(); > + /* Set initial, which starts the timer */ /initial/interval/ > + apic_write(APIC_TMICT, interval); > + while (!lvtt_counter); You'll loop forever if you don't get the interrupt. You may want to adjust the timeout for this test in the unittests.cfg file, or add a sufficiently large trial counter in order to give up, failing the test. > + tsc2 = rdtsc(); > + > + /* > + * For LVT Timer clock, SDM vol 3 10.5.4 says it should be > + * derived from processor's bus clock (IIUC which is the same > + * as TSC), however QEMU seems to be using nanosecond. In all > + * cases, the following should satisfy on all modern > + * processors. > + */ > + report("APIC LVT timer one shot", tsc2 - tsc1 >= interval); Since you're using a counter in the interrupt handler, instead of just a boolean, then you may also wish to test that the counter is exactly 1, i.e. that the oneshot timer isn't injecting too many interrupts. > +} > + > int main() > { > setup_vm(); > @@ -368,6 +408,7 @@ int main() > test_sti_nmi(); > test_multiple_nmi(); > > + test_apic_timer_one_shot(); > test_tsc_deadline_timer(); > > return report_summary(); > -- > 2.7.4 Thanks, drew -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Sep 20, 2016 at 10:25:35AM +0200, Andrew Jones wrote: > On Tue, Sep 20, 2016 at 03:49:22PM +0800, Peter Xu wrote: > > This is fairly basic, and guest codes of this part are rarely changed. > > However maybe it's something good to have to make APIC tests more > > complete. > > > > Signed-off-by: Peter Xu <peterx@redhat.com> > > --- > > > > I wrote this for fun, in case we want to have this... so I posted. :) > > Thanks for having fun :-) Thanks for reviewing! [...] > > +static void test_apic_timer_one_shot(void) > > +{ > > + uint64_t tsc1, tsc2; > > + static const uint32_t interval = 0x10000; > > + > > +#define APIC_LVT_TIMER_VECTOR (0xee) > > +#define APIC_LVT_TIMER_ONE_SHOT (0) > > + > > + handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); > > + irq_enable(); > > + > > + /* One shot mode */ > > + apic_write(APIC_LVTT, APIC_LVT_TIMER_ONE_SHOT | > > + APIC_LVT_TIMER_VECTOR); > > + /* Divider == 1 */ > > + apic_write(APIC_TDCR, 0x0000000b); > > + > > + tsc1 = rdtsc(); > > + /* Set initial, which starts the timer */ > > /initial/interval/ Here I mean "Initial Count Register" below. I should use the full term. > > > + apic_write(APIC_TMICT, interval); > > + while (!lvtt_counter); > > You'll loop forever if you don't get the interrupt. You may want to > adjust the timeout for this test in the unittests.cfg file, or add > a sufficiently large trial counter in order to give up, failing the > test. Yes. I would prefer to tune the timeout. I see that the NMI test might take seconds to complete on my laptop. Maybe 30 seconds a good choice? I assume the default is 90s. > > > + tsc2 = rdtsc(); > > + > > + /* > > + * For LVT Timer clock, SDM vol 3 10.5.4 says it should be > > + * derived from processor's bus clock (IIUC which is the same > > + * as TSC), however QEMU seems to be using nanosecond. In all > > + * cases, the following should satisfy on all modern > > + * processors. > > + */ > > + report("APIC LVT timer one shot", tsc2 - tsc1 >= interval); > > Since you're using a counter in the interrupt handler, instead of > just a boolean, then you may also wish to test that the counter is > exactly 1, i.e. that the oneshot timer isn't injecting too many > interrupts. Right. Will do. Thanks! -- peterx -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/x86/apic.c b/x86/apic.c index 5fc83c6..4125ce2 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -350,6 +350,46 @@ static void test_multiple_nmi(void) report("multiple nmi", ok); } +static volatile int lvtt_counter = 0; + +static void lvtt_handler(isr_regs_t *regs) +{ + lvtt_counter++; +} + +static void test_apic_timer_one_shot(void) +{ + uint64_t tsc1, tsc2; + static const uint32_t interval = 0x10000; + +#define APIC_LVT_TIMER_VECTOR (0xee) +#define APIC_LVT_TIMER_ONE_SHOT (0) + + handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); + irq_enable(); + + /* One shot mode */ + apic_write(APIC_LVTT, APIC_LVT_TIMER_ONE_SHOT | + APIC_LVT_TIMER_VECTOR); + /* Divider == 1 */ + apic_write(APIC_TDCR, 0x0000000b); + + tsc1 = rdtsc(); + /* Set initial, which starts the timer */ + apic_write(APIC_TMICT, interval); + while (!lvtt_counter); + tsc2 = rdtsc(); + + /* + * For LVT Timer clock, SDM vol 3 10.5.4 says it should be + * derived from processor's bus clock (IIUC which is the same + * as TSC), however QEMU seems to be using nanosecond. In all + * cases, the following should satisfy on all modern + * processors. + */ + report("APIC LVT timer one shot", tsc2 - tsc1 >= interval); +} + int main() { setup_vm(); @@ -368,6 +408,7 @@ int main() test_sti_nmi(); test_multiple_nmi(); + test_apic_timer_one_shot(); test_tsc_deadline_timer(); return report_summary();
This is fairly basic, and guest codes of this part are rarely changed. However maybe it's something good to have to make APIC tests more complete. Signed-off-by: Peter Xu <peterx@redhat.com> --- I wrote this for fun, in case we want to have this... so I posted. :) x86/apic.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)