mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
VMX: tertiary execution control infrastructure
This is a prereq to enabling e.g. the MSRLIST feature. Note that the PROCBASED_CTLS3 MSR is different from other VMX feature reporting MSRs, in that all 64 bits report allowed 1-settings. vVMX code is left alone, though, for the time being. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
1 parent
59a69674b5
commit
878159bf25
5 files changed
+73
-6
No files matched your search
@@ -164,6 +164,7 @@ static int cf_check parse_ept_param_runtime(const char *s)
|
||||
u32 vmx_pin_based_exec_control __read_mostly;
|
||||
u32 vmx_cpu_based_exec_control __read_mostly;
|
||||
u32 vmx_secondary_exec_control __read_mostly;
|
||||
uint64_t vmx_tertiary_exec_control __read_mostly;
|
||||
u32 vmx_vmexit_control __read_mostly;
|
||||
u32 vmx_vmentry_control __read_mostly;
|
||||
u64 vmx_ept_vpid_cap __read_mostly;
|
||||
@@ -228,10 +229,32 @@ static u32 adjust_vmx_controls(
|
||||
return ctl;
|
||||
}
|
||||
|
||||
static bool cap_check(const char *name, u32 expected, u32 saw)
|
||||
static uint64_t adjust_vmx_controls2(
|
||||
const char *name, uint64_t ctl_min, uint64_t ctl_opt, unsigned int msr,
|
||||
bool *mismatch)
|
||||
{
|
||||
uint64_t vmx_msr, ctl = ctl_min | ctl_opt;
|
||||
|
||||
rdmsrl(msr, vmx_msr);
|
||||
|
||||
ctl &= vmx_msr; /* bit == 0 ==> must be zero */
|
||||
|
||||
/* Ensure minimum (required) set of control bits are supported. */
|
||||
if ( ctl_min & ~ctl )
|
||||
{
|
||||
*mismatch = true;
|
||||
printk("VMX: CPU%u has insufficient %s (%#lx; requires %#lx)\n",
|
||||
smp_processor_id(), name, ctl, ctl_min);
|
||||
}
|
||||
|
||||
return ctl;
|
||||
}
|
||||
|
||||
static bool cap_check(
|
||||
const char *name, unsigned long expected, unsigned long saw)
|
||||
{
|
||||
if ( saw != expected )
|
||||
printk("VMX %s: saw %#x expected %#x\n", name, saw, expected);
|
||||
printk("VMX %s: saw %#lx expected %#lx\n", name, saw, expected);
|
||||
return saw != expected;
|
||||
}
|
||||
|
||||
@@ -241,6 +264,7 @@ static int vmx_init_vmcs_config(bool bsp)
|
||||
u32 _vmx_pin_based_exec_control;
|
||||
u32 _vmx_cpu_based_exec_control;
|
||||
u32 _vmx_secondary_exec_control = 0;
|
||||
uint64_t _vmx_tertiary_exec_control = 0;
|
||||
u64 _vmx_ept_vpid_cap = 0;
|
||||
u64 _vmx_misc_cap = 0;
|
||||
u32 _vmx_vmexit_control;
|
||||
@@ -274,7 +298,8 @@ static int vmx_init_vmcs_config(bool bsp)
|
||||
opt = (CPU_BASED_ACTIVATE_MSR_BITMAP |
|
||||
CPU_BASED_TPR_SHADOW |
|
||||
CPU_BASED_MONITOR_TRAP_FLAG |
|
||||
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
|
||||
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS |
|
||||
CPU_BASED_ACTIVATE_TERTIARY_CONTROLS);
|
||||
_vmx_cpu_based_exec_control = adjust_vmx_controls(
|
||||
"CPU-Based Exec Control", min, opt,
|
||||
MSR_IA32_VMX_PROCBASED_CTLS, &mismatch);
|
||||
@@ -338,6 +363,15 @@ static int vmx_init_vmcs_config(bool bsp)
|
||||
MSR_IA32_VMX_PROCBASED_CTLS2, &mismatch);
|
||||
}
|
||||
|
||||
if ( _vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS )
|
||||
{
|
||||
uint64_t opt = 0;
|
||||
|
||||
_vmx_tertiary_exec_control = adjust_vmx_controls2(
|
||||
"Tertiary Exec Control", 0, opt,
|
||||
MSR_IA32_VMX_PROCBASED_CTLS3, &mismatch);
|
||||
}
|
||||
|
||||
/* The IA32_VMX_EPT_VPID_CAP MSR exists only when EPT or VPID available */
|
||||
if ( _vmx_secondary_exec_control & (SECONDARY_EXEC_ENABLE_EPT |
|
||||
SECONDARY_EXEC_ENABLE_VPID) )
|
||||
@@ -468,6 +502,7 @@ static int vmx_init_vmcs_config(bool bsp)
|
||||
vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
|
||||
vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
|
||||
vmx_secondary_exec_control = _vmx_secondary_exec_control;
|
||||
vmx_tertiary_exec_control = _vmx_tertiary_exec_control;
|
||||
vmx_ept_vpid_cap = _vmx_ept_vpid_cap;
|
||||
vmx_vmexit_control = _vmx_vmexit_control;
|
||||
vmx_vmentry_control = _vmx_vmentry_control;
|
||||
@@ -502,6 +537,9 @@ static int vmx_init_vmcs_config(bool bsp)
|
||||
mismatch |= cap_check(
|
||||
"Secondary Exec Control",
|
||||
vmx_secondary_exec_control, _vmx_secondary_exec_control);
|
||||
mismatch |= cap_check(
|
||||
"Tertiary Exec Control",
|
||||
vmx_tertiary_exec_control, _vmx_tertiary_exec_control);
|
||||
mismatch |= cap_check(
|
||||
"VMExit Control",
|
||||
vmx_vmexit_control, _vmx_vmexit_control);
|
||||
@@ -1080,6 +1118,7 @@ static int construct_vmcs(struct vcpu *v)
|
||||
v->arch.hvm.vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
|
||||
|
||||
v->arch.hvm.vmx.secondary_exec_control = vmx_secondary_exec_control;
|
||||
v->arch.hvm.vmx.tertiary_exec_control = vmx_tertiary_exec_control;
|
||||
|
||||
/*
|
||||
* Disable features which we don't want active by default:
|
||||
@@ -1134,6 +1173,10 @@ static int construct_vmcs(struct vcpu *v)
|
||||
__vmwrite(SECONDARY_VM_EXEC_CONTROL,
|
||||
v->arch.hvm.vmx.secondary_exec_control);
|
||||
|
||||
if ( cpu_has_vmx_tertiary_exec_control )
|
||||
__vmwrite(TERTIARY_VM_EXEC_CONTROL,
|
||||
v->arch.hvm.vmx.tertiary_exec_control);
|
||||
|
||||
/* MSR access bitmap. */
|
||||
if ( cpu_has_vmx_msr_bitmap )
|
||||
{
|
||||
@@ -2068,10 +2111,12 @@ void vmcs_dump_vcpu(struct vcpu *v)
|
||||
vmr(HOST_PERF_GLOBAL_CTRL));
|
||||
|
||||
printk("*** Control State ***\n");
|
||||
printk("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n",
|
||||
printk("PinBased=%08x CPUBased=%08x\n",
|
||||
vmr32(PIN_BASED_VM_EXEC_CONTROL),
|
||||
vmr32(CPU_BASED_VM_EXEC_CONTROL),
|
||||
vmr32(SECONDARY_VM_EXEC_CONTROL));
|
||||
vmr32(CPU_BASED_VM_EXEC_CONTROL));
|
||||
printk("SecondaryExec=%08x TertiaryExec=%016lx\n",
|
||||
vmr32(SECONDARY_VM_EXEC_CONTROL),
|
||||
vmr(TERTIARY_VM_EXEC_CONTROL));
|
||||
printk("EntryControls=%08x ExitControls=%08x\n", vmentry_ctl, vmexit_ctl);
|
||||
printk("ExceptionBitmap=%08x PFECmask=%08x PFECmatch=%08x\n",
|
||||
vmr32(EXCEPTION_BITMAP),
|
||||
@@ -2174,6 +2219,7 @@ int __init vmx_vmcs_init(void)
|
||||
vmx_pin_based_exec_control = 0;
|
||||
vmx_cpu_based_exec_control = 0;
|
||||
vmx_secondary_exec_control = 0;
|
||||
vmx_tertiary_exec_control = 0;
|
||||
vmx_vmexit_control = 0;
|
||||
vmx_vmentry_control = 0;
|
||||
vmx_ept_vpid_cap = 0;
|
||||
|
||||
@@ -760,6 +760,12 @@ void vmx_update_secondary_exec_control(struct vcpu *v)
|
||||
v->arch.hvm.vmx.secondary_exec_control);
|
||||
}
|
||||
|
||||
void vmx_update_tertiary_exec_control(const struct vcpu *v)
|
||||
{
|
||||
__vmwrite(TERTIARY_VM_EXEC_CONTROL,
|
||||
v->arch.hvm.vmx.tertiary_exec_control);
|
||||
}
|
||||
|
||||
void vmx_update_exception_bitmap(struct vcpu *v)
|
||||
{
|
||||
u32 bitmap = unlikely(v->arch.hvm.vmx.vmx_realmode)
|
||||
|
||||
@@ -114,6 +114,7 @@ struct vmx_vcpu {
|
||||
/* Cache of cpu execution control. */
|
||||
u32 exec_control;
|
||||
u32 secondary_exec_control;
|
||||
uint64_t tertiary_exec_control;
|
||||
u32 exception_bitmap;
|
||||
|
||||
uint64_t shadow_gs;
|
||||
@@ -196,6 +197,7 @@ void vmx_vmcs_reload(struct vcpu *v);
|
||||
#define CPU_BASED_RDTSC_EXITING 0x00001000U
|
||||
#define CPU_BASED_CR3_LOAD_EXITING 0x00008000U
|
||||
#define CPU_BASED_CR3_STORE_EXITING 0x00010000U
|
||||
#define CPU_BASED_ACTIVATE_TERTIARY_CONTROLS 0x00020000U
|
||||
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000U
|
||||
#define CPU_BASED_CR8_STORE_EXITING 0x00100000U
|
||||
#define CPU_BASED_TPR_SHADOW 0x00200000U
|
||||
@@ -260,6 +262,14 @@ extern u32 vmx_vmentry_control;
|
||||
#define SECONDARY_EXEC_NOTIFY_VM_EXITING 0x80000000U
|
||||
extern u32 vmx_secondary_exec_control;
|
||||
|
||||
#define TERTIARY_EXEC_LOADIWKEY_EXITING BIT(0, UL)
|
||||
#define TERTIARY_EXEC_ENABLE_HLAT BIT(1, UL)
|
||||
#define TERTIARY_EXEC_EPT_PAGING_WRITE BIT(2, UL)
|
||||
#define TERTIARY_EXEC_GUEST_PAGING_VERIFY BIT(3, UL)
|
||||
#define TERTIARY_EXEC_IPI_VIRT BIT(4, UL)
|
||||
#define TERTIARY_EXEC_VIRT_SPEC_CTRL BIT(7, UL)
|
||||
extern uint64_t vmx_tertiary_exec_control;
|
||||
|
||||
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
|
||||
#define VMX_EPT_WALK_LENGTH_4_SUPPORTED 0x00000040
|
||||
#define VMX_EPT_MEMORY_TYPE_UC 0x00000100
|
||||
@@ -296,6 +306,8 @@ extern u64 vmx_ept_vpid_cap;
|
||||
(vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP)
|
||||
#define cpu_has_vmx_secondary_exec_control \
|
||||
(vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
|
||||
#define cpu_has_vmx_tertiary_exec_control \
|
||||
(vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
|
||||
#define cpu_has_vmx_ept \
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT)
|
||||
#define cpu_has_vmx_dt_exiting \
|
||||
@@ -423,6 +435,7 @@ enum vmcs_field {
|
||||
VIRT_EXCEPTION_INFO = 0x0000202a,
|
||||
XSS_EXIT_BITMAP = 0x0000202c,
|
||||
TSC_MULTIPLIER = 0x00002032,
|
||||
TERTIARY_VM_EXEC_CONTROL = 0x00002034,
|
||||
GUEST_PHYSICAL_ADDRESS = 0x00002400,
|
||||
VMCS_LINK_POINTER = 0x00002800,
|
||||
GUEST_IA32_DEBUGCTL = 0x00002802,
|
||||
|
||||
@@ -81,6 +81,7 @@ void vmx_realmode(struct cpu_user_regs *regs);
|
||||
void vmx_update_exception_bitmap(struct vcpu *v);
|
||||
void vmx_update_cpu_exec_control(struct vcpu *v);
|
||||
void vmx_update_secondary_exec_control(struct vcpu *v);
|
||||
void vmx_update_tertiary_exec_control(const struct vcpu *v);
|
||||
|
||||
#define POSTED_INTR_ON 0
|
||||
#define POSTED_INTR_SN 1
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x48f
|
||||
#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x490
|
||||
#define MSR_IA32_VMX_VMFUNC 0x491
|
||||
#define MSR_IA32_VMX_PROCBASED_CTLS3 0x492
|
||||
|
||||
/* K7/K8 MSRs. Not complete. See the architecture manual for a more
|
||||
complete list. */
|
||||
|
||||