aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/lapic.c
diff options
context:
space:
mode:
authorHe, Qing <qing.he@intel.com>2007-09-03 10:07:41 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:26 -0400
commitc5ec153402b6d276fe20029da1059ba42a4b55e5 (patch)
treea323fd0466f606b66fc7239e78569863d62f6300 /drivers/kvm/lapic.c
parent932f72adbe76f098922c746737cb0bd75fc21e27 (diff)
KVM: enable in-kernel APIC INIT/SIPI handling
This patch enables INIT/SIPI handling using in-kernel APIC by introducing a ->mp_state field to emulate the SMP state transition. [avi: remove smp_processor_id() warning] Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Xin Li <xin.b.li@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/lapic.c')
-rw-r--r--drivers/kvm/lapic.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index ca1db3852ace..a190587cf6a5 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -312,8 +312,8 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
312static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, 312static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
313 int vector, int level, int trig_mode) 313 int vector, int level, int trig_mode)
314{ 314{
315 int result = 0; 315 int orig_irr, result = 0;
316 int orig_irr; 316 struct kvm_vcpu *vcpu = apic->vcpu;
317 317
318 switch (delivery_mode) { 318 switch (delivery_mode) {
319 case APIC_DM_FIXED: 319 case APIC_DM_FIXED:
@@ -335,7 +335,13 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
335 } else 335 } else
336 apic_clear_vector(vector, apic->regs + APIC_TMR); 336 apic_clear_vector(vector, apic->regs + APIC_TMR);
337 337
338 kvm_vcpu_kick(apic->vcpu); 338 if (vcpu->mp_state == VCPU_MP_STATE_RUNNABLE)
339 kvm_vcpu_kick(vcpu);
340 else if (vcpu->mp_state == VCPU_MP_STATE_HALTED) {
341 vcpu->mp_state = VCPU_MP_STATE_RUNNABLE;
342 if (waitqueue_active(&vcpu->wq))
343 wake_up_interruptible(&vcpu->wq);
344 }
339 345
340 result = (orig_irr == 0); 346 result = (orig_irr == 0);
341 break; 347 break;
@@ -352,11 +358,30 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
352 break; 358 break;
353 359
354 case APIC_DM_INIT: 360 case APIC_DM_INIT:
355 printk(KERN_DEBUG "Ignoring guest INIT\n"); 361 if (level) {
362 if (vcpu->mp_state == VCPU_MP_STATE_RUNNABLE)
363 printk(KERN_DEBUG
364 "INIT on a runnable vcpu %d\n",
365 vcpu->vcpu_id);
366 vcpu->mp_state = VCPU_MP_STATE_INIT_RECEIVED;
367 kvm_vcpu_kick(vcpu);
368 } else {
369 printk(KERN_DEBUG
370 "Ignoring de-assert INIT to vcpu %d\n",
371 vcpu->vcpu_id);
372 }
373
356 break; 374 break;
357 375
358 case APIC_DM_STARTUP: 376 case APIC_DM_STARTUP:
359 printk(KERN_DEBUG "Ignoring guest STARTUP\n"); 377 printk(KERN_DEBUG "SIPI to vcpu %d vector 0x%02x\n",
378 vcpu->vcpu_id, vector);
379 if (vcpu->mp_state == VCPU_MP_STATE_INIT_RECEIVED) {
380 vcpu->sipi_vector = vector;
381 vcpu->mp_state = VCPU_MP_STATE_SIPI_RECEIVED;
382 if (waitqueue_active(&vcpu->wq))
383 wake_up_interruptible(&vcpu->wq);
384 }
360 break; 385 break;
361 386
362 default: 387 default:
@@ -792,7 +817,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu)
792} 817}
793EXPORT_SYMBOL_GPL(kvm_lapic_get_base); 818EXPORT_SYMBOL_GPL(kvm_lapic_get_base);
794 819
795static void lapic_reset(struct kvm_vcpu *vcpu) 820void kvm_lapic_reset(struct kvm_vcpu *vcpu)
796{ 821{
797 struct kvm_lapic *apic; 822 struct kvm_lapic *apic;
798 int i; 823 int i;
@@ -839,6 +864,7 @@ static void lapic_reset(struct kvm_vcpu *vcpu)
839 vcpu, kvm_apic_id(apic), 864 vcpu, kvm_apic_id(apic),
840 vcpu->apic_base, apic->base_address); 865 vcpu->apic_base, apic->base_address);
841} 866}
867EXPORT_SYMBOL_GPL(kvm_lapic_reset);
842 868
843int kvm_lapic_enabled(struct kvm_vcpu *vcpu) 869int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
844{ 870{
@@ -867,7 +893,10 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
867 893
868 atomic_inc(&apic->timer.pending); 894 atomic_inc(&apic->timer.pending);
869 if (waitqueue_active(q)) 895 if (waitqueue_active(q))
896 {
897 apic->vcpu->mp_state = VCPU_MP_STATE_RUNNABLE;
870 wake_up_interruptible(q); 898 wake_up_interruptible(q);
899 }
871 if (apic_lvtt_period(apic)) { 900 if (apic_lvtt_period(apic)) {
872 result = 1; 901 result = 1;
873 apic->timer.dev.expires = ktime_add_ns( 902 apic->timer.dev.expires = ktime_add_ns(
@@ -928,7 +957,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
928 apic->base_address = APIC_DEFAULT_PHYS_BASE; 957 apic->base_address = APIC_DEFAULT_PHYS_BASE;
929 vcpu->apic_base = APIC_DEFAULT_PHYS_BASE; 958 vcpu->apic_base = APIC_DEFAULT_PHYS_BASE;
930 959
931 lapic_reset(vcpu); 960 kvm_lapic_reset(vcpu);
932 apic->dev.read = apic_mmio_read; 961 apic->dev.read = apic_mmio_read;
933 apic->dev.write = apic_mmio_write; 962 apic->dev.write = apic_mmio_write;
934 apic->dev.in_range = apic_mmio_range; 963 apic->dev.in_range = apic_mmio_range;