New definitions provide a convenient way of accessing contents of
VMX MSRs. They are separated into 5 logical blocks based on the
availability conditions of MSRs in the each block:

    1. vmx: [VMX_BASIC, VMX_VMCS_ENUM]
    2. VMX_PROCBASED_CTLS2
    3. VMX_EPT_VPID_CAP
    4. vmx_true_ctls: [VMX_TRUE_PINBASED_CTLS, VMX_TRUE_ENTRY_CTLS]
    5. VMX_VMFUNC

Every bit value is accessible by its name and bit names match existing
Xen's definitions as close as possible. There is a "raw" 64-bit field
for each MSR as well as "raw" arrays for vmx and vmx_true_ctls blocks.

Add calculate_raw_vmx_policy() which fills Raw policy with H/W values
of VMX MSRs. Host policy will contain a copy of these values (for now).

Signed-off-by: Sergey Dyasli <sergey.dya...@citrix.com>
---
v5 --> v6:
- Removed "_bits" and "_based" from union names
- Removed "_exiting" suffixes from control bit names
- Various shortenings of control bit names
---
 xen/arch/x86/msr.c              | 118 ++++++++++++++
 xen/include/asm-x86/msr.h       | 330 ++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/x86-defns.h |  54 +++++++
 3 files changed, 502 insertions(+)

diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index 369b4754ce..87239e151e 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -34,10 +34,65 @@ struct msr_domain_policy __read_mostly     
raw_msr_domain_policy,
 struct msr_vcpu_policy __read_mostly hvm_max_msr_vcpu_policy,
                        __read_mostly  pv_max_msr_vcpu_policy;
 
+static bool vmx_procbased_ctls2_available(const struct msr_domain_policy *dp)
+{
+    return dp->vmx.procbased_ctls.allowed_1.secondary;
+}
+
+static bool vmx_ept_vpid_cap_available(const struct msr_domain_policy *dp)
+{
+    return dp->vmx_procbased_ctls2.allowed_1.ept ||
+           dp->vmx_procbased_ctls2.allowed_1.vpid;
+}
+
+static bool vmx_true_ctls_available(const struct msr_domain_policy *dp)
+{
+    return dp->vmx.basic.default1_zero;
+}
+
+static bool vmx_vmfunc_available(const struct msr_domain_policy *dp)
+{
+    return dp->vmx_procbased_ctls2.allowed_1.vmfunc;
+}
+
+static void __init calculate_raw_vmx_policy(struct msr_domain_policy *dp)
+{
+    unsigned int i, start_msr, end_msr;
+
+    if ( !cpu_has_vmx )
+        return;
+
+    start_msr = MSR_IA32_VMX_BASIC;
+    end_msr = MSR_IA32_VMX_VMCS_ENUM;
+    for ( i = start_msr; i <= end_msr; i++ )
+        rdmsrl(i, dp->vmx.raw[i - start_msr]);
+
+    if ( vmx_procbased_ctls2_available(dp) )
+        rdmsrl(MSR_IA32_VMX_PROCBASED_CTLS2, dp->vmx_procbased_ctls2.raw);
+
+    if ( vmx_ept_vpid_cap_available(dp) )
+        rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, dp->vmx_ept_vpid_cap.raw);
+
+    if ( vmx_true_ctls_available(dp) )
+    {
+        start_msr = MSR_IA32_VMX_TRUE_PINBASED_CTLS;
+        end_msr = MSR_IA32_VMX_TRUE_ENTRY_CTLS;
+        for ( i = start_msr; i <= end_msr; i++ )
+            rdmsrl(i, dp->vmx_true_ctls.raw[i - start_msr]);
+    }
+
+    if ( vmx_vmfunc_available(dp) )
+        rdmsrl(MSR_IA32_VMX_VMFUNC, dp->vmx_vmfunc.raw);
+}
+
 static void __init calculate_raw_policy(void)
 {
+    struct msr_domain_policy *dp = &raw_msr_domain_policy;
+
     /* 0x000000ce  MSR_INTEL_PLATFORM_INFO */
     /* Was already added by probe_cpuid_faulting() */
+
+    calculate_raw_vmx_policy(dp);
 }
 
 static void __init calculate_host_policy(void)
@@ -284,6 +339,69 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
     return X86EMUL_EXCEPTION;
 }
 
+static void __init __maybe_unused build_assertions(void)
+{
+    struct msr_domain_policy dp;
+
+    BUILD_BUG_ON(sizeof(dp.vmx.basic) !=
+                 sizeof(dp.vmx.basic.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.pinbased_ctls) !=
+                 sizeof(dp.vmx.pinbased_ctls.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.procbased_ctls) !=
+                 sizeof(dp.vmx.procbased_ctls.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.exit_ctls) !=
+                 sizeof(dp.vmx.exit_ctls.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.entry_ctls) !=
+                 sizeof(dp.vmx.entry_ctls.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.misc) !=
+                 sizeof(dp.vmx.misc.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.cr0_fixed0) !=
+                 sizeof(dp.vmx.cr0_fixed0.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.cr0_fixed1) !=
+                 sizeof(dp.vmx.cr0_fixed1.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.cr4_fixed0) !=
+                 sizeof(dp.vmx.cr4_fixed0.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.cr4_fixed1) !=
+                 sizeof(dp.vmx.cr4_fixed1.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.vmcs_enum) !=
+                 sizeof(dp.vmx.vmcs_enum.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx.raw) !=
+                     sizeof(dp.vmx.basic) +
+                     sizeof(dp.vmx.pinbased_ctls) +
+                     sizeof(dp.vmx.procbased_ctls) +
+                     sizeof(dp.vmx.exit_ctls) +
+                     sizeof(dp.vmx.entry_ctls) +
+                     sizeof(dp.vmx.misc) +
+                     sizeof(dp.vmx.cr0_fixed0) +
+                     sizeof(dp.vmx.cr0_fixed1) +
+                     sizeof(dp.vmx.cr4_fixed0) +
+                     sizeof(dp.vmx.cr4_fixed1) +
+                     sizeof(dp.vmx.vmcs_enum));
+
+    BUILD_BUG_ON(sizeof(dp.vmx_procbased_ctls2) !=
+                 sizeof(dp.vmx_procbased_ctls2.raw));
+
+    BUILD_BUG_ON(sizeof(dp.vmx_ept_vpid_cap) !=
+                 sizeof(dp.vmx_ept_vpid_cap.raw));
+
+    BUILD_BUG_ON(sizeof(dp.vmx_true_ctls.pinbased) !=
+                 sizeof(dp.vmx_true_ctls.pinbased.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx_true_ctls.procbased) !=
+                 sizeof(dp.vmx_true_ctls.procbased.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx_true_ctls.exit) !=
+                 sizeof(dp.vmx_true_ctls.exit.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx_true_ctls.entry) !=
+                 sizeof(dp.vmx_true_ctls.entry.raw));
+    BUILD_BUG_ON(sizeof(dp.vmx_true_ctls.raw) !=
+                     sizeof(dp.vmx_true_ctls.pinbased) +
+                     sizeof(dp.vmx_true_ctls.procbased) +
+                     sizeof(dp.vmx_true_ctls.exit) +
+                     sizeof(dp.vmx_true_ctls.entry));
+
+    BUILD_BUG_ON(sizeof(dp.vmx_vmfunc) !=
+                 sizeof(dp.vmx_vmfunc.raw));
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index f14f265aa5..5fdf82860e 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -10,6 +10,7 @@
 #include <xen/errno.h>
 #include <asm/asm_defns.h>
 #include <asm/cpufeature.h>
+#include <asm/x86-defns.h>
 
 #define rdmsr(msr,val1,val2) \
      __asm__ __volatile__("rdmsr" \
@@ -257,6 +258,127 @@ static inline void wrmsr_tsc_aux(uint32_t val)
     }
 }
 
+union vmx_pin_exec_control {
+    uint32_t raw;
+    struct {
+        bool         ext_intr:1;
+        uint32_t             :2;  /* 1:2 reserved */
+        bool              nmi:1;
+        uint32_t             :1;  /* 4 reserved */
+        bool            vnmis:1;
+        bool    preempt_timer:1;
+        bool posted_interrupt:1;
+        uint32_t             :24; /* 8:31 reserved */
+    };
+};
+
+union vmx_cpu_exec_control {
+    uint32_t raw;
+    struct {
+        uint32_t                 :2;  /* 0:1 reserved */
+        bool virtual_intr_pending:1;
+        bool           tsc_offset:1;
+        uint32_t                 :3;  /* 4:6 reserved */
+        bool                  hlt:1;
+        uint32_t                 :1;  /* 8 reserved */
+        bool               invlpg:1;
+        bool                mwait:1;
+        bool                rdpmc:1;
+        bool                rdtsc:1;
+        uint32_t                 :2;  /* 13:14 reserved */
+        bool             cr3_load:1;
+        bool            cr3_store:1;
+        uint32_t                 :2;  /* 17:18 reserved */
+        bool             cr8_load:1;
+        bool            cr8_store:1;
+        bool           tpr_shadow:1;
+        bool         vnmi_pending:1;
+        bool               mov_dr:1;
+        bool            uncond_io:1;
+        bool            io_bitmap:1;
+        uint32_t                 :1;  /* 26 reserved */
+        bool                  mtf:1;
+        bool           msr_bitmap:1;
+        bool              monitor:1;
+        bool                pause:1;
+        bool            secondary:1;
+    };
+};
+
+union vmx_vmexit_control {
+    uint32_t raw;
+    struct {
+        uint32_t               :2;  /* 0:1 reserved */
+        bool   save_guest_debug:1;
+        uint32_t               :6;  /* 3:8 reserved */
+        bool         ia32e_mode:1;
+        uint32_t               :2;  /* 10:11 reserved */
+        bool     load_perf_ctrl:1;
+        uint32_t               :2;  /* 13:14 reserved */
+        bool           ack_intr:1;
+        uint32_t               :2;  /* 16:17 reserved */
+        bool     save_guest_pat:1;
+        bool      load_host_pat:1;
+        bool    save_guest_efer:1;
+        bool     load_host_efer:1;
+        bool save_preempt_timer:1;
+        bool      clear_bndcfgs:1;
+        bool    conceal_from_pt:1;
+        uint32_t               :7;  /* 25:31 reserved */
+    };
+};
+
+union vmx_vmentry_control {
+    uint32_t raw;
+    struct {
+        uint32_t                    :2;  /* 0:1 reserved */
+        bool         load_debug_ctls:1;
+        uint32_t                    :6;  /* 3:8 reserved */
+        bool              ia32e_mode:1;
+        bool                     smm:1;
+        bool deactivate_dual_monitor:1;
+        uint32_t                    :1;  /* 12 reserved */
+        bool   load_perf_global_ctrl:1;
+        bool          load_guest_pat:1;
+        bool         load_guest_efer:1;
+        bool            load_bndcfgs:1;
+        bool conceal_entries_from_pt:1;
+        uint32_t                    :14; /* 18:31 reserved */
+    };
+};
+
+union vmx_secondary_exec_control {
+    uint32_t raw;
+    struct {
+        bool           apic_accesses:1;
+        bool                     ept:1;
+        bool              desc_table:1;
+        bool                  rdtscp:1;
+        bool  virtualize_x2apic_mode:1;
+        bool                    vpid:1;
+        bool                  wbinvd:1;
+        bool            unrestricted:1;
+        bool      apic_register_virt:1;
+        bool   virtual_intr_delivery:1;
+        bool                     ple:1;
+        bool                  rdrand:1;
+        bool                 invpcid:1;
+        bool                  vmfunc:1;
+        bool          vmcs_shadowing:1;
+        bool                   encls:1;
+        bool                  rdseed:1;
+        bool                     pml:1;
+        bool                      ve:1;
+        bool conceal_nonroot_from_pt:1;
+        bool                  xsaves:1;
+        uint32_t                    :1;  /* 21 reserved */
+        bool ept_mode_based_exec_ctl:1;
+        uint32_t                    :2;  /* 23:24 reserved */
+        bool             tsc_scaling:1;
+        uint32_t                    :6;  /* 26:31 reserved */
+    };
+};
+
 /* MSR policy object for shared per-domain MSRs */
 struct msr_domain_policy
 {
@@ -265,6 +387,214 @@ struct msr_domain_policy
         bool available; /* This MSR is non-architectural */
         bool cpuid_faulting;
     } plaform_info;
+
+    union {
+        uint64_t raw[MSR_IA32_VMX_VMCS_ENUM - MSR_IA32_VMX_BASIC + 1];
+
+        struct {
+            /* 0x00000480  MSR_IA32_VMX_BASIC */
+            union {
+                uint64_t raw;
+                struct {
+                    uint32_t      vmcs_rev_id:31;
+                    bool                  mbz:1;  /* 31 always zero */
+                    uint32_t vmcs_region_size:13;
+                    uint32_t                 :3;  /* 45:47 reserved */
+                    bool      addresses_32bit:1;
+                    bool         dual_monitor:1;
+                    uint32_t      memory_type:4;
+                    bool         ins_out_info:1;
+                    bool        default1_zero:1;
+                    uint32_t                 :8;  /* 56:63 reserved */
+                };
+            } basic;
+
+            /* 0x00000481  MSR_IA32_VMX_PINBASED_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_pin_exec_control allowed_0;
+                    union vmx_pin_exec_control allowed_1;
+                };
+            } pinbased_ctls;
+
+            /* 0x00000482  MSR_IA32_VMX_PROCBASED_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_cpu_exec_control allowed_0;
+                    union vmx_cpu_exec_control allowed_1;
+                };
+            } procbased_ctls;
+
+            /* 0x00000483  MSR_IA32_VMX_EXIT_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_vmexit_control allowed_0;
+                    union vmx_vmexit_control allowed_1;
+                };
+            } exit_ctls;
+
+            /* 0x00000484  MSR_IA32_VMX_ENTRY_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_vmentry_control allowed_0;
+                    union vmx_vmentry_control allowed_1;
+                };
+            } entry_ctls;
+
+            /* 0x00000485  MSR_IA32_VMX_MISC */
+            union {
+                uint64_t raw;
+                struct {
+                    uint32_t   preempt_timer_scale:5;
+                    bool         vmexit_stores_lma:1;
+                    bool                 hlt_state:1;
+                    bool            shutdown_state:1;
+                    bool       wait_for_sipi_state:1;
+                    uint32_t                      :5;  /* 9:13 reserved */
+                    bool                 pt_in_vmx:1;
+                    bool               ia32_smbase:1;
+                    uint32_t            cr3_target:9;
+                    uint32_t    max_msr_load_count:3;
+                    bool ia32_smm_monitor_ctl_bit2:1;
+                    bool               vmwrite_all:1;
+                    bool        inject_ilen0_event:1;
+                    uint32_t                      :1;  /* 31 reserved */
+                    uint32_t      mseg_revision_id;
+                };
+            } misc;
+
+            /* 0x00000486  MSR_IA32_VMX_CR0_FIXED0 */
+            union {
+                uint64_t raw;
+                union cr0_bits allowed_0;
+            } cr0_fixed0;
+
+            /* 0x00000487  MSR_IA32_VMX_CR0_FIXED1 */
+            union {
+                uint64_t raw;
+                union cr0_bits allowed_1;
+            } cr0_fixed1;
+
+            /* 0x00000488  MSR_IA32_VMX_CR4_FIXED0 */
+            union {
+                uint64_t raw;
+                union cr4_bits allowed_0;
+            } cr4_fixed0;
+
+            /* 0x00000489  MSR_IA32_VMX_CR4_FIXED1 */
+            union {
+                uint64_t raw;
+                union cr4_bits allowed_1;
+            } cr4_fixed1;
+
+            /* 0x0000048A  MSR_IA32_VMX_VMCS_ENUM */
+            union {
+                uint64_t raw;
+                struct {
+                    uint32_t             :1;  /* 0 reserved */
+                    uint32_t max_encoding:9;
+                    uint64_t             :54; /* 10:63 reserved */
+                };
+            } vmcs_enum;
+        };
+    } vmx;
+
+    /* 0x0000048B  MSR_IA32_VMX_PROCBASED_CTLS2 */
+    union {
+        uint64_t raw;
+        struct {
+            union vmx_secondary_exec_control allowed_0;
+            union vmx_secondary_exec_control allowed_1;
+        };
+    } vmx_procbased_ctls2;
+
+    /* 0x0000048C  MSR_IA32_VMX_EPT_VPID_CAP */
+    union {
+        uint64_t raw;
+        struct {
+            bool                   x_only:1;
+            uint32_t                     :5;  /* 1:5 reserved */
+            bool                      wl4:1;
+            uint32_t                     :1;  /* 7 reserved */
+            bool                       uc:1;
+            uint32_t                     :5;  /* 9:13 reserved */
+            bool                       wb:1;
+            uint32_t                     :1;  /* 15 reserved */
+            bool                 page_2mb:1;
+            bool                 page_1gb:1;
+            uint32_t                     :2;  /* 18:19 reserved */
+            bool                   invept:1;
+            bool                   ad_bit:1;
+            bool  advanced_ept_violations:1;
+            uint32_t                     :2;  /* 23:24 reserved */
+            bool            invept_single:1;
+            bool               invept_all:1;
+            uint32_t                     :5;  /* 27:31 reserved */
+            bool                  invvpid:1;
+            uint32_t                     :7;  /* 33:39 reserved */
+            bool  invvpid_individual_addr:1;
+            bool   invvpid_single_context:1;
+            bool      invvpid_all_context:1;
+            bool invvpid_single_nonglobal:1;
+            uint32_t                    :20; /* 44:63 reserved */
+        };
+    } vmx_ept_vpid_cap;
+
+    union {
+        uint64_t raw[MSR_IA32_VMX_TRUE_ENTRY_CTLS -
+                     MSR_IA32_VMX_TRUE_PINBASED_CTLS + 1];
+
+        struct {
+            /* 0x0000048D  MSR_IA32_VMX_TRUE_PINBASED_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_pin_exec_control allowed_0;
+                    union vmx_pin_exec_control allowed_1;
+                };
+            } pinbased;
+
+            /* 0x0000048E  MSR_IA32_VMX_TRUE_PROCBASED_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_cpu_exec_control allowed_0;
+                    union vmx_cpu_exec_control allowed_1;
+                };
+            } procbased;
+
+            /* 0x0000048F  MSR_IA32_VMX_TRUE_EXIT_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_vmexit_control allowed_0;
+                    union vmx_vmexit_control allowed_1;
+                };
+            } exit;
+
+            /* 0x00000490  MSR_IA32_VMX_TRUE_ENTRY_CTLS */
+            union {
+                uint64_t raw;
+                struct {
+                    union vmx_vmentry_control allowed_0;
+                    union vmx_vmentry_control allowed_1;
+                };
+            } entry;
+        };
+    } vmx_true_ctls;
+
+    /* 0x00000491  MSR_IA32_VMX_VMFUNC */
+    union {
+        uint64_t raw;
+        struct {
+            bool eptp_switching:1;
+            uint64_t           :63; /* 1:63 reserved */
+        };
+    } vmx_vmfunc;
 };
 
 /* RAW msr domain policy: contains the actual values from H/W MSRs */
diff --git a/xen/include/asm-x86/x86-defns.h b/xen/include/asm-x86/x86-defns.h
index ff8d66be3c..1d26328520 100644
--- a/xen/include/asm-x86/x86-defns.h
+++ b/xen/include/asm-x86/x86-defns.h
@@ -42,6 +42,28 @@
 #define X86_CR0_CD              0x40000000 /* Cache Disable            (RW) */
 #define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
 
+#ifndef __ASSEMBLY__
+union cr0_bits {
+    uint64_t raw;
+    struct {
+        bool     pe:1;
+        bool     mp:1;
+        bool     em:1;
+        bool     ts:1;
+        bool     et:1;
+        bool     ne:1;
+        uint32_t   :10; /* 6:15 reserved */
+        bool     wp:1;
+        uint32_t   :1;  /* 17 reserved */
+        bool     am:1;
+        uint32_t   :10; /* 19:28 reserved */
+        bool     nw:1;
+        bool     cd:1;
+        bool     pg:1;
+    };
+};
+#endif /* #ifndef __ASSEMBLY__ */
+
 /*
  * Intel CPU flags in CR3
  */
@@ -71,6 +93,38 @@
 #define X86_CR4_SMAP       0x00200000 /* enable SMAP */
 #define X86_CR4_PKE        0x00400000 /* enable PKE */
 
+#ifndef __ASSEMBLY__
+union cr4_bits {
+    uint64_t raw;
+    struct {
+        bool        vme:1;
+        bool        pvi:1;
+        bool        tsd:1;
+        bool         de:1;
+        bool        pse:1;
+        bool        pae:1;
+        bool        mce:1;
+        bool        pge:1;
+        bool        pce:1;
+        bool     osfxsr:1;
+        bool osxmmexcpt:1;
+        bool       umip:1;
+        uint32_t       :1;  /* 12 reserved */
+        bool       vmxe:1;
+        bool       smxe:1;
+        uint32_t       :1;  /* 15 reserved */
+        bool   fsgsbase:1;
+        bool      pcide:1;
+        bool    osxsave:1;
+        uint32_t       :1;  /* 19 reserved */
+        bool       smep:1;
+        bool       smap:1;
+        bool        pke:1;
+        uint32_t       :9;  /* 23:31 reserved */
+    };
+};
+#endif /* #ifndef __ASSEMBLY__ */
+
 /*
  * XSTATE component flags in XCR0
  */
-- 
2.14.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to