* [PATCH 2/6] kvmppc: magic page hypercall - host part
@ 2008-08-19 10:36 ehrhardt
2008-08-20 17:52 ` Hollis Blanchard
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: ehrhardt @ 2008-08-19 10:36 UTC (permalink / raw)
To: kvm-ppc
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).
The dtlb misses to the paravirtualized area are handled in the host to prevent
dead lock if those misses would occur in the dtlb miss handler. A new exit
counter in the ppc kvm stats cover this new exit type.
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
---
[diffstat]
arch/powerpc/kvm/booke_guest.c | 14 ++++++++++++++
arch/powerpc/kvm/emulate.c | 13 ++++++++++++-
arch/powerpc/kvm/powerpc.c | 19 ++++++++++++++++++-
include/asm-powerpc/kvm_host.h | 6 ++++++
include/asm-powerpc/kvm_para.h | 24 ++++++++++++++++++++++++
include/linux/kvm.h | 5 +++++
6 files changed, 79 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>
@@ -43,6 +44,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) },
{ "isi", VCPU_STAT(isi_exits) },
{ "dsi", VCPU_STAT(dsi_exits) },
@@ -337,6 +339,16 @@
unsigned long eaddr = vcpu->arch.fault_dear;
gfn_t gfn;
+
+ if (vcpu->arch.pvmem && 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) {
@@ -488,6 +500,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>
@@ -195,7 +196,7 @@
get_jiffies_64() + nr_jiffies);
} else {
del_timer(&vcpu->arch.dec_timer);
- }
+}
}
static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
@@ -207,8 +208,18 @@
static int kvmppc_do_hypercall(struct kvm_vcpu *vcpu)
{
int ret = 0;
+ struct page *pvmem_page;
switch (vcpu->arch.gpr[0]) {
+ case KVM_HCALL_RESERVE_MAGICPAGE:
+ vcpu->arch.pvmem_gvaddr = vcpu->arch.gpr[3];
+ vcpu->arch.pvmem_gpaddr = vcpu->arch.gpr[4];
+ down_read(¤t->mm->mmap_sem);
+ pvmem_page = gfn_to_page(vcpu->kvm,
+ vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT);
+ up_read(¤t->mm->mmap_sem);
+ vcpu->arch.pvmem = kmap(pvmem_page);
+ break;
default:
printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[0]);
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,6 +149,9 @@
case KVM_CAP_COALESCED_MMIO:
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break;
+ case KVM_CAP_PPCPV_MAGICPAGE:
+ r = 1;
+ break;
default:
r = 0;
break;
@@ -159,7 +163,20 @@
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 isi_exits;
@@ -151,6 +152,11 @@
struct timer_list dec_timer;
unsigned long pending_exceptions;
+
+ /* guest paravirtualization helpers */
+ long unsigned int pvmem_gvaddr; /* guests address to pvmem to rewrite guest code */
+ long unsigned int pvmem_gpaddr; /* guests physical backing gor the pvmem */
+ void *pvmem; /* host mapping 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 0x03ffffff
+
+#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)
{
@@ -34,6 +46,18 @@
return 0;
}
+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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/6] kvmppc: magic page hypercall - host part
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
2 siblings, 0 replies; 4+ messages in thread
From: Hollis Blanchard @ 2008-08-20 17:52 UTC (permalink / raw)
To: kvm-ppc
On Tue, 2008-08-19 at 12:36 +0200, ehrhardt@linux.vnet.ibm.com wrote:
> 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>
> @@ -43,6 +44,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) },
> { "isi", VCPU_STAT(isi_exits) },
> { "dsi", VCPU_STAT(dsi_exits) },
> @@ -337,6 +339,16 @@
> unsigned long eaddr = vcpu->arch.fault_dear;
> gfn_t gfn;
>
> +
> + if (vcpu->arch.pvmem && 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) {
By the way, when this code is running, what's the rate of this new
counter? How does it compare to the reduction in instruction emulation?
> @@ -488,6 +500,8 @@
>
> vcpu->arch.shadow_pid = 1;
>
> + vcpu->arch.pvmem = NULL;
Isn't the whole structure initialized to 0? I don't think this is
needed.
> /* 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>
>
> @@ -195,7 +196,7 @@
> get_jiffies_64() + nr_jiffies);
> } else {
> del_timer(&vcpu->arch.dec_timer);
> - }
> +}
> }
This looks wrong.
> static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
> @@ -207,8 +208,18 @@
> static int kvmppc_do_hypercall(struct kvm_vcpu *vcpu)
> {
> int ret = 0;
> + struct page *pvmem_page;
>
> switch (vcpu->arch.gpr[0]) {
> + case KVM_HCALL_RESERVE_MAGICPAGE:
> + vcpu->arch.pvmem_gvaddr = vcpu->arch.gpr[3];
> + vcpu->arch.pvmem_gpaddr = vcpu->arch.gpr[4];
> + down_read(¤t->mm->mmap_sem);
> + pvmem_page = gfn_to_page(vcpu->kvm,
> + vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT);
> + up_read(¤t->mm->mmap_sem);
> + vcpu->arch.pvmem = kmap(pvmem_page);
> + break;
> default:
> printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[0]);
> kvmppc_dump_vcpu(vcpu);
Where is vcpu->arch.pvmem unmapped?
What happens if the guest makes repeated KVM_HCALL_RESERVE_MAGICPAGE
hypercalls? Looks like a good way to leak host memory.
Also, if we migrate a guest which has a page registered, the new host
won't have vcpu->arch.pvmem set because the guest doesn't re-invoke the
KVM_HCALL_RESERVE_MAGICPAGE hypercall.
I think we need to put a little more thought into all the corner cases
here.
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/6] kvmppc: magic page hypercall - host part
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
2 siblings, 0 replies; 4+ messages in thread
From: Christian Ehrhardt @ 2008-08-21 13:27 UTC (permalink / raw)
To: kvm-ppc
Hollis Blanchard wrote:
> On Tue, 2008-08-19 at 12:36 +0200, ehrhardt@linux.vnet.ibm.com wrote:
>
>> 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>
>> @@ -43,6 +44,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) },
>> { "isi", VCPU_STAT(isi_exits) },
>> { "dsi", VCPU_STAT(dsi_exits) },
>> @@ -337,6 +339,16 @@
>> unsigned long eaddr = vcpu->arch.fault_dear;
>> gfn_t gfn;
>>
>> +
>> + if (vcpu->arch.pvmem && 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) {
>>
>
> By the way, when this code is running, what's the rate of this new
> counter? How does it compare to the reduction in instruction emulation?
>
>
>> @@ -488,6 +500,8 @@
>>
>> vcpu->arch.shadow_pid = 1;
>>
>> + vcpu->arch.pvmem = NULL;
>>
>
> Isn't the whole structure initialized to 0? I don't think this is
> needed.
>
>
Even if not necessary I would like to keep it. We might change arch
allocation or something else.
This initialization doesn't hurt anyone and is not performance critical.
But it's up to you - if you want me to remove it I'll do that. please
drop me a mail if I should do that.
*Like win popup - "do you really want to delete this line?" - yes/no/maybe
> [...]
>> static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
>> @@ -207,8 +208,18 @@
>> static int kvmppc_do_hypercall(struct kvm_vcpu *vcpu)
>> {
>> int ret = 0;
>> + struct page *pvmem_page;
>>
>> switch (vcpu->arch.gpr[0]) {
>> + case KVM_HCALL_RESERVE_MAGICPAGE:
>> + vcpu->arch.pvmem_gvaddr = vcpu->arch.gpr[3];
>> + vcpu->arch.pvmem_gpaddr = vcpu->arch.gpr[4];
>> + down_read(¤t->mm->mmap_sem);
>> + pvmem_page = gfn_to_page(vcpu->kvm,
>> + vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT);
>> + up_read(¤t->mm->mmap_sem);
>> + vcpu->arch.pvmem = kmap(pvmem_page);
>> + break;
>> default:
>> printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[0]);
>> kvmppc_dump_vcpu(vcpu);
>>
>
> Where is vcpu->arch.pvmem unmapped?
>
atm nowhere - it is persistent once it is registered
> What happens if the guest makes repeated KVM_HCALL_RESERVE_MAGICPAGE
> hypercalls? Looks like a good way to leak host memory.
>
> Also, if we migrate a guest which has a page registered, the new host
> won't have vcpu->arch.pvmem set because the guest doesn't re-invoke the
> KVM_HCALL_RESERVE_MAGICPAGE hypercall.
>
yeah, but I stored gvaddr/gpaddr. If the migration keeps those (and it
should or a lot other things break) we can fix that.
This is bringing me back to our discussion that I wanted to have a
"migration starts to run on new host" hook.
I need to look for that.
> I think we need to put a little more thought into all the corner cases
> here.
>
yeah, lets do that in a brainstorm session next week if you have some time.
It's better to clean corners interactively ;-)
--
Grüsse / regards,
Christian Ehrhardt
IBM Linux Technology Center, Open Virtualization
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/6] kvmppc: magic page hypercall - host part
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
2 siblings, 0 replies; 4+ messages in thread
From: ehrhardt @ 2008-09-16 6:27 UTC (permalink / raw)
To: kvm-ppc
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
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-09-16 6:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox