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