[PATCH 9/9] KVM: Adds support for TPR shadowing under VMX processors

Gregory Haskins
2007-05-09T15:19:42Z

drivers/kvm/vmx.c | 32 ++++++++++++++++++++++++++------
1 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index d99bbbb..470494e 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1159,13 +1159,26 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS,
CPU_BASED_VM_EXEC_CONTROL,
CPU_BASED_HLT_EXITING /* 20.6.2 */
- | CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */
- | CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */
+ | CPU_BASED_TPR_SHADOW /* 20.6.2 */
| CPU_BASED_ACTIVATE_IO_BITMAP /* 20.6.2 */
| CPU_BASED_MOV_DR_EXITING
| CPU_BASED_USE_TSC_OFFSETING /* 21.3 */
);

+ if (!(vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) & CPU_BASED_TPR_SHADOW)) {
+ u32 cbvec;
+
+ cbvec = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ cbvec |= CPU_BASED_CR8_LOAD_EXITING; /* 20.6.2 */
+ cbvec |= CPU_BASED_CR8_STORE_EXITING; /* 20.6.2 */
+ vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS,
+ CPU_BASED_VM_EXEC_CONTROL,
+ cbvec);
+
+ printk(KERN_WARNING "KVM: Warning - Host processor does " \
+ "not support TPR-shadow\n");
+ }
+
vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
@@ -1239,7 +1252,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */

#ifdef CONFIG_X86_64
- vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0);
+ vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, kvm_lapic_get_regs(vcpu));
vmcs_writel(TPR_THRESHOLD, 0);
#endif

@@ -1346,6 +1359,9 @@ static int do_intr_requests(struct kvm_vcpu *vcpu,
kvm_irqpin_t pin)
{
int handled = 0;
+ struct kvm_irqack_data ack;
+
+ memset(&ack, 0, sizeof(ack));

vcpu->interrupt_window_open =
((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
@@ -1357,11 +1373,8 @@ static int do_intr_requests(struct kvm_vcpu *vcpu,
* If interrupts enabled, and not blocked by sti or mov ss.
* Good.
*/
- struct kvm_irqack_data ack;
int r = 0;

- memset(&ack, 0, sizeof(ack));
-
switch (pin) {
case kvm_irqpin_localint:
r = kvm_vcpu_irq_pop(vcpu, &ack);
@@ -1414,6 +1427,13 @@ static int do_intr_requests(struct kvm_vcpu *vcpu,
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cbvec);
}

+#ifdef CONFIG_X86_64
+ if (ack.flags & KVM_IRQACKDATA_NEXT_VALID)
+ vmcs_writel(TPR_THRESHOLD, ack.next >> 4);
+ else
+ vmcs_writel(TPR_THRESHOLD, 0);
+#endif
+
return handled;