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