Page MenuHomeFreeBSD

D22942.id67815.diff
No OneTemporary

D22942.id67815.diff

Index: sys/amd64/vmm/intel/vmx.c
===================================================================
--- sys/amd64/vmm/intel/vmx.c
+++ sys/amd64/vmm/intel/vmx.c
@@ -172,6 +172,10 @@
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, invpcid, CTLFLAG_RD, &cap_invpcid,
0, "Guests are allowed to use INVPCID");
+static int tpr_shadowing;
+SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, tpr_shadowing, CTLFLAG_RD,
+ &tpr_shadowing, 0, "TPR shadowing support");
+
static int virtual_interrupt_delivery;
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, virtual_interrupt_delivery, CTLFLAG_RD,
&virtual_interrupt_delivery, 0, "APICv virtual interrupt delivery support");
@@ -627,7 +631,7 @@
static int
vmx_init(int ipinum)
{
- int error, use_tpr_shadow;
+ int error;
uint64_t basic, fixed0, fixed1, feature_control;
uint32_t tmp, procbased2_vid_bits;
@@ -750,6 +754,24 @@
MSR_VMX_PROCBASED_CTLS2, PROCBASED2_ENABLE_INVPCID, 0,
&tmp) == 0);
+ /*
+ * Check support for TPR shadow.
+ */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS, PROCBASED_USE_TPR_SHADOW, 0,
+ &tmp);
+ if (error == 0) {
+ tpr_shadowing = 1;
+ TUNABLE_INT_FETCH("hw.vmm.vmx.use_tpr_shadowing",
+ &tpr_shadowing);
+ }
+
+ if (tpr_shadowing) {
+ procbased_ctls |= PROCBASED_USE_TPR_SHADOW;
+ procbased_ctls &= ~PROCBASED_CR8_LOAD_EXITING;
+ procbased_ctls &= ~PROCBASED_CR8_STORE_EXITING;
+ }
+
/*
* Check support for virtual interrupt delivery.
*/
@@ -758,13 +780,9 @@
PROCBASED2_APIC_REGISTER_VIRTUALIZATION |
PROCBASED2_VIRTUAL_INTERRUPT_DELIVERY);
- use_tpr_shadow = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
- MSR_VMX_TRUE_PROCBASED_CTLS, PROCBASED_USE_TPR_SHADOW, 0,
- &tmp) == 0);
-
error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2,
procbased2_vid_bits, 0, &tmp);
- if (error == 0 && use_tpr_shadow) {
+ if (error == 0 && tpr_shadowing) {
virtual_interrupt_delivery = 1;
TUNABLE_INT_FETCH("hw.vmm.vmx.use_apic_vid",
&virtual_interrupt_delivery);
@@ -775,13 +793,6 @@
procbased_ctls2 |= procbased2_vid_bits;
procbased_ctls2 &= ~PROCBASED2_VIRTUALIZE_X2APIC_MODE;
- /*
- * No need to emulate accesses to %CR8 if virtual
- * interrupt delivery is enabled.
- */
- procbased_ctls &= ~PROCBASED_CR8_LOAD_EXITING;
- procbased_ctls &= ~PROCBASED_CR8_STORE_EXITING;
-
/*
* Check for Posted Interrupts only if Virtual Interrupt
* Delivery is enabled.
@@ -1051,10 +1062,13 @@
vmx->ctx[i].guest_dr6 = DBREG_DR6_RESERVED1;
error += vmwrite(VMCS_GUEST_DR7, DBREG_DR7_RESERVED1);
- if (virtual_interrupt_delivery) {
- error += vmwrite(VMCS_APIC_ACCESS, APIC_ACCESS_ADDRESS);
+ if (tpr_shadowing) {
error += vmwrite(VMCS_VIRTUAL_APIC,
vtophys(&vmx->apic_page[i]));
+ }
+
+ if (virtual_interrupt_delivery) {
+ error += vmwrite(VMCS_APIC_ACCESS, APIC_ACCESS_ADDRESS);
error += vmwrite(VMCS_EOI_EXIT0, 0);
error += vmwrite(VMCS_EOI_EXIT1, 0);
error += vmwrite(VMCS_EOI_EXIT2, 0);
@@ -2658,6 +2672,12 @@
SDT_PROBE3(vmm, vmx, exit, mwait, vmx, vcpu, vmexit);
vmexit->exitcode = VM_EXITCODE_MWAIT;
break;
+ case EXIT_REASON_TPR:
+ vlapic = vm_lapic(vmx->vm, vcpu);
+ vlapic_sync_tpr(vlapic);
+ vmexit->inst_length = 0;
+ handled = HANDLED;
+ break;
case EXIT_REASON_VMCALL:
case EXIT_REASON_VMCLEAR:
case EXIT_REASON_VMLAUNCH:
@@ -2943,6 +2963,16 @@
break;
}
+ /*
+ * If TPR Shadowing is enabled, the TPR Threshold
+ * must be updated right before entering the guest.
+ */
+ if (tpr_shadowing && !virtual_interrupt_delivery) {
+ if ((vmx->cap[vcpu].proc_ctls & PROCBASED_USE_TPR_SHADOW) != 0) {
+ vmcs_write(VMCS_TPR_THRESHOLD, vlapic_get_cr8(vlapic));
+ }
+ }
+
/*
* VM exits restore the base address but not the
* limits of GDTR and IDTR. The VMCS only stores the
@@ -3631,7 +3661,30 @@
}
static void
-vmx_enable_x2apic_mode(struct vlapic *vlapic)
+vmx_enable_x2apic_mode_ts(struct vlapic *vlapic)
+{
+ struct vmx *vmx;
+ struct vmcs *vmcs;
+ uint32_t proc_ctls;
+ int vcpuid;
+
+ vcpuid = vlapic->vcpuid;
+ vmx = ((struct vlapic_vtx *)vlapic)->vmx;
+ vmcs = &vmx->vmcs[vcpuid];
+
+ proc_ctls = vmx->cap[vcpuid].proc_ctls;
+ proc_ctls &= ~PROCBASED_USE_TPR_SHADOW;
+ proc_ctls |= PROCBASED_CR8_LOAD_EXITING;
+ proc_ctls |= PROCBASED_CR8_STORE_EXITING;
+ vmx->cap[vcpuid].proc_ctls = proc_ctls;
+
+ VMPTRLD(vmcs);
+ vmcs_write(VMCS_PRI_PROC_BASED_CTLS, proc_ctls);
+ VMCLEAR(vmcs);
+}
+
+static void
+vmx_enable_x2apic_mode_vid(struct vlapic *vlapic)
{
struct vmx *vmx;
struct vmcs *vmcs;
@@ -3792,12 +3845,16 @@
vlapic_vtx->pir_desc = &vmx->pir_desc[vcpuid];
vlapic_vtx->vmx = vmx;
+ if (tpr_shadowing) {
+ vlapic->ops.enable_x2apic_mode = vmx_enable_x2apic_mode_ts;
+ }
+
if (virtual_interrupt_delivery) {
vlapic->ops.set_intr_ready = vmx_set_intr_ready;
vlapic->ops.pending_intr = vmx_pending_intr;
vlapic->ops.intr_accepted = vmx_intr_accepted;
vlapic->ops.set_tmr = vmx_set_tmr;
- vlapic->ops.enable_x2apic_mode = vmx_enable_x2apic_mode;
+ vlapic->ops.enable_x2apic_mode = vmx_enable_x2apic_mode_vid;
}
if (posted_interrupts)
Index: sys/amd64/vmm/io/vlapic.h
===================================================================
--- sys/amd64/vmm/io/vlapic.h
+++ sys/amd64/vmm/io/vlapic.h
@@ -74,6 +74,8 @@
void vlapic_fire_cmci(struct vlapic *vlapic);
int vlapic_trigger_lvt(struct vlapic *vlapic, int vector);
+void vlapic_sync_tpr(struct vlapic *vlapic);
+
uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
int vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val);
void vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state s);
Index: sys/amd64/vmm/io/vlapic.c
===================================================================
--- sys/amd64/vmm/io/vlapic.c
+++ sys/amd64/vmm/io/vlapic.c
@@ -555,6 +555,12 @@
VLAPIC_CTR1(vlapic, "vlapic_update_ppr 0x%02x", ppr);
}
+void
+vlapic_sync_tpr(struct vlapic *vlapic)
+{
+ vlapic_update_ppr(vlapic);
+}
+
static VMM_STAT(VLAPIC_GRATUITOUS_EOI, "EOI without any in-service interrupt");
static void
@@ -1079,6 +1085,8 @@
int idx, i, bitpos, vector;
uint32_t *irrptr, val;
+ vlapic_update_ppr(vlapic);
+
if (vlapic->ops.pending_intr)
return ((*vlapic->ops.pending_intr)(vlapic, vecptr));
@@ -1136,7 +1144,6 @@
panic("isrvec_stk_top overflow %d", stk_top);
vlapic->isrvec_stk[stk_top] = vector;
- vlapic_update_ppr(vlapic);
}
void

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 16, 5:01 PM (13 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28784218
Default Alt Text
D22942.id67815.diff (6 KB)

Event Timeline