kvm: test: timer testcase
Test timer interrupts (HPET, LAPIC, PIT) in correlation with ACPI/TSC counters.
New tests/variations are easy to add.
kvm/user/config-x86-common.mak +3 -0
@@ -58,6 +58,9 @@ $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST $(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ $(TEST_DIR)/print.o +$(TEST_DIR)/time.flat: $(cstart.o) $(TEST_DIR)/time.o $(TEST_DIR)/vm.o \ + $(TEST_DIR)/print.o + $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
kvm/user/config-x86_64.mak +2 -1
@@ -7,6 +7,7 @@ CFLAGS += -D__x86_64__ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/sieve.flat \ $(TEST_DIR)/simple.flat $(TEST_DIR)/stringio.flat \ $(TEST_DIR)/memtest1.flat $(TEST_DIR)/emulator.flat \ - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat \ + $(TEST_DIR)/time.flat include config-x86-common.mak
kvm/user/test/x86/io.h new file +35 -0
@@ -0,0 +1,35 @@ +static inline void outb (unsigned char val,unsigned short port) +{ + asmvolatile ("outb %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outw (unsigned short val,unsigned short port) +{ + asmvolatile ("outw %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outl (unsigned long val,unsigned short port) +{ + asmvolatile ("outl %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline unsigned char inb (unsigned short port) +{ +unsigned char val; + asmvolatile ("inb %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline short inw (unsigned short port) +{ +short val; + asmvolatile ("inw %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline unsigned int inl (unsigned short port) +{ +unsigned int val; + asmvolatile ("inl %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +}
kvm/user/test/x86/time.c new file +1010 -0
1,010 lines not on this page · raw message
Quoted 13 lines · Marcelo Tosatti
Test timer interrupts (HPET, LAPIC, PIT) in correlation with ACPI/TSC counters.
New tests/variations are easy to add.
Signed-off-by Marcelo Tosatti<[email protected]>Index: qemu-kvm/kvm/user/config-x86-common.mak
===================================================================
kvm/user/config-x86-common.mak $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST · line 63
Quoted 6 lines
kvm/user/config-x86-common.mak +2
-0@@ -58,6 +58,9 @@ $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST $(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ $(TEST_DIR)/print.o +$(TEST_DIR)/time.flat: $(cstart.o) $(TEST_DIR)/time.o $(TEST_DIR)/vm.o \ + $(TEST_DIR)/print.o
Is print.o really needed?
Quoted 30 lines
===================================================================
kvm/user/test/x86/io.h new file +25
-0@@ -0,0 +1,35 @@ +static inline void outb (unsigned char val,unsigned short port) +{ + asmvolatile ("outb %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outw (unsigned short val,unsigned short port) +{ + asmvolatile ("outw %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outl (unsigned long val,unsigned short port) +{ + asmvolatile ("outl %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline unsigned char inb (unsigned short port) +{ +unsigned char val; + asmvolatile ("inb %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline short inw (unsigned short port) +{ +short val;
kvm/user/test/x86/io.h line 35
Quoted 10 lines
kvm/user/test/x86/io.h new file +10
-0+ asmvolatile ("inw %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline unsigned int inl (unsigned short port) +{ +unsigned int val; + asmvolatile ("inl %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +}
Include guards.
Quoted 206 lines
Index:
qemu-kvm/kvm/user/test/x86/time.c
===================================================================kvm/user/test/x86/time.c new file +200
-0@@ -0,0 +1,1010 @@ +#include "libcflat.h" +#include "apic.h" +#include "vm.h" +#include "io.h" + +typedef unsigned char u8 ; +typedef unsigned short u16 ; +typedef unsigned u32 ; +typedef unsigned long ulong ; +typedef unsigned long long u64 ; + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0])) +#endif + +typedef struct { +unsigned short offset0; +unsigned short selector; +unsigned short ist :3 ; + unsigned short : 5; +unsigned short type :4 ; + unsigned short : 1; +unsigned short dpl :2 ; +unsigned short p :1 ; +unsigned short offset1; +#ifdef __x86_64__ +unsigned offset2; +unsigned reserved; +#endif +}idt_entry_t ; + +typedef struct { +ulong rflags; +ulong cs; +ulong rip; +ulong func; +ulong regs[sizeof (ulong)*2 ]; +}isr_regs_t ; + +#ifdef __x86_64__ +# define R "r" +#else +# define R "e" +#endif + +extern char isr_entry_point[]; + +asm ( + "isr_entry_point: \n" +#ifdef __x86_64__ + "push %r15 \n\t" + "push %r14 \n\t" + "push %r13 \n\t" + "push %r12 \n\t" + "push %r11 \n\t" + "push %r10 \n\t" + "push %r9 \n\t" + "push %r8 \n\t" +#endif + "push %"R "di \n\t" + "push %"R "si \n\t" + "push %"R "bp \n\t" + "push %"R "sp \n\t" + "push %"R "bx \n\t" + "push %"R "dx \n\t" + "push %"R "cx \n\t" + "push %"R "ax \n\t" +#ifdef __x86_64__ + "mov %rsp, %rdi \n\t" + "callq *8*16(%rsp) \n\t" +#else + "push %esp \n\t" + "calll *4+4*8(%esp) \n\t" + "add $4, %esp \n\t" +#endif + "pop %"R "ax \n\t" + "pop %"R "cx \n\t" + "pop %"R "dx \n\t" + "pop %"R "bx \n\t" + "pop %"R "bp \n\t" + "pop %"R "bp \n\t" + "pop %"R "si \n\t" + "pop %"R "di \n\t" +#ifdef __x86_64__ + "pop %r8 \n\t" + "pop %r9 \n\t" + "pop %r10 \n\t" + "pop %r11 \n\t" + "pop %r12 \n\t" + "pop %r13 \n\t" + "pop %r14 \n\t" + "pop %r15 \n\t" +#endif +#ifdef __x86_64__ + "add $8, %rsp \n\t" + "iretq \n\t" +#else +"add $4, %esp \n\t" +"iretl \n\t" +#endif + ); + +static idt_entry_t idt[256 ]; + +static int g_fail; +static int g_tests; + +static void report (const char *msg,int pass) +{ + ++g_tests; +printf ("%s: %s\n" , msg, (pass ?"PASS" :"FAIL" )); +if (!pass) + ++g_fail; +} + +static u16 read_cs (void ) +{ +u16 v; + + asm("mov %%cs, %0" :"=rm" (v)); +return v; +} + +static void init_idt (void ) +{ +struct { +u16 limit; +ulong idt; + } __attribute__((packed)) idt_ptr = { +sizeof (idt_entry_t) *256 -1 , + (ulong)&idt, + }; + + asmvolatile ("lidt %0" : :"m" (idt_ptr)); +} + +static void set_idt_entry (unsigned vec,void (*func)(isr_regs_t *regs)) +{ +u8 *thunk =vmalloc (50 ); +ulong ptr = (ulong )thunk; +idt_entry_t ent = { + .offset0 = ptr, + .selector =read_cs (), + .ist =0 , + .type =14 , + .dpl =0 , + .p =1 , + .offset1 = ptr>>16 , +#ifdef __x86_64__ + .offset2 = ptr>>32 , +#endif + }; +#ifdef __x86_64__ +/* sub $8, %rsp */ + *thunk++ =0x48 ; *thunk++ =0x83 ; *thunk++ =0xec ; *thunk++ =0x08 ; +/* mov $func_low, %(rsp) */ + *thunk++ =0xc7 ; *thunk++ =0x04 ; *thunk++ =0x24 ; + *(u32 *)thunk = (ulong )func; thunk +=4 ; +/* mov $func_high, %(rsp+4) */ + *thunk++ =0xc7 ; *thunk++ =0x44 ; *thunk++ =0x24 ; *thunk++ =0x04 ; + *(u32 *)thunk = (ulong )func>>32 ; thunk +=4 ; +/* jmp isr_entry_point */ + *thunk ++ =0xe9 ; + *(u32 *)thunk = (ulong )isr_entry_point - (ulong)(thunk +4 ); +#else +/* push $func */ + *thunk++ =0x68 ; + *(u32 *)thunk = (ulong )func; +/* jmp isr_entry_point */ + *thunk ++ =0xe9 ; + *(u32 *)thunk = (ulong )isr_entry_point - (ulong)(thunk +4 ); +#endif + idt[vec] = ent; +} + +static void irq_disable (void ) +{ + asmvolatile ("cli" ); +} + +static void irq_enable (void ) +{ + asmvolatile ("sti" ); +} + +static void eoi (void ) +{ +apic_write (APIC_EOI ,0 ); +} + +static int ipi_count; + +static void self_ipi_isr (isr_regs_t *regs) +{ + ++ipi_count; +eoi (); +} + +static void test_self_ipi (void ) +{
kvm/user/test/x86/time.c line 210
Quoted 10 lines
kvm/user/test/x86/time.c new file +10
-0+int vec =0xf1 ; + +set_idt_entry (vec, self_ipi_isr); +irq_enable (); +apic_write (APIC_ICR , +APIC_DEST_SELF |APIC_DEST_PHYSICAL |APIC_DM_FIXED | vec); + asmvolatile ("nop" ); +report ("self ipi" , ipi_count ==1 ); +} +
Needed?
Quoted 68 lines
kvm/user/test/x86/time.c new file +67
-0+static void set_ioapic_redir (unsigned line,unsigned vec,unsigned trig_mode) +{ +ioapic_redir_entry_t e = { + .vector = vec, + .delivery_mode =0 , + .trig_mode = trig_mode, + }; + +ioapic_write_redir (line, e); +} + +/* interrupt handlers */ + +#define TIMER_VEC_BASE 0x90 + +struct int_table { +void (*func)(isr_regs_t *regs); +void (*irq_handler)(void *irq_priv); +void *irq_priv; +}; + +static struct int_table int_handlers[]; + +#define decl_irq_handler (N ) \ +static void timer_int_##N(isr_regs_t *regs) { \ + struct int_table *t =&int_handlers[N]; \ + t->irq_handler(t->irq_priv); \ + eoi(); \ +} + +void set_irq_handler (int vec,void (*func)(void *irq_priv),void *irq_priv); + +void hlt (void ) { asmvolatile ("hlt" ); } + +#define NS_FREQ 1000000000ULL +#define US_FREQ 1000000ULL + +#define ns2cyc (ns) (ns*cpu_hz)/NS_FREQ +#define cyc2ns (cyc) (cyc*NS_FREQ)/cpu_hz + +#define us_to_ns (n) (1000*n) +#define ms_to_ns (n) (1000000*n) +#define s_to_ns (n) (1000000000*n) + +#define sdelay (n) nsdelay(s_to_ns(n)) + +u64 cpu_hz; + +static inline int fls (int x) +{ +int r; + asm("bsrl %1,%0\n\t" +"jnz 1f\n\t" +"movl $-1,%0\n" +"1:" :"=r" (r) :"rm" (x)); +return r +1 ; +} + +# define do_div (n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ + }) + +static inline u64 div_u64_rem (u64 dividend,u32 divisor,u32 *remainder)
kvm/user/test/x86/time.c line 287
Quoted 10 lines
kvm/user/test/x86/time.c new file +10
-0+{ + *remainder = dividend % divisor; +return dividend / divisor; +} + +static inline u64 div_u64 (u64 dividend,u32 divisor) +{ +u32 remainder; +return div_u64_rem (dividend, divisor,&remainder); +}
What's wrong with / and %?
Quoted 7 lines
kvm/user/test/x86/time.c new file +6
-0+/* 64bit divisor, dividend and result. dynamic precision */ +u64 div64_u64 (u64 dividend,u64 divisor) +{ +u32 high, d; + + high = divisor>>32 ;
kvm/user/test/x86/time.c line 310
Quoted 10 lines
kvm/user/test/x86/time.c new file +10
-0+if (high) { +unsigned int shift =fls (high); + + d = divisor>> shift; + dividend>>= shift; + }else + d = divisor; + +return div_u64 (dividend, d); +}
Ordinary 64-bit divides should work, no?
Signature · 1 line
error compiling committee.c: too many arguments to function
kvm: test: timer testcase (v2)
Avi, vm.o needs print.o (all other comments addressed).
-----------------
Test timer interrupts (HPET, LAPIC, PIT) in correlation with ACPI/TSC counters.
New tests/variations are easy to add.
kvm/user/config-x86-common.mak +3 -0
@@ -58,6 +58,9 @@ $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST $(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ $(TEST_DIR)/print.o +$(TEST_DIR)/time.flat: $(cstart.o) $(TEST_DIR)/time.o $(TEST_DIR)/vm.o \ + $(TEST_DIR)/print.o + $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
kvm/user/config-x86_64.mak +2 -1
@@ -7,6 +7,7 @@ CFLAGS += -D__x86_64__ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/sieve.flat \ $(TEST_DIR)/simple.flat $(TEST_DIR)/stringio.flat \ $(TEST_DIR)/memtest1.flat $(TEST_DIR)/emulator.flat \ - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat \ + $(TEST_DIR)/time.flat include config-x86-common.mak
kvm/user/test/x86/io.h new file +40 -0
@@ -0,0 +1,40 @@ +#ifndef __PIO_H +#define __PIO_H + +static inline void outb (unsigned char val,unsigned short port) +{ + asmvolatile ("outb %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outw (unsigned short val,unsigned short port) +{ + asmvolatile ("outw %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline void outl (unsigned long val,unsigned short port) +{ + asmvolatile ("outl %0, %w1" : :"a" (val),"Nd" (port)); +} + +static inline unsigned char inb (unsigned short port) +{ +unsigned char val; + asmvolatile ("inb %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline short inw (unsigned short port) +{ +short val; + asmvolatile ("inw %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +static inline unsigned int inl (unsigned short port) +{ +unsigned int val; + asmvolatile ("inl %w1, %0" :"=a" (val) :"Nd" (port)); +return val; +} + +#endif
kvm/user/test/x86/time.c new file +938 -0
938 lines not on this page · raw message