@@ -161,6 +161,7 @@ static int cf_check parse_ept_param_runt
#endif
/* Dynamic (run-time adjusted) execution control flags. */
+struct vmx_caps __ro_after_init vmx_caps;
u32 vmx_pin_based_exec_control __read_mostly;
u32 vmx_cpu_based_exec_control __read_mostly;
u32 vmx_secondary_exec_control __read_mostly;
@@ -175,8 +176,7 @@ static DEFINE_PER_CPU(paddr_t, current_v
static DEFINE_PER_CPU(struct list_head, active_vmcs_list);
DEFINE_PER_CPU(bool, vmxon);
-#define vmcs_revision_id (vmx_basic_msr & VMX_BASIC_REVISION_MASK)
-u64 __read_mostly vmx_basic_msr;
+#define vmcs_revision_id (vmx_caps.basic_msr & VMX_BASIC_REVISION_MASK)
static void __init vmx_display_features(void)
{
@@ -505,8 +505,8 @@ static int vmx_init_vmcs_config(bool bsp
vmx_ept_vpid_cap = _vmx_ept_vpid_cap;
vmx_vmexit_control = _vmx_vmexit_control;
vmx_vmentry_control = _vmx_vmentry_control;
- vmx_basic_msr = ((u64)vmx_basic_msr_high << 32) |
- vmx_basic_msr_low;
+ vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
+ vmx_basic_msr_low;
vmx_vmfunc = _vmx_vmfunc;
vmx_display_features();
@@ -560,7 +560,7 @@ static int vmx_init_vmcs_config(bool bsp
mismatch = 1;
}
if ( (vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32)) !=
- ((vmx_basic_msr & VMX_BASIC_VMCS_SIZE_MASK) >> 32) )
+ ((vmx_caps.basic_msr & VMX_BASIC_VMCS_SIZE_MASK) >> 32) )
{
printk("VMX: CPU%d unexpected VMCS size %Lu\n",
smp_processor_id(),
@@ -2214,7 +2214,7 @@ int __init vmx_vmcs_init(void)
* _vmx_vcpu_up() may have made it past feature identification.
* Make sure all dependent features are off as well.
*/
- vmx_basic_msr = 0;
+ memset(&vmx_caps, 0, sizeof(vmx_caps));
vmx_pin_based_exec_control = 0;
vmx_cpu_based_exec_control = 0;
vmx_secondary_exec_control = 0;
@@ -294,6 +294,12 @@ extern u64 vmx_ept_vpid_cap;
#define VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL
+/* Capabilities and dynamic (run-time adjusted) execution control flags. */
+struct vmx_caps {
+ uint64_t basic_msr;
+};
+extern struct vmx_caps vmx_caps;
+
#define cpu_has_wbinvd_exiting \
(vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
#define cpu_has_vmx_virtualize_apic_accesses \
@@ -379,9 +385,8 @@ extern u64 vmx_ept_vpid_cap;
*/
#define VMX_BASIC_DEFAULT1_ZERO (1ULL << 55)
-extern u64 vmx_basic_msr;
#define cpu_has_vmx_ins_outs_instr_info \
- (!!(vmx_basic_msr & VMX_BASIC_INS_OUT_INFO))
+ (!!(vmx_caps.basic_msr & VMX_BASIC_INS_OUT_INFO))
/* Guest interrupt status */
#define VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK 0x0FF
@@ -1561,7 +1561,7 @@ static int nvmx_handle_vmxon(struct cpu_
rc = hvm_copy_from_guest_phys(&nvmcs_revid, gpa, sizeof(nvmcs_revid));
if ( rc != HVMTRANS_okay ||
(nvmcs_revid & ~VMX_BASIC_REVISION_MASK) ||
- ((nvmcs_revid ^ vmx_basic_msr) & VMX_BASIC_REVISION_MASK) )
+ ((nvmcs_revid ^ vmx_caps.basic_msr) & VMX_BASIC_REVISION_MASK) )
{
vmfail_invalid(regs);
return X86EMUL_OKAY;
@@ -1799,7 +1799,7 @@ static int nvmx_handle_vmptrld(struct cp
{
struct vmcs_struct *vvmcs = vvmcx;
- if ( ((vvmcs->revision_id ^ vmx_basic_msr) &
+ if ( ((vvmcs->revision_id ^ vmx_caps.basic_msr) &
VMX_BASIC_REVISION_MASK) ||
(!cpu_has_vmx_vmcs_shadowing &&
(vvmcs->revision_id & ~VMX_BASIC_REVISION_MASK)) )
@@ -2192,7 +2192,7 @@ int nvmx_msr_read_intercept(unsigned int
case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
case MSR_IA32_VMX_TRUE_EXIT_CTLS:
case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
- if ( !(vmx_basic_msr & VMX_BASIC_DEFAULT1_ZERO) )
+ if ( !(vmx_caps.basic_msr & VMX_BASIC_DEFAULT1_ZERO) )
return 0;
break;
... to a struct field, which is then going to be accompanied by other capability/control data presently living in individual variables. As this structure isn't supposed to be altered post-boot, put it in .data.ro_after_init right away. Suggested-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> --- v2: New.