linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: kvm-ppc@vger.kernel.org
Cc: linuxppc-dev <linuxppc-dev@lists.ozlabs.org>,
	KVM list <kvm@vger.kernel.org>
Subject: [PATCH 07/26] KVM: PPC: Implement hypervisor interface
Date: Sat, 26 Jun 2010 01:24:55 +0200	[thread overview]
Message-ID: <1277508314-915-8-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1277508314-915-1-git-send-email-agraf@suse.de>

To communicate with KVM directly we need to plumb some sort of interface
between the guest and KVM. Usually those interfaces use hypercalls.

This hypercall implementation is described in the last patch of the series
in a special documentation file. Please read that for further information.

This patch implements stubs to handle KVM PPC hypercalls on the host and
guest side alike.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/kvm_para.h |  100 ++++++++++++++++++++++++++++++++++-
 arch/powerpc/include/asm/kvm_ppc.h  |    1 +
 arch/powerpc/kvm/book3s.c           |   10 +++-
 arch/powerpc/kvm/booke.c            |   11 ++++-
 arch/powerpc/kvm/emulate.c          |   11 ++++-
 arch/powerpc/kvm/powerpc.c          |   28 ++++++++++
 include/linux/kvm_para.h            |    1 +
 7 files changed, 156 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index e402999..eaab306 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -34,16 +34,112 @@ struct kvm_vcpu_arch_shared {
 	__u32 dsisr;
 };
 
+#define KVM_PVR_PARA		0x4b564d3f /* "KVM?" */
+#define KVM_SC_MAGIC_R3		0x4b564d52 /* "KVMR" */
+#define KVM_SC_MAGIC_R4		0x554c455a /* "ULEZ" */
+
 #ifdef __KERNEL__
 
 static inline int kvm_para_available(void)
 {
-	return 0;
+	unsigned long pvr = KVM_PVR_PARA;
+
+	asm volatile("mfpvr %0" : "=r"(pvr) : "0"(pvr));
+	return pvr == KVM_PVR_PARA;
+}
+
+static inline long kvm_hypercall0(unsigned int nr)
+{
+	unsigned long register r3 asm("r3") = KVM_SC_MAGIC_R3;
+	unsigned long register r4 asm("r4") = KVM_SC_MAGIC_R4;
+	unsigned long register _nr asm("r5") = nr;
+
+	asm volatile("sc"
+		     : "=r"(r3)
+		     : "r"(r3), "r"(r4), "r"(_nr)
+		     : "memory");
+
+	return r3;
 }
 
+static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
+{
+	unsigned long register r3 asm("r3") = KVM_SC_MAGIC_R3;
+	unsigned long register r4 asm("r4") = KVM_SC_MAGIC_R4;
+	unsigned long register _nr asm("r5") = nr;
+	unsigned long register _p1 asm("r6") = p1;
+
+	asm volatile("sc"
+		     : "=r"(r3)
+		     : "r"(r3), "r"(r4), "r"(_nr), "r"(_p1)
+		     : "memory");
+
+	return r3;
+}
+
+static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
+				  unsigned long p2)
+{
+	unsigned long register r3 asm("r3") = KVM_SC_MAGIC_R3;
+	unsigned long register r4 asm("r4") = KVM_SC_MAGIC_R4;
+	unsigned long register _nr asm("r5") = nr;
+	unsigned long register _p1 asm("r6") = p1;
+	unsigned long register _p2 asm("r7") = p2;
+
+	asm volatile("sc"
+		     : "=r"(r3)
+		     : "r"(r3), "r"(r4), "r"(_nr), "r"(_p1), "r"(_p2)
+		     : "memory");
+
+	return r3;
+}
+
+static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
+				  unsigned long p2, unsigned long p3)
+{
+	unsigned long register r3 asm("r3") = KVM_SC_MAGIC_R3;
+	unsigned long register r4 asm("r4") = KVM_SC_MAGIC_R4;
+	unsigned long register _nr asm("r5") = nr;
+	unsigned long register _p1 asm("r6") = p1;
+	unsigned long register _p2 asm("r7") = p2;
+	unsigned long register _p3 asm("r8") = p3;
+
+	asm volatile("sc"
+		     : "=r"(r3)
+		     : "r"(r3), "r"(r4), "r"(_nr), "r"(_p1), "r"(_p2), "r"(_p3)
+		     : "memory");
+
+	return r3;
+}
+
+static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
+				  unsigned long p2, unsigned long p3,
+				  unsigned long p4)
+{
+	unsigned long register r3 asm("r3") = KVM_SC_MAGIC_R3;
+	unsigned long register r4 asm("r4") = KVM_SC_MAGIC_R4;
+	unsigned long register _nr asm("r5") = nr;
+	unsigned long register _p1 asm("r6") = p1;
+	unsigned long register _p2 asm("r7") = p2;
+	unsigned long register _p3 asm("r8") = p3;
+	unsigned long register _p4 asm("r9") = p4;
+
+	asm volatile("sc"
+		     : "=r"(r3)
+		     : "r"(r3), "r"(r4), "r"(_nr), "r"(_p1), "r"(_p2), "r"(_p3),
+		       "r"(_p4)
+		     : "memory");
+
+	return r3;
+}
+
+
 static inline unsigned int kvm_arch_para_features(void)
 {
-	return 0;
+	if (!kvm_para_available())
+		return 0;
+
+	return kvm_hypercall0(KVM_HC_FEATURES);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 18d139e..ecb3bc7 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -107,6 +107,7 @@ extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
 
 extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
+extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
 
 /*
  * Cuts out inst bits with ordering according to spec.
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 5a6f055..e8001c5 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -947,10 +947,10 @@ program_interrupt:
 		break;
 	}
 	case BOOK3S_INTERRUPT_SYSCALL:
-		// 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)) {
+			/* MOL hypercalls */
 			u64 *gprs = run->osi.gprs;
 			int i;
 
@@ -959,8 +959,14 @@ program_interrupt:
 				gprs[i] = kvmppc_get_gpr(vcpu, i);
 			vcpu->arch.osi_needed = 1;
 			r = RESUME_HOST_NV;
-
+		} else if (!(vcpu->arch.shared->msr & MSR_PR) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 3)) == KVM_SC_MAGIC_R3) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 4)) == KVM_SC_MAGIC_R4)) {
+			/* KVM PV hypercalls */
+			kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
+			r = RESUME_GUEST;
 		} else {
+			/* Guest syscalls */
 			vcpu->stat.syscall_exits++;
 			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
 			r = RESUME_GUEST;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 984c461..e7d1216 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -338,7 +338,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		break;
 
 	case BOOKE_INTERRUPT_SYSCALL:
-		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL);
+		if (!(vcpu->arch.shared->msr & MSR_PR) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 3)) == KVM_SC_MAGIC_R3) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 4)) == KVM_SC_MAGIC_R4)) {
+			/* KVM PV hypercalls */
+			kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
+			r = RESUME_GUEST;
+		} else {
+			/* Guest syscalls */
+			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL);
+		}
 		kvmppc_account_exit(vcpu, SYSCALL_EXITS);
 		r = RESUME_GUEST;
 		break;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 454869b..5efde36 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -248,7 +248,16 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->srr1);
 				break;
 			case SPRN_PVR:
-				kvmppc_set_gpr(vcpu, rt, vcpu->arch.pvr); break;
+			{
+				/* Expose PV interface */
+				if (kvmppc_get_gpr(vcpu, rt) == KVM_PVR_PARA) {
+					kvmppc_set_gpr(vcpu, rt, KVM_PVR_PARA);
+					break;
+				}
+
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.pvr);
+				break;
+			}
 			case SPRN_PIR:
 				kvmppc_set_gpr(vcpu, rt, vcpu->vcpu_id); break;
 			case SPRN_MSSSR0:
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 22f6fa2..fe7a1c8 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -42,6 +42,34 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 	       !!(v->arch.pending_exceptions);
 }
 
+int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
+{
+	int nr = kvmppc_get_gpr(vcpu, 5);
+	int r;
+	unsigned long __maybe_unused param1 = kvmppc_get_gpr(vcpu, 6);
+	unsigned long __maybe_unused param2 = kvmppc_get_gpr(vcpu, 7);
+	unsigned long __maybe_unused param3 = kvmppc_get_gpr(vcpu, 8);
+	unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 9);
+
+	if (!(vcpu->arch.shared->msr & MSR_SF)) {
+		/* 32 bit mode */
+		param1 &= 0xffffffff;
+		param2 &= 0xffffffff;
+		param3 &= 0xffffffff;
+		param4 &= 0xffffffff;
+	}
+
+	switch (nr) {
+	case KVM_HC_FEATURES:
+		r = 0;
+		break;
+	default:
+		r = -KVM_ENOSYS;
+		break;
+	}
+
+	return r;
+}
 
 int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index d731092..3b8080e 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -17,6 +17,7 @@
 
 #define KVM_HC_VAPIC_POLL_IRQ		1
 #define KVM_HC_MMU_OP			2
+#define KVM_HC_FEATURES			3
 
 /*
  * hypercalls use architecture specific
-- 
1.6.0.2

  parent reply	other threads:[~2010-06-25 23:25 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-25 23:24 [PATCH 00/26] KVM PPC PV framework Alexander Graf
2010-06-25 23:24 ` [PATCH 01/26] KVM: PPC: Introduce shared page Alexander Graf
2010-06-27 12:12   ` Avi Kivity
2010-06-29  9:54     ` Alexander Graf
2010-06-29 10:55       ` Avi Kivity
2010-06-25 23:24 ` [PATCH 02/26] KVM: PPC: Convert MSR to " Alexander Graf
2010-06-27  8:16   ` Avi Kivity
2010-06-27  9:38     ` Alexander Graf
2010-06-27  9:50       ` Avi Kivity
2010-06-27 10:40         ` Alexander Graf
2010-06-25 23:24 ` [PATCH 03/26] KVM: PPC: Convert DSISR " Alexander Graf
2010-06-25 23:24 ` [PATCH 04/26] KVM: PPC: Convert DAR " Alexander Graf
2010-06-25 23:24 ` [PATCH 05/26] KVM: PPC: Convert SRR0 and SRR1 " Alexander Graf
2010-06-25 23:24 ` [PATCH 06/26] KVM: PPC: Convert SPRG[0-4] " Alexander Graf
2010-06-25 23:24 ` Alexander Graf [this message]
2010-06-25 23:24 ` [PATCH 08/26] KVM: PPC: Add PV guest critical sections Alexander Graf
2010-06-27  8:21   ` Avi Kivity
2010-06-27  9:40     ` Alexander Graf
2010-06-27  9:52       ` Avi Kivity
2010-06-27 10:33         ` Alexander Graf
2010-06-27 10:59           ` Avi Kivity
2010-06-27 11:49             ` Alexander Graf
2010-06-27 11:53               ` Avi Kivity
2010-06-27 12:06                 ` Alexander Graf
2010-06-27 22:03                   ` Benjamin Herrenschmidt
2010-06-27 10:03   ` Avi Kivity
2010-06-27 10:35     ` Alexander Graf
2010-06-25 23:24 ` [PATCH 09/26] KVM: PPC: Add PV guest scratch registers Alexander Graf
2010-06-27  8:22   ` Avi Kivity
2010-06-27  9:41     ` Alexander Graf
2010-06-27  9:53       ` Avi Kivity
2010-06-25 23:24 ` [PATCH 10/26] KVM: PPC: Tell guest about pending interrupts Alexander Graf
2010-06-25 23:24 ` [PATCH 11/26] KVM: PPC: Make RMO a define Alexander Graf
2010-06-26 16:52   ` Segher Boessenkool
2010-06-27  9:08     ` Alexander Graf
2010-06-29  7:32       ` Segher Boessenkool
2010-06-29  7:39         ` Alexander Graf
2010-06-29  7:52           ` Segher Boessenkool
2010-06-29  8:04             ` Alexander Graf
2010-06-25 23:25 ` [PATCH 12/26] KVM: PPC: First magic page steps Alexander Graf
2010-06-27  8:24   ` Avi Kivity
2010-06-27  9:44     ` Alexander Graf
2010-06-25 23:25 ` [PATCH 13/26] KVM: PPC: Magic Page Book3s support Alexander Graf
2010-06-25 23:25 ` [PATCH 14/26] KVM: PPC: Magic Page BookE support Alexander Graf
2010-06-25 23:25 ` [PATCH 15/26] KVM: PPC: Expose magic page support to guest Alexander Graf
2010-06-25 23:25 ` [PATCH 16/26] KVM: Move kvm_guest_init out of generic code Alexander Graf
2010-06-25 23:25 ` [PATCH 17/26] KVM: PPC: Generic KVM PV guest support Alexander Graf
2010-06-25 23:25 ` [PATCH 18/26] KVM: PPC: KVM PV guest stubs Alexander Graf
2010-06-27  8:28   ` Avi Kivity
2010-06-27  9:47     ` Alexander Graf
2010-06-27 10:16       ` Avi Kivity
2010-06-27 10:38         ` Alexander Graf
2010-06-27 22:04       ` Benjamin Herrenschmidt
2010-06-28  4:39   ` Matt Evans
2010-06-28  6:33     ` Alexander Graf
2010-06-28  8:15       ` Avi Kivity
2010-06-28  8:23         ` Alexander Graf
2010-06-28  8:33           ` Avi Kivity
2010-06-25 23:25 ` [PATCH 19/26] KVM: PPC: PV instructions to loads and stores Alexander Graf
2010-06-25 23:25 ` [PATCH 20/26] KVM: PPC: PV tlbsync to nop Alexander Graf
2010-06-25 23:25 ` [PATCH 21/26] KVM: PPC: Introduce kvm_tmp framework Alexander Graf
2010-06-25 23:25 ` [PATCH 22/26] KVM: PPC: PV assembler helpers Alexander Graf
2010-06-25 23:25 ` [PATCH 23/26] KVM: PPC: PV mtmsrd L=1 Alexander Graf
2010-06-25 23:25 ` [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr Alexander Graf
2010-06-26 17:03   ` Segher Boessenkool
2010-06-27  9:10     ` Alexander Graf
2010-06-29  7:37       ` Segher Boessenkool
2010-06-25 23:25 ` [PATCH 25/26] KVM: PPC: PV wrteei Alexander Graf
2010-06-25 23:25 ` [PATCH 26/26] KVM: PPC: Add Documentation about PV interface Alexander Graf
2010-06-27  8:14   ` Avi Kivity
2010-06-27  9:33     ` Alexander Graf
     [not found]       ` <4C270876.2050806%40redhat.com>
2010-06-28  7:18         ` Milton Miller
2010-06-28  7:49           ` Alexander Graf
2010-06-28  8:13             ` Avi Kivity
2010-06-28  8:21               ` Alexander Graf
2010-06-28  8:32                 ` Avi Kivity
2010-06-27  8:34   ` Avi Kivity
2010-06-27  9:49     ` Alexander Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1277508314-915-8-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).