Re: [PATCH v2] VMX controls test framework

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

 



Ah, yes; I see it now. This test didn't catch the early setting of the
launched flag?

On Thu, Aug 24, 2017 at 9:40 AM, Paolo Bonzini <bonzini@xxxxxxx> wrote:
> 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