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 <[email protected]>
---
 arch/powerpc/include/asm/kvm_book3s.h |    5 +++++
 arch/powerpc/include/asm/kvm_host.h   |    2 ++
 arch/powerpc/kvm/book3s.c             |   24 ++++++++++++++++++------
 arch/powerpc/kvm/powerpc.c            |   12 ++++++++++++
 include/linux/kvm.h                   |    6 ++++++
 5 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h 
b/arch/powerpc/include/asm/kvm_book3s.h
index 6476e70..5009cf8 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -148,6 +148,11 @@ static inline ulong dsisr(void)
 
 extern void kvm_return_point(void);
 
+/* Magic register values loaded into r3 and r4 before the 'sc' assembly
+ * instruction for the OSI hypercalls */
+#define OSI_SC_MAGIC_R3                        0x113724FA
+#define OSI_SC_MAGIC_R4                        0x77810F9B
+
 #define INS_DCBZ                       0x7c0007ec
 
 #endif /* __ASM_KVM_BOOK3S_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 0ebda67..486f1ca 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -273,6 +273,8 @@ struct kvm_vcpu_arch {
        u8 mmio_sign_extend;
        u8 dcr_needed;
        u8 dcr_is_write;
+       u8 osi_needed;
+       u8 osi_enabled;
 
        u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
 
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index b2405ab..7c079c0 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -873,12 +873,24 @@ program_interrupt:
                break;
        }
        case BOOK3S_INTERRUPT_SYSCALL:
-#ifdef EXIT_DEBUG
-               printk(KERN_INFO "Syscall Nr %d\n", (int)kvmppc_get_gpr(vcpu, 
0));
-#endif
-               vcpu->stat.syscall_exits++;
-               kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-               r = RESUME_GUEST;
+               // XXX make user settable
+               if (vcpu->arch.osi_enabled &&
+                   (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
+                   (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
+                       u64 *gprs = run->osi.gprs;
+                       int i;
+
+                       run->exit_reason = KVM_EXIT_OSI;
+                       for (i = 0; i < 32; i++)
+                               gprs[i] = kvmppc_get_gpr(vcpu, i);
+                       vcpu->arch.osi_needed = 1;
+                       r = RESUME_HOST_NV;
+
+               } else {
+                       vcpu->stat.syscall_exits++;
+                       kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+                       r = RESUME_GUEST;
+               }
                break;
        case BOOK3S_INTERRUPT_FP_UNAVAIL:
        case BOOK3S_INTERRUPT_ALTIVEC:
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index f52752c..9a57c02 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -148,6 +148,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
        case KVM_CAP_PPC_SEGSTATE:
        case KVM_CAP_PPC_PAIRED_SINGLES:
+       case KVM_CAP_PPC_OSI:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -429,6 +430,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct 
kvm_run *run)
                if (!vcpu->arch.dcr_is_write)
                        kvmppc_complete_dcr_load(vcpu, run);
                vcpu->arch.dcr_needed = 0;
+       } else if (vcpu->arch.osi_needed) {
+               u64 *gprs = run->osi.gprs;
+               int i;
+
+               for (i = 0; i < 32; i++)
+                       kvmppc_set_gpr(vcpu, i, gprs[i]);
+               vcpu->arch.osi_needed = 0;
        }
 
        kvmppc_core_deliver_interrupts(vcpu);
@@ -468,6 +476,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        int r;
 
        switch (cap->cap) {
+       case KVM_CAP_PPC_OSI:
+               r = 0;
+               vcpu->arch.osi_enabled = true;
+               break;
        default:
                r = -EINVAL;
                break;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index c7ed3cb..44291d7 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -160,6 +160,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_DCR              15
 #define KVM_EXIT_NMI              16
 #define KVM_EXIT_INTERNAL_ERROR   17
+#define KVM_EXIT_OSI              18
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -259,6 +260,10 @@ struct kvm_run {
                        __u32 ndata;
                        __u64 data[16];
                } internal;
+               /* KVM_EXIT_OSI */
+               struct {
+                       __u64 gprs[32];
+               } osi;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -513,6 +518,7 @@ struct kvm_enable_cap {
 #define KVM_CAP_DEBUGREGS 50
 #endif
 #define KVM_CAP_X86_ROBUST_SINGLESTEP 51
+#define KVM_CAP_PPC_OSI 52
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to