Re: [PATCH 2/2][kvm-unit-test] nVMX x86: Check PML and EPT on vmentry of L2 guests

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

 



On Wed, Sep 26, 2018 at 11:18 AM, Krish Sadhukhan
<krish.sadhukhan@xxxxxxxxxx> wrote:
> According to section "Checks on VMX Controls" in Intel SDM vol 3C, the
> following check needs to be enforced on vmentry of L2 guests:
>
>     If the "enable PML" VM-execution control is 1, the "enable EPT"
>     VM-execution control must also be 1. In addition, the PML address
>     must satisfy the following checks:
>
>       — Bits 11:0 of the address must be 0.
>       — The address should not set any bits beyond the processor’s
>         physical-address width.
>
> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx>
> Reviewed-by: Mark Kanda <mark.kanda@xxxxxxxxxx>
> ---
>  x86/vmx.h       |  3 ++
>  x86/vmx_tests.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
>  2 files changed, 91 insertions(+), 11 deletions(-)
>
> diff --git a/x86/vmx.h b/x86/vmx.h
> index 22b2892..78a786e 100644
> --- a/x86/vmx.h
> +++ b/x86/vmx.h
> @@ -448,6 +448,9 @@ enum Intr_type {
>  #define INTR_TYPE_SOFT_EXCEPTION       (6 << 8) /* software exception */
>  #define INTR_TYPE_OTHER_EVENT           (7 << 8) /* other event */
>
> +
> +#define        PMLADDR_RESV_BITS               0xfff
> +

This is unnecessary, since these are the same bits that are reserved
for all page references.

>  /*
>   * VM-instruction error numbers
>   */
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index 0e9d900..37db793 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -3452,14 +3452,18 @@ static void test_vmcs_page_addr(const char *name,
>  static void test_vmcs_page_values(const char *name,
>                                   enum Encoding encoding,
>                                   bool ignored,
> -                                 bool xfail_beyond_mapped_ram)
> +                                 bool xfail_beyond_mapped_ram,
> +                                 u64 resv_bits)
>  {
>         unsigned i;
>         u64 orig_val = vmcs_read(encoding);
>
> -       for (i = 0; i < 64; i++)
> +       for (i = 0; i < 64; i++) {
> +               if (i & resv_bits)
> +                       continue;
>                 test_vmcs_page_addr(name, encoding, ignored,
>                                     xfail_beyond_mapped_ram, 1ul << i);
> +       }
>
>         test_vmcs_page_addr(name, encoding, ignored,
>                             xfail_beyond_mapped_ram, PAGE_SIZE - 1);
> @@ -3483,7 +3487,7 @@ static void test_vmcs_page_reference(u32 control_bit, enum Encoding field,
>                                      const char *field_name,
>                                      const char *control_name,
>                                      bool xfail_beyond_mapped_ram,
> -                                    bool control_primary)
> +                                    bool control_primary, u64 resv_bits)
>  {
>         u32 primary = vmcs_read(CPU_EXEC_CTRL0);
>         u32 secondary = vmcs_read(CPU_EXEC_CTRL1);
> @@ -3506,7 +3510,8 @@ static void test_vmcs_page_reference(u32 control_bit, enum Encoding field,
>                 vmcs_write(CPU_EXEC_CTRL0, primary | CPU_SECONDARY);
>                 vmcs_write(CPU_EXEC_CTRL1, secondary | control_bit);
>         }
> -       test_vmcs_page_values(field_name, field, false, xfail_beyond_mapped_ram);
> +       test_vmcs_page_values(field_name, field, false,
> +           xfail_beyond_mapped_ram, resv_bits);
>         report_prefix_pop();
>
>         report_prefix_pushf("%s disabled", control_name);
> @@ -3516,7 +3521,7 @@ static void test_vmcs_page_reference(u32 control_bit, enum Encoding field,
>                 vmcs_write(CPU_EXEC_CTRL0, primary & ~CPU_SECONDARY);
>                 vmcs_write(CPU_EXEC_CTRL1, secondary & ~control_bit);
>         }
> -       test_vmcs_page_values(field_name, field, true, false);
> +       test_vmcs_page_values(field_name, field, true, false, resv_bits);
>         report_prefix_pop();
>
>         vmcs_write(field, page_addr);
> @@ -3533,10 +3538,10 @@ static void test_io_bitmaps(void)
>  {
>         test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_A,
>                                  "I/O bitmap A", "Use I/O bitmaps", false,
> -                                true);
> +                                true, 0);
>         test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_B,
>                                  "I/O bitmap B", "Use I/O bitmaps", false,
> -                                true);
> +                                true, 0);
>  }
>
>  /*
> @@ -3549,7 +3554,7 @@ static void test_msr_bitmap(void)
>  {
>         test_vmcs_page_reference(CPU_MSR_BITMAP, MSR_BITMAP,
>                                  "MSR bitmap", "Use MSR bitmaps", false,
> -                                true);
> +                                true, 0);
>  }
>
>  /*
> @@ -3564,7 +3569,7 @@ static void test_apic_virt_addr(void)
>  {
>         test_vmcs_page_reference(CPU_TPR_SHADOW, APIC_VIRT_ADDR,
>                                  "virtual-APIC address", "Use TPR shadow",
> -                                true, true);
> +                                true, true, 0);
>  }
>
>  /*
> @@ -3583,7 +3588,7 @@ static void test_apic_access_addr(void)
>
>         test_vmcs_page_reference(CPU_VIRT_APIC_ACCESSES, APIC_ACCS_ADDR,
>                                  "APIC-access address",
> -                                "virtualize APIC-accesses", false, false);
> +                                "virtualize APIC-accesses", false, false, 0);
>  }
>
>  static bool set_bit_pattern(u8 mask, u32 *secondary)
> @@ -3869,7 +3874,8 @@ static void test_posted_intr(void)
>         test_pi_desc_addr(0x00, true);
>         test_pi_desc_addr(0xc000, true);
>
> -       test_vmcs_page_values("process-posted interrupts", POSTED_INTR_DESC_ADDR, false, false);
> +       test_vmcs_page_values("process-posted interrupts",
> +           POSTED_INTR_DESC_ADDR, false, false, 0);
>
>         vmcs_write(CPU_EXEC_CTRL0, saved_primary);
>         vmcs_write(CPU_EXEC_CTRL1, saved_secondary);
> @@ -4408,6 +4414,76 @@ done:
>         vmcs_write(PIN_CONTROLS, pin_ctrls);
>  }
>
> +/*
> + * If the “enable PML” VM-execution control is 1, the “enable EPT”
> + * VM-execution control must also be 1. In addition, the PML address
> + * must satisfy the following checks:
> + *
> + *    — Bits 11:0 of the address must be 0.
> + *    — The address should not set any bits beyond the processor’s
> + *     physical-address width.
> +
> + *  [Intel SDM]
> + */
> +static void test_pml(void)
> +{
> +       u32 primary_saved = vmcs_read(CPU_EXEC_CTRL0);
> +       u32 secondary_saved = vmcs_read(CPU_EXEC_CTRL1);
> +       u32 primary = primary_saved;
> +       u32 secondary = secondary_saved;
> +       u64 pml_addr;
> +       int i;
> +
> +       if (!((ctrl_cpu_rev[0].clr & CPU_SECONDARY) &&
> +           (ctrl_cpu_rev[1].clr & CPU_EPT) && (ctrl_cpu_rev[1].clr & CPU_PML))) {
> +               test_skip("\"Secondary execution\" control or \"enable EPT\" control or \"enable PML\" control is not supported !");
> +               return;
> +       }
> +
> +       primary |= CPU_SECONDARY;
> +       vmcs_write(CPU_EXEC_CTRL0, primary);
> +       secondary &= ~(CPU_PML | CPU_EPT);
> +       vmcs_write(CPU_EXEC_CTRL1, secondary);
> +       report_prefix_pushf("enable-PML disabled, enable-EPT disabled");
> +       test_vmx_controls(true, false);
> +       report_prefix_pop();
> +
> +       secondary |= CPU_PML;
> +       vmcs_write(CPU_EXEC_CTRL1, secondary);
> +       report_prefix_pushf("enable-PML enabled, enable-EPT disabled");
> +       test_vmx_controls(false, false);
> +       report_prefix_pop();
> +
> +       secondary |= CPU_EPT;
> +       vmcs_write(CPU_EXEC_CTRL1, secondary);
> +       report_prefix_pushf("enable-PML enabled, enable-EPT enabled");
> +       test_vmx_controls(true, false);
> +       report_prefix_pop();
> +
> +       secondary &= ~CPU_PML;
> +       vmcs_write(CPU_EXEC_CTRL1, secondary);
> +       report_prefix_pushf("enable-PML disabled, enable EPT enabled");
> +       test_vmx_controls(true, false);
> +       report_prefix_pop();
> +
> +       secondary |= CPU_PML;
> +       vmcs_write(CPU_EXEC_CTRL1, secondary);
> +
> +       pml_addr = (u64) phys_to_virt(vmcs_read(PMLADDR));
> +       for (i = 0; i < 12; i++) {
> +               pml_addr |= 1ull << i;
> +               vmcs_write(PMLADDR, virt_to_phys((void *) pml_addr));
> +               report_prefix_pushf("PML address 0x%lx", pml_addr);
> +               test_vmx_controls(false, false);
> +               report_prefix_pop();
> +       }
> +
> +       test_vmcs_page_reference(CPU_PML, PMLADDR, "PML address",
> +           "PML", false, false, PMLADDR_RESV_BITS);
> +
> +       vmcs_write(CPU_EXEC_CTRL0, primary_saved);
> +       vmcs_write(CPU_EXEC_CTRL1, secondary_saved);
> +}

Except for the "enable EPT" requirement, this can all be done with a
variant of test_vmcs_page_reference that takes a secondary
processor-based control bit rather than a primary processor-based
control-bit.




[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