Re: [PATCH v2] VMX controls test framework

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

 



On 24/08/2017 18:38, Jim Mattson wrote:
> Ping. BTW, this would make sure that you didn't set the launched state
> of the VMCS12 too early. :-)

This is commit c9186188afdfef17eba4f3331594fb6b61c0b285, isn't it?

Paolo

> On Fri, Jul 7, 2017 at 9:12 AM, Jim Mattson <jmattson@xxxxxxxxxx> wrote:
>> Ultimately, this test will be expanded to cover all of the "Checks on
>> VMX Controls" described in the Intel SDM, volume 3, section
>> 26.2.1. For now, it just checks I/O bitmap and MSR bitmap settings.
>>
>> Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx>
>> ---
>>  x86/unittests.cfg |   6 +++
>>  x86/vmx_tests.c   | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 161 insertions(+)
>>
>> diff --git a/x86/unittests.cfg b/x86/unittests.cfg
>> index c9858159c657..419b135ca9d4 100644
>> --- a/x86/unittests.cfg
>> +++ b/x86/unittests.cfg
>> @@ -500,6 +500,12 @@ extra_params = -cpu host,+vmx -m 2048 -append invvpid_test_v2
>>  arch = x86_64
>>  groups = vmx
>>
>> +[vmx_controls]
>> +file = vmx.flat
>> +extra_params = -cpu host,+vmx -m 2048 -append vmx_controls_test
>> +arch = x86_64
>> +groups = vmx
>> +
>>  [debug]
>>  file = debug.flat
>>  arch = x86_64
>> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
>> index ffc913573fb4..0946bda50a8d 100644
>> --- a/x86/vmx_tests.c
>> +++ b/x86/vmx_tests.c
>> @@ -3133,6 +3133,159 @@ static void invvpid_test_v2(void)
>>         invvpid_test_not_in_vmx_operation();
>>  }
>>
>> +/*
>> + * Test for early VMLAUNCH failure. Returns true if VMLAUNCH makes it
>> + * at least as far as the guest-state checks. Returns false if the
>> + * VMLAUNCH fails early and execution falls through to the next
>> + * instruction.
>> + */
>> +static bool vmlaunch_succeeds(void)
>> +{
>> +       /*
>> +        * Indirectly set VMX_INST_ERR to 12 ("VMREAD/VMWRITE from/to
>> +        * unsupported VMCS component"). The caller can then check
>> +        * to see if a failed VM-entry sets VMX_INST_ERR as expected.
>> +        */
>> +       vmcs_write(~0u, 0);
>> +
>> +       vmcs_write(HOST_RIP, (uintptr_t)&&success);
>> +       __asm__ __volatile__ goto ("vmwrite %%rsp, %0; vmlaunch"
>> +                                  :
>> +                                  : "r" ((u64)HOST_RSP)
>> +                                  : "cc", "memory"
>> +                                  : success);
>> +       return false;
>> +success:
>> +       TEST_ASSERT(vmcs_read(EXI_REASON) ==
>> +                   (VMX_FAIL_STATE | VMX_ENTRY_FAILURE));
>> +       return true;
>> +}
>> +
>> +/*
>> + * Try to launch the current VMCS.
>> + */
>> +static void test_vmx_controls(bool controls_valid)
>> +{
>> +       bool success = vmlaunch_succeeds();
>> +       u32 vmx_inst_err;
>> +
>> +       report("vmlaunch %s", success == controls_valid,
>> +              controls_valid ? "succeeds" : "fails");
>> +       if (!controls_valid) {
>> +               vmx_inst_err = vmcs_read(VMX_INST_ERROR);
>> +               report("VMX inst error is %d (actual %d)",
>> +                      vmx_inst_err == VMXERR_ENTRY_INVALID_CONTROL_FIELD,
>> +                      VMXERR_ENTRY_INVALID_CONTROL_FIELD, vmx_inst_err);
>> +       }
>> +}
>> +
>> +/*
>> + * Test a particular address setting for a physical page reference in
>> + * the VMCS.
>> + */
>> +static void test_vmcs_page_addr(const char *name,
>> +                               enum Encoding encoding,
>> +                               bool ignored,
>> +                               u64 addr)
>> +{
>> +       report_prefix_pushf("%s = %lx", name, addr);
>> +       vmcs_write(encoding, addr);
>> +       test_vmx_controls(ignored || (IS_ALIGNED(addr, PAGE_SIZE) &&
>> +                                 addr < (1ul << cpuid_maxphyaddr())));
>> +       report_prefix_pop();
>> +}
>> +
>> +/*
>> + * Test interesting values for a physical page reference in the VMCS.
>> + */
>> +static void test_vmcs_page_values(const char *name,
>> +                                 enum Encoding encoding,
>> +                                 bool ignored)
>> +{
>> +       unsigned i;
>> +       u64 orig_val = vmcs_read(encoding);
>> +
>> +       for (i = 0; i < 64; i++)
>> +               test_vmcs_page_addr(name, encoding, ignored, 1ul << i);
>> +
>> +       test_vmcs_page_addr(name, encoding, ignored, PAGE_SIZE - 1);
>> +       test_vmcs_page_addr(name, encoding, ignored, PAGE_SIZE);
>> +       test_vmcs_page_addr(name, encoding, ignored,
>> +                           (1ul << cpuid_maxphyaddr()) - PAGE_SIZE);
>> +       test_vmcs_page_addr(name, encoding, ignored, -1ul);
>> +
>> +       vmcs_write(encoding, orig_val);
>> +}
>> +
>> +/*
>> + * Test a physical page reference in the VMCS, when the corresponding
>> + * feature is enabled and when the corresponding feature is disabled.
>> + */
>> +static void test_vmcs_page_reference(u32 control_bit, enum Encoding field,
>> +                                    const char *field_name,
>> +                                    const char *control_name)
>> +{
>> +       u32 primary = vmcs_read(CPU_EXEC_CTRL0);
>> +       u64 page_addr;
>> +
>> +       if (!(ctrl_cpu_rev[0].clr & control_bit))
>> +               return;
>> +
>> +       page_addr = vmcs_read(field);
>> +
>> +       report_prefix_pushf("%s enabled", control_name);
>> +       vmcs_write(CPU_EXEC_CTRL0, primary | control_bit);
>> +       test_vmcs_page_values(field_name, field, false);
>> +       report_prefix_pop();
>> +
>> +       report_prefix_pushf("%s disabled", control_name);
>> +       vmcs_write(CPU_EXEC_CTRL0, primary & ~control_bit);
>> +       test_vmcs_page_values(field_name, field, true);
>> +       report_prefix_pop();
>> +
>> +       vmcs_write(field, page_addr);
>> +       vmcs_write(CPU_EXEC_CTRL0, primary);
>> +}
>> +
>> +/*
>> + * If the "use I/O bitmaps" VM-execution control is 1, bits 11:0 of
>> + * each I/O-bitmap address must be 0. Neither address should set any
>> + * bits beyond the processor's physical-address width.
>> + * [Intel SDM]
>> + */
>> +static void test_io_bitmaps(void)
>> +{
>> +       test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_A,
>> +                                "I/O bitmap A", "Use I/O bitmaps");
>> +       test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_B,
>> +                                "I/O bitmap B", "Use I/O bitmaps");
>> +}
>> +
>> +/*
>> + * If the "use MSR bitmaps" VM-execution control is 1, bits 11:0 of
>> + * the MSR-bitmap address must be 0. The address should not set any
>> + * bits beyond the processor's physical-address width.
>> + * [Intel SDM]
>> + */
>> +static void test_msr_bitmap(void)
>> +{
>> +       test_vmcs_page_reference(CPU_MSR_BITMAP, MSR_BITMAP,
>> +                                "MSR bitmap", "Use MSR bitmaps");
>> +}
>> +
>> +static void vmx_controls_test(void)
>> +{
>> +       /*
>> +        * Bit 1 of the guest's RFLAGS must be 1, or VM-entry will
>> +        * fail due to invalid guest state, should we make it that
>> +        * far.
>> +        */
>> +       vmcs_write(GUEST_RFLAGS, 0);
>> +
>> +       test_io_bitmaps();
>> +       test_msr_bitmap();
>> +}
>> +
>>  #define TEST(name) { #name, .v2 = name }
>>
>>  /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */
>> @@ -3196,5 +3349,7 @@ struct vmx_test vmx_tests[] = {
>>         TEST(ept_access_test_force_2m_page),
>>         /* Opcode tests. */
>>         TEST(invvpid_test_v2),
>> +       /* VM-entry tests */
>> +       TEST(vmx_controls_test),
>>         { NULL, NULL, NULL, NULL, NULL, {0} },
>>  };
>> --
>> 2.13.2.725.g09c95d1e9-goog
>>




[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