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