[prev in list] [next in list] [prev in thread] [next in thread]
List: kvm-ppc
Subject: [PATCH 2/6] kvmppc: magic page hypercall - host part
From: ehrhardt () linux ! vnet ! ibm ! com
Date: 2008-09-16 6:27:51
Message-ID: 1221546475-15818-3-git-send-email-ehrhardt () linux ! vnet ! ibm ! com
[Download RAW message or body]
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
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic