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