aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-10-25 10:52:32 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 11:01:20 -0500
commitb93463aa59d67b21b4921e30bd5c5dcc7c35ffbd (patch)
tree8de9a2789624d27155d8a94c93a23c01f473fea7 /arch/x86/kvm/lapic.c
parentb209749f528488c4c0d20a42c0fbcbf49e6933b3 (diff)
KVM: Accelerated apic support
This adds a mechanism for exposing the virtual apic tpr to the guest, and a protocol for letting the guest update the tpr without causing a vmexit if conditions allow (e.g. there is no interrupt pending with a higher priority than the new tpr). Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 50c3f3a8dd3d..e7513bb98af1 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -815,7 +815,8 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
815 815
816 if (!apic) 816 if (!apic)
817 return; 817 return;
818 apic_set_tpr(apic, ((cr8 & 0x0f) << 4)); 818 apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
819 | (apic_get_reg(apic, APIC_TASKPRI) & 4));
819} 820}
820 821
821u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu) 822u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
@@ -1104,3 +1105,51 @@ void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
1104 hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS); 1105 hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
1105} 1106}
1106EXPORT_SYMBOL_GPL(kvm_migrate_apic_timer); 1107EXPORT_SYMBOL_GPL(kvm_migrate_apic_timer);
1108
1109void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
1110{
1111 u32 data;
1112 void *vapic;
1113
1114 if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr)
1115 return;
1116
1117 vapic = kmap_atomic(vcpu->arch.apic->vapic_page, KM_USER0);
1118 data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
1119 kunmap_atomic(vapic, KM_USER0);
1120
1121 apic_set_tpr(vcpu->arch.apic, data & 0xff);
1122}
1123
1124void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
1125{
1126 u32 data, tpr;
1127 int max_irr, max_isr;
1128 struct kvm_lapic *apic;
1129 void *vapic;
1130
1131 if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr)
1132 return;
1133
1134 apic = vcpu->arch.apic;
1135 tpr = apic_get_reg(apic, APIC_TASKPRI) & 0xff;
1136 max_irr = apic_find_highest_irr(apic);
1137 if (max_irr < 0)
1138 max_irr = 0;
1139 max_isr = apic_find_highest_isr(apic);
1140 if (max_isr < 0)
1141 max_isr = 0;
1142 data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
1143
1144 vapic = kmap_atomic(vcpu->arch.apic->vapic_page, KM_USER0);
1145 *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
1146 kunmap_atomic(vapic, KM_USER0);
1147}
1148
1149void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
1150{
1151 if (!irqchip_in_kernel(vcpu->kvm))
1152 return;
1153
1154 vcpu->arch.apic->vapic_addr = vapic_addr;
1155}