aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-03-24 16:48:30 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:17:10 -0400
commitad0a048b096ac819f28667602285453468a8d8f9 (patch)
tree491128ccab48eb277a5cf5919a798b0507da9859 /arch/powerpc/kvm
parent71fbfd5f38f73515f1516a68fbe04dba198b70f0 (diff)
KVM: PPC: Add OSI hypercall interface
MOL uses its own hypercall interface to call back into userspace when the guest wants to do something. So let's implement that as an exit reason, specify it with a CAP and only really use it when userspace wants us to. The only user of it so far is MOL. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s.c24
-rw-r--r--arch/powerpc/kvm/powerpc.c12
2 files changed, 30 insertions, 6 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index de12202fe1c6..7696d0f547e3 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -872,12 +872,24 @@ program_interrupt:
872 break; 872 break;
873 } 873 }
874 case BOOK3S_INTERRUPT_SYSCALL: 874 case BOOK3S_INTERRUPT_SYSCALL:
875#ifdef EXIT_DEBUG 875 // XXX make user settable
876 printk(KERN_INFO "Syscall Nr %d\n", (int)kvmppc_get_gpr(vcpu, 0)); 876 if (vcpu->arch.osi_enabled &&
877#endif 877 (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
878 vcpu->stat.syscall_exits++; 878 (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
879 kvmppc_book3s_queue_irqprio(vcpu, exit_nr); 879 u64 *gprs = run->osi.gprs;
880 r = RESUME_GUEST; 880 int i;
881
882 run->exit_reason = KVM_EXIT_OSI;
883 for (i = 0; i < 32; i++)
884 gprs[i] = kvmppc_get_gpr(vcpu, i);
885 vcpu->arch.osi_needed = 1;
886 r = RESUME_HOST_NV;
887
888 } else {
889 vcpu->stat.syscall_exits++;
890 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
891 r = RESUME_GUEST;
892 }
881 break; 893 break;
882 case BOOK3S_INTERRUPT_FP_UNAVAIL: 894 case BOOK3S_INTERRUPT_FP_UNAVAIL:
883 case BOOK3S_INTERRUPT_ALTIVEC: 895 case BOOK3S_INTERRUPT_ALTIVEC:
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 646bfd256e5d..9a4dd8146d39 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -151,6 +151,7 @@ int kvm_dev_ioctl_check_extension(long ext)
151 case KVM_CAP_PPC_PAIRED_SINGLES: 151 case KVM_CAP_PPC_PAIRED_SINGLES:
152 case KVM_CAP_PPC_UNSET_IRQ: 152 case KVM_CAP_PPC_UNSET_IRQ:
153 case KVM_CAP_ENABLE_CAP: 153 case KVM_CAP_ENABLE_CAP:
154 case KVM_CAP_PPC_OSI:
154 r = 1; 155 r = 1;
155 break; 156 break;
156 case KVM_CAP_COALESCED_MMIO: 157 case KVM_CAP_COALESCED_MMIO:
@@ -433,6 +434,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
433 if (!vcpu->arch.dcr_is_write) 434 if (!vcpu->arch.dcr_is_write)
434 kvmppc_complete_dcr_load(vcpu, run); 435 kvmppc_complete_dcr_load(vcpu, run);
435 vcpu->arch.dcr_needed = 0; 436 vcpu->arch.dcr_needed = 0;
437 } else if (vcpu->arch.osi_needed) {
438 u64 *gprs = run->osi.gprs;
439 int i;
440
441 for (i = 0; i < 32; i++)
442 kvmppc_set_gpr(vcpu, i, gprs[i]);
443 vcpu->arch.osi_needed = 0;
436 } 444 }
437 445
438 kvmppc_core_deliver_interrupts(vcpu); 446 kvmppc_core_deliver_interrupts(vcpu);
@@ -475,6 +483,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
475 return -EINVAL; 483 return -EINVAL;
476 484
477 switch (cap->cap) { 485 switch (cap->cap) {
486 case KVM_CAP_PPC_OSI:
487 r = 0;
488 vcpu->arch.osi_enabled = true;
489 break;
478 default: 490 default:
479 r = -EINVAL; 491 r = -EINVAL;
480 break; 492 break;