From patchwork Tue Nov 29 01:20:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Wood X-Patchwork-Id: 128194 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 19AE4B6F87 for ; Tue, 29 Nov 2011 12:20:18 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751494Ab1K2BUP (ORCPT ); Mon, 28 Nov 2011 20:20:15 -0500 Received: from va3ehsobe001.messaging.microsoft.com ([216.32.180.11]:33602 "EHLO VA3EHSOBE001.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752378Ab1K2BUL (ORCPT ); Mon, 28 Nov 2011 20:20:11 -0500 Received: from mail95-va3-R.bigfish.com (10.7.14.243) by VA3EHSOBE001.bigfish.com (10.7.40.21) with Microsoft SMTP Server id 14.1.225.22; Tue, 29 Nov 2011 01:19:23 +0000 Received: from mail95-va3 (localhost [127.0.0.1]) by mail95-va3-R.bigfish.com (Postfix) with ESMTP id BB7701602D2; Tue, 29 Nov 2011 01:19:23 +0000 (UTC) X-SpamScore: 3 X-BigFish: VS3(zz853kzz1202hzz8275bhz2dh2a8h668h839h944h62h) X-Spam-TCS-SCL: 1:0 X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI Received: from mail95-va3 (localhost.localdomain [127.0.0.1]) by mail95-va3 (MessageSwitch) id 1322529563241958_17949; Tue, 29 Nov 2011 01:19:23 +0000 (UTC) Received: from VA3EHSMHS017.bigfish.com (unknown [10.7.14.241]) by mail95-va3.bigfish.com (Postfix) with ESMTP id 2A83EE0045; Tue, 29 Nov 2011 01:19:23 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS017.bigfish.com (10.7.99.27) with Microsoft SMTP Server (TLS) id 14.1.225.22; Tue, 29 Nov 2011 01:19:20 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server id 14.1.339.2; Mon, 28 Nov 2011 19:20:06 -0600 Received: from schlenkerla.am.freescale.net (schlenkerla.am.freescale.net [10.82.121.12]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id pAT1K6qN011382; Mon, 28 Nov 2011 19:20:06 -0600 (CST) Date: Mon, 28 Nov 2011 19:20:06 -0600 From: Scott Wood To: CC: , Subject: [PATCH 3/3] KVM: PPC: e500: use hardware hint when loading TLB0 entries Message-ID: <20111129012006.GC9130@schlenkerla.am.freescale.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20111129011909.GA9113@schlenkerla.am.freescale.net> User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginatorOrg: freescale.com Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The hardware maintains a per-set next victim hint. Using this reduces conflicts, especially on e500v2 where a single guest TLB entry is mapped to two shadow TLB entries (user and kernel). We want those two entries to go to different TLB ways. sesel is now only used for TLB1. Reported-by: Liu Yu Signed-off-by: Scott Wood --- arch/powerpc/include/asm/mmu-book3e.h | 1 + arch/powerpc/kvm/e500_tlb.c | 68 ++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index 4c30de3..3a7042d 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h @@ -44,6 +44,7 @@ #define MAS0_ESEL(x) (((x) << 16) & 0x0FFF0000) #define MAS0_NV(x) ((x) & 0x00000FFF) #define MAS0_ESEL_MASK 0x0FFF0000 +#define MAS0_ESEL_SHIFT 16 #define MAS0_HES 0x00004000 #define MAS0_WQ_ALLWAYS 0x00000000 #define MAS0_WQ_COND 0x00001000 diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index d041f5e..6be6917 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -299,17 +299,40 @@ static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry *stlbe, stlbe->mas2, stlbe->mas7_3); } -/* esel is index into set, not whole array */ +/* + * Acquire a mas0 with victim hint, as if we just took a TLB miss. + * + * We don't care about the address we're searching for, other than that + * it's right set and is not present in the TLB. Using a zero PID and a + * userspace address means we don't have to set and then restore MAS5, or + * calculate a proper MAS6 value. + */ +static u32 get_host_mas0(unsigned long eaddr) +{ + unsigned long flags, mas0; + + local_irq_save(flags); + mtspr(SPRN_MAS6, 0); + asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET)); + mas0 = mfspr(SPRN_MAS0); + local_irq_restore(flags); + + return mas0; +} + +/* sesel is for tlb1 only */ static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500, - int tlbsel, int esel, struct kvm_book3e_206_tlb_entry *stlbe) + int tlbsel, int sesel, struct kvm_book3e_206_tlb_entry *stlbe) { + unsigned long mas0; + if (tlbsel == 0) { - int way = esel & (vcpu_e500->gtlb_params[0].ways - 1); - __write_host_tlbe(stlbe, MAS0_TLBSEL(0) | MAS0_ESEL(way)); + mas0 = get_host_mas0(stlbe->mas2); + __write_host_tlbe(stlbe, mas0); } else { __write_host_tlbe(stlbe, MAS0_TLBSEL(1) | - MAS0_ESEL(to_htlb1_esel(esel))); + MAS0_ESEL(to_htlb1_esel(sesel))); } } @@ -424,12 +447,6 @@ static int gtlb0_set_base(struct kvmppc_vcpu_e500 *vcpu_e500, gva_t addr) vcpu_e500->gtlb_params[0].ways); } -static int htlb0_set_base(gva_t addr) -{ - return tlb0_set_base(addr, host_tlb_params[0].sets, - host_tlb_params[0].ways); -} - static unsigned int get_tlb_esel(struct kvm_vcpu *vcpu, int tlbsel) { struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); @@ -587,10 +604,9 @@ static inline void kvmppc_e500_setup_stlbe( vcpu_e500->vcpu.arch.shared->msr & MSR_PR); } -/* sesel is an index into the entire array, not just the set */ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, - int tlbsel, int sesel, struct kvm_book3e_206_tlb_entry *stlbe, + int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe, struct tlbe_ref *ref) { struct kvm_memory_slot *slot; @@ -723,27 +739,19 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } /* XXX only map the one-one case, for now use TLB0 */ -static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500, - int esel, - struct kvm_book3e_206_tlb_entry *stlbe) +static void kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500, + int esel, + struct kvm_book3e_206_tlb_entry *stlbe) { struct kvm_book3e_206_tlb_entry *gtlbe; struct tlbe_ref *ref; - int sesel = esel & (host_tlb_params[0].ways - 1); - int sesel_base; - gva_t ea; gtlbe = get_entry(vcpu_e500, 0, esel); ref = &vcpu_e500->gtlb_priv[0][esel].ref; - ea = get_tlb_eaddr(gtlbe); - sesel_base = htlb0_set_base(ea); - kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe), get_tlb_raddr(gtlbe) >> PAGE_SHIFT, - gtlbe, 0, sesel_base + sesel, stlbe, ref); - - return sesel; + gtlbe, 0, stlbe, ref); } /* Caller must ensure that the specified guest TLB entry is safe to insert into @@ -762,8 +770,7 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500, vcpu_e500->host_tlb1_nv = 0; ref = &vcpu_e500->tlb_refs[1][victim]; - kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, - victim, stlbe, ref); + kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, ref); return victim; } @@ -912,7 +919,7 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb) return EMULATE_DONE; } -/* sesel is index into the set, not the whole array */ +/* sesel is for tlb1 only */ static void write_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500, struct kvm_book3e_206_tlb_entry *gtlbe, struct kvm_book3e_206_tlb_entry *stlbe, @@ -965,7 +972,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu) gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K); stlbsel = 0; - sesel = kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe); + kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe); + sesel = 0; /* unused */ break; @@ -1054,7 +1062,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr, switch (tlbsel) { case 0: stlbsel = 0; - sesel = esel & (host_tlb_params[0].ways - 1); + sesel = 0; /* unused */ priv = &vcpu_e500->gtlb_priv[tlbsel][esel]; kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, BOOK3E_PAGESZ_4K,