From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Graf Subject: [PATCH 21/52] KVM: PPC: Use get/set for to_svcpu to help preemption Date: Fri, 13 Jan 2012 15:31:24 +0100 Message-ID: <1326465115-5976-22-git-send-email-agraf@suse.de> References: <1326465115-5976-1-git-send-email-agraf@suse.de> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: kvm list , Avi Kivity , Marcelo Tosatti To: kvm-ppc@vger.kernel.org Return-path: In-Reply-To: <1326465115-5976-1-git-send-email-agraf@suse.de> Sender: kvm-ppc-owner@vger.kernel.org List-Id: kvm.vger.kernel.org When running the 64-bit Book3s PR code without CONFIG_PREEMPT_NONE, we = were doing a few things wrong, most notably access to PACA fields without ma= king sure that the pointers stay stable accross the access (preempt_disable(= )). This patch moves to_svcpu towards a get/put model which allows us to di= sable preemption while accessing the shadow vcpu fields in the PACA. That way= we can run preemptible and everyone's happy! Reported-by: J=C3=B6rg Sommer Signed-off-by: Alexander Graf --- arch/powerpc/include/asm/kvm_book3s.h | 76 ++++++++++++++++++++++= +------- arch/powerpc/include/asm/kvm_book3s_32.h | 6 ++- arch/powerpc/include/asm/kvm_book3s_64.h | 8 +++- arch/powerpc/kvm/book3s_32_mmu_host.c | 21 ++++++-- arch/powerpc/kvm/book3s_64_mmu_host.c | 66 +++++++++++++++++-----= ---- arch/powerpc/kvm/book3s_emulate.c | 8 ++- arch/powerpc/kvm/book3s_pr.c | 62 ++++++++++++++++------= -- arch/powerpc/kvm/trace.h | 5 ++- 8 files changed, 181 insertions(+), 71 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/inclu= de/asm/kvm_book3s.h index 69c7377..c941c21 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -183,7 +183,9 @@ static inline void kvmppc_update_int_pending(struct= kvm_vcpu *vcpu, static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulon= g val) { if ( num < 14 ) { - to_svcpu(vcpu)->gpr[num] =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->gpr[num] =3D val; + svcpu_put(svcpu); to_book3s(vcpu)->shadow_vcpu->gpr[num] =3D val; } else vcpu->arch.gpr[num] =3D val; @@ -191,80 +193,120 @@ static inline void kvmppc_set_gpr(struct kvm_vcp= u *vcpu, int num, ulong val) =20 static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) { - if ( num < 14 ) - return to_svcpu(vcpu)->gpr[num]; - else + if ( num < 14 ) { + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong r =3D svcpu->gpr[num]; + svcpu_put(svcpu); + return r; + } else return vcpu->arch.gpr[num]; } =20 static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) { - to_svcpu(vcpu)->cr =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->cr =3D val; + svcpu_put(svcpu); to_book3s(vcpu)->shadow_vcpu->cr =3D val; } =20 static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->cr; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + u32 r; + r =3D svcpu->cr; + svcpu_put(svcpu); + return r; } =20 static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) { - to_svcpu(vcpu)->xer =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->xer =3D val; to_book3s(vcpu)->shadow_vcpu->xer =3D val; + svcpu_put(svcpu); } =20 static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->xer; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + u32 r; + r =3D svcpu->xer; + svcpu_put(svcpu); + return r; } =20 static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) { - to_svcpu(vcpu)->ctr =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->ctr =3D val; + svcpu_put(svcpu); } =20 static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->ctr; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong r; + r =3D svcpu->ctr; + svcpu_put(svcpu); + return r; } =20 static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) { - to_svcpu(vcpu)->lr =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->lr =3D val; + svcpu_put(svcpu); } =20 static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->lr; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong r; + r =3D svcpu->lr; + svcpu_put(svcpu); + return r; } =20 static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) { - to_svcpu(vcpu)->pc =3D val; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->pc =3D val; + svcpu_put(svcpu); } =20 static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->pc; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong r; + r =3D svcpu->pc; + svcpu_put(svcpu); + return r; } =20 static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) { ulong pc =3D kvmppc_get_pc(vcpu); - struct kvmppc_book3s_shadow_vcpu *svcpu =3D to_svcpu(vcpu); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + u32 r; =20 /* Load the instruction manually if it failed to do so in the * exit path */ if (svcpu->last_inst =3D=3D KVM_INST_FETCH_FAILED) kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false); =20 - return svcpu->last_inst; + r =3D svcpu->last_inst; + svcpu_put(svcpu); + return r; } =20 static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) { - return to_svcpu(vcpu)->fault_dar; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong r; + r =3D svcpu->fault_dar; + svcpu_put(svcpu); + return r; } =20 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) diff --git a/arch/powerpc/include/asm/kvm_book3s_32.h b/arch/powerpc/in= clude/asm/kvm_book3s_32.h index de604db..38040ff 100644 --- a/arch/powerpc/include/asm/kvm_book3s_32.h +++ b/arch/powerpc/include/asm/kvm_book3s_32.h @@ -20,11 +20,15 @@ #ifndef __ASM_KVM_BOOK3S_32_H__ #define __ASM_KVM_BOOK3S_32_H__ =20 -static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vc= pu *vcpu) +static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_v= cpu *vcpu) { return to_book3s(vcpu)->shadow_vcpu; } =20 +static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) +{ +} + #define PTE_SIZE 12 #define VSID_ALL 0 #define SR_INVALID 0x00000001 /* VSID 1 should always be unused */ diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/in= clude/asm/kvm_book3s_64.h index d0ac94f..2054e47 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -21,10 +21,16 @@ #define __ASM_KVM_BOOK3S_64_H__ =20 #ifdef CONFIG_KVM_BOOK3S_PR -static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vc= pu *vcpu) +static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_v= cpu *vcpu) { + preempt_disable(); return &get_paca()->shadow_vcpu; } + +static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) +{ + preempt_enable(); +} #endif =20 #define SPAPR_TCE_SHIFT 12 diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/b= ook3s_32_mmu_host.c index 9fecbfb..f922c29 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c @@ -151,13 +151,15 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, st= ruct kvmppc_pte *orig_pte) bool primary =3D false; bool evict =3D false; struct hpte_cache *pte; + int r =3D 0; =20 /* Get host physical address for gpa */ hpaddr =3D kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); if (is_error_pfn(hpaddr)) { printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr); - return -EINVAL; + r =3D -EINVAL; + goto out; } hpaddr <<=3D PAGE_SHIFT; =20 @@ -249,7 +251,8 @@ next_pteg: =20 kvmppc_mmu_hpte_cache_map(vcpu, pte); =20 - return 0; +out: + return r; } =20 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u6= 4 gvsid) @@ -297,12 +300,14 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu,= ulong eaddr) u64 gvsid; u32 sr; struct kvmppc_sid_map *map; - struct kvmppc_book3s_shadow_vcpu *svcpu =3D to_svcpu(vcpu); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + int r =3D 0; =20 if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) { /* Invalidate an entry */ svcpu->sr[esid] =3D SR_INVALID; - return -ENOENT; + r =3D -ENOENT; + goto out; } =20 map =3D find_sid_vsid(vcpu, gvsid); @@ -315,17 +320,21 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu,= ulong eaddr) =20 dprintk_sr("MMU: mtsr %d, 0x%x\n", esid, sr); =20 - return 0; +out: + svcpu_put(svcpu); + return r; } =20 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) { int i; - struct kvmppc_book3s_shadow_vcpu *svcpu =3D to_svcpu(vcpu); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); =20 dprintk_sr("MMU: flushing all segments (%d)\n", ARRAY_SIZE(svcpu->sr)= ); for (i =3D 0; i < ARRAY_SIZE(svcpu->sr); i++) svcpu->sr[i] =3D SR_INVALID; + + svcpu_put(svcpu); } =20 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/b= ook3s_64_mmu_host.c index fa2f084..6f87f39 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -88,12 +88,14 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, stru= ct kvmppc_pte *orig_pte) int vflags =3D 0; int attempt =3D 0; struct kvmppc_sid_map *map; + int r =3D 0; =20 /* Get host physical address for gpa */ hpaddr =3D kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); if (is_error_pfn(hpaddr)) { printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte-= >eaddr); - return -EINVAL; + r =3D -EINVAL; + goto out; } hpaddr <<=3D PAGE_SHIFT; hpaddr |=3D orig_pte->raddr & (~0xfffULL & ~PAGE_MASK); @@ -110,7 +112,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, stru= ct kvmppc_pte *orig_pte) printk(KERN_ERR "KVM: Segment map for 0x%llx (0x%lx) failed\n", vsid, orig_pte->eaddr); WARN_ON(true); - return -EINVAL; + r =3D -EINVAL; + goto out; } =20 vsid =3D map->host_vsid; @@ -131,8 +134,10 @@ map_again: =20 /* In case we tried normal mapping already, let's nuke old entries */ if (attempt > 1) - if (ppc_md.hpte_remove(hpteg) < 0) - return -1; + if (ppc_md.hpte_remove(hpteg) < 0) { + r =3D -1; + goto out; + } =20 ret =3D ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAG= E_4K, MMU_SEGSIZE_256M); =20 @@ -162,7 +167,8 @@ map_again: kvmppc_mmu_hpte_cache_map(vcpu, pte); } =20 - return 0; +out: + return r; } =20 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u6= 4 gvsid) @@ -207,25 +213,30 @@ static struct kvmppc_sid_map *create_sid_map(stru= ct kvm_vcpu *vcpu, u64 gvsid) =20 static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid) { + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); int i; int max_slb_size =3D 64; int found_inval =3D -1; int r; =20 - if (!to_svcpu(vcpu)->slb_max) - to_svcpu(vcpu)->slb_max =3D 1; + if (!svcpu->slb_max) + svcpu->slb_max =3D 1; =20 /* Are we overwriting? */ - for (i =3D 1; i < to_svcpu(vcpu)->slb_max; i++) { - if (!(to_svcpu(vcpu)->slb[i].esid & SLB_ESID_V)) + for (i =3D 1; i < svcpu->slb_max; i++) { + if (!(svcpu->slb[i].esid & SLB_ESID_V)) found_inval =3D i; - else if ((to_svcpu(vcpu)->slb[i].esid & ESID_MASK) =3D=3D esid) - return i; + else if ((svcpu->slb[i].esid & ESID_MASK) =3D=3D esid) { + r =3D i; + goto out; + } } =20 /* Found a spare entry that was invalidated before */ - if (found_inval > 0) - return found_inval; + if (found_inval > 0) { + r =3D found_inval; + goto out; + } =20 /* No spare invalid entry, so create one */ =20 @@ -233,30 +244,35 @@ static int kvmppc_mmu_next_segment(struct kvm_vcp= u *vcpu, ulong esid) max_slb_size =3D mmu_slb_size; =20 /* Overflowing -> purge */ - if ((to_svcpu(vcpu)->slb_max) =3D=3D max_slb_size) + if ((svcpu->slb_max) =3D=3D max_slb_size) kvmppc_mmu_flush_segments(vcpu); =20 - r =3D to_svcpu(vcpu)->slb_max; - to_svcpu(vcpu)->slb_max++; + r =3D svcpu->slb_max; + svcpu->slb_max++; =20 +out: + svcpu_put(svcpu); return r; } =20 int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr) { + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); u64 esid =3D eaddr >> SID_SHIFT; u64 slb_esid =3D (eaddr & ESID_MASK) | SLB_ESID_V; u64 slb_vsid =3D SLB_VSID_USER; u64 gvsid; int slb_index; struct kvmppc_sid_map *map; + int r =3D 0; =20 slb_index =3D kvmppc_mmu_next_segment(vcpu, eaddr & ESID_MASK); =20 if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) { /* Invalidate an entry */ - to_svcpu(vcpu)->slb[slb_index].esid =3D 0; - return -ENOENT; + svcpu->slb[slb_index].esid =3D 0; + r =3D -ENOENT; + goto out; } =20 map =3D find_sid_vsid(vcpu, gvsid); @@ -269,18 +285,22 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu,= ulong eaddr) slb_vsid &=3D ~SLB_VSID_KP; slb_esid |=3D slb_index; =20 - to_svcpu(vcpu)->slb[slb_index].esid =3D slb_esid; - to_svcpu(vcpu)->slb[slb_index].vsid =3D slb_vsid; + svcpu->slb[slb_index].esid =3D slb_esid; + svcpu->slb[slb_index].vsid =3D slb_vsid; =20 trace_kvm_book3s_slbmte(slb_vsid, slb_esid); =20 - return 0; +out: + svcpu_put(svcpu); + return r; } =20 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) { - to_svcpu(vcpu)->slb_max =3D 1; - to_svcpu(vcpu)->slb[0].esid =3D 0; + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + svcpu->slb_max =3D 1; + svcpu->slb[0].esid =3D 0; + svcpu_put(svcpu); } =20 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3= s_emulate.c index 0c9dc62..f1950d1 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -230,9 +230,12 @@ int kvmppc_core_emulate_op(struct kvm_run *run, st= ruct kvm_vcpu *vcpu, =20 r =3D kvmppc_st(vcpu, &addr, 32, zeros, true); if ((r =3D=3D -ENOENT) || (r =3D=3D -EPERM)) { + struct kvmppc_book3s_shadow_vcpu *svcpu; + + svcpu =3D svcpu_get(vcpu); *advance =3D 0; vcpu->arch.shared->dar =3D vaddr; - to_svcpu(vcpu)->fault_dar =3D vaddr; + svcpu->fault_dar =3D vaddr; =20 dsisr =3D DSISR_ISSTORE; if (r =3D=3D -ENOENT) @@ -241,7 +244,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, str= uct kvm_vcpu *vcpu, dsisr |=3D DSISR_PROTFAULT; =20 vcpu->arch.shared->dsisr =3D dsisr; - to_svcpu(vcpu)->fault_dsisr =3D dsisr; + svcpu->fault_dsisr =3D dsisr; + svcpu_put(svcpu); =20 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.= c index 857ecde..0c31507 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -56,10 +56,12 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu,= unsigned int exit_nr, void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { #ifdef CONFIG_PPC_BOOK3S_64 - memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_sv= cpu(vcpu)->slb)); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb)); memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu, sizeof(get_paca()->shadow_vcpu)); - to_svcpu(vcpu)->slb_max =3D to_book3s(vcpu)->slb_shadow_max; + svcpu->slb_max =3D to_book3s(vcpu)->slb_shadow_max; + svcpu_put(svcpu); #endif =20 #ifdef CONFIG_PPC_BOOK3S_32 @@ -70,10 +72,12 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, i= nt cpu) void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) { #ifdef CONFIG_PPC_BOOK3S_64 - memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_sv= cpu(vcpu)->slb)); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb)); memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu, sizeof(get_paca()->shadow_vcpu)); - to_book3s(vcpu)->slb_shadow_max =3D to_svcpu(vcpu)->slb_max; + to_book3s(vcpu)->slb_shadow_max =3D svcpu->slb_max; + svcpu_put(svcpu); #endif =20 kvmppc_giveup_ext(vcpu, MSR_FP); @@ -308,19 +312,22 @@ int kvmppc_handle_pagefault(struct kvm_run *run, = struct kvm_vcpu *vcpu, =20 if (page_found =3D=3D -ENOENT) { /* Page not found in guest PTE entries */ + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); vcpu->arch.shared->dar =3D kvmppc_get_fault_dar(vcpu); - vcpu->arch.shared->dsisr =3D to_svcpu(vcpu)->fault_dsisr; + vcpu->arch.shared->dsisr =3D svcpu->fault_dsisr; vcpu->arch.shared->msr |=3D - (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); + (svcpu->shadow_srr1 & 0x00000000f8000000ULL); + svcpu_put(svcpu); kvmppc_book3s_queue_irqprio(vcpu, vec); } else if (page_found =3D=3D -EPERM) { /* Storage protection */ + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); vcpu->arch.shared->dar =3D kvmppc_get_fault_dar(vcpu); - vcpu->arch.shared->dsisr =3D - to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE; + vcpu->arch.shared->dsisr =3D svcpu->fault_dsisr & ~DSISR_NOHPTE; vcpu->arch.shared->dsisr |=3D DSISR_PROTFAULT; vcpu->arch.shared->msr |=3D - (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); + svcpu->shadow_srr1 & 0x00000000f8000000ULL; + svcpu_put(svcpu); kvmppc_book3s_queue_irqprio(vcpu, vec); } else if (page_found =3D=3D -EINVAL) { /* Page not found in guest SLB */ @@ -521,21 +528,25 @@ int kvmppc_handle_exit(struct kvm_run *run, struc= t kvm_vcpu *vcpu, kvm_resched(vcpu); switch (exit_nr) { case BOOK3S_INTERRUPT_INST_STORAGE: + { + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong shadow_srr1 =3D svcpu->shadow_srr1; vcpu->stat.pf_instruc++; =20 #ifdef CONFIG_PPC_BOOK3S_32 /* We set segments as unused segments when invalidating them. So * treat the respective fault as segment fault. */ - if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT] - =3D=3D SR_INVALID) { + if (svcpu->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT] =3D=3D SR_INVALID) { kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); r =3D RESUME_GUEST; + svcpu_put(svcpu); break; } #endif + svcpu_put(svcpu); =20 /* only care about PTEG not found errors, but leave NX alone */ - if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) { + if (shadow_srr1 & 0x40000000) { r =3D kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_= nr); vcpu->stat.sp_instruc++; } else if (vcpu->arch.mmu.is_dcbz32(vcpu) && @@ -548,33 +559,37 @@ int kvmppc_handle_exit(struct kvm_run *run, struc= t kvm_vcpu *vcpu, kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); r =3D RESUME_GUEST; } else { - vcpu->arch.shared->msr |=3D - to_svcpu(vcpu)->shadow_srr1 & 0x58000000; + vcpu->arch.shared->msr |=3D shadow_srr1 & 0x58000000; kvmppc_book3s_queue_irqprio(vcpu, exit_nr); r =3D RESUME_GUEST; } break; + } case BOOK3S_INTERRUPT_DATA_STORAGE: { ulong dar =3D kvmppc_get_fault_dar(vcpu); + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + u32 fault_dsisr =3D svcpu->fault_dsisr; vcpu->stat.pf_storage++; =20 #ifdef CONFIG_PPC_BOOK3S_32 /* We set segments as unused segments when invalidating them. So * treat the respective fault as segment fault. */ - if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) =3D=3D SR_INVALID) { + if ((svcpu->sr[dar >> SID_SHIFT]) =3D=3D SR_INVALID) { kvmppc_mmu_map_segment(vcpu, dar); r =3D RESUME_GUEST; + svcpu_put(svcpu); break; } #endif + svcpu_put(svcpu); =20 /* The only case we need to handle is missing shadow PTEs */ - if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) { + if (fault_dsisr & DSISR_NOHPTE) { r =3D kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); } else { vcpu->arch.shared->dar =3D dar; - vcpu->arch.shared->dsisr =3D to_svcpu(vcpu)->fault_dsisr; + vcpu->arch.shared->dsisr =3D fault_dsisr; kvmppc_book3s_queue_irqprio(vcpu, exit_nr); r =3D RESUME_GUEST; } @@ -610,10 +625,13 @@ int kvmppc_handle_exit(struct kvm_run *run, struc= t kvm_vcpu *vcpu, case BOOK3S_INTERRUPT_PROGRAM: { enum emulation_result er; + struct kvmppc_book3s_shadow_vcpu *svcpu; ulong flags; =20 program_interrupt: - flags =3D to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull; + svcpu =3D svcpu_get(vcpu); + flags =3D svcpu->shadow_srr1 & 0x1f0000ull; + svcpu_put(svcpu); =20 if (vcpu->arch.shared->msr & MSR_PR) { #ifdef EXIT_DEBUG @@ -741,14 +759,18 @@ program_interrupt: r =3D RESUME_GUEST; break; default: + { + struct kvmppc_book3s_shadow_vcpu *svcpu =3D svcpu_get(vcpu); + ulong shadow_srr1 =3D svcpu->shadow_srr1; + svcpu_put(svcpu); /* Ugh - bork here! What did we get? */ printk(KERN_EMERG "exit_nr=3D0x%x | pc=3D0x%lx | msr=3D0x%lx\n", - exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1); + exit_nr, kvmppc_get_pc(vcpu), shadow_srr1); r =3D RESUME_HOST; BUG(); break; } - + } =20 if (!(r & RESUME_HOST)) { /* To avoid clobbering exit_reason, only check for signals if diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index b135d3d..609d8bf 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h @@ -118,11 +118,14 @@ TRACE_EVENT(kvm_book3s_exit, ), =20 TP_fast_assign( + struct kvmppc_book3s_shadow_vcpu *svcpu; __entry->exit_nr =3D exit_nr; __entry->pc =3D kvmppc_get_pc(vcpu); __entry->dar =3D kvmppc_get_fault_dar(vcpu); __entry->msr =3D vcpu->arch.shared->msr; - __entry->srr1 =3D to_svcpu(vcpu)->shadow_srr1; + svcpu =3D svcpu_get(vcpu); + __entry->srr1 =3D svcpu->shadow_srr1; + svcpu_put(svcpu); ), =20 TP_printk("exit=3D0x%x | pc=3D0x%lx | msr=3D0x%lx | dar=3D0x%lx | srr= 1=3D0x%lx", --=20 1.6.0.2