1d482c497SMarcelo Tosatti /* 2d482c497SMarcelo Tosatti * qemu command line | grep latency | cut -f 2 -d ":" > latency 3d482c497SMarcelo Tosatti * 4d482c497SMarcelo Tosatti * In octave: 5d482c497SMarcelo Tosatti * load latency 66d7f1387SMarcelo Tosatti * min(latency) 76d7f1387SMarcelo Tosatti * max(latency) 86d7f1387SMarcelo Tosatti * mean(latency) 9d482c497SMarcelo Tosatti * hist(latency, 50) 10d482c497SMarcelo Tosatti */ 11d482c497SMarcelo Tosatti 12*24ce2536SMarcelo Tosatti /* 13*24ce2536SMarcelo Tosatti * for host tracing of breakmax option: 14*24ce2536SMarcelo Tosatti * 15*24ce2536SMarcelo Tosatti * # cd /sys/kernel/debug/tracing/ 16*24ce2536SMarcelo Tosatti * # echo x86-tsc > trace_clock 17*24ce2536SMarcelo Tosatti * # echo "kvm_exit kvm_entry kvm_msr" > set_event 18*24ce2536SMarcelo Tosatti * # echo "sched_switch $extratracepoints" >> set_event 19*24ce2536SMarcelo Tosatti * # echo apic_timer_fn > set_ftrace_filter 20*24ce2536SMarcelo Tosatti * # echo "function" > current_tracer 21*24ce2536SMarcelo Tosatti */ 22*24ce2536SMarcelo Tosatti 23d482c497SMarcelo Tosatti #include "libcflat.h" 24d482c497SMarcelo Tosatti #include "apic.h" 25d482c497SMarcelo Tosatti #include "vm.h" 26d482c497SMarcelo Tosatti #include "smp.h" 27d482c497SMarcelo Tosatti #include "desc.h" 28d482c497SMarcelo Tosatti #include "isr.h" 29d482c497SMarcelo Tosatti #include "msr.h" 30d482c497SMarcelo Tosatti 31d482c497SMarcelo Tosatti static void test_lapic_existence(void) 32d482c497SMarcelo Tosatti { 33d482c497SMarcelo Tosatti u32 lvr; 34d482c497SMarcelo Tosatti 35d482c497SMarcelo Tosatti lvr = apic_read(APIC_LVR); 36d482c497SMarcelo Tosatti printf("apic version: %x\n", lvr); 37d482c497SMarcelo Tosatti report("apic existence", (u16)lvr == 0x14); 38d482c497SMarcelo Tosatti } 39d482c497SMarcelo Tosatti 40d482c497SMarcelo Tosatti #define TSC_DEADLINE_TIMER_MODE (2 << 17) 41d482c497SMarcelo Tosatti #define TSC_DEADLINE_TIMER_VECTOR 0xef 42d482c497SMarcelo Tosatti #define MSR_IA32_TSC 0x00000010 43d482c497SMarcelo Tosatti #define MSR_IA32_TSCDEADLINE 0x000006e0 44d482c497SMarcelo Tosatti 45d482c497SMarcelo Tosatti static int tdt_count; 46d482c497SMarcelo Tosatti u64 exptime; 47d482c497SMarcelo Tosatti int delta; 48d482c497SMarcelo Tosatti #define TABLE_SIZE 10000 49d482c497SMarcelo Tosatti u64 table[TABLE_SIZE]; 50d482c497SMarcelo Tosatti volatile int table_idx; 51*24ce2536SMarcelo Tosatti volatile int hitmax = 0; 52*24ce2536SMarcelo Tosatti int breakmax = 0; 53d482c497SMarcelo Tosatti 54d482c497SMarcelo Tosatti static void tsc_deadline_timer_isr(isr_regs_t *regs) 55d482c497SMarcelo Tosatti { 56d482c497SMarcelo Tosatti u64 now = rdtsc(); 57d482c497SMarcelo Tosatti ++tdt_count; 58d482c497SMarcelo Tosatti 59d482c497SMarcelo Tosatti if (table_idx < TABLE_SIZE && tdt_count > 1) 60d482c497SMarcelo Tosatti table[table_idx++] = now - exptime; 61d482c497SMarcelo Tosatti 62*24ce2536SMarcelo Tosatti if (breakmax && tdt_count > 1 && (now - exptime) > breakmax) { 63*24ce2536SMarcelo Tosatti hitmax = 1; 64*24ce2536SMarcelo Tosatti apic_write(APIC_EOI, 0); 65*24ce2536SMarcelo Tosatti return; 66*24ce2536SMarcelo Tosatti } 67*24ce2536SMarcelo Tosatti 68d482c497SMarcelo Tosatti exptime = now+delta; 69d482c497SMarcelo Tosatti wrmsr(MSR_IA32_TSCDEADLINE, now+delta); 70d482c497SMarcelo Tosatti apic_write(APIC_EOI, 0); 71d482c497SMarcelo Tosatti } 72d482c497SMarcelo Tosatti 73d482c497SMarcelo Tosatti static void start_tsc_deadline_timer(void) 74d482c497SMarcelo Tosatti { 75d482c497SMarcelo Tosatti handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr); 76d482c497SMarcelo Tosatti irq_enable(); 77d482c497SMarcelo Tosatti 78d482c497SMarcelo Tosatti wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)+delta); 79d482c497SMarcelo Tosatti asm volatile ("nop"); 80d482c497SMarcelo Tosatti } 81d482c497SMarcelo Tosatti 82d482c497SMarcelo Tosatti static int enable_tsc_deadline_timer(void) 83d482c497SMarcelo Tosatti { 84d482c497SMarcelo Tosatti uint32_t lvtt; 85d482c497SMarcelo Tosatti 86d482c497SMarcelo Tosatti if (cpuid(1).c & (1 << 24)) { 87d482c497SMarcelo Tosatti lvtt = TSC_DEADLINE_TIMER_MODE | TSC_DEADLINE_TIMER_VECTOR; 88d482c497SMarcelo Tosatti apic_write(APIC_LVTT, lvtt); 89d482c497SMarcelo Tosatti start_tsc_deadline_timer(); 90d482c497SMarcelo Tosatti return 1; 91d482c497SMarcelo Tosatti } else { 92d482c497SMarcelo Tosatti return 0; 93d482c497SMarcelo Tosatti } 94d482c497SMarcelo Tosatti } 95d482c497SMarcelo Tosatti 96d482c497SMarcelo Tosatti static void test_tsc_deadline_timer(void) 97d482c497SMarcelo Tosatti { 98d482c497SMarcelo Tosatti if(enable_tsc_deadline_timer()) { 99d482c497SMarcelo Tosatti printf("tsc deadline timer enabled\n"); 100d482c497SMarcelo Tosatti } else { 101d482c497SMarcelo Tosatti printf("tsc deadline timer not detected\n"); 1023dea272fSPaolo Bonzini exit(1); 103d482c497SMarcelo Tosatti } 104d482c497SMarcelo Tosatti } 105d482c497SMarcelo Tosatti 1063dea272fSPaolo Bonzini int main(int argc, char **argv) 107d482c497SMarcelo Tosatti { 1083dea272fSPaolo Bonzini int i, size; 109d482c497SMarcelo Tosatti 110d482c497SMarcelo Tosatti setup_vm(); 111d482c497SMarcelo Tosatti smp_init(); 112d482c497SMarcelo Tosatti setup_idt(); 113d482c497SMarcelo Tosatti 114d482c497SMarcelo Tosatti test_lapic_existence(); 115d482c497SMarcelo Tosatti 116d482c497SMarcelo Tosatti mask_pic_interrupts(); 117d482c497SMarcelo Tosatti 1183dea272fSPaolo Bonzini delta = argc <= 1 ? 200000 : atol(argv[1]); 119*24ce2536SMarcelo Tosatti size = argc <= 2 ? TABLE_SIZE : atol(argv[2]); 120*24ce2536SMarcelo Tosatti breakmax = argc <= 3 ? 0 : atol(argv[3]); 121*24ce2536SMarcelo Tosatti printf("breakmax=%d\n", breakmax); 122d482c497SMarcelo Tosatti test_tsc_deadline_timer(); 123d482c497SMarcelo Tosatti irq_enable(); 124d482c497SMarcelo Tosatti 125d482c497SMarcelo Tosatti do { 126d482c497SMarcelo Tosatti asm volatile("hlt"); 127*24ce2536SMarcelo Tosatti } while (!hitmax && table_idx < size); 128d482c497SMarcelo Tosatti 129*24ce2536SMarcelo Tosatti for (i = 0; i < table_idx; i++) { 130*24ce2536SMarcelo Tosatti if (hitmax && i == table_idx-1) 131*24ce2536SMarcelo Tosatti printf("hit max: %d < ", breakmax); 132d482c497SMarcelo Tosatti printf("latency: %d\n", table[i]); 133*24ce2536SMarcelo Tosatti } 134d482c497SMarcelo Tosatti 135d482c497SMarcelo Tosatti return report_summary(); 136d482c497SMarcelo Tosatti } 137