aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2008-04-25 18:55:49 -0400
committerAvi Kivity <avi@qumranet.com>2008-05-04 07:44:44 -0400
commit45c5eb67da5a668abe79c23a7e64dbc87a600f90 (patch)
treeb2b9ff85ecb5b35d246d68da94b20cb9f9912bff /arch/powerpc/kvm
parent3fe913e7c550a869e250d04c34410f7a6e263f7c (diff)
KVM: ppc: Handle guest idle by emulating MSR[WE] writes
This reduces host CPU usage when the guest is idle. However, the guest must set MSR[WE] in its idle loop, which Linux did not do until 2.6.26. Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Jerone Young <jyoung5@us.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/booke_guest.c1
-rw-r--r--arch/powerpc/kvm/powerpc.c20
2 files changed, 18 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
index 6d9884a6884a..b3db6f4576ad 100644
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -49,6 +49,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
49 { "inst_emu", VCPU_STAT(emulated_inst_exits) }, 49 { "inst_emu", VCPU_STAT(emulated_inst_exits) },
50 { "dec", VCPU_STAT(dec_exits) }, 50 { "dec", VCPU_STAT(dec_exits) },
51 { "ext_intr", VCPU_STAT(ext_intr_exits) }, 51 { "ext_intr", VCPU_STAT(ext_intr_exits) },
52 { "halt_wakeup", VCPU_STAT(halt_wakeup) },
52 { NULL } 53 { NULL }
53}; 54};
54 55
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index bad40bd2d3ac..777e0f34e0ea 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -36,13 +36,12 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
36 36
37int kvm_cpu_has_interrupt(struct kvm_vcpu *v) 37int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
38{ 38{
39 /* XXX implement me */ 39 return !!(v->arch.pending_exceptions);
40 return 0;
41} 40}
42 41
43int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) 42int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
44{ 43{
45 return 1; 44 return !(v->arch.msr & MSR_WE);
46} 45}
47 46
48 47
@@ -214,6 +213,11 @@ static void kvmppc_decrementer_func(unsigned long data)
214 struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; 213 struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
215 214
216 kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); 215 kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
216
217 if (waitqueue_active(&vcpu->wq)) {
218 wake_up_interruptible(&vcpu->wq);
219 vcpu->stat.halt_wakeup++;
220 }
217} 221}
218 222
219int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) 223int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
@@ -339,6 +343,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
339 int r; 343 int r;
340 sigset_t sigsaved; 344 sigset_t sigsaved;
341 345
346 vcpu_load(vcpu);
347
342 if (vcpu->sigset_active) 348 if (vcpu->sigset_active)
343 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); 349 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
344 350
@@ -363,12 +369,20 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
363 if (vcpu->sigset_active) 369 if (vcpu->sigset_active)
364 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 370 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
365 371
372 vcpu_put(vcpu);
373
366 return r; 374 return r;
367} 375}
368 376
369int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) 377int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
370{ 378{
371 kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); 379 kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
380
381 if (waitqueue_active(&vcpu->wq)) {
382 wake_up_interruptible(&vcpu->wq);
383 vcpu->stat.halt_wakeup++;
384 }
385
372 return 0; 386 return 0;
373} 387}
374 388