KVM PPC PV framework
Subsystems (7)
cover KVM PPC PV framework
On PPC we run PR=0 (kernel mode) code in PR=1 (user mode) and don't use the hypervisor extensions.
While that is all great to show that virtualization is possible, there are quite some cases where the emulation overhead of privileged instructions is killing performance.
This patchset tackles exactly that issue. It introduces a paravirtual framework using which KVM and Linux share a page to exchange register state with. That way we don't have to switch to the hypervisor just to change a value of a privileged register.
To prove my point, I ran the same test I did for the MMU optimizations against the PV framework. Here are the results:
[without]
debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello > /dev/null; donereal 0m14.659s user 0m8.967s sys 0m5.688s
[with]
debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello > /dev/null; donereal 0m7.557s user 0m4.121s sys 0m3.426s
So this is a significant performance improvement! I'm quite happy how fast this whole thing becomes :)
I tried to take all comments I've heard from people so far about such a PV framework into account. In case you told me something before that is a no-go and I still did it, please just tell me again.
Now go and have fun with fast VMs on PPC! Get yourself a G5 on ebay and start experiencing the power yourself. - heh
Alexander Graf (26):
KVM: PPC: Introduce shared page
KVM: PPC: Convert MSR to shared page
KVM: PPC: Convert DSISR to shared page
KVM: PPC: Convert DAR to shared page.
KVM: PPC: Convert SRR0 and SRR1 to shared page
KVM: PPC: Convert SPRG[0-4] to shared page
KVM: PPC: Implement hypervisor interface
KVM: PPC: Add PV guest critical sections
KVM: PPC: Add PV guest scratch registers
KVM: PPC: Tell guest about pending interrupts
KVM: PPC: Make RMO a define
KVM: PPC: First magic page steps
KVM: PPC: Magic Page Book3s support
KVM: PPC: Magic Page BookE support
KVM: PPC: Expose magic page support to guest
KVM: Move kvm_guest_init out of generic code
KVM: PPC: Generic KVM PV guest support
KVM: PPC: KVM PV guest stubs
KVM: PPC: PV instructions to loads and stores
KVM: PPC: PV tlbsync to nop
KVM: PPC: Introduce kvm_tmp framework
KVM: PPC: PV assembler helpers
KVM: PPC: PV mtmsrd L=1
KVM: PPC: PV mtmsrd L=0 and mtmsr
KVM: PPC: PV wrteei
KVM: PPC: Add Documentation about PV interface
Documentation/kvm/ppc-pv.txt | 164 ++++++++++++ arch/powerpc/include/asm/kvm_book3s.h | 1 - arch/powerpc/include/asm/kvm_host.h | 14 +- arch/powerpc/include/asm/kvm_para.h | 121 +++++++++- arch/powerpc/include/asm/kvm_ppc.h | 1 + arch/powerpc/kernel/Makefile | 2 + arch/powerpc/kernel/asm-offsets.c | 18 ++- arch/powerpc/kernel/kvm.c | 399 ++++++++++++++++++++++++++++++ arch/powerpc/kernel/kvm_emul.S | 237 ++++++++++++++++++ arch/powerpc/kvm/44x.c | 7 + arch/powerpc/kvm/44x_tlb.c | 8 +- arch/powerpc/kvm/book3s.c | 162 ++++++++----- arch/powerpc/kvm/book3s_32_mmu.c | 28 ++- arch/powerpc/kvm/book3s_32_mmu_host.c | 16 +- arch/powerpc/kvm/book3s_64_mmu.c | 42 +++- arch/powerpc/kvm/book3s_64_mmu_host.c | 16 +- arch/powerpc/kvm/book3s_emulate.c | 25 +- arch/powerpc/kvm/book3s_paired_singles.c | 11 +- arch/powerpc/kvm/booke.c | 110 +++++++-- arch/powerpc/kvm/booke.h | 6 +- arch/powerpc/kvm/booke_emulate.c | 14 +- arch/powerpc/kvm/booke_interrupts.S | 3 +- arch/powerpc/kvm/e500.c | 7 + arch/powerpc/kvm/e500_tlb.c | 31 ++- arch/powerpc/kvm/e500_tlb.h | 2 +- arch/powerpc/kvm/emulate.c | 47 +++- arch/powerpc/kvm/powerpc.c | 42 +++- arch/powerpc/platforms/Kconfig | 10 + arch/x86/include/asm/kvm_para.h | 6 + include/linux/kvm_para.h | 7 +- 30 files changed, 1383 insertions(+), 174 deletions(-) create mode 100644 Documentation/kvm/ppc-pv.txt create mode 100644 arch/powerpc/kernel/kvm.c create mode 100644 arch/powerpc/kernel/kvm_emul.S
PATCH 1/26 KVM: PPC: Introduce shared page
For transparent variable sharing between the hypervisor and guest, I introduce a shared page. This shared page will contain all the registers the guest can read and write safely without exiting guest context.
This patch only implements the stubs required for the basic structure of the shared page. The actual register moving follows.
--- arch/powerpc/include/asm/kvm_host.h | 2 ++ arch/powerpc/include/asm/kvm_para.h | 5 +++++ arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kvm/44x.c | 7 +++++++ arch/powerpc/kvm/book3s.c | 7 +++++++ arch/powerpc/kvm/e500.c | 7 +++++++ 6 files changed, 29 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/kvm_host.h +2 -0
@@ -25,6 +25,7 @@#include <linux/interrupt.h> #include <linux/types.h> #include <linux/kvm_types.h> +#include <linux/kvm_para.h> #include <asm/kvm_asm.h> #define KVM_MAX_VCPUS 1
@@ -289,6 +290,7 @@ struct kvm_vcpu_arch {struct tasklet_struct tasklet;u64 dec_jiffies;unsigned long pending_exceptions; +struct kvm_vcpu_arch_shared *shared;#ifdef CONFIG_PPC_BOOK3S struct kmem_cache *hpte_cache;
arch/powerpc/include/asm/kvm_para.h +5 -0
@@ -20,6 +20,11 @@#ifndef __POWERPC_KVM_PARA_H__#define __POWERPC_KVM_PARA_H__ +#include <linux/types.h> + +struct kvm_vcpu_arch_shared { +}; +#ifdef __KERNEL__static inline int kvm_para_available (void )
arch/powerpc/kernel/asm-offsets.c +1 -0
@@ -400,6 +400,7 @@ int main(void) DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6)); DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7)); DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid)); + DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));/* book3s */ #ifdef CONFIG_PPC_BOOK3S
arch/powerpc/kvm/44x.c +7 -0
@@ -123,8 +123,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto free_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; +return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_vcpu:kmem_cache_free (kvm_vcpu_cache, vcpu_44x); out:
@@ -135,6 +141,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_44x); }
arch/powerpc/kvm/book3s.c +7 -0
@@ -1247,6 +1247,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto free_shadow_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; + vcpu->arch.host_retip = kvm_return_point; vcpu->arch.host_msr =mfmsr ();#ifdef CONFIG_PPC_BOOK3S_64
@@ -1277,6 +1281,8 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_shadow_vcpu:kfree (vcpu_book3s->shadow_vcpu); free_vcpu:
@@ -1289,6 +1295,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_book3s *vcpu_book3s =to_book3s (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kfree (vcpu_book3s->shadow_vcpu);vfree (vcpu_book3s);
arch/powerpc/kvm/e500.c +7 -0
@@ -117,8 +117,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto uninit_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_tlb; +return vcpu; +uninit_tlb: +kvmppc_e500_tlb_uninit (vcpu_e500); uninit_vcpu:kvm_vcpu_uninit (vcpu); free_vcpu:
@@ -131,6 +137,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_e500 *vcpu_e500 =to_e500 (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvmppc_e500_tlb_uninit (vcpu_e500);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_e500);
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-2-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 01/26] KVM: PPC: Introduce shared page
Quoted 84 lines · Alexander Graf
For transparent variable sharing between the hypervisor and guest, I introduce a shared page. This shared page will contain all the registers the guest can read and write safely without exiting guest context.
This patch only implements the stubs required for the basic structure of the shared page. The actual register moving follows.
arch/powerpc/kvm/44x.c +7
-0@@ -123,8 +123,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto free_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; +return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_vcpu:kmem_cache_free (kvm_vcpu_cache, vcpu_44x); out:@@ -135,6 +141,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_44x); }arch/powerpc/kvm/book3s.c +7
-0@@ -1247,6 +1247,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto free_shadow_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; + vcpu->arch.host_retip = kvm_return_point; vcpu->arch.host_msr =mfmsr ();#ifdef CONFIG_PPC_BOOK3S_64 @@ -1277,6 +1281,8 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_shadow_vcpu:kfree (vcpu_book3s->shadow_vcpu); free_vcpu:@@ -1289,6 +1295,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_book3s *vcpu_book3s =to_book3s (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kfree (vcpu_book3s->shadow_vcpu);vfree (vcpu_book3s);arch/powerpc/kvm/e500.c +6
-0@@ -117,8 +117,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto uninit_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_tlb; +return vcpu; +uninit_tlb: +kvmppc_e500_tlb_uninit (vcpu_e500); uninit_vcpu:kvm_vcpu_uninit (vcpu); free_vcpu:
arch/powerpc/kvm/e500.c void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) · line 143
Quoted 7 lines
arch/powerpc/kvm/e500.c +1
-0@@ -131,6 +137,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_e500 *vcpu_e500 =to_e500 (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvmppc_e500_tlb_uninit (vcpu_e500);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_e500);
Code repeats 3x. Share please.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 01/26] KVM: PPC: Introduce shared page
Quoted 94 lines · Avi Kivity
Quoted 93 lines · Alexander Graf
For transparent variable sharing between the hypervisor and guest, I introduce
a shared page. This shared page will contain all the registers the guest can
read and write safely without exiting guest context.This patch only implements the stubs required for the basic structure of the
shared page. The actual register moving follows.arch/powerpc/kvm/44x.c +6
-0@@ -123,8 +123,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) if (err) goto free_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; +return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_vcpu:kmem_cache_free (kvm_vcpu_cache, vcpu_44x);out:
arch/powerpc/kvm/44x.c +1
-0@@ -135,6 +141,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_44x); }arch/powerpc/kvm/book3s.c +4
-0@@ -1247,6 +1247,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)if (err) goto free_shadow_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_vcpu; + vcpu->arch.host_retip = kvm_return_point; vcpu->arch.host_msr =mfmsr ();#ifdef CONFIG_PPC_BOOK3S_64arch/powerpc/kvm/book3s.c +2
-0@@ -1277,6 +1281,8 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) return vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_shadow_vcpu:kfree (vcpu_book3s->shadow_vcpu);
free_vcpu:arch/powerpc/kvm/book3s.c +1
-0@@ -1289,6 +1295,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_book3s *vcpu_book3s =to_book3s (vcpu); +free_page ((unsigned long )vcpu->arch.shared);kvm_vcpu_uninit (vcpu);kfree (vcpu_book3s->shadow_vcpu);vfree (vcpu_book3s);arch/powerpc/kvm/e500.c +6
-0@@ -117,8 +117,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) if (err) goto uninit_vcpu; + vcpu->arch.shared = (void *)__get_free_page (GFP_KERNEL |__GFP_ZERO); +if (!vcpu->arch.shared) + goto uninit_tlb; +return vcpu; +uninit_tlb: +kvmppc_e500_tlb_uninit (vcpu_e500); uninit_vcpu:kvm_vcpu_uninit (vcpu);
free_vcpu:arch/powerpc/kvm/e500.c +0
-0@@ -131,6 +137,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) {struct kvmppc_vcpu_e500 *vcpu_e500 =to_e500 (vcpu);
Quoted 7 lines
arch/powerpc/kvm/e500.c void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) · line 143
Quoted 5 lines
arch/powerpc/kvm/e500.c +1
-0+free_page ((unsigned long )vcpu->arch.shared);kvmppc_e500_tlb_uninit (vcpu_e500);kvm_vcpu_uninit (vcpu);kmem_cache_free (kvm_vcpu_cache, vcpu_e500);Code repeats 3x. Share please.
Looking at this again, I could combine the 3 lines of init code into 3 lines of code that do a generic function call and then error checking. And I could convert the one free_page line with one function call that would free the page. Is there a real gain behind this?
Alex
Re: [PATCH 01/26] KVM: PPC: Introduce shared page
Quoted 9 lines · Alexander Graf
Quoted 3 lines
Code repeats 3x. Share please.
Looking at this again, I could combine the 3 lines of init code into 3 lines of code that do a generic function call and then error checking. And I could convert the one
free_pageline with one function call that would free the page. Is there a real gain behind this?
Looks marginal, yes. It will help if initialization is expanded later, but currently it doesn't help much.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-1-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
PATCH 2/26 KVM: PPC: Convert MSR to shared page
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the guest implementation that follows later for reference.
--- arch/powerpc/include/asm/kvm_host.h | 1 - arch/powerpc/include/asm/kvm_para.h | 1 + arch/powerpc/kernel/asm-offsets.c | 2 +- arch/powerpc/kvm/44x_tlb.c | 8 ++-- arch/powerpc/kvm/book3s.c | 65 ++++++++++++++++-------------- arch/powerpc/kvm/book3s_32_mmu.c | 12 +++--- arch/powerpc/kvm/book3s_32_mmu_host.c | 4 +- arch/powerpc/kvm/book3s_64_mmu.c | 12 +++--- arch/powerpc/kvm/book3s_64_mmu_host.c | 4 +- arch/powerpc/kvm/book3s_emulate.c | 9 ++-- arch/powerpc/kvm/book3s_paired_singles.c | 7 ++- arch/powerpc/kvm/booke.c | 20 +++++----- arch/powerpc/kvm/booke.h | 6 +- arch/powerpc/kvm/booke_emulate.c | 6 +- arch/powerpc/kvm/booke_interrupts.S | 3 +- arch/powerpc/kvm/e500_tlb.c | 12 +++--- arch/powerpc/kvm/e500_tlb.h | 2 +- arch/powerpc/kvm/powerpc.c | 3 +- 18 files changed, 93 insertions(+), 84 deletions(-)
arch/powerpc/include/asm/kvm_host.h +0 -1
@@ -210,7 +210,6 @@ struct kvm_vcpu_arch {u32 cr;#endif -ulong msr;#ifdef CONFIG_PPC_BOOK3S ulong shadow_msr;ulong hflags;
arch/powerpc/include/asm/kvm_para.h +1 -0
@@ -23,6 +23,7 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 msr; };#ifdef __KERNEL__
arch/powerpc/kernel/asm-offsets.c +1 -1
@@ -394,13 +394,13 @@ int main(void) DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); - DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr)); DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4)); DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5)); DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6)); DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7)); DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid)); DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared)); +DEFINE (VCPU_SHARED_MSR , offsetof(struct kvm_vcpu_arch_shared , msr));/* book3s */ #ifdef CONFIG_PPC_BOOK3S
arch/powerpc/kvm/44x_tlb.c +4 -4
@@ -221,14 +221,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,int kvmppc_mmu_itlb_index (struct kvm_vcpu *vcpu,gva_t eaddr) { -unsigned int as = !!(vcpu->arch.msr &MSR_IS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_IS );return kvmppc_44x_tlb_index (vcpu, eaddr, vcpu->arch.pid, as); }int kvmppc_mmu_dtlb_index (struct kvm_vcpu *vcpu,gva_t eaddr) { -unsigned int as = !!(vcpu->arch.msr &MSR_DS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_DS );return kvmppc_44x_tlb_index (vcpu, eaddr, vcpu->arch.pid, as); }
@@ -353,7 +353,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, stlbe.word1 = (hpaddr &0xfffffc00 ) | ((hpaddr >>32 ) &0xf ); stlbe.word2 =kvmppc_44x_tlb_shadow_attrib (flags, - vcpu->arch.msr &MSR_PR ); + vcpu->arch.shared->msr &MSR_PR ); stlbe.tid = !(asid &0xff );/* Keep track of the reference so we can properly release it later. */
@@ -422,7 +422,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,/* Does it match current guest AS? */ /* XXX what about IS != DS? */ -if (get_tlb_ts (tlbe) != !!(vcpu->arch.msr &MSR_IS )) +if (get_tlb_ts (tlbe) != !!(vcpu->arch.shared->msr &MSR_IS ))return 0 ; gpa =get_tlb_raddr (tlbe);
arch/powerpc/kvm/book3s.c +35 -30
192 lines not on this page · raw message
arch/powerpc/kvm/book3s_32_mmu.c +6 -6
@@ -133,7 +133,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,else bat = &vcpu_book3s->ibat[i]; -if (vcpu->arch.msr &MSR_PR ) { +if (vcpu->arch.shared->msr &MSR_PR ) {if (!bat->vp)continue ; }else {
@@ -214,8 +214,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, pte->raddr = (pteg[i+1 ] & ~(0xFFFULL )) | (eaddr &0xFFF ); pp = pteg[i+1 ] &3 ; -if ((sre->Kp && (vcpu->arch.msr &MSR_PR )) || - (sre->Ks && !(vcpu->arch.msr &MSR_PR ))) +if ((sre->Kp && (vcpu->arch.shared->msr &MSR_PR )) || + (sre->Ks && !(vcpu->arch.shared->msr &MSR_PR ))) pp |=4 ; pte->may_write = false;
@@ -334,7 +334,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,struct kvmppc_sr *sr;u64 gvsid = esid; -if (vcpu->arch.msr & (MSR_DR |MSR_IR )) { +if (vcpu->arch.shared->msr & (MSR_DR |MSR_IR )) { sr =find_sr (to_book3s (vcpu), ea);if (sr->valid) gvsid = sr->vsid;
@@ -343,7 +343,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,/* In case we only have one of MSR_IR or MSR_DR set, let's put that in the real-mode context (and hope RM doesn't access high memory) */ -switch (vcpu->arch.msr & (MSR_DR |MSR_IR )) { +switch (vcpu->arch.shared->msr & (MSR_DR |MSR_IR )) {case 0 : *vsid =VSID_REAL | esid;break ;
@@ -363,7 +363,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,BUG (); } -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) *vsid |=VSID_PR ;return 0 ;
arch/powerpc/kvm/book3s_32_mmu_host.c +2 -2
@@ -86,7 +86,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)struct kvmppc_sid_map *map;u16 sid_map_mask; -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) gvsid |=VSID_PR ; sid_map_mask =kvmppc_sid_hash (vcpu, gvsid);
@@ -253,7 +253,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)u16 sid_map_mask;static int backwards_map =0 ; -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) gvsid |=VSID_PR ;/* We might get collisions that trap in preceding order, so let's
arch/powerpc/kvm/book3s_64_mmu.c +6 -6
@@ -180,9 +180,9 @@ do_second: goto no_page_found; } -if ((vcpu->arch.msr &MSR_PR ) && slbe->Kp) +if ((vcpu->arch.shared->msr &MSR_PR ) && slbe->Kp) key =4 ; -else if (!(vcpu->arch.msr &MSR_PR ) && slbe->Ks) +else if (!(vcpu->arch.shared->msr &MSR_PR ) && slbe->Ks) key =4 ;for (i=0 ; i<16 ; i+=2 ) {
@@ -381,7 +381,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)for (i =1 ; i < vcpu_book3s->slb_nr; i++) vcpu_book3s->slb[i].valid = false; -if (vcpu->arch.msr &MSR_IR ) { +if (vcpu->arch.shared->msr &MSR_IR ) {kvmppc_mmu_flush_segments (vcpu);kvmppc_mmu_map_segment (vcpu,kvmppc_get_pc (vcpu)); }
@@ -446,13 +446,13 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,struct kvmppc_slb *slb;u64 gvsid = esid; -if (vcpu->arch.msr & (MSR_DR |MSR_IR )) { +if (vcpu->arch.shared->msr & (MSR_DR |MSR_IR )) { slb =kvmppc_mmu_book3s_64_find_slbe (to_book3s (vcpu), ea);if (slb) gvsid = slb->vsid; } -switch (vcpu->arch.msr & (MSR_DR |MSR_IR )) { +switch (vcpu->arch.shared->msr & (MSR_DR |MSR_IR )) {case 0 : *vsid =VSID_REAL | esid;break ;
@@ -473,7 +473,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,break ; } -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) *vsid |=VSID_PR ;return 0 ;
arch/powerpc/kvm/book3s_64_mmu_host.c +2 -2
@@ -66,7 +66,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)struct kvmppc_sid_map *map;u16 sid_map_mask; -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) gvsid |=VSID_PR ; sid_map_mask =kvmppc_sid_hash (vcpu, gvsid);
@@ -191,7 +191,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)u16 sid_map_mask;static int backwards_map =0 ; -if (vcpu->arch.msr &MSR_PR ) +if (vcpu->arch.shared->msr &MSR_PR ) gvsid |=VSID_PR ;/* We might get collisions that trap in preceding order, so let's
arch/powerpc/kvm/book3s_emulate.c +5 -4
@@ -86,14 +86,15 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,case 31 :switch (get_xop (inst)) {case OP_31_XOP_MFMSR : -kvmppc_set_gpr (vcpu,get_rt (inst), vcpu->arch.msr); +kvmppc_set_gpr (vcpu,get_rt (inst), + vcpu->arch.shared->msr);break ;case OP_31_XOP_MTMSRD : {ulong rs =kvmppc_get_gpr (vcpu,get_rs (inst));if (inst &0x10000 ) { - vcpu->arch.msr &= ~(MSR_RI |MSR_EE ); - vcpu->arch.msr |= rs & (MSR_RI |MSR_EE ); + vcpu->arch.shared->msr &= ~(MSR_RI |MSR_EE ); + vcpu->arch.shared->msr |= rs & (MSR_RI |MSR_EE ); }else kvmppc_set_msr (vcpu, rs);break ;
@@ -204,7 +205,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, ra =kvmppc_get_gpr (vcpu,get_ra (inst)); addr = (ra + rb) & ~31ULL ; -if (!(vcpu->arch.msr &MSR_SF )) +if (!(vcpu->arch.shared->msr &MSR_SF )) addr &=0xffffffff ; vaddr = addr;
arch/powerpc/kvm/book3s_paired_singles.c +4 -3
@@ -165,9 +165,10 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)static void kvmppc_inject_pf (struct kvm_vcpu *vcpu,ulong eaddr,bool is_store) {u64 dsisr; +struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared; - vcpu->arch.msr =kvmppc_set_field (vcpu->arch.msr,33 ,36 ,0 ); - vcpu->arch.msr =kvmppc_set_field (vcpu->arch.msr,42 ,47 ,0 ); + shared->msr =kvmppc_set_field (shared->msr,33 ,36 ,0 ); + shared->msr =kvmppc_set_field (shared->msr,42 ,47 ,0 ); vcpu->arch.dear = eaddr;/* Page Fault */ dsisr =kvmppc_set_field (0 ,33 ,33 ,1 );
@@ -658,7 +659,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)if (!kvmppc_inst_is_paired_single (vcpu, inst))return EMULATE_FAIL ; -if (!(vcpu->arch.msr &MSR_FP )) { +if (!(vcpu->arch.shared->msr &MSR_FP )) {kvmppc_book3s_queue_irqprio (vcpu,BOOK3S_INTERRUPT_FP_UNAVAIL );return EMULATE_AGAIN ; }
arch/powerpc/kvm/booke.c +10 -10
@@ -62,7 +62,7 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) {int i; -printk ("pc: %08lx msr: %08lx\n" , vcpu->arch.pc, vcpu->arch.msr); +printk ("pc: %08lx msr: %08llx\n" , vcpu->arch.pc, vcpu->arch.shared->msr);printk ("lr: %08lx ctr: %08lx\n" , vcpu->arch.lr, vcpu->arch.ctr);printk ("srr0: %08lx srr1: %08lx\n" , vcpu->arch.srr0, vcpu->arch.srr1);
@@ -169,34 +169,34 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,break ;case BOOKE_IRQPRIO_CRITICAL :case BOOKE_IRQPRIO_WATCHDOG : - allowed = vcpu->arch.msr &MSR_CE ; + allowed = vcpu->arch.shared->msr &MSR_CE ; msr_mask =MSR_ME ;break ;case BOOKE_IRQPRIO_MACHINE_CHECK : - allowed = vcpu->arch.msr &MSR_ME ; + allowed = vcpu->arch.shared->msr &MSR_ME ; msr_mask =0 ;break ;case BOOKE_IRQPRIO_EXTERNAL :case BOOKE_IRQPRIO_DECREMENTER :case BOOKE_IRQPRIO_FIT : - allowed = vcpu->arch.msr &MSR_EE ; + allowed = vcpu->arch.shared->msr &MSR_EE ; msr_mask =MSR_CE |MSR_ME |MSR_DE ;break ;case BOOKE_IRQPRIO_DEBUG : - allowed = vcpu->arch.msr &MSR_DE ; + allowed = vcpu->arch.shared->msr &MSR_DE ; msr_mask =MSR_ME ;break ; }if (allowed) { vcpu->arch.srr0 = vcpu->arch.pc; - vcpu->arch.srr1 = vcpu->arch.msr; + vcpu->arch.srr1 = vcpu->arch.shared->msr; vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];if (update_esr == true) vcpu->arch.esr = vcpu->arch.queued_esr;if (update_dear == true) vcpu->arch.dear = vcpu->arch.queued_dear; -kvmppc_set_msr (vcpu, vcpu->arch.msr & msr_mask); +kvmppc_set_msr (vcpu, vcpu->arch.shared->msr & msr_mask);clear_bit (priority, &vcpu->arch.pending_exceptions); }
@@ -265,7 +265,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,break ;case BOOKE_INTERRUPT_PROGRAM : -if (vcpu->arch.msr &MSR_PR ) { +if (vcpu->arch.shared->msr &MSR_PR ) {/* Program traps generated by user-level software must be handled * by the guest kernel. */ kvmppc_core_queue_program (vcpu, vcpu->arch.fault_esr);
@@ -467,7 +467,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,int kvm_arch_vcpu_setup (struct kvm_vcpu *vcpu) { vcpu->arch.pc =0 ; - vcpu->arch.msr =0 ; + vcpu->arch.shared->msr =0 ;kvmppc_set_gpr (vcpu,1 , (16 <<20 ) -8 );/* -8 for the callee-save LR slot */ vcpu->arch.shadow_pid =1 ;
@@ -490,7 +490,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->ctr = vcpu->arch.ctr; regs->lr = vcpu->arch.lr; regs->xer =kvmppc_get_xer (vcpu); - regs->msr = vcpu->arch.msr; + regs->msr = vcpu->arch.shared->msr; regs->srr0 = vcpu->arch.srr0; regs->srr1 = vcpu->arch.srr1; regs->pid = vcpu->arch.pid;
arch/powerpc/kvm/booke.h +3 -3
@@ -54,12 +54,12 @@ extern unsigned long kvmppc_booke_handlers;* changing. */ static inline void kvmppc_set_msr (struct kvm_vcpu *vcpu,u32 new_msr) { -if ((new_msr &MSR_PR ) != (vcpu->arch.msr &MSR_PR )) +if ((new_msr &MSR_PR ) != (vcpu->arch.shared->msr &MSR_PR ))kvmppc_mmu_priv_switch (vcpu, new_msr &MSR_PR ); - vcpu->arch.msr = new_msr; + vcpu->arch.shared->msr = new_msr; -if (vcpu->arch.msr &MSR_WE ) { +if (vcpu->arch.shared->msr &MSR_WE ) {kvm_vcpu_block (vcpu);kvmppc_set_exit_type (vcpu,EMULATED_MTMSRWE_EXITS ); };
arch/powerpc/kvm/booke_emulate.c +3 -3
@@ -62,7 +62,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,case OP_31_XOP_MFMSR : rt =get_rt (inst); -kvmppc_set_gpr (vcpu, rt, vcpu->arch.msr); +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->msr);kvmppc_set_exit_type (vcpu,EMULATED_MFMSR_EXITS );break ;
@@ -74,13 +74,13 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,case OP_31_XOP_WRTEE : rs =get_rs (inst); - vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE ) + vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE ) | (kvmppc_get_gpr (vcpu, rs) &MSR_EE );kvmppc_set_exit_type (vcpu,EMULATED_WRTEE_EXITS );break ;case OP_31_XOP_WRTEEI : - vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE ) + vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE ) | (inst &MSR_EE );kvmppc_set_exit_type (vcpu,EMULATED_WRTEE_EXITS );break ;
arch/powerpc/kvm/booke_interrupts.S +2 -1
@@ -415,7 +415,8 @@ lightweight_exit: lwz r8, VCPU_GPR(r8)(r4) lwz r3, VCPU_PC(r4) mtsrr0 r3 - lwz r3, VCPU_MSR(r4) + lwz r3, VCPU_SHARED(r4) + lwz r3, VCPU_SHARED_MSR(r3) oris r3, r3, KVMPPC_MSR_MASK@h ori r3, r3, KVMPPC_MSR_MASK@l mtsrr1 r3
arch/powerpc/kvm/e500_tlb.c +6 -6
@@ -317,10 +317,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID; stlbe->mas2 = (gvaddr &MAS2_EPN ) |e500_shadow_mas2_attrib (gtlbe->mas2, - vcpu_e500->vcpu.arch.msr &MSR_PR ); + vcpu_e500->vcpu.arch.shared->msr &MSR_PR ); stlbe->mas3 = (hpaddr &MAS3_RPN ) |e500_shadow_mas3_attrib (gtlbe->mas3, - vcpu_e500->vcpu.arch.msr &MSR_PR ); + vcpu_e500->vcpu.arch.shared->msr &MSR_PR ); stlbe->mas7 = (hpaddr >>32 ) &MAS7_RPN ; trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
@@ -579,28 +579,28 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)int kvmppc_mmu_itlb_index (struct kvm_vcpu *vcpu,gva_t eaddr) { -unsigned int as = !!(vcpu->arch.msr &MSR_IS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_IS );return kvmppc_e500_tlb_search (vcpu, eaddr,get_cur_pid (vcpu), as); }int kvmppc_mmu_dtlb_index (struct kvm_vcpu *vcpu,gva_t eaddr) { -unsigned int as = !!(vcpu->arch.msr &MSR_DS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_DS );return kvmppc_e500_tlb_search (vcpu, eaddr,get_cur_pid (vcpu), as); }void kvmppc_mmu_itlb_miss (struct kvm_vcpu *vcpu) { -unsigned int as = !!(vcpu->arch.msr &MSR_IS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_IS );kvmppc_e500_deliver_tlb_miss (vcpu, vcpu->arch.pc, as); }void kvmppc_mmu_dtlb_miss (struct kvm_vcpu *vcpu) { -unsigned int as = !!(vcpu->arch.msr &MSR_DS ); +unsigned int as = !!(vcpu->arch.shared->msr &MSR_DS );kvmppc_e500_deliver_tlb_miss (vcpu, vcpu->arch.fault_dear, as); }
arch/powerpc/kvm/e500_tlb.h +1 -1
@@ -171,7 +171,7 @@ static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,/* Does it match current guest AS? */ /* XXX what about IS != DS? */ -if (get_tlb_ts (tlbe) != !!(vcpu->arch.msr &MSR_IS )) +if (get_tlb_ts (tlbe) != !!(vcpu->arch.shared->msr &MSR_IS ))return 0 ; gpa =get_tlb_raddr (tlbe);
arch/powerpc/kvm/powerpc.c +2 -1
@@ -38,7 +38,8 @@int kvm_arch_vcpu_runnable (struct kvm_vcpu *v) { -return !(v->arch.msr &MSR_WE ) || !!(v->arch.pending_exceptions); +return !(v->arch.shared->msr &MSR_WE ) || + !!(v->arch.pending_exceptions); }
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-3-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
Quoted 10 lines · Alexander Graf
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the guest implementation that follows later for reference.
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the documentation.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
Am 27.06.2010 um 10:16 schrieb Avi Kivity <[email protected]>:
Quoted 13 lines · Alexander Graf
Quoted 10 lines
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the guest implementation that follows later for reference.
Quoted 3 lines
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the documentation.
*shrug* since we're writing open source I don't mind telling people to read code for a reference implemenration. If well written, that's more comprehensible than documentation anyways :).
But either way, you can take a look at both - documentation and code, yes.
What I really meant here is that the list of registers we patch should be taken from the patch code. I didn't want to write out all of them in the description.
Alex
A message that is not in the archive (sent off-list or not yet received): 651805F1-54AB-466F-8D23-D053D8082177-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
Quoted 16 lines · Alexander Graf
Am 27.06.2010 um 10:16 schrieb Avi Kivity <[email protected]>:
Quoted 13 lines · Alexander Graf
Quoted 10 lines
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the guest implementation that follows later for reference.
Quoted 5 lines
Quoted 3 lines
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the documentation.
*shrug* since we're writing open source I don't mind telling people to read code for a reference implemenration.
It's impossible to infer from the source what's a guaranteed part of the interface and what is just an implementation artifact. So people rely on implementation artifacts (or even bugs) and that reduces our ability to change things.
Quoted 1 line
If well written, that's more comprehensible than documentation anyways :).
If the documentation is poorly written, yes.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
Am 27.06.2010 um 11:50 schrieb Avi Kivity <[email protected]>:
Quoted 21 lines · Alexander Graf
Quoted 20 lines
Am 27.06.2010 um 10:16 schrieb Avi Kivity <[email protected]>:
Quoted 16 lines · Alexander Graf
Quoted 10 lines
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the guest implementation that follows later for reference.
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the documentation.
Quoted 7 lines
Quoted 1 line
*shrug* since we're writing open source I don't mind telling people to read code for a reference implemenration.
It's impossible to infer from the source what's a guaranteed part of the interface and what is just an implementation artifact. So people rely on implementation artifacts (or even bugs) and that reduces our ability to change things.
Quoted 1 line
If well written, that's more comprehensible than documentation anyways :).
If the documentation is poorly written, yes.
I think I start to agree. I guess i should just list all fields of the MSR that are ok to modify inside the guest context.
Alex
PATCH 4/26 KVM: PPC: Convert DAR to shared page.
In reply to a message not in the archiveThe DAR register contains the address a data page fault occured at. This register behaves pretty much like a simple data storage register that gets written to on data faults. There is no hypervisor interaction required on read or write.
This patch converts all users of the current field to the shared page.
--- arch/powerpc/include/asm/kvm_host.h | 1 - arch/powerpc/include/asm/kvm_para.h | 1 + arch/powerpc/kvm/book3s.c | 14 +++++++------- arch/powerpc/kvm/book3s_emulate.c | 6 +++--- arch/powerpc/kvm/book3s_paired_singles.c | 2 +- arch/powerpc/kvm/booke.c | 2 +- arch/powerpc/kvm/booke_emulate.c | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-)
arch/powerpc/include/asm/kvm_host.h +0 -1
@@ -230,7 +230,6 @@ struct kvm_vcpu_arch {ulong csrr1;ulong dsrr0;ulong dsrr1; -ulong dear;ulong esr;u32 dec;u32 decar;
arch/powerpc/include/asm/kvm_para.h +1 -0
@@ -23,6 +23,7 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 dar;__u64 msr;__u32 dsisr; };
arch/powerpc/kvm/book3s.c +7 -7
@@ -594,14 +594,14 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,if (page_found == -ENOENT ) {/* Page not found in guest PTE entries */ - vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); + vcpu->arch.shared->dar =kvmppc_get_fault_dar (vcpu); vcpu->arch.shared->dsisr =to_svcpu (vcpu)->fault_dsisr; vcpu->arch.shared->msr |= (to_svcpu (vcpu)->shadow_srr1 &0x00000000f8000000ULL );kvmppc_book3s_queue_irqprio (vcpu, vec); }else if (page_found == -EPERM ) {/* Storage protection */ - vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); + vcpu->arch.shared->dar =kvmppc_get_fault_dar (vcpu); vcpu->arch.shared->dsisr =to_svcpu (vcpu)->fault_dsisr & ~DSISR_NOHPTE ; vcpu->arch.shared->dsisr |=DSISR_PROTFAULT ;
@@ -610,7 +610,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,kvmppc_book3s_queue_irqprio (vcpu, vec); }else if (page_found == -EINVAL ) {/* Page not found in guest SLB */ - vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); + vcpu->arch.shared->dar =kvmppc_get_fault_dar (vcpu);kvmppc_book3s_queue_irqprio (vcpu, vec +0x80 ); }else if (!is_mmio &&kvmppc_visible_gfn (vcpu, pte.raddr >>PAGE_SHIFT )) {
@@ -867,17 +867,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,if (to_svcpu (vcpu)->fault_dsisr &DSISR_NOHPTE ) { r =kvmppc_handle_pagefault (run, vcpu, dar, exit_nr); }else { - vcpu->arch.dear = dar; + vcpu->arch.shared->dar = dar; vcpu->arch.shared->dsisr =to_svcpu (vcpu)->fault_dsisr;kvmppc_book3s_queue_irqprio (vcpu, exit_nr); -kvmppc_mmu_pte_flush (vcpu, vcpu->arch.dear, ~0xFFFUL ); +kvmppc_mmu_pte_flush (vcpu, dar, ~0xFFFUL ); r =RESUME_GUEST ; }break ; }case BOOK3S_INTERRUPT_DATA_SEGMENT :if (kvmppc_mmu_map_segment (vcpu,kvmppc_get_fault_dar (vcpu)) <0 ) { - vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); + vcpu->arch.shared->dar =kvmppc_get_fault_dar (vcpu);kvmppc_book3s_queue_irqprio (vcpu,BOOK3S_INTERRUPT_DATA_SEGMENT ); }
@@ -997,7 +997,7 @@ program_interrupt:if (kvmppc_read_inst (vcpu) ==EMULATE_DONE ) { vcpu->arch.shared->dsisr =kvmppc_alignment_dsisr (vcpu,kvmppc_get_last_inst (vcpu)); - vcpu->arch.dear =kvmppc_alignment_dar (vcpu, + vcpu->arch.shared->dar =kvmppc_alignment_dar (vcpu,kvmppc_get_last_inst (vcpu));kvmppc_book3s_queue_irqprio (vcpu, exit_nr); }
arch/powerpc/kvm/book3s_emulate.c +3 -3
@@ -212,7 +212,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, r =kvmppc_st (vcpu, &addr,32 , zeros, true);if ((r == -ENOENT ) || (r == -EPERM )) { *advance =0 ; - vcpu->arch.dear = vaddr; + vcpu->arch.shared->dar = vaddr;to_svcpu (vcpu)->fault_dar = vaddr; dsisr =DSISR_ISSTORE ;
@@ -330,7 +330,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) vcpu->arch.shared->dsisr = spr_val;break ;case SPRN_DAR : - vcpu->arch.dear = spr_val; + vcpu->arch.shared->dar = spr_val;break ;case SPRN_HIOR :to_book3s (vcpu)->hior = spr_val;
@@ -443,7 +443,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->dsisr);break ;case SPRN_DAR : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.dear); +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->dar);break ;case SPRN_HIOR :kvmppc_set_gpr (vcpu, rt,to_book3s (vcpu)->hior);
arch/powerpc/kvm/book3s_paired_singles.c +1 -1
@@ -169,7 +169,7 @@ static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store) shared->msr =kvmppc_set_field (shared->msr,33 ,36 ,0 ); shared->msr =kvmppc_set_field (shared->msr,42 ,47 ,0 ); - vcpu->arch.dear = eaddr; + shared->dar = eaddr;/* Page Fault */ dsisr =kvmppc_set_field (0 ,33 ,33 ,1 );if (is_store)
arch/powerpc/kvm/booke.c +1 -1
@@ -195,7 +195,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,if (update_esr == true) vcpu->arch.esr = vcpu->arch.queued_esr;if (update_dear == true) - vcpu->arch.dear = vcpu->arch.queued_dear; + vcpu->arch.shared->dar = vcpu->arch.queued_dear;kvmppc_set_msr (vcpu, vcpu->arch.shared->msr & msr_mask);clear_bit (priority, &vcpu->arch.pending_exceptions);
arch/powerpc/kvm/booke_emulate.c +2 -2
@@ -105,7 +105,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)switch (sprn) {case SPRN_DEAR : - vcpu->arch.dear = spr_val;break ; + vcpu->arch.shared->dar = spr_val;break ;case SPRN_ESR : vcpu->arch.esr = spr_val;break ;case SPRN_DBCR0 :
@@ -200,7 +200,7 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)case SPRN_IVPR :kvmppc_set_gpr (vcpu, rt, vcpu->arch.ivpr);break ;case SPRN_DEAR : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.dear);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->dar);break ;case SPRN_ESR :kvmppc_set_gpr (vcpu, rt, vcpu->arch.esr);break ;case SPRN_DBCR0 :
Signature · 1 line
1.6.0.2
PATCH 8/26 KVM: PPC: Add PV guest critical sections
In reply to a message not in the archiveWhen running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
--- arch/powerpc/include/asm/kvm_para.h | 1 + arch/powerpc/kvm/book3s.c | 15 +++++++++++++-- arch/powerpc/kvm/booke.c | 12 ++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/kvm_para.h +1 -0
@@ -23,6 +23,7 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 critical;/* Guest may not get interrupts if == r1 */ __u64 sprg0;__u64 sprg1;__u64 sprg2;
arch/powerpc/kvm/book3s.c +13 -2
@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)int deliver =1 ;int vec =0 ;ulong flags =0ULL ; +ulong crit_raw = vcpu->arch.shared->critical; +ulong crit_r1 =kvmppc_get_gpr (vcpu,1 ); +bool crit; + +/* Truncate crit indicators in 32 bit mode */ +if (!(vcpu->arch.shared->msr &MSR_SF )) { + crit_raw &=0xffffffff ; + crit_r1 &=0xffffffff ; + } + + crit = (crit_raw == crit_r1);switch (priority) {case BOOK3S_IRQPRIO_DECREMENTER : - deliver = vcpu->arch.shared->msr &MSR_EE ; + deliver = (vcpu->arch.shared->msr &MSR_EE ) && !crit; vec =BOOK3S_INTERRUPT_DECREMENTER ;break ;case BOOK3S_IRQPRIO_EXTERNAL : - deliver = vcpu->arch.shared->msr &MSR_EE ; + deliver = (vcpu->arch.shared->msr &MSR_EE ) && !crit; vec =BOOK3S_INTERRUPT_EXTERNAL ;break ;case BOOK3S_IRQPRIO_SYSTEM_RESET :
arch/powerpc/kvm/booke.c +12 -0
@@ -147,6 +147,17 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,int allowed =0 ;ulong uninitialized_var (msr_mask );bool update_esr = false, update_dear = false; +ulong crit_raw = vcpu->arch.shared->critical; +ulong crit_r1 =kvmppc_get_gpr (vcpu,1 ); +bool crit; + +/* Truncate crit indicators in 32 bit mode */ +if (!(vcpu->arch.shared->msr &MSR_SF )) { + crit_raw &=0xffffffff ; + crit_r1 &=0xffffffff ; + } + + crit = (crit_raw == crit_r1);switch (priority) {case BOOKE_IRQPRIO_DTLB_MISS :
@@ -181,6 +192,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,case BOOKE_IRQPRIO_DECREMENTER :case BOOKE_IRQPRIO_FIT : allowed = vcpu->arch.shared->msr &MSR_EE ; + allowed = allowed && !crit; msr_mask =MSR_CE |MSR_ME |MSR_DE ;break ;case BOOKE_IRQPRIO_DEBUG :
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-9-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Quoted 7 lines · Alexander Graf
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
Is r1 reserved for this purpose? Can't it match accidentally?
Why won't zero/nonzero work for this?
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Am 27.06.2010 um 10:21 schrieb Avi Kivity <[email protected]>:
Quoted 10 lines · Alexander Graf
Quoted 7 lines
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
Quoted 2 lines
Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Alex
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Quoted 7 lines · Alexander Graf
Am 27.06.2010 um 10:21 schrieb Avi Kivity <[email protected]>:
Quoted 4 lines · Alexander Graf
Quoted 3 lines
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
Neat trick!
Quoted 4 lines
Quoted 2 lines
Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Or inc/dec...
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Am 27.06.2010 um 11:52 schrieb Avi Kivity <[email protected]>:
Quoted 17 lines · Alexander Graf
Quoted 7 lines
Am 27.06.2010 um 10:21 schrieb Avi Kivity <[email protected]>:
Quoted 4 lines · Alexander Graf
Quoted 3 lines
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
Quoted 8 lines
Neat trick!
Quoted 4 lines
Quoted 2 lines
Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Or inc/dec...
Uh - huh? How would that help?
Alex
A message that is not in the archive (sent off-list or not yet received): DFC77851-3BE7-4746-93DE-287D5E27EF7D-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Quoted 4 lines · Alexander Graf
Quoted 1 line
Or inc/dec...
Uh - huh? How would that help?
inc shared->critical # disable interrupts
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Am 27.06.2010 um 12:59 schrieb Avi Kivity <[email protected]>:
Quoted 7 lines · Alexander Graf
Quoted 4 lines
Quoted 1 line
Or inc/dec...
Uh - huh? How would that help?
inc
shared->critical# disable interrupts
There is no opcode in the ppc isa that acts on momery without involving a register.
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)
Alex
Quoted 1 line
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Quoted 11 lines · Alexander Graf
Am 27.06.2010 um 12:59 schrieb Avi Kivity <[email protected]>:
Quoted 7 lines · Alexander Graf
Quoted 4 lines
Quoted 1 line
Or inc/dec...
Uh - huh? How would that help?
inc
shared->critical# disable interrupts
Quoted 8 lines
There is no opcode in the ppc isa that acts on momery without involving a register.
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)
Right, I was agreeing with you. I meant there was no inc/dec mem insns.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Am 27.06.2010 um 13:53 schrieb Avi Kivity <[email protected]>:
Quoted 14 lines · Alexander Graf
Quoted 13 lines
Am 27.06.2010 um 12:59 schrieb Avi Kivity <[email protected]>:
Quoted 7 lines · Alexander Graf
Quoted 4 lines
Quoted 1 line
Or inc/dec...
Uh - huh? How would that help?
inc
shared->critical# disable interruptsThere is no opcode in the ppc isa that acts on momery without involving a register.
Quoted 7 lines
Quoted 5 lines
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)Right, I was agreeing with you. I meant there was no inc/dec mem insns.
Ah, I see :). I think that's really the only point where I deem the x86 isa superior :).
Alex
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Quoted 5 lines · Alexander Graf
Quoted 2 lines
Right, I was agreeing with you. I meant there was no inc/dec mem insns.
Ah, I see :). I think that's really the only point where I deem the x86 isa superior :).
Heh, well, that's a typical RISC thing tho. I think ARM and MIPS are like PowerPC here at least :-)
Cheers,
Ben.
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
In reply to a message not in the archiveQuoted 16 lines · Alexander Graf
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
arch/powerpc/kvm/book3s.c +2
-0@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)int deliver =1 ;int vec =0 ;ulong flags =0ULL ; +ulong crit_raw = vcpu->arch.shared->critical; +ulong crit_r1 =kvmppc_get_gpr (vcpu,1 );
arch/powerpc/kvm/book3s.c int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) · line 265
Quoted 10 lines
arch/powerpc/kvm/book3s.c +9
-0+bool crit; + +/* Truncate crit indicators in 32 bit mode */ +if (!(vcpu->arch.shared->msr&MSR_SF )) { + crit_raw&=0xffffffff ; + crit_r1&=0xffffffff ; + } + + crit = (crit_raw == crit_r1);
I think you need to qualify that for supervisor mode only. Otherwise guest userspace can guess the value of shared->critical and disable interrupts.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
Am 27.06.2010 um 12:03 schrieb Avi Kivity <[email protected]>:
Quoted 22 lines · Alexander Graf
Quoted 21 lines
When running in hooked code we need a way to disable interrupts without clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If that field is equal to the r1 register of the guest, it tells the hypervisor that we're in such a critical section and thus may not receive any interrupts.
arch/powerpc/kvm/book3s.c +6
-0@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) int deliver = 1;int vec =0 ;ulong flags =0ULL ; +ulong crit_raw = vcpu->arch.shared->critical; +ulong crit_r1 =kvmppc_get_gpr (vcpu,1 ); +bool crit; + +/* Truncate crit indicators in 32 bit mode */ +if (!(vcpu->arch.shared->msr&MSR_SF )) {
Quoted 8 lines
arch/powerpc/kvm/book3s.c int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) · line 265
Quoted 6 lines
arch/powerpc/kvm/book3s.c +5
-0+ crit_raw&=0xffffffff ; + crit_r1&=0xffffffff ; + } + + crit = (crit_raw == crit_r1);I think you need to qualify that for supervisor mode only. Otherwise guest userspace can guess the value of
shared->criticaland disable interrupts.
Yes, you're right. Good catch!
Alex
Quoted 1 line
PATCH 13/26 KVM: PPC: Magic Page Book3s support
In reply to a message not in the archiveWe need to override EA as well as PA lookups for the magic page. When the guest tells us to project it, the magic page overrides any guest mappings.
In order to reflect that, we need to hook into all the MMU layers of KVM to force map the magic page if necessary.
--- arch/powerpc/kvm/book3s.c | 7 +++++++ arch/powerpc/kvm/book3s_32_mmu.c | 16 ++++++++++++++++ arch/powerpc/kvm/book3s_32_mmu_host.c | 12 ++++++++++++ arch/powerpc/kvm/book3s_64_mmu.c | 30 +++++++++++++++++++++++++++++- arch/powerpc/kvm/book3s_64_mmu_host.c | 12 ++++++++++++ 5 files changed, 76 insertions(+), 1 deletions(-)
arch/powerpc/kvm/book3s.c +7 -0
@@ -551,6 +551,13 @@ mmio:static int kvmppc_visible_gfn (struct kvm_vcpu *vcpu,gfn_t gfn) { +ulong mp_pa = vcpu->arch.magic_page_pa; + +if (unlikely (mp_pa) && +unlikely ((mp_pa &KVM_RMO ) >>PAGE_SHIFT == gfn)) { +return 1 ; + } +return kvm_is_visible_gfn (vcpu->kvm, gfn); }
arch/powerpc/kvm/book3s_32_mmu.c +16 -0
@@ -281,8 +281,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data) { int r; +ulong mp_ea = vcpu->arch.magic_page_ea; pte->eaddr = eaddr; + +/* Magic page override */ +if (unlikely (mp_ea) && +unlikely ((eaddr & ~0xfffULL ) == (mp_ea & ~0xfffULL )) && + !(vcpu->arch.shared->msr &MSR_PR )) { + pte->vpage =kvmppc_mmu_book3s_32_ea_to_vp (vcpu, eaddr, data); + pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr &0xfff ); + pte->raddr &=KVM_RMO ; + pte->may_execute = true; + pte->may_read = true; + pte->may_write = true; + +return 0 ; + } + r =kvmppc_mmu_book3s_32_xlate_bat (vcpu, eaddr, pte, data);if (r <0 ) r =kvmppc_mmu_book3s_32_xlate_pte (vcpu, eaddr, pte, data, true);
arch/powerpc/kvm/book3s_32_mmu_host.c +12 -0
@@ -145,6 +145,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)bool primary = false;bool evict = false;struct hpte_cache *pte; +ulong mp_pa = vcpu->arch.magic_page_pa; + +/* Magic page override */ +if (unlikely (mp_pa) && +unlikely ((orig_pte->raddr & ~0xfffUL &KVM_RMO ) == + (mp_pa & ~0xfffUL &KVM_RMO ))) { + hpaddr = (pfn_t )virt_to_phys (vcpu->arch.shared); +get_page (pfn_to_page (hpaddr >>PAGE_SHIFT )); + goto mapped; + }/* Get host physical address for gpa */ hpaddr =gfn_to_pfn (vcpu->kvm, orig_pte->raddr >>PAGE_SHIFT );
@@ -155,6 +165,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) } hpaddr <<=PAGE_SHIFT ; +mapped: +/* and write the mapping ea -> hpa into the pt */ vcpu->arch.mmu.esid_to_vsid (vcpu, orig_pte->eaddr >>SID_SHIFT , &vsid); map =find_sid_vsid (vcpu, vsid);
arch/powerpc/kvm/book3s_64_mmu.c +29 -1
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,bool found = false;bool perm_err = false;int second =0 ; +ulong mp_ea = vcpu->arch.magic_page_ea; + +/* Magic page override */ +if (unlikely (mp_ea) && +unlikely ((eaddr & ~0xfffULL ) == (mp_ea & ~0xfffULL )) && + !(vcpu->arch.shared->msr &MSR_PR )) { + gpte->eaddr = eaddr; + gpte->vpage =kvmppc_mmu_book3s_64_ea_to_vp (vcpu, eaddr, data); + gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr &0xfff ); + gpte->raddr &=KVM_RMO ; + gpte->may_execute = true; + gpte->may_read = true; + gpte->may_write = true; + +return 0 ; + } slbe =kvmppc_mmu_book3s_64_find_slbe (vcpu_book3s, eaddr);if (!slbe)
@@ -445,6 +461,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,ulong ea = esid <<SID_SHIFT ;struct kvmppc_slb *slb;u64 gvsid = esid; +ulong mp_ea = vcpu->arch.magic_page_ea;if (vcpu->arch.shared->msr & (MSR_DR |MSR_IR )) { slb =kvmppc_mmu_book3s_64_find_slbe (to_book3s (vcpu), ea);
@@ -464,7 +481,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,break ;case MSR_DR |MSR_IR :if (!slb) -return -ENOENT ; + goto no_slb; *vsid = gvsid;break ;
@@ -477,6 +494,17 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, *vsid |=VSID_PR ;return 0 ; + +no_slb: +/* Catch magic page case */ +if (unlikely (mp_ea) && +unlikely (esid == (mp_ea >>SID_SHIFT )) && + !(vcpu->arch.shared->msr &MSR_PR )) { + *vsid =VSID_REAL | esid; +return 0 ; + } + +return -EINVAL ; }static bool kvmppc_mmu_book3s_64_is_dcbz32 (struct kvm_vcpu *vcpu)
arch/powerpc/kvm/book3s_64_mmu_host.c +12 -0
@@ -99,6 +99,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)int vflags =0 ;int attempt =0 ;struct kvmppc_sid_map *map; +ulong mp_pa = vcpu->arch.magic_page_pa; + +/* Magic page override */ +if (unlikely (mp_pa) && +unlikely ((orig_pte->raddr & ~0xfffULL &KVM_RMO ) == + (mp_pa & ~0xfffULL &KVM_RMO ))) { + hpaddr = (pfn_t )virt_to_phys (vcpu->arch.shared); +get_page (pfn_to_page (hpaddr >>PAGE_SHIFT )); + goto mapped; + }/* Get host physical address for gpa */ hpaddr =gfn_to_pfn (vcpu->kvm, orig_pte->raddr >>PAGE_SHIFT );
@@ -114,6 +124,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)#error Unknown page size#endif +mapped: +/* and write the mapping ea -> hpa into the pt */ vcpu->arch.mmu.esid_to_vsid (vcpu, orig_pte->eaddr >>SID_SHIFT , &vsid); map =find_sid_vsid (vcpu, vsid);
Signature · 1 line
1.6.0.2
PATCH 14/26 KVM: PPC: Magic Page BookE support
In reply to a message not in the archiveAs we now have Book3s support for the magic page, we also need BookE to join in on the party.
This patch implements generic magic page logic for BookE and specific TLB logic for e500. I didn't have any 440 around, so I didn't dare to blindly try and write up broken code.
--- arch/powerpc/kvm/booke.c | 29 +++++++++++++++++++++++++++++ arch/powerpc/kvm/e500_tlb.c | 19 +++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-)
arch/powerpc/kvm/booke.c +29 -0
@@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) vcpu->arch.shared->int_pending =0 ; } +/* Check if a DTLB miss was on the magic page. Returns !0 if so. */ +int kvmppc_dtlb_magic_page (struct kvm_vcpu *vcpu,ulong eaddr) +{ +ulong mp_ea = vcpu->arch.magic_page_ea; +ulong gpaddr = vcpu->arch.magic_page_pa; +int gtlb_index =11 | (1 <<16 );/* Random number in TLB1 */ + +/* Check for existence of magic page */ +if (likely (!mp_ea)) +return 0 ; + +/* Check if we're on the magic page */ +if (likely ((eaddr >>12 ) != (mp_ea >>12 ))) +return 0 ; + +/* Don't map in user mode */ +if (vcpu->arch.shared->msr &MSR_PR ) +return 0 ; + +kvmppc_mmu_map (vcpu, vcpu->arch.magic_page_ea, gpaddr, gtlb_index); +kvmppc_account_exit (vcpu,DTLB_VIRT_MISS_EXITS ); + +return 1 ; +} +/** * kvmppc_handle_exit *
@@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r =RESUME_HOST ;break ;case EMULATE_FAIL : +case EMULATE_DO_MMIO :/* XXX Deliver Program interrupt to guest. */ printk (KERN_CRIT "%s: emulation at %lx failed (%08x)\n" , __func__, vcpu->arch.pc, vcpu->arch.last_inst);
@@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,gpa_t gpaddr;gfn_t gfn; +if (kvmppc_dtlb_magic_page (vcpu, eaddr)) +break ; +/* Check the guest TLB. */ gtlb_index =kvmppc_mmu_dtlb_index (vcpu, eaddr);if (gtlb_index <0 ) {
arch/powerpc/kvm/e500_tlb.c +17 -2
@@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,struct page *new_page;struct tlbe *stlbe;hpa_t hpaddr; +u32 mas2 = gtlbe->mas2; +u32 mas3 = gtlbe->mas3; stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; +if ((vcpu_e500->vcpu.arch.magic_page_ea) && + ((vcpu_e500->vcpu.arch.magic_page_pa >>PAGE_SHIFT ) == gfn) && + !(vcpu_e500->vcpu.arch.shared->msr &MSR_PR )) { + mas2 =0 ; + mas3 =E500_TLB_SUPER_PERM_MASK ; + hpaddr =virt_to_phys (vcpu_e500->vcpu.arch.shared); + new_page =pfn_to_page (hpaddr >>PAGE_SHIFT ); +get_page (new_page); + goto mapped; + } +/* Get reference to new page. */ new_page =gfn_to_page (vcpu_e500->vcpu.kvm, gfn);if (is_error_page (new_page)) {
@@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,kvm_release_page_clean (new_page);return ; } + +mapped: hpaddr =page_to_phys (new_page);/* Drop reference to old page. */
@@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, stlbe->mas1 =MAS1_TSIZE (BOOK3E_PAGESZ_4K ) |MAS1_TID (get_tlb_tid (gtlbe)) |MAS1_TS |MAS1_VALID ; stlbe->mas2 = (gvaddr &MAS2_EPN ) - |e500_shadow_mas2_attrib (gtlbe->mas2, + |e500_shadow_mas2_attrib (mas2, vcpu_e500->vcpu.arch.shared->msr &MSR_PR ); stlbe->mas3 = (hpaddr &MAS3_RPN ) - |e500_shadow_mas3_attrib (gtlbe->mas3, + |e500_shadow_mas3_attrib (mas3, vcpu_e500->vcpu.arch.shared->msr &MSR_PR ); stlbe->mas7 = (hpaddr >>32 ) &MAS7_RPN ;
Signature · 1 line
1.6.0.2
PATCH 17/26 KVM: PPC: Generic KVM PV guest support
In reply to a message not in the archiveWe have all the hypervisor pieces in place now, but the guest parts are still missing.
This patch implements basic awareness of KVM when running Linux as guest. It doesn't do anything with it yet though.
--- arch/powerpc/kernel/Makefile | 2 ++ arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++++ arch/powerpc/kernel/kvm.c | 34 ++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/kvm_emul.S | 27 +++++++++++++++++++++++++++ arch/powerpc/platforms/Kconfig | 10 ++++++++++ 5 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/kernel/kvm.c create mode 100644 arch/powerpc/kernel/kvm_emul.S
arch/powerpc/kernel/Makefile +2 -0
@@ -125,6 +125,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) obj-y += ppc_save_regs.o endif +obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o + # Disable GCOV in odd or sensitive code GCOV_PROFILE_prom_init.o := n GCOV_PROFILE_ftrace.o := n
arch/powerpc/kernel/asm-offsets.c +15 -0
@@ -465,6 +465,21 @@ int main(void) DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));#endif /* CONFIG_PPC_BOOK3S */ #endif + +#ifdef CONFIG_KVM_GUEST +DEFINE (KVM_MAGIC_SCRATCH1 , offsetof(struct kvm_vcpu_arch_shared , + scratch1)); +DEFINE (KVM_MAGIC_SCRATCH2 , offsetof(struct kvm_vcpu_arch_shared , + scratch2)); +DEFINE (KVM_MAGIC_SCRATCH3 , offsetof(struct kvm_vcpu_arch_shared , + scratch3)); +DEFINE (KVM_MAGIC_INT , offsetof(struct kvm_vcpu_arch_shared , + int_pending)); +DEFINE (KVM_MAGIC_MSR , offsetof(struct kvm_vcpu_arch_shared , msr)); +DEFINE (KVM_MAGIC_CRITICAL , offsetof(struct kvm_vcpu_arch_shared , + critical)); +#endif +#ifdef CONFIG_44xDEFINE (PGD_T_LOG2 ,PGD_T_LOG2 );DEFINE (PTE_T_LOG2 ,PTE_T_LOG2 );
arch/powerpc/kernel/kvm.c new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved. +* +* Authors: +* Alexander Graf <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License, version 2, as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <linux/kvm_host.h> +#include <linux/init.h> +#include <linux/kvm_para.h> +#include <linux/slab.h> + +#include <asm/reg.h> +#include <asm/kvm_ppc.h> +#include <asm/sections.h> +#include <asm/cacheflush.h> +#include <asm/disassemble.h> + +#define KVM_MAGIC_PAGE (-4096L) +#define magic_var (x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) +
arch/powerpc/kernel/kvm_emul.S new file +27 -0
@@ -0,0 +1,27 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2010 + * + * Authors: Alexander Graf <[email protected]> + */ + +#include <asm/ppc_asm.h> +#include <asm/kvm_asm.h> +#include <asm/reg.h> +#include <asm/page.h> +#include <asm/asm-offsets.h> + +#define KVM_MAGIC_PAGE (-4096) +
arch/powerpc/platforms/Kconfig +10 -0
@@ -21,6 +21,16 @@ source "arch/powerpc/platforms/44x/Kconfig" source "arch/powerpc/platforms/40x/Kconfig" source "arch/powerpc/platforms/amigaone/Kconfig" +config KVM_GUEST + bool "KVM Guest support" + default y + ---help--- + This option enables various optimizations for running under the KVM + hypervisor. Overhead for the kernel when not running inside KVM should + be minimal. + + In case of doubt, say Y + config PPC_NATIVE bool depends on 6xx || PPC64
Signature · 1 line
1.6.0.2
PATCH 19/26 KVM: PPC: PV instructions to loads and stores
In reply to a message not in the archiveSome instructions can simply be replaced by load and store instructions to or from the magic page.
This patch replaces often called instructions that fall into the above category.
--- arch/powerpc/kernel/kvm.c | 111 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 111 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +111 -0
@@ -32,8 +32,65 @@#define KVM_MAGIC_PAGE (-4096L)#define magic_var (x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) +#define KVM_INST_LWZ 0x80000000 +#define KVM_INST_STW 0x90000000 +#define KVM_INST_LD 0xe8000000 +#define KVM_INST_STD 0xf8000000 +#define KVM_INST_NOP 0x60000000 +#define KVM_INST_B 0x48000000 +#define KVM_INST_B_MASK 0x03ffffff +#define KVM_INST_B_MAX 0x01ffffff + +#define KVM_MASK_RT 0x03e00000 +#define KVM_INST_MFMSR 0x7c0000a6 +#define KVM_INST_MFSPR_SPRG0 0x7c1042a6 +#define KVM_INST_MFSPR_SPRG1 0x7c1142a6 +#define KVM_INST_MFSPR_SPRG2 0x7c1242a6 +#define KVM_INST_MFSPR_SPRG3 0x7c1342a6 +#define KVM_INST_MFSPR_SRR0 0x7c1a02a6 +#define KVM_INST_MFSPR_SRR1 0x7c1b02a6 +#define KVM_INST_MFSPR_DAR 0x7c1302a6 +#define KVM_INST_MFSPR_DSISR 0x7c1202a6 + +#define KVM_INST_MTSPR_SPRG0 0x7c1043a6 +#define KVM_INST_MTSPR_SPRG1 0x7c1143a6 +#define KVM_INST_MTSPR_SPRG2 0x7c1243a6 +#define KVM_INST_MTSPR_SPRG3 0x7c1343a6 +#define KVM_INST_MTSPR_SRR0 0x7c1a03a6 +#define KVM_INST_MTSPR_SRR1 0x7c1b03a6 +#define KVM_INST_MTSPR_DAR 0x7c1303a6 +#define KVM_INST_MTSPR_DSISR 0x7c1203a6 +static bool kvm_patching_worked = true; +static void kvm_patch_ins_ld (u32 *inst,long addr,u32 rt) +{ +#ifdef CONFIG_64BIT + *inst =KVM_INST_LD | rt | (addr &0x0000fffc ); +#else + *inst =KVM_INST_LWZ | rt | ((addr +4 ) &0x0000fffc ); +#endif +} + +static void kvm_patch_ins_lwz (u32 *inst,long addr,u32 rt) +{ + *inst =KVM_INST_LWZ | rt | (addr &0x0000ffff ); +} + +static void kvm_patch_ins_std (u32 *inst,long addr,u32 rt) +{ +#ifdef CONFIG_64BIT + *inst =KVM_INST_STD | rt | (addr &0x0000fffc ); +#else + *inst =KVM_INST_STW | rt | ((addr +4 ) &0x0000fffc ); +#endif +} + +static void kvm_patch_ins_stw (u32 *inst,long addr,u32 rt) +{ + *inst =KVM_INST_STW | rt | (addr &0x0000fffc ); +} +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -48,6 +105,60 @@ static void kvm_check_ins(u32 *inst)u32 inst_rt = _inst &KVM_MASK_RT ;switch (inst_no_rt) { +/* Loads */ +case KVM_INST_MFMSR : +kvm_patch_ins_ld (inst,magic_var (msr), inst_rt); +break ; +case KVM_INST_MFSPR_SPRG0 : +kvm_patch_ins_ld (inst,magic_var (sprg0), inst_rt); +break ; +case KVM_INST_MFSPR_SPRG1 : +kvm_patch_ins_ld (inst,magic_var (sprg1), inst_rt); +break ; +case KVM_INST_MFSPR_SPRG2 : +kvm_patch_ins_ld (inst,magic_var (sprg2), inst_rt); +break ; +case KVM_INST_MFSPR_SPRG3 : +kvm_patch_ins_ld (inst,magic_var (sprg3), inst_rt); +break ; +case KVM_INST_MFSPR_SRR0 : +kvm_patch_ins_ld (inst,magic_var (srr0), inst_rt); +break ; +case KVM_INST_MFSPR_SRR1 : +kvm_patch_ins_ld (inst,magic_var (srr1), inst_rt); +break ; +case KVM_INST_MFSPR_DAR : +kvm_patch_ins_ld (inst,magic_var (dar), inst_rt); +break ; +case KVM_INST_MFSPR_DSISR : +kvm_patch_ins_lwz (inst,magic_var (dsisr), inst_rt); +break ; + +/* Stores */ +case KVM_INST_MTSPR_SPRG0 : +kvm_patch_ins_std (inst,magic_var (sprg0), inst_rt); +break ; +case KVM_INST_MTSPR_SPRG1 : +kvm_patch_ins_std (inst,magic_var (sprg1), inst_rt); +break ; +case KVM_INST_MTSPR_SPRG2 : +kvm_patch_ins_std (inst,magic_var (sprg2), inst_rt); +break ; +case KVM_INST_MTSPR_SPRG3 : +kvm_patch_ins_std (inst,magic_var (sprg3), inst_rt); +break ; +case KVM_INST_MTSPR_SRR0 : +kvm_patch_ins_std (inst,magic_var (srr0), inst_rt); +break ; +case KVM_INST_MTSPR_SRR1 : +kvm_patch_ins_std (inst,magic_var (srr1), inst_rt); +break ; +case KVM_INST_MTSPR_DAR : +kvm_patch_ins_std (inst,magic_var (dar), inst_rt); +break ; +case KVM_INST_MTSPR_DSISR : +kvm_patch_ins_stw (inst,magic_var (dsisr), inst_rt); +break ; }switch (_inst) {
Signature · 1 line
1.6.0.2
PATCH 20/26 KVM: PPC: PV tlbsync to nop
In reply to a message not in the archiveWith our current MMU scheme we don't need to know about the tlbsync instruction. So we can just nop it out.
--- arch/powerpc/kernel/kvm.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +12 -0
@@ -61,6 +61,8 @@#define KVM_INST_MTSPR_DAR 0x7c1303a6#define KVM_INST_MTSPR_DSISR 0x7c1203a6 +#define KVM_INST_TLBSYNC 0x7c00046c +static bool kvm_patching_worked = true;static void kvm_patch_ins_ld (u32 *inst,long addr,u32 rt)
@@ -91,6 +93,11 @@ static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt) *inst =KVM_INST_STW | rt | (addr &0x0000fffc ); } +static void kvm_patch_ins_nop (u32 *inst) +{ + *inst =KVM_INST_NOP ; +} +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -159,6 +166,11 @@ static void kvm_check_ins(u32 *inst)case KVM_INST_MTSPR_DSISR :kvm_patch_ins_stw (inst,magic_var (dsisr), inst_rt);break ; + +/* Nops */ +case KVM_INST_TLBSYNC : +kvm_patch_ins_nop (inst); +break ; }switch (_inst) {
Signature · 1 line
1.6.0.2
PATCH 22/26 KVM: PPC: PV assembler helpers
In reply to a message not in the archiveWhen we hook an instruction we need to make sure we don't clobber any of the registers at that point. So we write them out to scratch space in the magic page. To make sure we don't fall into a race with another piece of hooked code, we need to disable interrupts.
To make the later patches and code in general easier readable, let's introduce a set of defines that save and restore r30, r31 and cr. Let's also define some helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.
--- arch/powerpc/kernel/kvm_emul.S | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm_emul.S +29 -0
@@ -25,3 +25,32 @@ #define KVM_MAGIC_PAGE (-4096) +#ifdef CONFIG_64BIT +#define LL64(reg, offs, reg2) ld reg, (offs)(reg2) +#define STL64(reg, offs, reg2) std reg, (offs)(reg2) +#else +#define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2) +#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2) +#endif + +#define SCRATCH_SAVE \ + /* Enable critical section. We are critical if \ + shared->critical == r1 */ \ + STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \ + \ + /* Save state */ \ + PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ + PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ + mfcr r31; \ + stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); + +#define SCRATCH_RESTORE \ + /* Restore state */ \ + PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ + lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \ + mtcr r30; \ + PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ + \ + /* Disable critical section. We are critical if \ + shared->critical == r1 and r2 is always != r1 */ \ + STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
Signature · 1 line
1.6.0.2
PATCH 24/26 KVM: PPC: PV mtmsrd L=0 and mtmsr
In reply to a message not in the archiveThere is also a form of mtmsr where all bits need to be addressed. While the PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the L=1 form but does mtmsr even for simple things like only changing EE.
So we need to hook into that one as well and check for a mask of bits that we deem safe to change from within guest context.
--- arch/powerpc/kernel/kvm.c | 51 ++++++++++++++++++++++++ arch/powerpc/kernel/kvm_emul.S | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +51 -0
@@ -62,7 +62,9 @@#define KVM_INST_MTSPR_DSISR 0x7c1203a6#define KVM_INST_TLBSYNC 0x7c00046c +#define KVM_INST_MTMSRD_L0 0x7c000164#define KVM_INST_MTMSRD_L1 0x7c010164 +#define KVM_INST_MTMSR 0x7c000124static bool kvm_patching_worked = true;static char kvm_tmp[1024 *1024 ];
@@ -155,6 +157,49 @@ static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt) *inst =KVM_INST_B | (distance_start &KVM_INST_B_MASK ); } +extern u32 kvm_emulate_mtmsr_branch_offs; +extern u32 kvm_emulate_mtmsr_reg1_offs; +extern u32 kvm_emulate_mtmsr_reg2_offs; +extern u32 kvm_emulate_mtmsr_reg3_offs; +extern u32 kvm_emulate_mtmsr_orig_ins_offs; +extern u32 kvm_emulate_mtmsr_len; +extern u32 kvm_emulate_mtmsr[]; + +static void kvm_patch_ins_mtmsr (u32 *inst,u32 rt) +{ +u32 *p; +int distance_start; +int distance_end; +ulong next_inst; + + p =kvm_alloc (kvm_emulate_mtmsr_len *4 ); +if (!p) +return ; + +/* Find out where we are and put everything there */ + distance_start = (ulong )p - (ulong )inst; + next_inst = ((ulong )inst +4 ); + distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs]; + +/* Make sure we only write valid b instructions */ +if (distance_start >KVM_INST_B_MAX ) { + kvm_patching_worked = false; +return ; + } + +/* Modify the chunk to fit the invocation */ +memcpy (p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len *4 ); + p[kvm_emulate_mtmsr_branch_offs] |= distance_end &KVM_INST_B_MASK ; + p[kvm_emulate_mtmsr_reg1_offs] |= rt; + p[kvm_emulate_mtmsr_reg2_offs] |= rt; + p[kvm_emulate_mtmsr_reg3_offs] |= rt; + p[kvm_emulate_mtmsr_orig_ins_offs] = *inst; +flush_icache_range ((ulong )p, (ulong )p + kvm_emulate_mtmsr_len *4 ); + +/* Patch the invocation */ + *inst =KVM_INST_B | (distance_start &KVM_INST_B_MASK ); +} +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -235,6 +280,12 @@ static void kvm_check_ins(u32 *inst)if (get_rt (inst_rt) <30 )kvm_patch_ins_mtmsrd (inst, inst_rt);break ; +case KVM_INST_MTMSR : +case KVM_INST_MTMSRD_L0 : +/* We use r30 and r31 during the hook */ +if (get_rt (inst_rt) <30 ) +kvm_patch_ins_mtmsr (inst, inst_rt); +break ; }switch (_inst) {
arch/powerpc/kernel/kvm_emul.S +84 -0
87 lines not on this page · raw message
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-25-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
Quoted 3 lines
There is also a form of mtmsr where all bits need to be addressed. While the PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the L=1 form but does mtmsr even for simple things like only changing EE.
You make it sound like the 32-bit kernel does something stupid, while there is no other choice. The "L=1" thing only exists for 64-bit.
Segher
A message that is not in the archive (sent off-list or not yet received): EDF0A567-C440-4F1B-9AF5-2E0F8203D566-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
Am 26.06.2010 um 19:03 schrieb Segher Boessenkool <[email protected]>:
Quoted 6 lines
Quoted 3 lines
There is also a form of mtmsr where all bits need to be addressed. While the PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the L=1 form but does mtmsr even for simple things like only changing EE.
You make it sound like the 32-bit kernel does something stupid, while there is no other choice. The "L=1" thing only exists for 64-bit.
Oh, so that's why :). That doesn't really change the fact that it's very hard to distinguish between a mtmsr that only changes MSR_EE vs one that changes MSR_IR for example :).
Alex
Quoted 1 line
Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
There is also a form of mtmsr where all bits need to be addressed. While the
PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the
L=1 form but does mtmsr even for simple things like only changing EE.
Quoted 6 lines
Quoted 2 lines
You make it sound like the 32-bit kernel does something stupid, while there is no other choice. The "L=1" thing only exists for 64-bit.
Oh, so that's why :). That doesn't really change the fact that it's very hard to distinguish between a mtmsr that only changes
MSR_EEvs one that changesMSR_IRfor example :).
Hard to predict for the CPU as well, guess why there is a separate instruction now :-P
By the way, L=1 _does_ exist for mtmsr; it's just that no 32-bit "classic"
implementations support it.
Segher
PATCH 26/26 KVM: PPC: Add Documentation about PV interface
In reply to a message not in the archiveWe just introduced a new PV interface that screams for documentation. So here it is - a shiny new and awesome text file describing the internal works of the PPC KVM paravirtual interface.
--- Documentation/kvm/ppc-pv.txt | 164 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 164 insertions(+), 0 deletions(-) create mode 100644 Documentation/kvm/ppc-pv.txt
Documentation/kvm/ppc-pv.txt new file +164 -0
@@ -0,0 +1,164 @@ +The PPC KVM paravirtual interface +================================= + +The basic execution principle by which KVM on PowerPC works is to run all kernel +space code in PR=1 which is user space. This way we trap all privileged +instructions and can emulate them accordingly. + +Unfortunately that is also the downfall. There are quite some privileged +instructions that needlessly return us to the hypervisor even though they +could be handled differently. + +This is what the PPC PV interface helps with. It takes privileged instructions +and transforms them into unprivileged ones with some help from the hypervisor. +This cuts down virtualization costs by about 50% on some of my benchmarks. + +The code for that interface can be found in arch/powerpc/kernel/kvm* + +Querying for existence +====================== + +To find out if we're running on KVM or not, we overlay the PVR register. Usually +the PVR register contains an id that identifies your CPU type. If, however, you +pass KVM_PVR_PARA in the register that you want the PVR result in, the register +still contains KVM_PVR_PARA after the mfpvr call. + + LOAD_REG_IMM(r5, KVM_PVR_PARA) + mfpvr r5 + [r5 still contains KVM_PVR_PARA] + +Once determined to run under a PV capable KVM, you can now use hypercalls as +described below. + +PPC hypercalls +============== + +The only viable ways to reliably get from guest context to host context are: + + 1) Call an invalid instruction + 2) Call the "sc" instruction with a parameter to "sc" + 3) Call the "sc" instruction with parameters in GPRs + +Method 1 is always a bad idea. Invalid instructions can be replaced later on +by valid instructions, rendering the interface broken. + +Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is +rather unclear if the sc is targeted directly for the hypervisor or the +supervisor. It would also require that we read the syscall issuing instruction +every time a syscall is issued, slowing down guest syscalls. + +Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these +magic values arrives from the guest's kernel mode, we take the syscall as a +hypercall. + +The parameters are as follows: + + r3 KVM_SC_MAGIC_R3 + r4 KVM_SC_MAGIC_R4 + r5 Hypercall number + r6 First parameter + r7 Second parameter + r8 Third parameter + r9 Fourth parameter + +Hypercall definitions are shared in generic code, so the same hypercall numbers +apply for x86 and powerpc alike. + +The magic page +============== + +To enable communication between the hypervisor and guest there is a new shared +page that contains parts of supervisor visible register state. The guest can +map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE. + +With this hypercall issued the guest always gets the magic page mapped at the +desired location in effective and physical address space. For now, we always +map the page to -4096. This way we can access it using absolute load and store +functions. The following instruction reads the first field of the magic page: + + ld rX, -4096(0) + +The interface is designed to be extensible should there be need later to add +additional registers to the magic page. If you add fields to the magic page, +also define a new hypercall feature to indicate that the host can give you more +registers. Only if the host supports the additional features, make use of them. + +The magic page has the following layout as described in +arch/powerpc/include/asm/kvm_para.h: + +struct kvm_vcpu_arch_shared { + __u64 scratch1; + __u64 scratch2; + __u64 scratch3; + __u64 critical; /* Guest may not get interrupts if == r1 */ + __u64 sprg0; + __u64 sprg1; + __u64 sprg2; + __u64 sprg3; + __u64 srr0; + __u64 srr1; + __u64 dar; + __u64 msr; + __u32 dsisr; + __u32 int_pending; /* Tells the guest if we have an interrupt */ +}; + +Additions to the page must only occur at the end. Struct fields are always 32 +bit aligned. + +Patched instructions +==================== + +The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions +respectively on 32 bit systems with an added offset of 4 to accomodate for big +endianness. + +From To +==== == + +mfmsr rX ld rX, magic_page->msr +mfsprg rX, 0 ld rX, magic_page->sprg0 +mfsprg rX, 1 ld rX, magic_page->sprg1 +mfsprg rX, 2 ld rX, magic_page->sprg2 +mfsprg rX, 3 ld rX, magic_page->sprg3 +mfsrr0 rX ld rX, magic_page->srr0 +mfsrr1 rX ld rX, magic_page->srr1 +mfdar rX ld rX, magic_page->dar +mfdsisr rX ld rX, magic_page->dsisr + +mtmsr rX std rX, magic_page->msr +mtsprg 0, rX std rX, magic_page->sprg0 +mtsprg 1, rX std rX, magic_page->sprg1 +mtsprg 2, rX std rX, magic_page->sprg2 +mtsprg 3, rX std rX, magic_page->sprg3 +mtsrr0 rX std rX, magic_page->srr0 +mtsrr1 rX std rX, magic_page->srr1 +mtdar rX std rX, magic_page->dar +mtdsisr rX std rX, magic_page->dsisr + +tlbsync nop + +mtmsrd rX, 0 b <special mtmsr section> +mtmsr b <special mtmsr section> + +mtmsrd rX, 1 b <special mtmsrd section> + +[BookE only] +wrteei [0|1] b <special wrteei section> + + +Some instructions require more logic to determine what's going on than a load +or store instruction can deliver. To enable patching of those, we keep some +RAM around where we can live translate instructions to. What happens is the +following: + + 1) copy emulation code to memory + 2) patch that code to fit the emulated instruction + 3) patch that code to return to the original pc + 4 + 4) patch the original instruction to branch to the new code + +That way we can inject an arbitrary amount of code as replacement for a single +instruction. This allows us to check for pending interrupts when setting EE=1 +for example. +
Signature · 1 line
1.6.0.2
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 4 lines · Alexander Graf
We just introduced a new PV interface that screams for documentation. So here it is - a shiny new and awesome text file describing the internal works of the PPC KVM paravirtual interface.
Good, that lets people who have no idea what they're talking about participate in the review.
Quoted 13 lines
Documentation/kvm/ppc-pv.txt new file +12
-0+ +PPC hypercalls +============== + +The only viable ways to reliably get from guest context to host context are: + + 1) Call an invalid instruction + 2) Call the "sc" instruction with a parameter to "sc" + 3) Call the "sc" instruction with parameters in GPRs + +Method 1 is always a bad idea. Invalid instructions can be replaced later on +by valid instructions, rendering the interface broken.
Documentation/kvm/ppc-pv.txt line 53
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ +Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is +rather unclear if the sc is targeted directly for the hypervisor or the +supervisor. It would also require that we read the syscall issuing instruction +every time a syscall is issued, slowing down guest syscalls. + +Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these +magic values arrives from the guest's kernel mode, we take the syscall as a +hypercall.
Is there any chance a normal syscall will have those values in r3 and r4?
If so, maybe it's better to use pc as they key for hypercalls. Let the guest designate one instruction address as the hypercall call point; kvm can easily check it and reflect it back to the guest if it doesn't match.
Is it valid and useful to issue sc from privileged mode anyway, except for calling the hypervisor?
Quoted 4 lines
Documentation/kvm/ppc-pv.txt new file +3
-0+ +The parameters are as follows: +
Documentation/kvm/ppc-pv.txt line 66
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ r3 KVM_SC_MAGIC_R3 + r4 KVM_SC_MAGIC_R4 + r5 Hypercall number + r6 First parameter + r7 Second parameter + r8 Third parameter + r9 Fourth parameter + +Hypercall definitions are shared in generic code, so the same hypercall numbers +apply for x86 and powerpc alike.
Addresses passed in hypercall paramters are guest physical addresses.
Do you have >32 bit physical addresses on 32-bit guests? if so, you'll need to pass physical addresses in two registers.
Quoted 5 lines
Documentation/kvm/ppc-pv.txt new file +4
-0+ +The magic page +============== +
Documentation/kvm/ppc-pv.txt line 80
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+To enable communication between the hypervisor and guest there is a new shared +page that contains parts of supervisor visible register state. The guest can +map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE. + +With this hypercall issued the guest always gets the magic page mapped at the +desired location in effective and physical address space. For now, we always +map the page to -4096. This way we can access it using absolute load and store +functions. The following instruction reads the first field of the magic page: + + ld rX, -4096(0)
Is the address guest controlled or host controlled?
Quoted 5 lines
Documentation/kvm/ppc-pv.txt new file +4
-0+ +The interface is designed to be extensible should there be need later to add +additional registers to the magic page. If you add fields to the magic page, +also define a new hypercall feature to indicate that the host can give you more
Documentation/kvm/ppc-pv.txt line 94
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+registers. Only if the host supports the additional features, make use of them. + +The magic page has the following layout as described in +arch/powerpc/include/asm/kvm_para.h: + +struct kvm_vcpu_arch_shared { + __u64 scratch1; + __u64 scratch2; + __u64 scratch3; + __u64 critical; /* Guest may not get interrupts if == r1 */
Elaborate?
Quoted 12 lines
Documentation/kvm/ppc-pv.txt new file +11
-0+ __u64 sprg0; + __u64 sprg1; + __u64 sprg2; + __u64 sprg3; + __u64 srr0; + __u64 srr1; + __u64 dar; + __u64 msr; + __u32 dsisr; + __u32 int_pending; /* Tells the guest if we have an interrupt */ +};
Documentation/kvm/ppc-pv.txt line 115
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ +Additions to the page must only occur at the end. Struct fields are always 32 +bit aligned. + +Patched instructions +==================== + +The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions +respectively on 32 bit systems with an added offset of 4 to accomodate for big +endianness.
Who does the patching? guest or host?
Quoted 24 lines
Documentation/kvm/ppc-pv.txt new file +23
-0+ +From To +==== == + +mfmsr rX ld rX, magic_page->msr +mfsprg rX, 0 ld rX, magic_page->sprg0 +mfsprg rX, 1 ld rX, magic_page->sprg1 +mfsprg rX, 2 ld rX, magic_page->sprg2 +mfsprg rX, 3 ld rX, magic_page->sprg3 +mfsrr0 rX ld rX, magic_page->srr0 +mfsrr1 rX ld rX, magic_page->srr1 +mfdar rX ld rX, magic_page->dar +mfdsisr rX ld rX, magic_page->dsisr + +mtmsr rX std rX, magic_page->msr +mtsprg 0, rX std rX, magic_page->sprg0 +mtsprg 1, rX std rX, magic_page->sprg1 +mtsprg 2, rX std rX, magic_page->sprg2 +mtsprg 3, rX std rX, magic_page->sprg3 +mtsrr0 rX std rX, magic_page->srr0 +mtsrr1 rX std rX, magic_page->srr1 +mtdar rX std rX, magic_page->dar +mtdsisr rX std rX, magic_page->dsisr
Documentation/kvm/ppc-pv.txt line 148
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ +tlbsync nop + +mtmsrd rX, 0 b <special mtmsr section> +mtmsr b <special mtmsr section> + +mtmsrd rX, 1 b <special mtmsrd section> + +[BookE only] +wrteei [0|1] b <special wrteei section>
Probably the guest, as only it can arrange for special * sections. Good.
Quoted 6 lines
Documentation/kvm/ppc-pv.txt new file +5
-0+ +Some instructions require more logic to determine what's going on than a load +or store instruction can deliver. To enable patching of those, we keep some +RAM around where we can live translate instructions to. What happens is the +following:
Documentation/kvm/ppc-pv.txt line 164
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ + 1) copy emulation code to memory + 2) patch that code to fit the emulated instruction + 3) patch that code to return to the original pc + 4 + 4) patch the original instruction to branch to the new code + +That way we can inject an arbitrary amount of code as replacement for a single +instruction. This allows us to check for pending interrupts when setting EE=1 +for example. +
Or not.
What about transitions from paravirt to non-paravirt? For example, a system reset.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Am 27.06.2010 um 10:14 schrieb Avi Kivity <[email protected]>:
Quoted 7 lines · Alexander Graf
Quoted 4 lines
We just introduced a new PV interface that screams for documentation. So here it is - a shiny new and awesome text file describing the internal works of the PPC KVM paravirtual interface.
Good, that lets people who have no idea what they're talking about participate in the review.
Heh, I knew you'd like this :).
Quoted 26 lines
Quoted 26 lines
Documentation/kvm/ppc-pv.txt new file +5
-0+ +PPC hypercalls +============== + +The only viable ways to reliably get from guest context to hostcontext are:
Documentation/kvm/ppc-pv.txt new file +6
-0+ + 1) Call an invalid instruction + 2) Call the "sc" instruction with a parameter to "sc" + 3) Call the "sc" instruction with parameters in GPRs + +Method 1 is always a bad idea. Invalid instructions can bereplaced later on
Documentation/kvm/ppc-pv.txt new file +3
-0+by valid instructions, rendering the interface broken. + +Method 2 also has downfalls. If the parameter to "sc" is != 0 thespec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instructionDocumentation/kvm/ppc-pv.txt new file +3
-0+every time a syscall is issued, slowing down guest syscalls. + +Method 3 is what KVM uses. We pass magic constants(
KVM_SC_MAGIC_R3and
Quoted 8 lines
Quoted 6 lines
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.Is there any chance a normal syscall will have those values in r3 and r4?
r3 is the syscall number. So as long as the guest doesn't reuse that value, we're safe. Since in general syscall numbers are not randomly scattered throughout the number range, we should be ok here.
Quoted 3 lines
If so, maybe it's better to use pc as they key for hypercalls. Let the guest designate one instruction address as the hypercall call point; kvm can easily check it and reflect it back to the guest if it doesn't match.
You mean the guest would tell the hv where the hypercall lies? That would require a hypercall, no? Defining it statically is tricky. I want to PV'nize osx using a kernel module later, so I don't have control over the physical layout.
Quoted 1 line
Is it valid and useful to issue sc from privileged mode anyway, except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue syscalls within itself.
Quoted 19 lines
Quoted 13 lines
Documentation/kvm/ppc-pv.txt new file +12
-0+ +The parameters are as follows: + + r3 KVM_SC_MAGIC_R3 + r4 KVM_SC_MAGIC_R4 + r5 Hypercall number + r6 First parameter + r7 Second parameter + r8 Third parameter + r9 Fourth parameter + +Hypercall definitions are shared in generic code, so the sameQuoted 3 lines
hypercall numbers
+apply for x86 and powerpc alike.Addresses passed in hypercall paramters are guest physical addresses.
Quoted 1 line
Do you have >32 bit physical addresses on 32-bit guests? if so, you'll need to pass physical addresses in two registers.
I think theoretically it's possible. Will we ever support it? Doubtful. Do we need to pass hogh memory addresses to the hv? Even more doubtful.
If we hit such a case, I'd just disable the hypercall for 32 bit. Or define param1 and param2 to contain the address if the guest is in 32-bit mode. No need to always make all params 64 bit imho.
Quoted 17 lines
Quoted 17 lines
Documentation/kvm/ppc-pv.txt new file +5
-0+ +The magic page +============== + +To enable communication between the hypervisor and guest there isa new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercallKVM_HC_PPC_MAP_MAGIC_PAGE.(quoted diff) +2
-0+ +With this hypercall issued the guest always gets the magic pagemapped at the
+desired location in effective and physical address space. For now, we always
+map the page to -4096. This way we can access it using absolute
Quoted 8 lines
Review
Quoted 6 lines
load and store
+functions. The following instruction reads the first field of the magic page:(quoted diff) +2
-0+ + ld rX, -4096(0)Is the address guest controlled or host controlled?
Guest controlled. It's passed in to the map_magic_page hypercall.
Quoted 15 lines
Quoted 15 lines
(quoted diff) +2
-0+ +The interface is designed to be extensible should there be needlater to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.Documentation/kvm/ppc-pv.txt new file +5
-0+ +The magic page has the following layout as described in +arch/powerpc/include/asm/kvm_para.h: + +struct kvm_vcpu_arch_shared {
Quoted 8 lines
Quoted 6 lines
Documentation/kvm/ppc-pv.txt new file +4
-0+ __u64 scratch1; + __u64 scratch2; + __u64 scratch3; + __u64 critical; /* Guest may not get interrupts if ==r1 */
Elaborate?
I think I have a description in the respective patch. Probably a good idea to add it to the documentation.
Quoted 21 lines
Quoted 21 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ __u64 sprg0; + __u64 sprg1; + __u64 sprg2; + __u64 sprg3; + __u64 srr0; + __u64 srr1; + __u64 dar; + __u64 msr; + __u32 dsisr; + __u32 int_pending; /* Tells the guest if we have aninterrupt */
Documentation/kvm/ppc-pv.txt new file +3
-0+}; + +Additions to the page must only occur at the end. Struct fieldsare always 32
Documentation/kvm/ppc-pv.txt new file +5
-0+bit aligned. + +Patched instructions +==================== +
Quoted 8 lines
Quoted 6 lines
+The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accomodate for big
+endianness.Who does the patching? guest or host?
All patching is done by the guest. Probably worth mentioning, yeah.
Quoted 62 lines
Quoted 25 lines
Documentation/kvm/ppc-pv.txt new file +23
-0+ +From To +==== == + +mfmsr rX ld rX, magic_page->msr +mfsprg rX, 0 ld rX, magic_page->sprg0 +mfsprg rX, 1 ld rX, magic_page->sprg1 +mfsprg rX, 2 ld rX, magic_page->sprg2 +mfsprg rX, 3 ld rX, magic_page->sprg3 +mfsrr0 rX ld rX, magic_page->srr0 +mfsrr1 rX ld rX, magic_page->srr1 +mfdar rX ld rX, magic_page->dar +mfdsisr rX ld rX, magic_page->dsisr + +mtmsr rX std rX, magic_page->msr +mtsprg 0, rX std rX, magic_page->sprg0 +mtsprg 1, rX std rX, magic_page->sprg1 +mtsprg 2, rX std rX, magic_page->sprg2 +mtsprg 3, rX std rX, magic_page->sprg3 +mtsrr0 rX std rX, magic_page->srr0 +mtsrr1 rX std rX, magic_page->srr1 +mtdar rX std rX, magic_page->dar +mtdsisr rX std rX, magic_page->dsisrDocumentation/kvm/ppc-pv.txt line 148
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+ +tlbsync nop + +mtmsrd rX, 0 b <special mtmsr section> +mtmsr b <special mtmsr section> + +mtmsrd rX, 1 b <special mtmsrd section> + +[BookE only] +wrteei [0|1] b <special wrteei section>Probably the guest, as only it can arrange for special * sections. Good.
Quoted 19 lines
(quoted diff) +2
-0+ +Some instructions require more logic to determine what's going onthan a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is theDocumentation/kvm/ppc-pv.txt new file +8
-0+following: + + 1) copy emulation code to memory + 2) patch that code to fit the emulated instruction + 3) patch that code to return to the original pc + 4 + 4) patch the original instruction to branch to the new code + +That way we can inject an arbitrary amount of code as replacementfor a single
+instruction. This allows us to check for pending interrupts when setting EE=1Documentation/kvm/ppc-pv.txt line 164
Quoted 2 lines
Documentation/kvm/ppc-pv.txt new file +2
-0+for example. +Or not.
Quoted 1 line
What about transitions from paravirt to non-paravirt? For example, a system reset.
That ... eh ... good question. It would leave the map pending, but everything still continues working.
I don't really know in kvm when a reset occured. So we have to make qemu set the map to 0 on reset. Let's add then when we add migration support and actually expose all those missing states to userspace. Currently we only expose half the necessary state for migration anyway :).
Alex
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 18 lines · On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
Quoted 17 lines · Alexander Graf
Quoted 16 lines
Documentation/kvm/ppc-pv.txt new file +5
-0+ +PPC hypercalls +============== + +The only viable ways to reliably get from guest context to hostcontext are:
Documentation/kvm/ppc-pv.txt new file +6
-0+ + 1) Call an invalid instruction + 2) Call the "sc" instruction with a parameter to "sc" + 3) Call the "sc" instruction with parameters in GPRs + +Method 1 is always a bad idea. Invalid instructions can bereplaced later on
(quoted diff) +2
-0+by valid instructions, rendering the interface broken. +
Quoted 8 lines
Quoted 8 lines
Review
Quoted 8 lines
+Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instruction(quoted diff) +2
-0+every time a syscall is issued, slowing down guest syscalls. +
It goes to the hypervisor, and it would require the hypervisor to return to the supervisor, but I believe it just returns to the user with permission denied.
Quoted 12 lines
Quoted 11 lines
Quoted 8 lines
+Method 3 is what KVM uses. We pass magic constants (
KVM_SC_MAGIC_R3and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.Is there any chance a normal syscall will have those values in r3 and r4?
Quoted 4 lines
r3 is the syscall number. So as long as the guest doesn't reuse that value, we're safe. Since in general syscall numbers are not randomly scattered throughout the number range, we should be ok here.
No, r0 has the system call number. Registers 3 and 4 are the first 2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux syscall abi special. (In addition, it returns success or failure in cr0).
Quoted 12 lines
Quoted 6 lines
If so, maybe it's better to use pc as they key for hypercalls. Let the guest designate one instruction address as the hypercall call point; kvm can easily check it and reflect it back to the guest if it doesn't match.
You mean the guest would tell the hv where the hypercall lies? That would require a hypercall, no? Defining it statically is tricky. I want to PV'nize osx using a kernel module later, so I don't have control over the physical layout.
Quoted 7 lines
Quoted 2 lines
Is it valid and useful to issue sc from privileged mode anyway, except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue syscalls within itself.
I don't believe we support the kernel actually doing a syscall to itself anymore, at least on powerpc. The callers call the underlying system call function, or kernel_thread.
That said, I would suggest we allocate a syscall number for this, as it would document the usage. (In additon to 0..nr_syscalls - 1 we have 0x1ebe in use).
Also, is there any desire to nest such emulation?
milton
A message that is not in the archive (sent off-list or not yet received): 1277709531_13308-qolCYAvwHvWlVDA81TZ6el6hYfS7NtTn@public.gmane.org
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 23 lines · Milton Miller
Quoted 22 lines · On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
Quoted 21 lines · Alexander Graf
Quoted 20 lines
Documentation/kvm/ppc-pv.txt new file +5
-0+ +PPC hypercalls +============== + +The only viable ways to reliably get from guest context to hostcontext are:
Documentation/kvm/ppc-pv.txt new file +6
-0+ + 1) Call an invalid instruction + 2) Call the "sc" instruction with a parameter to "sc" + 3) Call the "sc" instruction with parameters in GPRs + +Method 1 is always a bad idea. Invalid instructions can bereplaced later on
Documentation/kvm/ppc-pv.txt new file +3
-0+by valid instructions, rendering the interface broken. + +Method 2 also has downfalls. If the parameter to "sc" is != 0 thespec is
+rather unclear if the sc is targeted directly for the hypervisor or the
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Review
Quoted 4 lines
+supervisor. It would also require that we read the syscall issuing instruction
(quoted diff) +2
-0+every time a syscall is issued, slowing down guest syscalls. +It goes to the hypervisor, and it would require the hypervisor to return to the supervisor, but I believe it just returns to the user with permission denied.
That's what I assumed, yeah :(.
Quoted 18 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
+Method 3 is what KVM uses. We pass magic constants (
KVM_SC_MAGIC_R3and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.Is there any chance a normal syscall will have those values in r3 and r4?
Quoted 4 lines
r3 is the syscall number. So as long as the guest doesn't reuse that value, we're safe. Since in general syscall numbers are not randomly scattered throughout the number range, we should be ok here.
Quoted 4 lines
No, r0 has the system call number. Registers 3 and 4 are the first 2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux syscall abi special. (In addition, it returns success or failure in cr0).
Oh. Ahem :)
Quoted 21 lines
Quoted 13 lines
Quoted 7 lines
If so, maybe it's better to use pc as they key for hypercalls. Let the guest designate one instruction address as the hypercall call point; kvm can easily check it and reflect it back to the guest if it doesn't match.
You mean the guest would tell the hv where the hypercall lies? That would require a hypercall, no? Defining it statically is tricky. I want to PV'nize osx using a kernel module later, so I don't have control over the physical layout.
Quoted 7 lines
Quoted 2 lines
Is it valid and useful to issue sc from privileged mode anyway, except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue syscalls within itself.
Quoted 7 lines
I don't believe we support the kernel actually doing a syscall to itself anymore, at least on powerpc. The callers call the underlying system call function, or
kernel_thread.That said, I would suggest we allocate a syscall number for this, as it would document the usage. (In additon to 0..nr_syscalls - 1 we have
0x1ebein use).
That's actually a pretty good idea.
Quoted 2 lines
Also, is there any desire to nest such emulation?
Nesting should just work, right? Since we only accept hypercalls from PR=0 and guests run in PR=1, we get the sc interrupt in the l1 guest by then.
The only issue I'm aware of that completely breaks when using nested KVM on PPC is the MSR_IR != MSR_DR logic. We fetch the instruction we got an interrupt on for certain interrupts in the world switch handler by keeping MSR_IR=0, but setting MSR_DR=1. And KVM speeds up MSR_DR != MSR_IR by mapping both of them lazily in a special address space. So if you access the same page as instruction and as data, you get an invalid result.
Alex
A message that is not in the archive (sent off-list or not yet received): 92F4A3F3-A89F-418D-BD4D-66E2489F2E42-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 11 lines · Alexander Graf
Quoted 9 lines
I don't believe we support the kernel actually doing a syscall to itself anymore, at least on powerpc. The callers call the underlying system call function, or
kernel_thread.That said, I would suggest we allocate a syscall number for this, as it would document the usage. (In additon to 0..nr_syscalls - 1 we have
0x1ebein use).That's actually a pretty good idea.
Since the syscall register is not architectual (or rather it is architectural but Linux ignores it) I don't see the point. It would work for Linux but may alias some random parameter for a different guest. We need a reliable method of distinguishing between syscalls and hypercalls. Matching pc would work (but is defeated by inlining) so long as we find some other way of identifying the hc pc to the hypervisor.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 6 lines · Avi Kivity
Quoted 5 lines · Alexander Graf
Quoted 5 lines
I don't believe we support the kernel actually doing a syscall to itself anymore, at least on powerpc. The callers call the underlying system call function, or
kernel_thread.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
That said, I would suggest we allocate a syscall number for this, as it would document the usage. (In additon to 0..nr_syscalls - 1 we have
0x1ebein use).That's actually a pretty good idea.
Since the syscall register is not architectual (or rather it is architectural but Linux ignores it) I don't see the point. It would work for Linux but may alias some random parameter for a different guest. We need a reliable method of distinguishing between syscalls and hypercalls. Matching pc would work (but is defeated by inlining) so long as we find some other way of identifying the hc pc to the hypervisor.
The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
Alex
A message that is not in the archive (sent off-list or not yet received): 4330E5DC-63C5-40EA-9E99-34EE58074D1A-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 8 lines · Alexander Graf
The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
Magic = liable to break without notice.
Given r0 is the architectural syscall number, and r3 is the Linux syscall number, we can use a combination of r0 and r3, reserve r3 in Linux, and hope that no one else uses our selection of r0.
Still smelly, but not as bad.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-27-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Quoted 10 lines · Alexander Graf
We just introduced a new PV interface that screams for documentation. So here it is - a shiny new and awesome text file describing the internal works of the PPC KVM paravirtual interface.
Documentation/kvm/ppc-pv.txt new file +4
-0+Querying for existence +====================== + +To find out if we're running on KVM or not, we overlay the PVR register. Usually
Documentation/kvm/ppc-pv.txt line 31
Quoted 10 lines
Documentation/kvm/ppc-pv.txt new file +10
-0+the PVR register contains an id that identifies your CPU type. If, however, you +pass KVM_PVR_PARA in the register that you want the PVR result in, the register +still contains KVM_PVR_PARA after the mfpvr call. + + LOAD_REG_IMM(r5, KVM_PVR_PARA) + mfpvr r5 + [r5 still contains KVM_PVR_PARA] + +Once determined to run under a PV capable KVM, you can now use hypercalls as +described below.
On x86 we allow host userspace to determine whether the guest sees the paravirt interface (and what features are exposed). This allows you to live migrate from a newer host to an older host, by not exposing the newer features.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
Am 27.06.2010 um 10:34 schrieb Avi Kivity <[email protected]>:
Quoted 19 lines · Alexander Graf
Quoted 18 lines
We just introduced a new PV interface that screams for documentation. So here it is - a shiny new and awesome text file describing the internal works of the PPC KVM paravirtual interface.
Documentation/kvm/ppc-pv.txt new file +4
-0+Querying for existence +====================== + +To find out if we're running on KVM or not, we overlay the PVRregister. Usually
+the PVR register contains an id that identifies your CPU type. If, however, you
+passKVM_PVR_PARAin the register that you want the PVR result in, the registerDocumentation/kvm/ppc-pv.txt new file +4
-0+still contains KVM_PVR_PARA after the mfpvr call. + + LOAD_REG_IMM(r5, KVM_PVR_PARA) + mfpvr r5
Quoted 8 lines
Quoted 6 lines
Documentation/kvm/ppc-pv.txt new file +3
-0+ [r5 still contains KVM_PVR_PARA] + +Once determined to run under a PV capable KVM, you can now usehypercalls as
+described below.On x86 we allow host userspace to determine whether the guest sees the paravirt interface (and what features are exposed). This allows you to live migrate from a newer host to an older host, by not exposing the newer features.
A very good idea indeed. Let's postpone that to when we expose enough state to make live migration possible.
Alex
PATCH 3/26 KVM: PPC: Convert DSISR to shared page
In reply to Alexander GrafThe DSISR register contains information about a data page fault. It is fully read/write from inside the guest context and we don't need to worry about interacting based on writes of this register.
This patch converts all users of the current field to the shared page.
--- arch/powerpc/include/asm/kvm_book3s.h | 1 - arch/powerpc/include/asm/kvm_para.h | 1 + arch/powerpc/kvm/book3s.c | 11 ++++++----- arch/powerpc/kvm/book3s_emulate.c | 6 +++--- arch/powerpc/kvm/book3s_paired_singles.c | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-)
arch/powerpc/include/asm/kvm_book3s.h +0 -1
@@ -85,7 +85,6 @@ struct kvmppc_vcpu_book3s {u64 hid[6 ];u64 gqr[8 ];int slb_nr; -u32 dsisr;u64 sdr1;u64 hior;u64 msr_mask;
arch/powerpc/include/asm/kvm_para.h +1 -0
@@ -24,6 +24,7 @@struct kvm_vcpu_arch_shared {__u64 msr; +__u32 dsisr; };#ifdef __KERNEL__
arch/powerpc/kvm/book3s.c +5 -5
@@ -595,15 +595,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,if (page_found = -ENOENT ) {/* Page not found in guest PTE entries */ vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); -to_book3s (vcpu)->dsisr =to_svcpu (vcpu)->fault_dsisr; + vcpu->arch.shared->dsisr =to_svcpu (vcpu)->fault_dsisr; vcpu->arch.shared->msr | (to_svcpu (vcpu)->shadow_srr1 &0x00000000f8000000ULL );kvmppc_book3s_queue_irqprio (vcpu, vec); }else if (page_found = -EPERM ) {/* Storage protection */ vcpu->arch.dear =kvmppc_get_fault_dar (vcpu); -to_book3s (vcpu)->dsisr =to_svcpu (vcpu)->fault_dsisr & ~DSISR_NOHPTE ; -to_book3s (vcpu)->dsisr |=DSISR_PROTFAULT ; + vcpu->arch.shared->dsisr +to_svcpu (vcpu)->fault_dsisr & ~DSISR_NOHPTE ; + vcpu->arch.shared->dsisr |=DSISR_PROTFAULT ; vcpu->arch.shared->msr | (to_svcpu (vcpu)->shadow_srr1 &0x00000000f8000000ULL );kvmppc_book3s_queue_irqprio (vcpu, vec);
@@ -867,7 +868,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r =kvmppc_handle_pagefault (run, vcpu, dar, exit_nr); }else { vcpu->arch.dear = dar; -to_book3s (vcpu)->dsisr =to_svcpu (vcpu)->fault_dsisr; + vcpu->arch.shared->dsisr =to_svcpu (vcpu)->fault_dsisr;kvmppc_book3s_queue_irqprio (vcpu, exit_nr);kvmppc_mmu_pte_flush (vcpu, vcpu->arch.dear, ~0xFFFUL ); r =RESUME_GUEST ;
@@ -994,7 +995,7 @@ program_interrupt: }case BOOK3S_INTERRUPT_ALIGNMENT :if (kvmppc_read_inst (vcpu) =EMULATE_DONE ) { -to_book3s (vcpu)->dsisr =kvmppc_alignment_dsisr (vcpu, + vcpu->arch.shared->dsisr =kvmppc_alignment_dsisr (vcpu,kvmppc_get_last_inst (vcpu)); vcpu->arch.dear =kvmppc_alignment_dar (vcpu,kvmppc_get_last_inst (vcpu));
arch/powerpc/kvm/book3s_emulate.c +3 -3
@@ -221,7 +221,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,else if (r = -EPERM ) dsisr |=DSISR_PROTFAULT ; -to_book3s (vcpu)->dsisr = dsisr; + vcpu->arch.shared->dsisr = dsisr;to_svcpu (vcpu)->fault_dsisr = dsisr; kvmppc_book3s_queue_irqprio(vcpu,
@@ -327,7 +327,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)to_book3s (vcpu)->sdr1 = spr_val;break ;case SPRN_DSISR : -to_book3s (vcpu)->dsisr = spr_val; + vcpu->arch.shared->dsisr = spr_val;break ;case SPRN_DAR : vcpu->arch.dear = spr_val;
@@ -440,7 +440,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)kvmppc_set_gpr (vcpu, rt,to_book3s (vcpu)->sdr1);break ;case SPRN_DSISR : -kvmppc_set_gpr (vcpu, rt,to_book3s (vcpu)->dsisr); +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->dsisr);break ;case SPRN_DAR :kvmppc_set_gpr (vcpu, rt, vcpu->arch.dear);
arch/powerpc/kvm/book3s_paired_singles.c +1 -1
@@ -173,7 +173,7 @@ static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)/* Page Fault */ dsisr =kvmppc_set_field (0 ,33 ,33 ,1 );if (is_store) -to_book3s (vcpu)->dsisr =kvmppc_set_field (dsisr,38 ,38 ,1 ); + shared->dsisr =kvmppc_set_field (dsisr,38 ,38 ,1 );kvmppc_book3s_queue_irqprio (vcpu,BOOK3S_INTERRUPT_DATA_STORAGE ); }
Signature · 1 line
1.6.0.2
PATCH 5/26 KVM: PPC: Convert SRR0 and SRR1 to shared page
In reply to Alexander GrafThe SRR0 and SRR1 registers contain cached values of the PC and MSR respectively. They get written to by the hypervisor when an interrupt occurs or directly by the kernel. They are also used to tell the rfi(d) instruction where to jump to.
Because it only gets touched on defined events that, it's very simple to share with the guest. Hypervisor and guest both have full r/w access.
This patch converts all users of the current field to the shared page.
--- arch/powerpc/include/asm/kvm_host.h | 2 -- arch/powerpc/include/asm/kvm_para.h | 2 ++ arch/powerpc/kvm/book3s.c | 12 ++++++------ arch/powerpc/kvm/book3s_emulate.c | 4 ++-- arch/powerpc/kvm/booke.c | 15 ++++++++------- arch/powerpc/kvm/booke_emulate.c | 4 ++-- arch/powerpc/kvm/emulate.c | 12 ++++++++---- 7 files changed, 28 insertions(+), 23 deletions(-)
arch/powerpc/include/asm/kvm_host.h +0 -2
@@ -224,8 +224,6 @@ struct kvm_vcpu_arch {ulong sprg5;ulong sprg6;ulong sprg7; -ulong srr0; -ulong srr1;ulong csrr0;ulong csrr1;ulong dsrr0;
arch/powerpc/include/asm/kvm_para.h +2 -0
@@ -23,6 +23,8 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 srr0; +__u64 srr1;__u64 dar;__u64 msr;__u32 dsisr;
arch/powerpc/kvm/book3s.c +6 -6
@@ -162,8 +162,8 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)void kvmppc_inject_interrupt (struct kvm_vcpu *vcpu,int vec,u64 flags) { - vcpu->arch.srr0 =kvmppc_get_pc (vcpu); - vcpu->arch.srr1 = vcpu->arch.shared->msr | flags; + vcpu->arch.shared->srr0 =kvmppc_get_pc (vcpu); + vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags;kvmppc_set_pc (vcpu,to_book3s (vcpu)->hior + vec); vcpu->arch.mmu.reset_msr (vcpu); }
@@ -1059,8 +1059,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->lr =kvmppc_get_lr (vcpu); regs->xer =kvmppc_get_xer (vcpu); regs->msr = vcpu->arch.shared->msr; - regs->srr0 = vcpu->arch.srr0; - regs->srr1 = vcpu->arch.srr1; + regs->srr0 = vcpu->arch.shared->srr0; + regs->srr1 = vcpu->arch.shared->srr1; regs->pid = vcpu->arch.pid; regs->sprg0 = vcpu->arch.sprg0; regs->sprg1 = vcpu->arch.sprg1;
@@ -1086,8 +1086,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)kvmppc_set_lr (vcpu, regs->lr);kvmppc_set_xer (vcpu, regs->xer);kvmppc_set_msr (vcpu, regs->msr); - vcpu->arch.srr0 = regs->srr0; - vcpu->arch.srr1 = regs->srr1; + vcpu->arch.shared->srr0 = regs->srr0; + vcpu->arch.shared->srr1 = regs->srr1; vcpu->arch.sprg0 = regs->sprg0; vcpu->arch.sprg1 = regs->sprg1; vcpu->arch.sprg2 = regs->sprg2;
arch/powerpc/kvm/book3s_emulate.c +2 -2
@@ -73,8 +73,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,switch (get_xop (inst)) {case OP_19_XOP_RFID :case OP_19_XOP_RFI : -kvmppc_set_pc (vcpu, vcpu->arch.srr0); -kvmppc_set_msr (vcpu, vcpu->arch.srr1); +kvmppc_set_pc (vcpu, vcpu->arch.shared->srr0); +kvmppc_set_msr (vcpu, vcpu->arch.shared->srr1); *advance =0 ;break ;
arch/powerpc/kvm/booke.c +8 -7
@@ -64,7 +64,8 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)printk ("pc: %08lx msr: %08llx\n" , vcpu->arch.pc, vcpu->arch.shared->msr);printk ("lr: %08lx ctr: %08lx\n" , vcpu->arch.lr, vcpu->arch.ctr); -printk ("srr0: %08lx srr1: %08lx\n" , vcpu->arch.srr0, vcpu->arch.srr1); +printk ("srr0: %08llx srr1: %08llx\n" , vcpu->arch.shared->srr0, + vcpu->arch.shared->srr1);printk ("exceptions: %08lx\n" , vcpu->arch.pending_exceptions);
@@ -189,8 +190,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, }if (allowed) { - vcpu->arch.srr0 = vcpu->arch.pc; - vcpu->arch.srr1 = vcpu->arch.shared->msr; + vcpu->arch.shared->srr0 = vcpu->arch.pc; + vcpu->arch.shared->srr1 = vcpu->arch.shared->msr; vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];if (update_esr = true) vcpu->arch.esr = vcpu->arch.queued_esr;
@@ -491,8 +492,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->lr = vcpu->arch.lr; regs->xer =kvmppc_get_xer (vcpu); regs->msr = vcpu->arch.shared->msr; - regs->srr0 = vcpu->arch.srr0; - regs->srr1 = vcpu->arch.srr1; + regs->srr0 = vcpu->arch.shared->srr0; + regs->srr1 = vcpu->arch.shared->srr1; regs->pid = vcpu->arch.pid; regs->sprg0 = vcpu->arch.sprg0; regs->sprg1 = vcpu->arch.sprg1;
@@ -518,8 +519,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) vcpu->arch.lr = regs->lr;kvmppc_set_xer (vcpu, regs->xer);kvmppc_set_msr (vcpu, regs->msr); - vcpu->arch.srr0 = regs->srr0; - vcpu->arch.srr1 = regs->srr1; + vcpu->arch.shared->srr0 = regs->srr0; + vcpu->arch.shared->srr1 = regs->srr1; vcpu->arch.sprg0 = regs->sprg0; vcpu->arch.sprg1 = regs->sprg1; vcpu->arch.sprg2 = regs->sprg2;
arch/powerpc/kvm/booke_emulate.c +2 -2
@@ -31,8 +31,8 @@static void kvmppc_emul_rfi (struct kvm_vcpu *vcpu) { - vcpu->arch.pc = vcpu->arch.srr0; -kvmppc_set_msr (vcpu, vcpu->arch.srr1); + vcpu->arch.pc = vcpu->arch.shared->srr0; +kvmppc_set_msr (vcpu, vcpu->arch.shared->srr1); } int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
arch/powerpc/kvm/emulate.c +8 -4
@@ -242,9 +242,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)switch (sprn) {case SPRN_SRR0 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.srr0);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->srr0); +break ;case SPRN_SRR1 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.srr1);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->srr1); +break ;case SPRN_PVR :kvmppc_set_gpr (vcpu, rt, vcpu->arch.pvr);break ;case SPRN_PIR :
@@ -320,9 +322,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) rs =get_rs (inst);switch (sprn) {case SPRN_SRR0 : - vcpu->arch.srr0 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->srr0 =kvmppc_get_gpr (vcpu, rs); +break ;case SPRN_SRR1 : - vcpu->arch.srr1 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->srr1 =kvmppc_get_gpr (vcpu, rs); +break ;/* XXX We need to context-switch the timebase for * watchdog and FIT. */
Signature · 1 line
1.6.0.2
PATCH 6/26 KVM: PPC: Convert SPRG[0-4] to shared page
In reply to Alexander GrafWhen in kernel mode there are 4 additional registers available that are simple data storage. Instead of exiting to the hypervisor to read and write those, we can just share them with the guest using the page.
This patch converts all users of the current field to the shared page.
--- arch/powerpc/include/asm/kvm_host.h | 4 ---- arch/powerpc/include/asm/kvm_para.h | 4 ++++ arch/powerpc/kvm/book3s.c | 16 ++++++++-------- arch/powerpc/kvm/booke.c | 16 ++++++++-------- arch/powerpc/kvm/emulate.c | 24 ++++++++++++++++-------- 5 files changed, 36 insertions(+), 28 deletions(-)
arch/powerpc/include/asm/kvm_host.h +0 -4
@@ -216,10 +216,6 @@ struct kvm_vcpu_arch {ulong guest_owned_ext;#endif u32 mmucr; -ulong sprg0; -ulong sprg1; -ulong sprg2; -ulong sprg3;ulong sprg4;ulong sprg5;ulong sprg6;
arch/powerpc/include/asm/kvm_para.h +4 -0
@@ -23,6 +23,10 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 sprg0; +__u64 sprg1; +__u64 sprg2; +__u64 sprg3;__u64 srr0;__u64 srr1;__u64 dar;
arch/powerpc/kvm/book3s.c +8 -8
@@ -1062,10 +1062,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->srr0 = vcpu->arch.shared->srr0; regs->srr1 = vcpu->arch.shared->srr1; regs->pid = vcpu->arch.pid; - regs->sprg0 = vcpu->arch.sprg0; - regs->sprg1 = vcpu->arch.sprg1; - regs->sprg2 = vcpu->arch.sprg2; - regs->sprg3 = vcpu->arch.sprg3; + regs->sprg0 = vcpu->arch.shared->sprg0; + regs->sprg1 = vcpu->arch.shared->sprg1; + regs->sprg2 = vcpu->arch.shared->sprg2; + regs->sprg3 = vcpu->arch.shared->sprg3; regs->sprg5 = vcpu->arch.sprg4; regs->sprg6 = vcpu->arch.sprg5; regs->sprg7 = vcpu->arch.sprg6;
@@ -1088,10 +1088,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)kvmppc_set_msr (vcpu, regs->msr); vcpu->arch.shared->srr0 = regs->srr0; vcpu->arch.shared->srr1 = regs->srr1; - vcpu->arch.sprg0 = regs->sprg0; - vcpu->arch.sprg1 = regs->sprg1; - vcpu->arch.sprg2 = regs->sprg2; - vcpu->arch.sprg3 = regs->sprg3; + vcpu->arch.shared->sprg0 = regs->sprg0; + vcpu->arch.shared->sprg1 = regs->sprg1; + vcpu->arch.shared->sprg2 = regs->sprg2; + vcpu->arch.shared->sprg3 = regs->sprg3; vcpu->arch.sprg5 = regs->sprg4; vcpu->arch.sprg6 = regs->sprg5; vcpu->arch.sprg7 = regs->sprg6;
arch/powerpc/kvm/booke.c +8 -8
@@ -495,10 +495,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->srr0 = vcpu->arch.shared->srr0; regs->srr1 = vcpu->arch.shared->srr1; regs->pid = vcpu->arch.pid; - regs->sprg0 = vcpu->arch.sprg0; - regs->sprg1 = vcpu->arch.sprg1; - regs->sprg2 = vcpu->arch.sprg2; - regs->sprg3 = vcpu->arch.sprg3; + regs->sprg0 = vcpu->arch.shared->sprg0; + regs->sprg1 = vcpu->arch.shared->sprg1; + regs->sprg2 = vcpu->arch.shared->sprg2; + regs->sprg3 = vcpu->arch.shared->sprg3; regs->sprg5 = vcpu->arch.sprg4; regs->sprg6 = vcpu->arch.sprg5; regs->sprg7 = vcpu->arch.sprg6;
@@ -521,10 +521,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)kvmppc_set_msr (vcpu, regs->msr); vcpu->arch.shared->srr0 = regs->srr0; vcpu->arch.shared->srr1 = regs->srr1; - vcpu->arch.sprg0 = regs->sprg0; - vcpu->arch.sprg1 = regs->sprg1; - vcpu->arch.sprg2 = regs->sprg2; - vcpu->arch.sprg3 = regs->sprg3; + vcpu->arch.shared->sprg0 = regs->sprg0; + vcpu->arch.shared->sprg1 = regs->sprg1; + vcpu->arch.shared->sprg2 = regs->sprg2; + vcpu->arch.shared->sprg3 = regs->sprg3; vcpu->arch.sprg5 = regs->sprg4; vcpu->arch.sprg6 = regs->sprg5; vcpu->arch.sprg7 = regs->sprg6;
arch/powerpc/kvm/emulate.c +16 -8
@@ -263,13 +263,17 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)kvmppc_set_gpr (vcpu, rt,get_tb ());break ;case SPRN_SPRG0 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.sprg0);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->sprg0); +break ;case SPRN_SPRG1 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.sprg1);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->sprg1); +break ;case SPRN_SPRG2 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.sprg2);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->sprg2); +break ;case SPRN_SPRG3 : -kvmppc_set_gpr (vcpu, rt, vcpu->arch.sprg3);break ; +kvmppc_set_gpr (vcpu, rt, vcpu->arch.shared->sprg3); +break ;/* Note: SPRG4-7 are user-readable, so we don't get * a trap. */
@@ -341,13 +345,17 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)break ;case SPRN_SPRG0 : - vcpu->arch.sprg0 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->sprg0 =kvmppc_get_gpr (vcpu, rs); +break ;case SPRN_SPRG1 : - vcpu->arch.sprg1 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->sprg1 =kvmppc_get_gpr (vcpu, rs); +break ;case SPRN_SPRG2 : - vcpu->arch.sprg2 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->sprg2 =kvmppc_get_gpr (vcpu, rs); +break ;case SPRN_SPRG3 : - vcpu->arch.sprg3 =kvmppc_get_gpr (vcpu, rs);break ; + vcpu->arch.shared->sprg3 =kvmppc_get_gpr (vcpu, rs); +break ;default : emulated =kvmppc_core_emulate_mtspr (vcpu, sprn, rs);
Signature · 1 line
1.6.0.2
PATCH 7/26 KVM: PPC: Implement hypervisor interface
In reply to Alexander GrafTo 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.
--- 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(-)
arch/powerpc/include/asm/kvm_para.h +98 -2
@@ -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 ; + + asmvolatile ("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; + + asmvolatile ("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; + + asmvolatile ("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; + + asmvolatile ("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; + + asmvolatile ("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; + + asmvolatile ("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__ */
arch/powerpc/include/asm/kvm_ppc.h +1 -0
@@ -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.
arch/powerpc/kvm/book3s.c +8 -2
@@ -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 ;
arch/powerpc/kvm/booke.c +10 -1
@@ -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 ;
arch/powerpc/kvm/emulate.c +10 -1
@@ -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 :
arch/powerpc/kvm/powerpc.c +28 -0
@@ -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) {
include/linux/kvm_para.h +1 -0
@@ -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
Signature · 1 line
1.6.0.2
PATCH 9/26 KVM: PPC: Add PV guest scratch registers
In reply to Alexander GrafWhile running in hooked code we need to store register contents out because we must not clobber any registers.
So let's add some fields to the shared page we can just happily write to.
--- arch/powerpc/include/asm/kvm_para.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/kvm_para.h +3 -0
@@ -23,6 +23,9 @@#include <linux/types.h> struct kvm_vcpu_arch_shared { +__u64 scratch1; +__u64 scratch2; +__u64 scratch3;__u64 critical;/* Guest may not get interrupts if = r1 */ __u64 sprg0;__u64 sprg1;
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-10-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 09/26] KVM: PPC: Add PV guest scratch registers
Quoted 6 lines · Alexander Graf
While running in hooked code we need to store register contents out because we must not clobber any registers.
So let's add some fields to the shared page we can just happily write to.
How are these protected during interrupts?
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 09/26] KVM: PPC: Add PV guest scratch registers
Am 27.06.2010 um 10:22 schrieb Avi Kivity <[email protected]>:
Quoted 9 lines · Alexander Graf
Quoted 6 lines
While running in hooked code we need to store register contents out because we must not clobber any registers.
So let's add some fields to the shared page we can just happily write to.
How are these protected during interrupts?
By the 'critical section' bit. When in a critical section (read: using scratch registers), we don't issue interrupts.
Alex
A message that is not in the archive (sent off-list or not yet received): 27BB673F-F34E-4CC6-A22D-02CF95E7529F-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 09/26] KVM: PPC: Add PV guest scratch registers
Quoted 7 lines · Alexander Graf
Am 27.06.2010 um 10:22 schrieb Avi Kivity <[email protected]>:
Quoted 4 lines · Alexander Graf
Quoted 3 lines
While running in hooked code we need to store register contents out because we must not clobber any registers.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
So let's add some fields to the shared page we can just happily write to.
How are these protected during interrupts?
By the 'critical section' bit. When in a critical section (read: using scratch registers), we don't issue interrupts.
Ok. I thought you needed scratch registers to set up the critical section, but you don't. Neat stuff.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 10/26 KVM: PPC: Tell guest about pending interrupts
In reply to Alexander GrafWhen the guest turns on interrupts again, it needs to know if we have an interrupt pending for it. Because if so, it should rather get out of guest context and get the interrupt.
So we introduce a new field in the shared page that we use to tell the guest that there's a pending interrupt lying around.
--- arch/powerpc/include/asm/kvm_para.h | 1 + arch/powerpc/kvm/book3s.c | 7 +++++++ arch/powerpc/kvm/booke.c | 7 +++++++ 3 files changed, 15 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/kvm_para.h +1 -0
@@ -36,6 +36,7 @@ struct kvm_vcpu_arch_shared {__u64 dar;__u64 msr;__u32 dsisr; +__u32 int_pending;/* Tells the guest if we have an interrupt */ };#define KVM_PVR_PARA 0x4b564d3f/* "KVM?" */
arch/powerpc/kvm/book3s.c +7 -0
@@ -334,6 +334,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)void kvmppc_core_deliver_interrupts (struct kvm_vcpu *vcpu) {unsigned long *pending = &vcpu->arch.pending_exceptions; +unsigned long old_pending = vcpu->arch.pending_exceptions;unsigned int priority;#ifdef EXIT_DEBUG
@@ -353,6 +354,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)BITS_PER_BYTE *sizeof (*pending), priority + 1); } + +/* Tell the guest about our interrupt status */ +if (*pending) + vcpu->arch.shared->int_pending =1 ; +else if (old_pending) + vcpu->arch.shared->int_pending =0 ; }void kvmppc_set_pvr (struct kvm_vcpu *vcpu,u32 pvr)
arch/powerpc/kvm/booke.c +7 -0
@@ -221,6 +221,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,void kvmppc_core_deliver_interrupts (struct kvm_vcpu *vcpu) {unsigned long *pending = &vcpu->arch.pending_exceptions; +unsigned long old_pending = vcpu->arch.pending_exceptions;unsigned int priority; priority =__ffs (*pending);
@@ -232,6 +233,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)BITS_PER_BYTE *sizeof (*pending), priority + 1); } + +/* Tell the guest about our interrupt status */ +if (*pending) + vcpu->arch.shared->int_pending =1 ; +else if (old_pending) + vcpu->arch.shared->int_pending =0 ; }/**
Signature · 1 line
1.6.0.2
PATCH 11/26 KVM: PPC: Make RMO a define
In reply to Alexander GrafOn PowerPC it's very normal to not support all of the physical RAM in real mode. To check if we're matching on the shared page or not, we need to know the limits so we can restrain ourselves to that range.
So let's make it a define instead of open-coding it. And while at it, let's also increase it.
--- arch/powerpc/include/asm/kvm_host.h | 2 ++ arch/powerpc/kvm/book3s.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/kvm_host.h +2 -0
@@ -47,6 +47,8 @@#define HPTEG_HASH_NUM_VPTE (1 << HPTEG_HASH_BITS_VPTE)#define HPTEG_HASH_NUM_VPTE_LONG (1 << HPTEG_HASH_BITS_VPTE_LONG) +#define KVM_RMO 0x0fffffffffffffffULL +struct kvm ;struct kvm_run ;struct kvm_vcpu ;
arch/powerpc/kvm/book3s.c +2 -2
@@ -462,7 +462,7 @@ static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, r = vcpu->arch.mmu.xlate (vcpu, eaddr, pte, data); }else { pte->eaddr = eaddr; - pte->raddr = eaddr &0xffffffff ; + pte->raddr = eaddr &KVM_RMO ; pte->vpage =VSID_REAL | eaddr >>12 ; pte->may_read = true; pte->may_write = true;
@@ -576,7 +576,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, pte.may_execute = true; pte.may_read = true; pte.may_write = true; - pte.raddr = eaddr &0xffffffff ; + pte.raddr = eaddr &KVM_RMO ; pte.eaddr = eaddr; pte.vpage = eaddr >>12 ; }
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-12-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Quoted 1 line
On PowerPC it's very normal to not support all of the physical RAM in real mode.
Oh? Are you referring to "real mode limit", or 32-bit implementations with more than 32 address lines, or something else?
Either way, RMO is a really bad name for this, since that name is already used for a similar but different concept.
Also, it seems you construct the physical address by masking out bits from the effective address. Most implementations will trap or machine check if you address outside of physical address space, instead.
Segher
A message that is not in the archive (sent off-list or not yet received): 2078D8A9-7D36-4B5D-A779-9BBAB545A53D-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Am 26.06.2010 um 18:52 schrieb Segher Boessenkool <[email protected]>:
Quoted 4 lines
Quoted 1 line
On PowerPC it's very normal to not support all of the physical RAM in real mode.
Oh? Are you referring to "real mode limit", or 32-bit implementations with more than 32 address lines, or something else?
The former.
Quoted 3 lines
Either way, RMO is a really bad name for this, since that name is already used for a similar but different concept.
It's the same concept, no? Not all physical memory is accessible from real mode.
Quoted 4 lines
Also, it seems you construct the physical address by masking out bits from the effective address. Most implementations will trap or machine check if you address outside of physical address space, instead.
Well the only case where I remember to have hit a real RMO case is on the PS3 - that issues a data/instruction storage interrupt when accessing anything > 8MB in real mode.
So I'd argue this is heavily implementation specific.
Apart from that what I'm trying to cover is that on ppc64 accessing 0xc0000000000000 in real mode gets you 0x0. Is there a better name for this?
Alex
Quoted 1 line
A message that is not in the archive (sent off-list or not yet received): 9B84B663-7DC6-4543-96F7-23F77106065C-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
On PowerPC it's very normal to not support all of the physical RAM in real mode.
Oh? Are you referring to "real mode limit", or 32-bit implementations with more than 32 address lines, or something else?
The former.
Okay. In that case, the hypervisor can usually access all of physical ram directly, unless it limits itself; and a supervisor gets either no real mode access, or all ram, or some part -- whatever the hypervisor likes.
If you access outside of ram, you will most likely get a machine check. Depends on the implementation (like most things here).
Quoted 4 lines
Quoted 2 lines
Either way, RMO is a really bad name for this, since that name is already used for a similar but different concept.
It's the same concept, no? Not all physical memory is accessible from real mode.
I think you're looking for "real mode limit":
The concept is called "offset real mode".
RMO ("real mode offset") is the value that is ORed to an effective address to make the physical address (not added, "offset" is a pretty bad name). RML ("real mode limit") is the value that has to be bigger than the effective address or you will get an exception.
RMA ("real mode area") is the name for the range of addresses usable in offset real mode.
Quoted 7 lines
Quoted 3 lines
Also, it seems you construct the physical address by masking out bits from the effective address. Most implementations will trap or machine check if you address outside of physical address space, instead.
Well the only case where I remember to have hit a real RMO case is on the PS3 - that issues a data/instruction storage interrupt when accessing anything > 8MB in real mode.
So I'd argue this is heavily implementation specific.
It is. So what is the behaviour you want to implement?
Quoted 1 line
Apart from that what I'm trying to cover is that on ppc64 accessing
0xc0000000000000in real mode gets you0x0. Is there a better name for this?
(You missed two zeroes).
In hypervisor real mode, the top few bits are magic. They are used for e.g. enabling hypervisor offset real mode.
In supervisor real mode, those bits are ignored (and all other bits that do not correspond to physical address lines may also be ignored).
Maybe you want to call it physical_address_mask or similar?
Segher
A message that is not in the archive (sent off-list or not yet received): 07830DA6-1B53-4E84-A0E2-8449289C71F1-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Quoted 35 lines · Segher Boessenkool
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
On PowerPC it's very normal to not support all of the physical RAM in real mode.
Oh? Are you referring to "real mode limit", or 32-bit implementations with more than 32 address lines, or something else?
The former.
Okay. In that case, the hypervisor can usually access all of physical ram directly, unless it limits itself; and a supervisor gets either no real mode access, or all ram, or some part -- whatever the hypervisor likes.
If you access outside of ram, you will most likely get a machine check. Depends on the implementation (like most things here).
Quoted 4 lines
Quoted 2 lines
Either way, RMO is a really bad name for this, since that name is already used for a similar but different concept.
It's the same concept, no? Not all physical memory is accessible from real mode.
I think you're looking for "real mode limit":
The concept is called "offset real mode".
RMO ("real mode offset") is the value that is ORed to an effective address to make the physical address (not added, "offset" is a pretty bad name). RML ("real mode limit") is the value that has to be bigger than the effective address or you will get an exception.
RMA ("real mode area") is the name for the range of addresses usable in offset real mode.Quoted 4 lines
Quoted 3 lines
Also, it seems you construct the physical address by masking out bits from the effective address. Most implementations will trap or machine check if you address outside of physical address space, instead.
Quoted 5 lines
Quoted 3 lines
Well the only case where I remember to have hit a real RMO case is on the PS3 - that issues a data/instruction storage interrupt when accessing anything > 8MB in real mode.
So I'd argue this is heavily implementation specific.
It is. So what is the behaviour you want to implement?
The one below.
Quoted 8 lines
Quoted 2 lines
Apart from that what I'm trying to cover is that on ppc64 accessing
0xc0000000000000in real mode gets you0x0. Is there a better name for this?(You missed two zeroes).
In hypervisor real mode, the top few bits are magic. They are used for e.g. enabling hypervisor offset real mode.
In supervisor real mode, those bits are ignored (and all other bits that do not correspond to physical address lines may also be ignored).
So which bits exactly are reserved? I couldn't find a reference to that part.
Quoted 1 line
Maybe you want to call it
physical_address_maskor similar?
PAM - doesn't sound bad :).
Alex
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 5 lines
Also, it seems you construct the physical address by masking out bits from
the effective address. Most implementations will trap or machine check if
you address outside of physical address space, instead.Well the only case where I remember to have hit a real RMO case is on the PS3 - that issues a data/instruction storage interrupt when accessing anything > 8MB in real mode.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
So I'd argue this is heavily implementation specific.
It is. So what is the behaviour you want to implement?
The one below.
I'm sorry, I lost it. "Below"?
Quoted 12 lines
Quoted 11 lines
Quoted 3 lines
Apart from that what I'm trying to cover is that on ppc64 accessing
0xc0000000000000in real mode gets you0x0. Is there a better name for this?(You missed two zeroes).
In hypervisor real mode, the top few bits are magic. They are used for e.g.
enabling hypervisor offset real mode.
In supervisor real mode, those bits are ignored (and all other bits that do
not correspond to physical address lines may also be ignored).
Quoted 2 lines
So which bits exactly are reserved? I couldn't find a reference to that part.
If by "reserved" you mean "cannot be used for addressing", it's the top four
bits. Book III-S chapter 5.7.3 in the Power Architecture 2.06 document. Implementations are allowed to ignore more bits than that.
I believe in earlier versions of the architecture it was the top two bits,
not four, but maybe I misremember.
Quoted 3 lines
Quoted 1 line
Maybe you want to call it
physical_address_maskor similar?PAM - doesn't sound bad :).
And miraculously nothing in the Power arch uses that acronym yet! But I would spell it out if I were you, acronyms are confusing.
Segher
A message that is not in the archive (sent off-list or not yet received): 1550A5F0-3A22-48ED-8251-96328E2FEAE3-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
Re: [PATCH 11/26] KVM: PPC: Make RMO a define
Quoted 6 lines · Segher Boessenkool
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
Also, it seems you construct the physical address by masking out bits from the effective address. Most implementations will trap or machine check if you address outside of physical address space, instead.
Well the only case where I remember to have hit a real RMO case is on the PS3 - that issues a data/instruction storage interrupt when accessing anything > 8MB in real mode.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
So I'd argue this is heavily implementation specific.
It is. So what is the behaviour you want to implement?
The one below.
I'm sorry, I lost it. "Below"?
Well, the ones a few lines below :).
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 2 lines
Apart from that what I'm trying to cover is that on ppc64 accessing
0xc0000000000000in real mode gets you0x0. Is there a better name for this?(You missed two zeroes).
In hypervisor real mode, the top few bits are magic. They are used for e.g. enabling hypervisor offset real mode.
In supervisor real mode, those bits are ignored (and all other bits that do not correspond to physical address lines may also be ignored).
Quoted 8 lines
Quoted 1 line
So which bits exactly are reserved? I couldn't find a reference to that part.
If by "reserved" you mean "cannot be used for addressing", it's the top four bits. Book III-S chapter 5.7.3 in the Power Architecture 2.06 document. Implementations are allowed to ignore more bits than that.
I believe in earlier versions of the architecture it was the top two bits, not four, but maybe I misremember.
Ah, nice. So that part is implementation specific too. Awesome ;).
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Maybe you want to call it
physical_address_maskor similar?PAM - doesn't sound bad :).
And miraculously nothing in the Power arch uses that acronym yet! But I would spell it out if I were you, acronyms are confusing.
Well, the bad thing about not using acronyms here is that I'll run out of the 80 character limit pretty soon. And that means line wraps and more confusingness when reading the code.
Alex
PATCH 12/26 KVM: PPC: First magic page steps
In reply to Alexander GrafWe will be introducing a method to project the shared page in guest context. As soon as we're talking about this coupling, the shared page is colled magic page.
This patch introduces simple defines, so the follow-up patches are easier to read.
--- arch/powerpc/include/asm/kvm_host.h | 2 ++ include/linux/kvm_para.h | 1 + 2 files changed, 3 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/kvm_host.h +2 -0
@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {u64 dec_jiffies;unsigned long pending_exceptions;struct kvm_vcpu_arch_shared *shared; +unsigned long magic_page_pa;/* phys addr to map the magic page to */ +unsigned long magic_page_ea;/* effect. addr to map the magic page to */ #ifdef CONFIG_PPC_BOOK3S struct kmem_cache *hpte_cache;
include/linux/kvm_para.h +1 -0
@@ -18,6 +18,7 @@#define KVM_HC_VAPIC_POLL_IRQ 1#define KVM_HC_MMU_OP 2#define KVM_HC_FEATURES 3 +#define KVM_HC_PPC_MAP_MAGIC_PAGE 4/* * hypercalls use architecture specific
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-13-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 12/26] KVM: PPC: First magic page steps
Quoted 14 lines · Alexander Graf
We will be introducing a method to project the shared page in guest context. As soon as we're talking about this coupling, the shared page is colled magic page.
This patch introduces simple defines, so the follow-up patches are easier to read.
arch/powerpc/include/asm/kvm_host.h +0
-0
arch/powerpc/include/asm/kvm_host.h struct kvm_vcpu_arch { · line 290
Quoted 6 lines
arch/powerpc/include/asm/kvm_host.h +2
-0@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {u64 dec_jiffies;unsigned long pending_exceptions;struct kvm_vcpu_arch_shared *shared; +unsigned long magic_page_pa;/* phys addr to map the magic page to */ +unsigned long magic_page_ea;/* effect. addr to map the magic page to */
Is ea like a va? If so, can't the guest specify it by manipulating the hash table (or tlb)?
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 12/26] KVM: PPC: First magic page steps
Am 27.06.2010 um 10:24 schrieb Avi Kivity <[email protected]>:
Quoted 10 lines · Alexander Graf
Quoted 9 lines
We will be introducing a method to project the shared page in guest context. As soon as we're talking about this coupling, the shared page is colled magic page.
This patch introduces simple defines, so the follow-up patches are easier to read.
Quoted 15 lines
Quoted 9 lines
arch/powerpc/include/asm/kvm_host.h +1
-0@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {u64 dec_jiffies;unsigned long pending_exceptions;struct kvm_vcpu_arch_shared *shared; +unsigned long magic_page_pa;/* phys addr to map the magic Quoted 4 lines
page to */
+ unsigned longmagic_page_ea; /* effect. addr to map the magic
page to */Is ea like a va? If so, can't the guest specify it by manipulating the hash table (or tlb)?
ea in ppc speech is va in x86 speech. Yes, the guest could map it itself, but I couldn't find out how. This way I at least know what's happening :).
Alex
PATCH 15/26 KVM: PPC: Expose magic page support to guest
In reply to Alexander GrafNow that we have the shared page in place and the MMU code knows about the magic page, we can expose that capability to the guest!
--- arch/powerpc/include/asm/kvm_para.h | 2 ++ arch/powerpc/kvm/powerpc.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/kvm_para.h +2 -0
@@ -43,6 +43,8 @@ struct kvm_vcpu_arch_shared {#define KVM_SC_MAGIC_R3 0x4b564d52/* "KVMR" */ #define KVM_SC_MAGIC_R4 0x554c455a/* "ULEZ" */ +#define KVM_FEATURE_MAGIC_PAGE 1 +#ifdef __KERNEL__static inline int kvm_para_available (void )
arch/powerpc/kvm/powerpc.c +11 -0
@@ -60,8 +60,19 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) }switch (nr) { +case KVM_HC_PPC_MAP_MAGIC_PAGE : + { + vcpu->arch.magic_page_pa = param1; + vcpu->arch.magic_page_ea = param2; + + r =0 ; +break ; + }case KVM_HC_FEATURES : r =0 ; +#if !defined(CONFIG_KVM_440 )/* XXX missing bits on 440 */ + r |= (1 <<KVM_FEATURE_MAGIC_PAGE ); +#endif break ;default : r = -KVM_ENOSYS ;
Signature · 1 line
1.6.0.2
PATCH 16/26 KVM: Move kvm_guest_init out of generic code
In reply to Alexander GrafCurrently x86 is the only architecture that uses kvm_guest_init(). With PowerPC we're getting a second user, but the signature is different there and we don't need to export it, as it uses the normal kernel init framework.
So let's move the x86 specific definition of that function over to the x86 specfic header file.
--- arch/x86/include/asm/kvm_para.h | 6 ++++++ include/linux/kvm_para.h | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-)
arch/x86/include/asm/kvm_para.h +6 -0
@@ -158,6 +158,12 @@ static inline unsigned int kvm_arch_para_features(void)return cpuid_eax (KVM_CPUID_FEATURES ); } +#ifdef CONFIG_KVM_GUEST +void __init kvm_guest_init (void ); +#else +#define kvm_guest_init () do { } while (0)#endif +#endif /* __KERNEL__ */ +#endif /* _ASM_X86_KVM_PARA_H */
include/linux/kvm_para.h +0 -5
@@ -26,11 +26,6 @@#include <asm/kvm_para.h> #ifdef __KERNEL__ -#ifdef CONFIG_KVM_GUEST -void __init kvm_guest_init (void ); -#else -#define kvm_guest_init () do { } while (0) -#endif static inline int kvm_para_has_feature (unsigned int feature) {
Signature · 1 line
1.6.0.2
PATCH 18/26 KVM: PPC: KVM PV guest stubs
In reply to Alexander GrafWe will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
--- arch/powerpc/kernel/kvm.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +59 -0
@@ -32,3 +32,62 @@#define KVM_MAGIC_PAGE (-4096L)#define magic_var (x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) +static bool kvm_patching_worked = true; + +static void kvm_map_magic_page (void *data) +{ +kvm_hypercall2 (KVM_HC_PPC_MAP_MAGIC_PAGE , +KVM_MAGIC_PAGE ,/* Physical Address */ +KVM_MAGIC_PAGE );/* Effective Address */ +} + +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst & ~KVM_MASK_RT ; +u32 inst_rt = _inst &KVM_MASK_RT ; + +switch (inst_no_rt) { + } + +switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +} + +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ + +on_each_cpu (kvm_map_magic_page,NULL ,1 ); + +/* Now loop through all code and find instructions */ + + start = (void *)_stext; + end = (void *)_etext; + +for (p = start; p < end; p++) +kvm_check_ins (p); +} + +static int __init kvm_guest_init (void ) +{ +char *p; + +if (!kvm_para_available ()) +return 0 ; + +if (kvm_para_has_feature (KVM_FEATURE_MAGIC_PAGE )) +kvm_use_magic_page (); + +printk (KERN_INFO "KVM: Live patching for a fast VM %s\n" , + kvm_patching_worked ?"worked" :"failed" ); + +return 0 ; +} + +postcore_initcall (kvm_guest_init);
Signature · 1 line
1.6.0.2
A message that is not in the archive (sent off-list or not yet received): 1277508314-915-19-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 14 lines · Alexander Graf
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
arch/powerpc/kernel/kvm.c +5
-0+ +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst& ~KVM_MASK_RT ;
arch/powerpc/kernel/kvm.c line 57
Quoted 10 lines
arch/powerpc/kernel/kvm.c +10
-0+u32 inst_rt = _inst&KVM_MASK_RT ; + +switch (inst_no_rt) { + } + +switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +}
Shouldn't we flush only if we patched something?
Quoted 10 lines
arch/powerpc/kernel/kvm.c +9
-0+ +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ + +on_each_cpu (kvm_map_magic_page,NULL ,1 );
arch/powerpc/kernel/kvm.c line 76
Quoted 10 lines
arch/powerpc/kernel/kvm.c +10
-0+ +/* Now loop through all code and find instructions */ + + start = (void *)_stext; + end = (void *)_etext; + +for (p = start; p< end; p++) +kvm_check_ins (p); +} +
Or, flush the entire thing here.
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Am 27.06.2010 um 10:28 schrieb Avi Kivity <[email protected]>:
Quoted 19 lines · Alexander Graf
Quoted 18 lines
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
arch/powerpc/kernel/kvm.c +10
-0+ +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst& ~KVM_MASK_RT ; +u32 inst_rt = _inst&KVM_MASK_RT ; + +switch (inst_no_rt) { + } +
Quoted 8 lines
arch/powerpc/kernel/kvm.c line 57
Quoted 6 lines
arch/powerpc/kernel/kvm.c +5
-0+switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +}Shouldn't we flush only if we patched something?
We introduce the patching in the next patches. This is only a preparation stub.
Quoted 15 lines
Quoted 15 lines
arch/powerpc/kernel/kvm.c +14
-0+ +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ + +on_each_cpu (kvm_map_magic_page,NULL ,1 ); + +/* Now loop through all code and find instructions */ + + start = (void *)_stext; + end = (void *)_etext;
Quoted 8 lines
arch/powerpc/kernel/kvm.c line 76
Quoted 6 lines
arch/powerpc/kernel/kvm.c +5
-0+ +for (p = start; p< end; p++) +kvm_check_ins (p); +} +Or, flush the entire thing here.
I did that at first. It breaks. During the patching we may take interrupts (pahe faults for example) that contain just patched instructions. And really, hell breaks loose if we don't flush it immediately :). I was hoping at first a 32 bit replace would be atomic in cache, but the cpu tried to execute invalid instructions, so it must have gotten some intermediate state.
Alex
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 32 lines · Alexander Graf
Am 27.06.2010 um 10:28 schrieb Avi Kivity <[email protected]>:
Quoted 20 lines · Alexander Graf
Quoted 19 lines
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches
I split out the generic looping and magic page mapping code out.This patch still only contains stubs. But at least it loops through the text section :).
arch/powerpc/kernel/kvm.c +10
-0+ +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst& ~KVM_MASK_RT ; +u32 inst_rt = _inst&KVM_MASK_RT ; + +switch (inst_no_rt) { + } +Quoted 8 lines
arch/powerpc/kernel/kvm.c line 57
Quoted 6 lines
arch/powerpc/kernel/kvm.c +5
-0+switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +}Shouldn't we flush only if we patched something?
Quoted 2 lines
We introduce the patching in the next patches. This is only a preparation stub.
Well, unless I missed something, this remains unconditional after all the patches.
A helper patch(pc, replacement) could patch and flush in one go.
Quoted 25 lines
Quoted 16 lines
Quoted 16 lines
arch/powerpc/kernel/kvm.c +14
-0+ +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ + +on_each_cpu (kvm_map_magic_page,NULL ,1 ); + +/* Now loop through all code and find instructions */ + + start = (void *)_stext; + end = (void *)_etext;Quoted 8 lines
arch/powerpc/kernel/kvm.c line 76
Quoted 6 lines
arch/powerpc/kernel/kvm.c +5
-0+ +for (p = start; p< end; p++) +kvm_check_ins (p); +} +Or, flush the entire thing here.
Quoted 6 lines
I did that at first. It breaks. During the patching we may take interrupts (pahe faults for example) that contain just patched instructions. And really, hell breaks loose if we don't flush it immediately :). I was hoping at first a 32 bit replace would be atomic in cache, but the cpu tried to execute invalid instructions, so it must have gotten some intermediate state.
Surprising. Maybe you need a flush after writing to the out-of-line code?
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Am 27.06.2010 um 12:16 schrieb Avi Kivity <[email protected]>:
Quoted 32 lines · Alexander Graf
Quoted 31 lines
Am 27.06.2010 um 10:28 schrieb Avi Kivity <[email protected]>:
Quoted 27 lines · Alexander Graf
Quoted 14 lines
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
(quoted diff) +5
-0+ +static void kvm_check_ins(u32 *inst) +{ + u32 _inst = *inst; + u32 inst_no_rt = _inst& ~KVM_MASK_RT;Review
Quoted 10 lines
(quoted diff) +10
-0+ u32 inst_rt = _inst& KVM_MASK_RT; + + switch (inst_no_rt) { + } + + switch (_inst) { + } + + flush_icache_range((ulong)inst, (ulong)inst + 4); +}Shouldn't we flush only if we patched something?
Quoted 5 lines
Quoted 1 line
We introduce the patching in the next patches. This is only a preparation stub.
Well, unless I missed something, this remains unconditional after all the patches.
A helper
patch(pc, replacement)could patch and flush in one go.
Oh I see what you mean. While not necessary, it would save a few cycles on guest bootup.
Quoted 26 lines
Quoted 26 lines
Quoted 25 lines
Quoted 13 lines
(quoted diff) +9
-0+ +static void kvm_use_magic_page(void) +{ + u32 *p; + u32 *start, *end; + + /* Tell the host to map the magic page to -4096 on all CPUs */ + + on_each_cpu(kvm_map_magic_page, NULL, 1);Review
Quoted 10 lines
(quoted diff) +10
-0+ + /* Now loop through all code and find instructions */ + + start = (void*)_stext; + end = (void*)_etext; + + for (p = start; p< end; p++) + kvm_check_ins(p); +} +Or, flush the entire thing here.
Quoted 3 lines
Quoted 1 line
I did that at first. It breaks. During the patching we may take interrupts (pahe faults for example) that contain just patched instructions. And really, hell breaks loose if we don't flush it immediately :). I was hoping at first a 32 bit replace would be atomic in cache, but the cpu tried to execute invalid instructions, so it must have gotten some intermediate state.
Surprising. Maybe you need a flush after writing to the out-of-line code?
I do that too now :). Better flush too often that too rarely. It's not _that_ expensive after all.
Alex
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
In reply to Alexander GrafQuoted 7 lines · Alexander Graf
I did that at first. It breaks. During the patching we may take interrupts (pahe faults for example) that contain just patched instructions. And really, hell breaks loose if we don't flush it immediately :). I was hoping at first a 32 bit replace would be atomic
in cache, but the cpu tried to execute invalid instructions, so it must have gotten some intermediate state.
A 32-bit aligned store -is- atomic. The other threads/cpu will see either the old or the new instruction, nothing in between.
Cheers,
Ben.
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
In reply to a message not in the archiveHowdy Alex!
Quoted 51 lines · Alexander Graf
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
Signed-off-by Alexander Graf <[email protected]>--- arch/powerpc/kernel/kvm.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)arch/powerpc/kernel/kvm.c +31
-0@@ -32,3 +32,62 @@#define KVM_MAGIC_PAGE (-4096L)#define magic_var (x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) +static bool kvm_patching_worked = true; + +static void kvm_map_magic_page (void *data) +{ +kvm_hypercall2 (KVM_HC_PPC_MAP_MAGIC_PAGE , +KVM_MAGIC_PAGE ,/* Physical Address */ +KVM_MAGIC_PAGE );/* Effective Address */ +} + +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst & ~KVM_MASK_RT ; +u32 inst_rt = _inst &KVM_MASK_RT ; + +switch (inst_no_rt) { + } + +switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +} + +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ +
arch/powerpc/kernel/kvm.c line 75
Quoted 10 lines
arch/powerpc/kernel/kvm.c +10
-0+on_each_cpu (kvm_map_magic_page,NULL ,1 ); + +/* Now loop through all code and find instructions */ + + start = (void *)_stext; + end = (void *)_etext; + +for (p = start; p < end; p++) +kvm_check_ins (p); +}
Could you do something similar in module_finalize() to patch loaded modules' .text sections?
Quoted 8 lines
arch/powerpc/kernel/kvm.c +8
-0+ +static int __init kvm_guest_init (void ) +{ +char *p; + +if (!kvm_para_available ()) +return 0 ; +
arch/powerpc/kernel/kvm.c line 93
Quoted 10 lines
arch/powerpc/kernel/kvm.c +10
-0+if (kvm_para_has_feature (KVM_FEATURE_MAGIC_PAGE )) +kvm_use_magic_page (); + +printk (KERN_INFO "KVM: Live patching for a fast VM %s\n" , + kvm_patching_worked ?"worked" :"failed" ); + +return 0 ; +} + +postcore_initcall (kvm_guest_init);
Cheers,
Matt
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 58 lines · Matt Evans
Howdy Alex!
Quoted 55 lines · Alexander Graf
We will soon start and replace instructions from the text section with other, paravirtualized versions. To ease the readability of those patches I split out the generic looping and magic page mapping code out.
This patch still only contains stubs. But at least it loops through the text section :).
Signed-off-by Alexander Graf <[email protected]>---
arch/powerpc/kernel/kvm.c| 59 +++++++++++++++++++++++++++++++++++++++++++++1 files changed, 59 insertions(+), 0 deletions(-)arch/powerpc/kernel/kvm.c +35
-0@@ -32,3 +32,62 @@#define KVM_MAGIC_PAGE (-4096L)#define magic_var (x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) +static bool kvm_patching_worked = true; + +static void kvm_map_magic_page (void *data) +{ +kvm_hypercall2 (KVM_HC_PPC_MAP_MAGIC_PAGE , +KVM_MAGIC_PAGE ,/* Physical Address */ +KVM_MAGIC_PAGE );/* Effective Address */ +} + +static void kvm_check_ins (u32 *inst) +{ +u32 _inst = *inst; +u32 inst_no_rt = _inst & ~KVM_MASK_RT ; +u32 inst_rt = _inst &KVM_MASK_RT ; + +switch (inst_no_rt) { + } + +switch (_inst) { + } + +flush_icache_range ((ulong )inst, (ulong )inst +4 ); +} + +static void kvm_use_magic_page (void ) +{ +u32 *p; +u32 *start, *end; + +/* Tell the host to map the magic page to -4096 on all CPUs */ + +on_each_cpu (kvm_map_magic_page,NULL ,1 ); + +/* Now loop through all code and find instructions */ +
Quoted 8 lines
arch/powerpc/kernel/kvm.c line 75
Quoted 6 lines
arch/powerpc/kernel/kvm.c +6
-0+ start = (void *)_stext; + end = (void *)_etext; + +for (p = start; p < end; p++) +kvm_check_ins (p); +}Could you do something similar in
module_finalize()to patch loaded modules' .text sections?
I could, but do we need it? I objdump -d | grep'ed all my modules and didn't find any need to do so.
Alex
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 5 lines · Alexander Graf
Quoted 3 lines
Could you do something similar in
module_finalize()to patch loaded modules' .text sections?I could, but do we need it? I objdump -d | grep'ed all my modules and didn't find any need to do so.
You mean even kvm.ko doesn't use privileged instructions?
Signature · 1 line
error compiling committee.c: too many arguments to function
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 8 lines · Avi Kivity
Quoted 5 lines · Alexander Graf
Quoted 3 lines
Could you do something similar in
module_finalize()to patch loaded modules' .text sections?I could, but do we need it? I objdump -d | grep'ed all my modules and didn't find any need to do so.
You mean even kvm.ko doesn't use privileged instructions?
It does, but I don't think it's worth speeding those up. There are only a couple. Most of the privileged instructions in PPC KVM are statically compiled into the kernel because we need to guarantee they're in the RMO (first 8MB for the PS3).
Even with the magic page in use, trapping instructions still works exactly as before, so we're only talking about a speed difference.
Alex
A message that is not in the archive (sent off-list or not yet received): AD79CD04-74CF-49B9-BACC-4C190DF5214A-l3A5Bk7waGM@public.gmane.org
Re: [PATCH 18/26] KVM: PPC: KVM PV guest stubs
Quoted 7 lines · Alexander Graf
Quoted 2 lines
You mean even kvm.ko doesn't use privileged instructions?
It does, but I don't think it's worth speeding those up. There are only a couple. Most of the privileged instructions in PPC KVM are statically compiled into the kernel because we need to guarantee they're in the RMO (first 8MB for the PS3).
Even with the magic page in use, trapping instructions still works exactly as before, so we're only talking about a speed difference.
Yeah, that also answers my question re pv->nonpv transition.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 21/26 KVM: PPC: Introduce kvm_tmp framework
In reply to Alexander GrafWe will soon require more sophisticated methods to replace single instructions with multiple instructions. We do that by branching to a memory region where we write replacement code for the instruction to.
This region needs to be within 32 MB of the patched instruction though, because that's the furthest we can jump with immediate branches.
So we keep 1MB of free space around in bss. After we're done initing we can just tell the mm system that the unused pages are free, but until then we have enough space to fit all our code in.
--- arch/powerpc/kernel/kvm.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 files changed, 39 insertions(+), 2 deletions(-)
arch/powerpc/kernel/kvm.c +39 -2
@@ -64,6 +64,8 @@#define KVM_INST_TLBSYNC 0x7c00046cstatic bool kvm_patching_worked = true; +static char kvm_tmp[1024 *1024 ]; +static int kvm_tmp_index;static void kvm_patch_ins_ld (u32 *inst,long addr,u32 rt) {
@@ -98,6 +100,23 @@ static void kvm_patch_ins_nop(u32 *inst) *inst =KVM_INST_NOP ; } +static u32 *kvm_alloc (int len) +{ +u32 *p; + +if ((kvm_tmp_index + len) >ARRAY_SIZE (kvm_tmp)) { +printk (KERN_ERR "KVM: No more space (%d + %d)\n" , + kvm_tmp_index, len); + kvm_patching_worked = false; +return NULL ; + } + + p = (void *)&kvm_tmp[kvm_tmp_index]; + kvm_tmp_index += len; + +return p; +} +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -197,12 +216,27 @@ static void kvm_use_magic_page(void)kvm_check_ins (p); } +static void kvm_free_tmp (void ) +{ +unsigned long start, end; + + start = (ulong)&kvm_tmp[kvm_tmp_index + (PAGE_SIZE -1 )] &PAGE_MASK ; + end = (ulong)&kvm_tmp[ARRAY_SIZE (kvm_tmp)] &PAGE_MASK ; + +/* Free the tmp space we don't need */ +for (; start < end; start +=PAGE_SIZE ) { +ClearPageReserved (virt_to_page (start)); +init_page_count (virt_to_page (start)); +free_page (start); + totalram_pages++; + } +} +static int __init kvm_guest_init (void ) { -char *p;if (!kvm_para_available ()) -return 0 ; + goto free_tmp;if (kvm_para_has_feature (KVM_FEATURE_MAGIC_PAGE ))kvm_use_magic_page ();
@@ -210,6 +244,9 @@ static int __init kvm_guest_init(void)printk (KERN_INFO "KVM: Live patching for a fast VM %s\n" , kvm_patching_worked ?"worked" :"failed" ); +free_tmp: +kvm_free_tmp (); +return 0 ; }
Signature · 1 line
1.6.0.2
PATCH 23/26 KVM: PPC: PV mtmsrd L=1
In reply to Alexander GrafThe PowerPC ISA has a special instruction for mtmsr that only changes the EE and RI bits, namely the L=1 form.
Since that one is reasonably often occuring and simple to implement, let's go with this first. Writing EE=0 is always just a store. Doing EE=1 also requires us to check for pending interrupts and if necessary exit back to the hypervisor.
--- arch/powerpc/kernel/kvm.c | 45 ++++++++++++++++++++++++++++++++ arch/powerpc/kernel/kvm_emul.S | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +45 -0
@@ -62,6 +62,7 @@#define KVM_INST_MTSPR_DSISR 0x7c1203a6#define KVM_INST_TLBSYNC 0x7c00046c +#define KVM_INST_MTMSRD_L1 0x7c010164static bool kvm_patching_worked = true;static char kvm_tmp[1024 *1024 ];
@@ -117,6 +118,43 @@ static u32 *kvm_alloc(int len)return p; } +extern u32 kvm_emulate_mtmsrd_branch_offs; +extern u32 kvm_emulate_mtmsrd_reg_offs; +extern u32 kvm_emulate_mtmsrd_len; +extern u32 kvm_emulate_mtmsrd[]; + +static void kvm_patch_ins_mtmsrd (u32 *inst,u32 rt) +{ +u32 *p; +int distance_start; +int distance_end; +ulong next_inst; + + p =kvm_alloc (kvm_emulate_mtmsrd_len *4 ); +if (!p) +return ; + +/* Find out where we are and put everything there */ + distance_start = (ulong )p - (ulong )inst; + next_inst = ((ulong )inst +4 ); + distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsrd_branch_offs]; + +/* Make sure we only write valid b instructions */ +if (distance_start >KVM_INST_B_MAX ) { + kvm_patching_worked = false; +return ; + } + +/* Modify the chunk to fit the invocation */ +memcpy (p, kvm_emulate_mtmsrd, kvm_emulate_mtmsrd_len *4 ); + p[kvm_emulate_mtmsrd_branch_offs] |= distance_end &KVM_INST_B_MASK ; + p[kvm_emulate_mtmsrd_reg_offs] |= rt; +flush_icache_range ((ulong )p, (ulong )p + kvm_emulate_mtmsrd_len *4 ); + +/* Patch the invocation */ + *inst =KVM_INST_B | (distance_start &KVM_INST_B_MASK ); +} +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -190,6 +228,13 @@ static void kvm_check_ins(u32 *inst)case KVM_INST_TLBSYNC :kvm_patch_ins_nop (inst);break ; + +/* Rewrites */ +case KVM_INST_MTMSRD_L1 : +/* We use r30 and r31 during the hook */ +if (get_rt (inst_rt) <30 ) +kvm_patch_ins_mtmsrd (inst, inst_rt); +break ; }switch (_inst) {
arch/powerpc/kernel/kvm_emul.S +56 -0
59 lines not on this page · raw message
Signature · 1 line
1.6.0.2
PATCH 25/26 KVM: PPC: PV wrteei
In reply to Alexander GrafOn BookE the preferred way to write the EE bit is the wrteei instruction. It already encodes the EE bit in the instruction.
So in order to get BookE some speedups as well, let's also PV'nize thati instruction.
--- arch/powerpc/kernel/kvm.c | 50 ++++++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/kvm_emul.S | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 0 deletions(-)
arch/powerpc/kernel/kvm.c +50 -0
@@ -66,6 +66,9 @@#define KVM_INST_MTMSRD_L1 0x7c010164#define KVM_INST_MTMSR 0x7c000124 +#define KVM_INST_WRTEEI_0 0x7c000146 +#define KVM_INST_WRTEEI_1 0x7c008146 +static bool kvm_patching_worked = true;static char kvm_tmp[1024 *1024 ];static int kvm_tmp_index;
@@ -200,6 +203,47 @@ static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt) *inst =KVM_INST_B | (distance_start &KVM_INST_B_MASK ); } +#ifdef CONFIG_BOOKE + +extern u32 kvm_emulate_wrteei_branch_offs; +extern u32 kvm_emulate_wrteei_ee_offs; +extern u32 kvm_emulate_wrteei_len; +extern u32 kvm_emulate_wrteei[]; + +static void kvm_patch_ins_wrteei (u32 *inst) +{ +u32 *p; +int distance_start; +int distance_end; +ulong next_inst; + + p =kvm_alloc (kvm_emulate_wrteei_len *4 ); +if (!p) +return ; + +/* Find out where we are and put everything there */ + distance_start = (ulong )p - (ulong )inst; + next_inst = ((ulong )inst +4 ); + distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_branch_offs]; + +/* Make sure we only write valid b instructions */ +if (distance_start >KVM_INST_B_MAX ) { + kvm_patching_worked = false; +return ; + } + +/* Modify the chunk to fit the invocation */ +memcpy (p, kvm_emulate_wrteei, kvm_emulate_wrteei_len *4 ); + p[kvm_emulate_wrteei_branch_offs] |= distance_end &KVM_INST_B_MASK ; + p[kvm_emulate_wrteei_ee_offs] |= (*inst &MSR_EE ); +flush_icache_range ((ulong )p, (ulong )p + kvm_emulate_wrteei_len *4 ); + +/* Patch the invocation */ + *inst =KVM_INST_B | (distance_start &KVM_INST_B_MASK ); +} + +#endif +static void kvm_map_magic_page (void *data) { kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -289,6 +333,12 @@ static void kvm_check_ins(u32 *inst) }switch (_inst) { +#ifdef CONFIG_BOOKE +case KVM_INST_WRTEEI_0 : +case KVM_INST_WRTEEI_1 : +kvm_patch_ins_wrteei (inst); +break ; +#endif }flush_icache_range ((ulong )inst, (ulong )inst +4 );
arch/powerpc/kernel/kvm_emul.S +41 -0
44 lines not on this page · raw message
Signature · 1 line
1.6.0.2