test: Drop print.S
PATCH 1/3 test: Drop print.S
We have already had lib/printf.c.
Signed-off-by Jason Wang <[email protected]>
--- kvm/test/x86/print.S | 31 ------------------------------- 1 files changed, 0 insertions(+), 31 deletions(-) delete mode 100644 kvm/test/x86/print.S
kvm/test/config-x86-common.mak +4 -5
@@ -33,7 +33,7 @@ test_cases: $(tests-common) $(tests) $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86 -$(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/print.o +$(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/hypercall.flat: $(cstart.o) $(TEST_DIR)/hypercall.o
@@ -45,14 +45,13 @@ $(TEST_DIR)/vmexit.flat: $(cstart.o) $(TEST_DIR)/vmexit.o $(TEST_DIR)/smptest.flat: $(cstart.o) $(TEST_DIR)/smptest.o $(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/emulator.o \ - $(TEST_DIR)/vm.o $(TEST_DIR)/print.o + $(TEST_DIR)/vm.o $(TEST_DIR)/port80.flat: $(cstart.o) $(TEST_DIR)/port80.o $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST_DIR)/tsc.o -$(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ - $(TEST_DIR)/print.o +$(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
@@ -66,7 +65,7 @@ $(TEST_DIR)/idt_test.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/idt_test.o $(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o $(TEST_DIR)/rmap_chain.flat: $(cstart.o) $(TEST_DIR)/rmap_chain.o \ - $(TEST_DIR)/print.o $(TEST_DIR)/vm.o + $(TEST_DIR)/vm.o arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \
kvm/test/x86/print.S deleted +0 -31
@@ -1,31 +0,0 @@ - -#include "print.h" - -#define PSEUDO_SERIAL_PORT 0xf1 - - -.text - PRINT "boo" - hlt -1: jmp 1b - -.globl print -print: - push %rax - push %rsi - push %rdx - - mov %rdi, %rsi - mov $(PSEUDO_SERIAL_PORT), %edx - -putchar: - cmpb $0, (%rsi) - jz done - outsb - jmp putchar -done: - - pop %rdx - pop %rsi - pop %rax - ret
PATCH 2/3 test: Add kvmclock driver
This patch add a kvmclock driver for unittest. A special bit:PV_CLOCK_CYCLE_RAW_TEST_BIT is used to notify the driver to return just the raw cycle supplied by the hypervisor.
Signed-off-by Jason Wang <[email protected]>
--- kvm/test/x86/kvmclock.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++ kvm/test/x86/kvmclock.h | 51 ++++++++++++ 2 files changed, 257 insertions(+), 0 deletions(-) create mode 100644 kvm/test/x86/kvmclock.c create mode 100644 kvm/test/x86/kvmclock.h
kvm/test/x86/kvmclock.c new file +206 -0
@@ -0,0 +1,206 @@ +#include "libcflat.h" +#include "smp.h" +#include "kvmclock.h" + +#define barrier () asm volatile("":::"memory") +#define rmb () asm volatile("lfence":::"memory") + +struct pvclock_vcpu_time_info hv_clock[MAX_CPU ]; +struct pvclock_wall_clock wall_clock; +static unsigned char valid_flags =0 ; +static u64 __attribute__((aligned (8 ))) last_value =0 ; + +#ifdef __i386__ +static inline u64 atomic64_read (const u64 *v) +{ +u64 res; + + asmvolatile ("mov %%ebx, %%eax;" +"mov %%ecx, %%edx;" +"lock cmpxchg8b %1;" + :"=&A" (res) + :"m" (*v) + ); + +return res; +} + +static u64 atomic64_cmpxchg (u64 *v,u64 old,u64 new) +{ +u32 low = new; +u32 high = new >>32 ; + + asmvolatile ("lock cmpxchg8b %1\n" + :"+A" (old),"+m" (*v) + :"b" (low),"c" (high) + ); + +return old; +} +#elif defined(__x86_64__) +static inline u64 atomic64_read (const u64 *v) +{ +return (*(volatile long *)v); +} + +static u64 atomic64_cmpxchg (u64 *v,u64 old,u64 new) +{ +u64 ret; +u64 _old = old; +u64 _new = new; + + asmvolatile ("lock cmpxchgq %1,%2" + :"=a" (ret) + :"r" (_new),"m" (*(volatile long *)v),"0" (_old) + :"memory" + ); +return ret; +} +#endif + +static void wrmsr (unsigned index,u64 value) +{ +unsigned a = value, d = value >>32 ; + + asmvolatile ("wrmsr" : :"a" (a),"d" (d),"c" (index)); +} + +static u64 native_read_tsc (void ) +{ +unsigned a, d; + + asmvolatile ("rdtsc" :"=a" (a),"=d" (d)); +return a | (u64 )d <<32 ; +} + +static inline u64 scale_delta (u64 delta,u32 mul_frac,int shift) +{ +u64 product; +#ifdef __i386__ +u32 tmp1, tmp2; +#endif + +if (shift <0 ) + delta >>= -shift; +else + delta <<= shift; + +#ifdef __i386__ + __asm__ ( +"mul %5 ; " +"mov %4,%%eax ; " +"mov %%edx,%4 ; " +"mul %5 ; " +"xor %5,%5 ; " +"add %4,%%eax ; " +"adc %5,%%edx ; " + :"=A" (product),"=r" (tmp1),"=r" (tmp2) + :"a" ((u32 )delta),"1" ((u32)(delta >>32 )),"2" (mul_frac) ); +#elif defined(__x86_64__) + __asm__ ( +"mul %%rdx ; shrd $32,%%rdx,%%rax" + :"=a" (product) :"0" (delta),"d" ((u64 )mul_frac) ); +#else +#error implement me! +#endif + +return product; +} + +static unsigned pvclock_get_time_values (struct pvclock_shadow_time *dst, +struct pvclock_vcpu_time_info *src) +{ +do { + dst->version = src->version; +rmb ();/* fetch version before data */ + dst->tsc_timestamp = src->tsc_timestamp; + dst->system_timestamp = src->system_time; + dst->tsc_to_nsec_mul = src->tsc_to_system_mul; + dst->tsc_shift = src->tsc_shift; + dst->flags = src->flags; +rmb ();/* test version after fetching data */ + }while ((src->version &1 ) || (dst->version != src->version)); + +return dst->version; +} + +static u64 pvclock_get_nsec_offset (struct pvclock_shadow_time *shadow) +{ +u64 delta =native_read_tsc () - shadow->tsc_timestamp; +return scale_delta (delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift); +} + +static cycle_t pvclock_clocksource_read (struct pvclock_vcpu_time_info *src) +{ +struct pvclock_shadow_time shadow; +unsigned version; +cycle_t ret, offset; +u64 last; + +do { + version =pvclock_get_time_values (&shadow, src); +barrier (); + offset =pvclock_get_nsec_offset (&shadow); + ret = shadow.system_timestamp + offset; +barrier (); + }while (version != src->version); + +if ((valid_flags &PVCLOCK_CYCLE_RAW_TEST_BIT ) || + ((valid_flags &PVCLOCK_TSC_STABLE_BIT ) && + (shadow.flags &PVCLOCK_TSC_STABLE_BIT ))) +return ret; + + last =atomic64_read (&last_value); +do { +if (ret < last) +return last; + last =atomic64_cmpxchg (&last_value, last, ret); + }while (last != ret); + +return ret; +} + +cycle_t kvm_clock_read () +{ +struct pvclock_vcpu_time_info *src; +cycle_t ret; +int index =smp_id (); + + src = &hv_clock[index]; + ret =pvclock_clocksource_read (src); +return ret; +} + +void kvm_clock_init (void *data) +{ +int index =smp_id (); +struct pvclock_vcpu_time_info *hvc = &hv_clock[index]; + +printf ("kvm-clock: cpu %d, msr 0x:%lx \n" , index, hvc); +wrmsr (MSR_KVM_SYSTEM_TIME , (unsigned long )hvc |1 ); +} + +void kvm_clock_clear (void *data) +{ +wrmsr (MSR_KVM_SYSTEM_TIME ,0LL ); +} + +void kvm_get_wallclock (struct timespec *ts) +{ +u32 version; +wrmsr (MSR_KVM_WALL_CLOCK , (u64)&wall_clock); + +do { + version = wall_clock.version; +rmb ();/* fetch version before time */ + ts->sec = wall_clock.sec; + ts->nsec = wall_clock.nsec; +rmb ();/* fetch time before checking version */ + }while ((wall_clock.version &1 ) || (version != wall_clock.version)); + +} + +void pvclock_set_flags (unsigned char flags) +{ + valid_flags = flags; +}
kvm/test/x86/kvmclock.h new file +51 -0
51 lines not on this page · raw message
PATCH 3/3 test: Add test for kvmclock
In reply to Jason WangThis patch implements the following tests for kvmclock:
- A simple wall clock test to check whether a consistent value was returned.
- A monotonic cycle test to check whether the kvmclock driver could return monotnic cycles in SMP guests.
- A raw cycle test to check whether the hypervios could provide monotonic cycles.
Signed-off-by Jason Wang <[email protected]>
--- kvm/test/x86/kvmclock_test.c | 128 ++++++++++++++++++++++++++++++++++++++++++ kvm/test/x86/unittests.cfg | 4 + 2 files changed, 132 insertions(+), 0 deletions(-) create mode 100644 kvm/test/x86/kvmclock_test.c
kvm/test/config-x86-common.mak +5 -1
@@ -25,7 +25,8 @@ FLATLIBS = lib/libcflat.a $(libgcc) tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \ $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ + $(TEST_DIR)/kvmclock_test.flat tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
@@ -67,6 +68,9 @@ $(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o $(TEST_DIR)/rmap_chain.flat: $(cstart.o) $(TEST_DIR)/rmap_chain.o \ $(TEST_DIR)/vm.o +$(TEST_DIR)/kvmclock_test.flat: $(cstart.o) $(TEST_DIR)/kvmclock.o \ + $(TEST_DIR)/kvmclock_test.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \ $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
kvm/test/x86/kvmclock_test.c new file +128 -0
128 lines not on this page · raw message
kvm/test/x86/unittests.cfg +4 -0
@@ -53,3 +53,7 @@ file = xsave.flat [rmap_chain] file = rmap_chain.flat + +[kvmclock] +file = kvmclock_test.flat +smp = 2