All of lore.kernel.org
 help / color / mirror / Atom feed
From: ehrhardt@linux.vnet.ibm.com
To: kvm-ppc@vger.kernel.org
Subject: [PATCH 2/6] kvmppc: magic page hypercall - host part
Date: Tue, 16 Sep 2008 06:27:51 +0000	[thread overview]
Message-ID: <1221546475-15818-3-git-send-email-ehrhardt@linux.vnet.ibm.com> (raw)
In-Reply-To: <1219142205-12062-3-git-send-email-ehrhardt@linux.vnet.ibm.com>

From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

This adds the host part of the magic page registration. This is a memory
area of the guest granted to the host.
The patch just introduces the infrastruture to receive and map the guest paddr.
This is later used storage area a guest can read unprivileged (using binary
rewriting to change privileges instructions).

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
---

[diffstat]
 arch/powerpc/kvm/booke_guest.c |   13 +++++++++++++
 arch/powerpc/kvm/emulate.c     |    9 +++++++++
 arch/powerpc/kvm/powerpc.c     |   20 ++++++++++++++++++--
 include/asm-powerpc/kvm_host.h |    5 +++++
 include/asm-powerpc/kvm_para.h |   24 ++++++++++++++++++++++++
 include/linux/kvm.h            |    5 +++++
 6 files changed, 74 insertions(+), 2 deletions(-)

[diff]

diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
+#include <linux/kvm_para.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
@@ -44,6 +45,7 @@
 	{ "itlb_v",     VCPU_STAT(itlb_virt_miss_exits) },
 	{ "dtlb_r",     VCPU_STAT(dtlb_real_miss_exits) },
 	{ "dtlb_v",     VCPU_STAT(dtlb_virt_miss_exits) },
+	{ "dtlb_pv",    VCPU_STAT(dtlb_pvmem_miss_exits) },
 	{ "sysc",       VCPU_STAT(syscall_exits) },
 	{ "hcall",      VCPU_STAT(hcall_exits) },
 	{ "isi",        VCPU_STAT(isi_exits) },
@@ -344,6 +346,15 @@
 		unsigned long eaddr = vcpu->arch.fault_dear;
 		gfn_t gfn;
 
+		if (kvmppc_is_pvmem(vcpu, eaddr)) {
+			kvmppc_mmu_map(vcpu, eaddr,
+			 vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT,
+			 0, KVM_PPCPV_MAGIC_PAGE_FLAGS);
+			vcpu->stat.dtlb_pvmem_miss_exits++;
+			r = RESUME_GUEST;
+			break;
+		}
+
 		/* Check the guest TLB. */
 		gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
 		if (!gtlbe) {
@@ -495,6 +506,8 @@
 
 	vcpu->arch.shadow_pid = 1;
 
+	vcpu->arch.pvmem = NULL;
+
 	/* Eye-catching number so we know if the guest takes an interrupt
 	 * before it's programmed its own IVPR. */
 	vcpu->arch.ivpr = 0x55550000;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -21,6 +21,7 @@
 #include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/highmem.h>
 #include <linux/kvm_host.h>
 #include <linux/kvm_para.h>
 
@@ -207,8 +208,16 @@
 int kvmppc_do_hypercall(struct kvm_vcpu *vcpu)
 {
 	u32 ret = 0;
+	struct page *pvmem_page;
 
 	switch (vcpu->arch.gpr[11]) {
+	case KVM_HCALL_RESERVE_MAGICPAGE:
+		vcpu->arch.pvmem_gvaddr = vcpu->arch.gpr[3];
+		vcpu->arch.pvmem_gpaddr = vcpu->arch.gpr[4];
+		pvmem_page = gfn_to_page(vcpu->kvm,
+			vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT);
+		vcpu->arch.pvmem = kmap(pvmem_page);
+		break;
 	default:
 		printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[11]);
 		kvmppc_dump_vcpu(vcpu);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
+#include <linux/kvm_para.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
@@ -148,18 +149,33 @@
 	case KVM_CAP_COALESCED_MMIO:
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
+	case KVM_CAP_PPCPV_MAGICPAGE:
+		r = 1;
+		break;
 	default:
 		r = 0;
 		break;
 	}
 	return r;
-
 }
 
 long kvm_arch_dev_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg)
 {
-	return -EINVAL;
+	long r = -EINVAL;
+
+	switch (ioctl) {
+	case KVM_GET_PPCPV_MAGICPAGE_SIZE:
+		if (arg)
+			goto out;
+		r = KVM_PPCPV_MAGIC_PAGE_SIZE;
+		break;
+	default:
+		break;
+	}
+out:
+	return r;
+
 }
 
 int kvm_arch_set_memory_region(struct kvm *kvm,
diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h
--- a/include/asm-powerpc/kvm_host.h
+++ b/include/asm-powerpc/kvm_host.h
@@ -54,6 +54,7 @@
 	u32 itlb_real_miss_exits;
 	u32 itlb_virt_miss_exits;
 	u32 dtlb_real_miss_exits;
+	u32 dtlb_pvmem_miss_exits;
 	u32 dtlb_virt_miss_exits;
 	u32 syscall_exits;
 	u32 hcall_exits;
@@ -152,6 +153,10 @@
 
 	struct timer_list dec_timer;
 	unsigned long pending_exceptions;
+
+	long unsigned int pvmem_gvaddr;
+	long unsigned int pvmem_gpaddr;
+	void *pvmem;	  /* host mapping of pvmem */
 };
 
 struct kvm_guest_debug {
diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h
--- a/include/asm-powerpc/kvm_para.h
+++ b/include/asm-powerpc/kvm_para.h
@@ -22,7 +22,19 @@
 
 #ifdef __KERNEL__
 
+#include <linux/kvm_host.h>
+
 #define KVM_HYPERCALL_BIN 0x44000022
+
+#define KVM_HCALL_RESERVE_MAGICPAGE	0
+
+/*
+ * the guest guarantees alignment to requested size, choosing page size here
+ * easens tlb handling which is handled by host for the magic page
+ */
+#define KVM_PPCPV_MAGIC_PAGE_SIZE	4096
+#define KVM_PPCPV_MAGIC_PAGE_SHIFT	12
+#define KVM_PPCPV_MAGIC_PAGE_FLAGS	0x3f
 
 static inline int kvm_para_available(void)
 {
@@ -36,6 +48,18 @@
 
 extern int kvmppc_do_hypercall(struct kvm_vcpu *vcpu);
 
+static inline int kvmppc_is_pvmem(struct kvm_vcpu *vcpu, unsigned long eaddr)
+{
+	return vcpu->arch.pvmem &&
+		(eaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT) =
+		(vcpu->arch.pvmem_gvaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT);
+}
+
+static inline int kvmppc_has_pvmem(struct kvm_vcpu *vcpu)
+{
+	return !!vcpu->arch.pvmem;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* __POWERPC_KVM_PARA_H__ */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -365,6 +365,10 @@
 #define KVM_TRACE_PAUSE           _IO(KVMIO,  0x07)
 #define KVM_TRACE_DISABLE         _IO(KVMIO,  0x08)
 /*
+ * ioctls for powerpc paravirtualization extensions
+ */
+#define KVM_GET_PPCPV_MAGICPAGE_SIZE       _IO(KVMIO,   0x09)
+/*
  * Extension capability list.
  */
 #define KVM_CAP_IRQCHIP	  0
@@ -382,6 +386,7 @@
 #define KVM_CAP_PV_MMU 13
 #define KVM_CAP_MP_STATE 14
 #define KVM_CAP_COALESCED_MMIO 15
+#define KVM_CAP_PPCPV_MAGICPAGE 16
 
 /*
  * ioctls for VM fds

      parent reply	other threads:[~2008-09-16  6:27 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-19 10:36 [PATCH 2/6] kvmppc: magic page hypercall - host part ehrhardt
2008-08-20 17:52 ` Hollis Blanchard
2008-08-21 13:27 ` Christian Ehrhardt
2008-09-16  6:27 ` ehrhardt [this message]

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=1221546475-15818-3-git-send-email-ehrhardt@linux.vnet.ibm.com \
    --to=ehrhardt@linux.vnet.ibm.com \
    --cc=kvm-ppc@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.