xref: /kvm-unit-tests/x86/tscdeadline_latency.c (revision 3dea272f9ac14768c02e45bbeb9cd0000bc57839)
1d482c497SMarcelo Tosatti /*
2d482c497SMarcelo Tosatti  * qemu command line | grep latency | cut -f 2 -d ":" > latency
3d482c497SMarcelo Tosatti  *
4d482c497SMarcelo Tosatti  * In octave:
5d482c497SMarcelo Tosatti  * load latency
6d482c497SMarcelo Tosatti  * min(list)
7d482c497SMarcelo Tosatti  * max(list)
8d482c497SMarcelo Tosatti  * mean(list)
9d482c497SMarcelo Tosatti  * hist(latency, 50)
10d482c497SMarcelo Tosatti  */
11d482c497SMarcelo Tosatti 
12d482c497SMarcelo Tosatti #include "libcflat.h"
13d482c497SMarcelo Tosatti #include "apic.h"
14d482c497SMarcelo Tosatti #include "vm.h"
15d482c497SMarcelo Tosatti #include "smp.h"
16d482c497SMarcelo Tosatti #include "desc.h"
17d482c497SMarcelo Tosatti #include "isr.h"
18d482c497SMarcelo Tosatti #include "msr.h"
19d482c497SMarcelo Tosatti 
20d482c497SMarcelo Tosatti static void test_lapic_existence(void)
21d482c497SMarcelo Tosatti {
22d482c497SMarcelo Tosatti     u32 lvr;
23d482c497SMarcelo Tosatti 
24d482c497SMarcelo Tosatti     lvr = apic_read(APIC_LVR);
25d482c497SMarcelo Tosatti     printf("apic version: %x\n", lvr);
26d482c497SMarcelo Tosatti     report("apic existence", (u16)lvr == 0x14);
27d482c497SMarcelo Tosatti }
28d482c497SMarcelo Tosatti 
29d482c497SMarcelo Tosatti #define TSC_DEADLINE_TIMER_MODE (2 << 17)
30d482c497SMarcelo Tosatti #define TSC_DEADLINE_TIMER_VECTOR 0xef
31d482c497SMarcelo Tosatti #define MSR_IA32_TSC            0x00000010
32d482c497SMarcelo Tosatti #define MSR_IA32_TSCDEADLINE    0x000006e0
33d482c497SMarcelo Tosatti 
34d482c497SMarcelo Tosatti static int tdt_count;
35d482c497SMarcelo Tosatti u64 exptime;
36d482c497SMarcelo Tosatti int delta;
37d482c497SMarcelo Tosatti #define TABLE_SIZE 10000
38d482c497SMarcelo Tosatti u64 table[TABLE_SIZE];
39d482c497SMarcelo Tosatti volatile int table_idx;
40d482c497SMarcelo Tosatti 
41d482c497SMarcelo Tosatti static void tsc_deadline_timer_isr(isr_regs_t *regs)
42d482c497SMarcelo Tosatti {
43d482c497SMarcelo Tosatti     u64 now = rdtsc();
44d482c497SMarcelo Tosatti     ++tdt_count;
45d482c497SMarcelo Tosatti 
46d482c497SMarcelo Tosatti     if (table_idx < TABLE_SIZE && tdt_count > 1)
47d482c497SMarcelo Tosatti         table[table_idx++] = now - exptime;
48d482c497SMarcelo Tosatti 
49d482c497SMarcelo Tosatti     exptime = now+delta;
50d482c497SMarcelo Tosatti     wrmsr(MSR_IA32_TSCDEADLINE, now+delta);
51d482c497SMarcelo Tosatti     apic_write(APIC_EOI, 0);
52d482c497SMarcelo Tosatti }
53d482c497SMarcelo Tosatti 
54d482c497SMarcelo Tosatti static void start_tsc_deadline_timer(void)
55d482c497SMarcelo Tosatti {
56d482c497SMarcelo Tosatti     handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr);
57d482c497SMarcelo Tosatti     irq_enable();
58d482c497SMarcelo Tosatti 
59d482c497SMarcelo Tosatti     wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)+delta);
60d482c497SMarcelo Tosatti     asm volatile ("nop");
61d482c497SMarcelo Tosatti }
62d482c497SMarcelo Tosatti 
63d482c497SMarcelo Tosatti static int enable_tsc_deadline_timer(void)
64d482c497SMarcelo Tosatti {
65d482c497SMarcelo Tosatti     uint32_t lvtt;
66d482c497SMarcelo Tosatti 
67d482c497SMarcelo Tosatti     if (cpuid(1).c & (1 << 24)) {
68d482c497SMarcelo Tosatti         lvtt = TSC_DEADLINE_TIMER_MODE | TSC_DEADLINE_TIMER_VECTOR;
69d482c497SMarcelo Tosatti         apic_write(APIC_LVTT, lvtt);
70d482c497SMarcelo Tosatti         start_tsc_deadline_timer();
71d482c497SMarcelo Tosatti         return 1;
72d482c497SMarcelo Tosatti     } else {
73d482c497SMarcelo Tosatti         return 0;
74d482c497SMarcelo Tosatti     }
75d482c497SMarcelo Tosatti }
76d482c497SMarcelo Tosatti 
77d482c497SMarcelo Tosatti static void test_tsc_deadline_timer(void)
78d482c497SMarcelo Tosatti {
79d482c497SMarcelo Tosatti     if(enable_tsc_deadline_timer()) {
80d482c497SMarcelo Tosatti         printf("tsc deadline timer enabled\n");
81d482c497SMarcelo Tosatti     } else {
82d482c497SMarcelo Tosatti         printf("tsc deadline timer not detected\n");
83*3dea272fSPaolo Bonzini         exit(1);
84d482c497SMarcelo Tosatti     }
85d482c497SMarcelo Tosatti }
86d482c497SMarcelo Tosatti 
87*3dea272fSPaolo Bonzini int main(int argc, char **argv)
88d482c497SMarcelo Tosatti {
89*3dea272fSPaolo Bonzini     int i, size;
90d482c497SMarcelo Tosatti 
91d482c497SMarcelo Tosatti     setup_vm();
92d482c497SMarcelo Tosatti     smp_init();
93d482c497SMarcelo Tosatti     setup_idt();
94d482c497SMarcelo Tosatti 
95d482c497SMarcelo Tosatti     test_lapic_existence();
96d482c497SMarcelo Tosatti 
97d482c497SMarcelo Tosatti     mask_pic_interrupts();
98d482c497SMarcelo Tosatti 
99*3dea272fSPaolo Bonzini     delta = argc <= 1 ? 200000 : atol(argv[1]);
100*3dea272fSPaolo Bonzini     size = argc <= 2 ? TABLE_SIZE : atol(argv[1]);
101d482c497SMarcelo Tosatti     test_tsc_deadline_timer();
102d482c497SMarcelo Tosatti     irq_enable();
103d482c497SMarcelo Tosatti 
104d482c497SMarcelo Tosatti     do {
105d482c497SMarcelo Tosatti         asm volatile("hlt");
106*3dea272fSPaolo Bonzini     } while (table_idx < size);
107d482c497SMarcelo Tosatti 
108*3dea272fSPaolo Bonzini     for (i = 0; i < size; i++)
109d482c497SMarcelo Tosatti         printf("latency: %d\n", table[i]);
110d482c497SMarcelo Tosatti 
111d482c497SMarcelo Tosatti     return report_summary();
112d482c497SMarcelo Tosatti }
113