Re: [PATCH] kvm-unit-tests: VMX: Split VMX test suites to separate file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Aug 5, 2013 at 12:54 AM, Jan Kiszka <jan.kiszka@xxxxxx> wrote:
> On 2013-07-31 11:22, Arthur Chunqi Li wrote:
>> Reconstruct VMX codes and put all VMX test suites in x86/vmx_tests.c.
>>
>> Signed-off-by: Arthur Chunqi Li <yzt356@xxxxxxxxx>
>> ---
>>  config-x86-common.mak |    2 +-
>>  x86/vmx.c             |   71 +++----------------------------------------------
>>  x86/vmx.h             |   43 ++++++++++++++++++++++++------
>>  x86/vmx_tests.c       |   43 ++++++++++++++++++++++++++++++
>>  x86/vmx_tests.h       |    7 +++++
>>  5 files changed, 90 insertions(+), 76 deletions(-)
>>  create mode 100644 x86/vmx_tests.c
>>  create mode 100644 x86/vmx_tests.h
>>
>> diff --git a/config-x86-common.mak b/config-x86-common.mak
>> index 34a41e1..bf88c67 100644
>> --- a/config-x86-common.mak
>> +++ b/config-x86-common.mak
>> @@ -101,7 +101,7 @@ $(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
>>
>>  $(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
>>
>> -$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o
>> +$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
>>
>>  arch_clean:
>>       $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
>> diff --git a/x86/vmx.c b/x86/vmx.c
>> index 082c3bb..397554a 100644
>> --- a/x86/vmx.c
>> +++ b/x86/vmx.c
>> @@ -6,19 +6,7 @@
>>  #include "msr.h"
>>  #include "smp.h"
>>  #include "io.h"
>> -
>> -int fails = 0, tests = 0;
>> -u32 *vmxon_region;
>> -struct vmcs *vmcs_root;
>> -u32 vpid_cnt;
>> -void *guest_stack, *guest_syscall_stack;
>> -u32 ctrl_pin, ctrl_enter, ctrl_exit, ctrl_cpu[2];
>> -ulong fix_cr0_set, fix_cr0_clr;
>> -ulong fix_cr4_set, fix_cr4_clr;
>> -struct regs regs;
>> -struct vmx_test *current;
>> -u64 hypercall_field = 0;
>> -bool launched;
>> +#include "vmx_tests.h"
>>
>>  extern u64 gdt64_desc[];
>>  extern u64 idt_descr[];
>> @@ -27,17 +15,6 @@ extern void *vmx_return;
>>  extern void *entry_sysenter;
>>  extern void *guest_entry;
>>
>> -static void report(const char *name, int result)
>> -{
>> -     ++tests;
>> -     if (result)
>> -             printf("PASS: %s\n", name);
>> -     else {
>> -             printf("FAIL: %s\n", name);
>> -             ++fails;
>> -     }
>> -}
>> -
>>  static int make_vmcs_current(struct vmcs *vmcs)
>>  {
>>       bool ret;
>> @@ -80,7 +57,7 @@ static inline int vmx_off()
>>       return ret;
>>  }
>>
>> -static void print_vmexit_info()
>> +void print_vmexit_info()
>>  {
>>       u64 guest_rip, guest_rsp;
>>       ulong reason = vmcs_read(EXI_REASON) & 0xff;
>> @@ -587,48 +564,6 @@ static void basic_syscall_handler(u64 syscall_no)
>>  {
>>  }
>>
>> -static void vmenter_main()
>> -{
>> -     u64 rax;
>> -     u64 rsp, resume_rsp;
>> -
>> -     report("test vmlaunch", 1);
>> -
>> -     asm volatile(
>> -             "mov %%rsp, %0\n\t"
>> -             "mov %3, %%rax\n\t"
>> -             "vmcall\n\t"
>> -             "mov %%rax, %1\n\t"
>> -             "mov %%rsp, %2\n\t"
>> -             : "=r"(rsp), "=r"(rax), "=r"(resume_rsp)
>> -             : "g"(0xABCD));
>> -     report("test vmresume", (rax == 0xFFFF) && (rsp == resume_rsp));
>> -}
>> -
>> -static int vmenter_exit_handler()
>> -{
>> -     u64 guest_rip;
>> -     ulong reason;
>> -
>> -     guest_rip = vmcs_read(GUEST_RIP);
>> -     reason = vmcs_read(EXI_REASON) & 0xff;
>> -     switch (reason) {
>> -     case VMX_VMCALL:
>> -             if (current->guest_regs.rax != 0xABCD) {
>> -                     report("test vmresume", 0);
>> -                     return VMX_TEST_VMEXIT;
>> -             }
>> -             current->guest_regs.rax = 0xFFFF;
>> -             vmcs_write(GUEST_RIP, guest_rip + 3);
>> -             return VMX_TEST_RESUME;
>> -     default:
>> -             report("test vmresume", 0);
>> -             print_vmexit_info();
>> -     }
>> -     return VMX_TEST_VMEXIT;
>> -}
>> -
>> -
>>  /* name/init/guest_main/exit_handler/syscall_handler/guest_regs
>>     basic_* just implement some basic functions */
>>  static struct vmx_test vmx_tests[] = {
>> @@ -644,6 +579,8 @@ int main(void)
>>
>>       setup_vm();
>>       setup_idt();
>> +     fails = tests = 0;
>> +     hypercall_field = 0;
>>
>>       if (test_vmx_capability() != 0) {
>>               printf("ERROR : vmx not supported, check +vmx option\n");
>> diff --git a/x86/vmx.h b/x86/vmx.h
>> index d80e000..f82bf5a 100644
>> --- a/x86/vmx.h
>> +++ b/x86/vmx.h
>> @@ -1,5 +1,5 @@
>> -#ifndef __HYPERVISOR_H
>> -#define __HYPERVISOR_H
>> +#ifndef __VMX_H
>> +#define __VMX_H
>>
>>  #include "libcflat.h"
>>
>> @@ -41,7 +41,7 @@ struct vmx_test {
>>       int exits;
>>  };
>>
>> -static union vmx_basic {
>> +union vmx_basic {
>>       u64 val;
>>       struct {
>>               u32 revision;
>> @@ -55,35 +55,35 @@ static union vmx_basic {
>>       };
>>  } basic;
>
> extern union vmx_basic basic, and stick the definition in vmx.c. Same
> pattern for the other cases.
Here you mean put definition in vmx.c and "extern" definition in vmx.h?
>
>>
>> -static union vmx_ctrl_pin {
>> +union vmx_ctrl_pin {
>>       u64 val;
>>       struct {
>>               u32 set, clr;
>>       };
>>  } ctrl_pin_rev;
>>
>> -static union vmx_ctrl_cpu {
>> +union vmx_ctrl_cpu {
>>       u64 val;
>>       struct {
>>               u32 set, clr;
>>       };
>>  } ctrl_cpu_rev[2];
>>
>> -static union vmx_ctrl_exit {
>> +union vmx_ctrl_exit {
>>       u64 val;
>>       struct {
>>               u32 set, clr;
>>       };
>>  } ctrl_exit_rev;
>>
>> -static union vmx_ctrl_ent {
>> +union vmx_ctrl_ent {
>>       u64 val;
>>       struct {
>>               u32 set, clr;
>>       };
>>  } ctrl_enter_rev;
>>
>> -static union vmx_ept_vpid {
>> +union vmx_ept_vpid {
>>       u64 val;
>>       struct {
>>               u32:16,
>> @@ -432,6 +432,20 @@ enum Ctrl1 {
>>  #define HYPERCALL_MASK               0xFFF
>>  #define HYPERCALL_VMEXIT     0x1
>>
>> +
>> +u32 *vmxon_region;
>> +struct vmcs *vmcs_root;
>> +void *guest_stack, *guest_syscall_stack;
>> +int fails, tests;
>> +u64 hypercall_field;
>> +u32 vpid_cnt;
>> +u32 ctrl_pin, ctrl_enter, ctrl_exit, ctrl_cpu[2];
>> +ulong fix_cr0_set, fix_cr0_clr;
>> +ulong fix_cr4_set, fix_cr4_clr;
>> +struct regs regs;
>> +struct vmx_test *current;
>> +bool launched;
>> +
>
> extern <type> <varname>
>
> But do all these variables need to be exported to the test cases? Better
> confine it to a minimum, exporting more when test cases come along that
> actually need them.
>
>>  static inline int vmcs_clear(struct vmcs *vmcs)
>>  {
>>       bool ret;
>> @@ -462,5 +476,18 @@ static inline int vmcs_save(struct vmcs **vmcs)
>>       return ret;
>>  }
>>
>> +static inline void report(const char *name, int result)
>> +{
>> +     ++tests;
>> +     if (result)
>> +             printf("PASS: %s\n", name);
>> +     else {
>> +             printf("FAIL: %s\n", name);
>> +             ++fails;
>> +     }
>> +}
>> +
>
> Why static inline? Better leave this as service of the vmx core.
You mean put it in vmx.c and "extern" it here?
>
>> +void print_vmexit_info();
>> +
>>  #endif
>>
>> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
>> new file mode 100644
>> index 0000000..6bd36b0
>> --- /dev/null
>> +++ b/x86/vmx_tests.c
>> @@ -0,0 +1,43 @@
>> +#include "vmx.h"
>> +
>> +void vmenter_main()
>> +{
>> +     u64 rax;
>> +     u64 rsp, resume_rsp;
>> +
>> +     report("test vmlaunch", 1);
>> +
>> +     asm volatile(
>> +             "mov %%rsp, %0\n\t"
>> +             "mov %3, %%rax\n\t"
>> +             "vmcall\n\t"
>> +             "mov %%rax, %1\n\t"
>> +             "mov %%rsp, %2\n\t"
>> +             : "=r"(rsp), "=r"(rax), "=r"(resume_rsp)
>> +             : "g"(0xABCD));
>> +     report("test vmresume", (rax == 0xFFFF) && (rsp == resume_rsp));
>> +}
>> +
>> +int vmenter_exit_handler()
>> +{
>> +     u64 guest_rip;
>> +     ulong reason;
>> +
>> +     guest_rip = vmcs_read(GUEST_RIP);
>> +     reason = vmcs_read(EXI_REASON) & 0xff;
>> +     switch (reason) {
>> +     case VMX_VMCALL:
>> +             if (current->guest_regs.rax != 0xABCD) {
>> +                     report("test vmresume", 0);
>> +                     return VMX_TEST_VMEXIT;
>> +             }
>> +             current->guest_regs.rax = 0xFFFF;
>> +             vmcs_write(GUEST_RIP, guest_rip + 3);
>> +             return VMX_TEST_RESUME;
>> +     default:
>> +             report("test vmresume", 0);
>> +             print_vmexit_info();
>> +     }
>> +     return VMX_TEST_VMEXIT;
>> +}
>> +
>> diff --git a/x86/vmx_tests.h b/x86/vmx_tests.h
>> new file mode 100644
>> index 0000000..41580ff
>> --- /dev/null
>> +++ b/x86/vmx_tests.h
>> @@ -0,0 +1,7 @@
>> +#ifndef __VMX_TESTS_H
>> +#define __VMX_TESTS_H
>> +
>> +void vmenter_main();
>> +int vmenter_exit_handler();
>
> I'd rather move vmx_tests to, well, vmx_tests.c
I have tried to put vmx_tests in vmx_tests.c and extern definition in
vmx.h. But it is impossible to get its size statically when compiling,
thus the codes "for (i = 1; i < ARRAY_SIZE(vmx_tests); ++i) {" in main
of vmx.c is invalid. If we use ARRAY_SIZE to get its size, we should
make it static.

An alternative solution is put vmx_tests in vmx_tests.h, which will be
included by vmx.c

Arthur
>
>> +
>> +#endif
>>
>
> Jan
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux