Mailing List Archive

[xen staging-4.17] VMX: tertiary execution control infrastructure
commit 91c2a92231af71a50557c65e32e2f838ae3aed14
Author: Jan Beulich <jbeulich@suse.com>
AuthorDate: Wed Feb 7 13:46:11 2024 +0100
Commit: Andrew Cooper <andrew.cooper3@citrix.com>
CommitDate: Tue Apr 9 16:48:19 2024 +0100

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>
(cherry picked from commit 878159bf259bfbd7a40312829f1ea0ce1f6645e2)
---
xen/arch/x86/hvm/vmx/vmcs.c | 57 +++++++++++++++++++++++++++++----
xen/arch/x86/hvm/vmx/vmx.c | 6 ++++
xen/arch/x86/include/asm/hvm/vmx/vmcs.h | 13 ++++++++
xen/arch/x86/include/asm/hvm/vmx/vmx.h | 1 +
xen/arch/x86/include/asm/msr-index.h | 1 +
5 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index b5ecc51b43..49d51fb524 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -176,6 +176,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;
@@ -241,10 +242,32 @@ static u32 adjust_vmx_controls(
return ctl;
}

-static bool_t 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;
}

@@ -254,6 +277,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;
@@ -287,7 +311,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);
@@ -351,6 +376,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) )
@@ -481,6 +515,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;
@@ -516,6 +551,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);
@@ -1092,6 +1130,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:
@@ -1146,6 +1185,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 )
{
@@ -2069,10 +2112,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),
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index fed362bc32..26b6e4ca61 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -725,6 +725,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)
diff --git a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
index 0af021d5f5..bbb0966fc3 100644
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -125,6 +125,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;
@@ -207,6 +208,7 @@ void vmx_vmcs_reload(struct vcpu *v);
#define CPU_BASED_RDTSC_EXITING 0x00001000
#define CPU_BASED_CR3_LOAD_EXITING 0x00008000
#define CPU_BASED_CR3_STORE_EXITING 0x00010000
+#define CPU_BASED_ACTIVATE_TERTIARY_CONTROLS 0x00020000
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
#define CPU_BASED_CR8_STORE_EXITING 0x00100000
#define CPU_BASED_TPR_SHADOW 0x00200000
@@ -271,6 +273,14 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_NOTIFY_VM_EXITING 0x80000000
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
@@ -307,6 +317,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 \
@@ -430,6 +442,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,
diff --git a/xen/arch/x86/include/asm/hvm/vmx/vmx.h b/xen/arch/x86/include/asm/hvm/vmx/vmx.h
index 8e1e42ac47..4ff19488ea 100644
--- a/xen/arch/x86/include/asm/hvm/vmx/vmx.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmx.h
@@ -102,6 +102,7 @@ void vmx_update_debug_state(struct vcpu *v);
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
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index 9b5f67711f..521079191a 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -327,6 +327,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. */
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.17