P(cpu_has_vmx_tsc_scaling, "TSC Scaling");
P(cpu_has_vmx_bus_lock_detection, "Bus Lock Detection");
P(cpu_has_vmx_notify_vm_exiting, "Notify VM Exit");
+ P(cpu_has_vmx_virt_spec_ctrl, "Virtualize SPEC_CTRL");
#undef P
if ( !printed )
if ( _vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS )
{
- uint64_t opt = 0;
+ uint64_t opt = TERTIARY_EXEC_VIRT_SPEC_CTRL;
_vmx_tertiary_exec_control = adjust_vmx_controls2(
"Tertiary Exec Control", 0, opt,
if ( cpu_has_vmx_tsc_scaling )
__vmwrite(TSC_MULTIPLIER, d->arch.hvm.tsc_scaling_ratio);
+ if ( cpu_has_vmx_virt_spec_ctrl )
+ {
+ __vmwrite(SPEC_CTRL_MASK, 0);
+ __vmwrite(SPEC_CTRL_SHADOW, 0);
+ }
+
/* will update HOST & GUEST_CR3 as reqd */
paging_update_paging_modes(v);
if ( v->arch.hvm.vmx.secondary_exec_control &
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY )
printk("InterruptStatus = %04x\n", vmr16(GUEST_INTR_STATUS));
+ if ( cpu_has_vmx_virt_spec_ctrl )
+ printk("SPEC_CTRL mask = 0x%016lx shadow = 0x%016lx\n",
+ vmr(SPEC_CTRL_MASK), vmr(SPEC_CTRL_SHADOW));
printk("*** Host State ***\n");
printk("RIP = 0x%016lx (%ps) RSP = 0x%016lx\n",
/*
* We can safely pass MSR_SPEC_CTRL through to the guest, even if STIBP
* isn't enumerated in hardware, as SPEC_CTRL_STIBP is ignored.
+ *
+ * If VMX_VIRT_SPEC_CTRL is available, it is activated by default and the
+ * guest MSR_SPEC_CTRL value lives in the VMCS. Otherwise, it lives in
+ * the MSR load/save list.
*/
if ( cp->feat.ibrsb )
{
vmx_clear_msr_intercept(v, MSR_SPEC_CTRL, VMX_MSR_RW);
- rc = vmx_add_guest_msr(v, MSR_SPEC_CTRL, 0);
- if ( rc )
- goto out;
+ if ( !cpu_has_vmx_virt_spec_ctrl )
+ {
+ rc = vmx_add_guest_msr(v, MSR_SPEC_CTRL, 0);
+ if ( rc )
+ goto out;
+ }
}
else
{
vmx_set_msr_intercept(v, MSR_SPEC_CTRL, VMX_MSR_RW);
- rc = vmx_del_msr(v, MSR_SPEC_CTRL, VMX_MSR_GUEST);
- if ( rc && rc != -ESRCH )
- goto out;
- rc = 0; /* Tolerate -ESRCH */
+ if ( !cpu_has_vmx_virt_spec_ctrl )
+ vmx_del_msr(v, MSR_SPEC_CTRL, VMX_MSR_GUEST);
}
/* MSR_PRED_CMD is safe to pass through if the guest knows about it. */
switch ( reg )
{
case MSR_SPEC_CTRL:
+ if ( cpu_has_vmx_virt_spec_ctrl )
+ /* Guest value in VMCS - fetched below. */
+ break;
+
rc = vmx_read_guest_msr(v, reg, &val);
if ( rc )
{
vmx_vmcs_enter(v);
switch ( reg )
{
+ case MSR_SPEC_CTRL:
+ ASSERT(cpu_has_vmx_virt_spec_ctrl);
+ __vmread(SPEC_CTRL_SHADOW, &val);
+ break;
+
case MSR_IA32_BNDCFGS:
__vmread(GUEST_BNDCFGS, &val);
break;
switch ( reg )
{
case MSR_SPEC_CTRL:
+ if ( cpu_has_vmx_virt_spec_ctrl )
+ /* Guest value in VMCS - set below. */
+ break;
+
rc = vmx_write_guest_msr(v, reg, val);
if ( rc )
{
vmx_vmcs_enter(v);
switch ( reg )
{
+ case MSR_SPEC_CTRL:
+ ASSERT(cpu_has_vmx_virt_spec_ctrl);
+ __vmwrite(SPEC_CTRL_SHADOW, val);
+ break;
+
case MSR_IA32_BNDCFGS:
__vmwrite(GUEST_BNDCFGS, val);
break;
#define TERTIARY_EXEC_VIRT_SPEC_CTRL BIT(7, UL)
extern uint64_t vmx_tertiary_exec_control;
+#define cpu_has_vmx_virt_spec_ctrl \
+ (vmx_tertiary_exec_control & TERTIARY_EXEC_VIRT_SPEC_CTRL)
+
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
#define VMX_EPT_WALK_LENGTH_4_SUPPORTED 0x00000040
#define VMX_EPT_MEMORY_TYPE_UC 0x00000100
XSS_EXIT_BITMAP = 0x0000202c,
TSC_MULTIPLIER = 0x00002032,
TERTIARY_VM_EXEC_CONTROL = 0x00002034,
+ SPEC_CTRL_MASK = 0x0000204a,
+ SPEC_CTRL_SHADOW = 0x0000204c,
GUEST_PHYSICAL_ADDRESS = 0x00002400,
VMCS_LINK_POINTER = 0x00002800,
GUEST_IA32_DEBUGCTL = 0x00002802,
* For PV guests, this holds the guest kernel value. It is accessed on
* every entry/exit path.
*
- * For VT-x guests, the guest value is held in the MSR guest load/save
- * list.
+ * For VT-x guests, one of two situations exist:
+ *
+ * - If hardware supports virtualized MSR_SPEC_CTRL, it is active by
+ * default and the guest value lives in the VMCS.
+ * - Otherwise, the guest value is held in the MSR load/save list.
*
* For SVM, the guest value lives in the VMCB, and hardware saves/restores
* the host value automatically. However, guests run with the OR of the