diff options
author | He, Qing <qing.he@intel.com> | 2007-09-03 10:07:41 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:26 -0400 |
commit | c5ec153402b6d276fe20029da1059ba42a4b55e5 (patch) | |
tree | a323fd0466f606b66fc7239e78569863d62f6300 /drivers/kvm/kvm_main.c | |
parent | 932f72adbe76f098922c746737cb0bd75fc21e27 (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/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 02af24e8350c..d0a5a2b3d599 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -249,6 +249,10 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) | |||
249 | vcpu->mmu.root_hpa = INVALID_PAGE; | 249 | vcpu->mmu.root_hpa = INVALID_PAGE; |
250 | vcpu->kvm = kvm; | 250 | vcpu->kvm = kvm; |
251 | vcpu->vcpu_id = id; | 251 | vcpu->vcpu_id = id; |
252 | if (!irqchip_in_kernel(kvm) || id == 0) | ||
253 | vcpu->mp_state = VCPU_MP_STATE_RUNNABLE; | ||
254 | else | ||
255 | vcpu->mp_state = VCPU_MP_STATE_UNINITIALIZED; | ||
252 | init_waitqueue_head(&vcpu->wq); | 256 | init_waitqueue_head(&vcpu->wq); |
253 | 257 | ||
254 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 258 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
@@ -1371,7 +1375,7 @@ EXPORT_SYMBOL_GPL(emulate_instruction); | |||
1371 | /* | 1375 | /* |
1372 | * The vCPU has executed a HLT instruction with in-kernel mode enabled. | 1376 | * The vCPU has executed a HLT instruction with in-kernel mode enabled. |
1373 | */ | 1377 | */ |
1374 | static void kvm_vcpu_kernel_halt(struct kvm_vcpu *vcpu) | 1378 | static void kvm_vcpu_block(struct kvm_vcpu *vcpu) |
1375 | { | 1379 | { |
1376 | DECLARE_WAITQUEUE(wait, current); | 1380 | DECLARE_WAITQUEUE(wait, current); |
1377 | 1381 | ||
@@ -1380,24 +1384,28 @@ static void kvm_vcpu_kernel_halt(struct kvm_vcpu *vcpu) | |||
1380 | /* | 1384 | /* |
1381 | * We will block until either an interrupt or a signal wakes us up | 1385 | * We will block until either an interrupt or a signal wakes us up |
1382 | */ | 1386 | */ |
1383 | while(!(irqchip_in_kernel(vcpu->kvm) && kvm_cpu_has_interrupt(vcpu)) | 1387 | while (!kvm_cpu_has_interrupt(vcpu) |
1384 | && !vcpu->irq_summary | 1388 | && !signal_pending(current) |
1385 | && !signal_pending(current)) { | 1389 | && vcpu->mp_state != VCPU_MP_STATE_RUNNABLE |
1390 | && vcpu->mp_state != VCPU_MP_STATE_SIPI_RECEIVED) { | ||
1386 | set_current_state(TASK_INTERRUPTIBLE); | 1391 | set_current_state(TASK_INTERRUPTIBLE); |
1387 | vcpu_put(vcpu); | 1392 | vcpu_put(vcpu); |
1388 | schedule(); | 1393 | schedule(); |
1389 | vcpu_load(vcpu); | 1394 | vcpu_load(vcpu); |
1390 | } | 1395 | } |
1391 | 1396 | ||
1397 | __set_current_state(TASK_RUNNING); | ||
1392 | remove_wait_queue(&vcpu->wq, &wait); | 1398 | remove_wait_queue(&vcpu->wq, &wait); |
1393 | set_current_state(TASK_RUNNING); | ||
1394 | } | 1399 | } |
1395 | 1400 | ||
1396 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) | 1401 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) |
1397 | { | 1402 | { |
1398 | ++vcpu->stat.halt_exits; | 1403 | ++vcpu->stat.halt_exits; |
1399 | if (irqchip_in_kernel(vcpu->kvm)) { | 1404 | if (irqchip_in_kernel(vcpu->kvm)) { |
1400 | kvm_vcpu_kernel_halt(vcpu); | 1405 | vcpu->mp_state = VCPU_MP_STATE_HALTED; |
1406 | kvm_vcpu_block(vcpu); | ||
1407 | if (vcpu->mp_state != VCPU_MP_STATE_RUNNABLE) | ||
1408 | return -EINTR; | ||
1401 | return 1; | 1409 | return 1; |
1402 | } else { | 1410 | } else { |
1403 | vcpu->run->exit_reason = KVM_EXIT_HLT; | 1411 | vcpu->run->exit_reason = KVM_EXIT_HLT; |
@@ -2001,6 +2009,12 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2001 | 2009 | ||
2002 | vcpu_load(vcpu); | 2010 | vcpu_load(vcpu); |
2003 | 2011 | ||
2012 | if (unlikely(vcpu->mp_state == VCPU_MP_STATE_UNINITIALIZED)) { | ||
2013 | kvm_vcpu_block(vcpu); | ||
2014 | vcpu_put(vcpu); | ||
2015 | return -EAGAIN; | ||
2016 | } | ||
2017 | |||
2004 | if (vcpu->sigset_active) | 2018 | if (vcpu->sigset_active) |
2005 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); | 2019 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); |
2006 | 2020 | ||