From patchwork Wed Mar 23 05:30:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 88018 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 32460B6F44 for ; Wed, 23 Mar 2011 16:48:22 +1100 (EST) Received: from localhost ([127.0.0.1]:56020 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q2Goo-0000vU-LR for incoming@patchwork.ozlabs.org; Wed, 23 Mar 2011 01:41:18 -0400 Received: from [140.186.70.92] (port=36110 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q2Gf7-0006Eq-AB for qemu-devel@nongnu.org; Wed, 23 Mar 2011 01:31:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q2Gf5-0006H7-Sx for qemu-devel@nongnu.org; Wed, 23 Mar 2011 01:31:17 -0400 Received: from ozlabs.org ([203.10.76.45]:41518) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q2Gf5-0006Es-BW for qemu-devel@nongnu.org; Wed, 23 Mar 2011 01:31:15 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 566DE1007D8; Wed, 23 Mar 2011 16:31:07 +1100 (EST) From: David Gibson To: agraf@suse.de, qemu-devel@nongnu.org Date: Wed, 23 Mar 2011 16:30:30 +1100 Message-Id: <1300858247-8197-11-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1300858247-8197-1-git-send-email-david@gibson.dropbear.id.au> References: <1300858247-8197-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 203.10.76.45 Cc: paulus@samba.org Subject: [Qemu-devel] [PATCH 10/27] Better factor the ppc hash translation path X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently the path handling hash page table translation in get_segment() has a mix of common and 32 or 64 bit specific code. However the division is not done terribly well which results in a lot of messy code flipping between common and divided paths. This patch improves the organization, consolidating several divided paths into one. This in turn allows simplification of some code in get_segment(), removing a number of ugly interim variables. This new factorization will also make it easier to add support for the 1T segments added in newer CPUs. Signed-off-by: David Gibson --- target-ppc/cpu.h | 1 + target-ppc/helper.c | 67 ++++++++++++++------------------------------------ 2 files changed, 20 insertions(+), 48 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index cee1057..fd2dfcd 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -386,6 +386,7 @@ struct ppc_slb_t { #define SLB_VSID_B 0xc000000000000000ULL #define SLB_VSID_B_256M 0x0000000000000000ULL #define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL +#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID) #define SLB_VSID_KS 0x0000000000000800ULL #define SLB_VSID_KP 0x0000000000000400ULL #define SLB_VSID_N 0x0000000000000200ULL /* no-execute */ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 0efa2a8..ae8001c 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -661,29 +661,15 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h, return ret; } -static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw, - int type, int target_page_bits) -{ - return _find_pte(env, ctx, 0, h, rw, type, target_page_bits); -} - -#if defined(TARGET_PPC64) -static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw, - int type, int target_page_bits) -{ - return _find_pte(env, ctx, 1, h, rw, type, target_page_bits); -} -#endif - static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw, int type, int target_page_bits) { #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) - return find_pte64(env, ctx, h, rw, type, target_page_bits); + return _find_pte(env, ctx, 1, h, rw, type, target_page_bits); #endif - return find_pte32(env, ctx, h, rw, type, target_page_bits); + return _find_pte(env, ctx, 0, h, rw, type, target_page_bits); } #if defined(TARGET_PPC64) @@ -803,14 +789,16 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, int rw, int type) { target_phys_addr_t hash; - target_ulong sr, vsid, pgidx, page_mask; + target_ulong vsid; int ds, pr, target_page_bits; int ret, ret2; pr = msr_pr; + ctx->eaddr = eaddr; #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) { ppc_slb_t *slb; + target_ulong pageaddr; LOG_MMU("Check SLBs\n"); slb = slb_lookup(env, eaddr); @@ -819,19 +807,24 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, } vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT; - page_mask = ~SEGMENT_MASK_256M; target_page_bits = (slb->vsid & SLB_VSID_L) ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP) : (slb->vsid & SLB_VSID_KS)); ds = 0; ctx->nx = !!(slb->vsid & SLB_VSID_N); - ctx->eaddr = eaddr; + + pageaddr = eaddr & ((1ULL << 28) - (1ULL << target_page_bits)); + /* XXX: this is false for 1 TB segments */ + hash = vsid ^ (pageaddr >> target_page_bits); + /* Only 5 bits of the page index are used in the AVPN */ + ctx->ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & 0x0F80); } else #endif /* defined(TARGET_PPC64) */ { + target_ulong sr, pgidx; + sr = env->sr[eaddr >> 28]; - page_mask = 0x0FFFFFFF; ctx->key = (((sr & 0x20000000) && (pr != 0)) || ((sr & 0x40000000) && (pr == 0))) ? 1 : 0; ds = sr & 0x80000000 ? 1 : 0; @@ -843,6 +836,9 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, " ir=%d dr=%d pr=%d %d t=%d\n", eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0, rw, type); + pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; + hash = vsid ^ pgidx; + ctx->ptem = (vsid << 7) | (pgidx >> 10); } LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid); @@ -851,36 +847,12 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, /* Check if instruction fetch is allowed, if needed */ if (type != ACCESS_CODE || ctx->nx == 0) { /* Page address translation */ - pgidx = (eaddr & page_mask) >> target_page_bits; -#if defined(TARGET_PPC64) - if (env->mmu_model & POWERPC_MMU_64) { - /* XXX: this is false for 1 TB segments */ - hash = vsid ^ pgidx; - } else -#endif - { - hash = vsid ^ pgidx; - } LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, hash); ctx->hash[0] = hash; ctx->hash[1] = ~hash; -#if defined(TARGET_PPC64) - if (env->mmu_model & POWERPC_MMU_64) { - /* Only 5 bits of the page index are used in the AVPN */ - if (target_page_bits > 23) { - ctx->ptem = (vsid << 12) | - ((pgidx << (target_page_bits - 16)) & 0xF80); - } else { - ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); - } - } else -#endif - { - ctx->ptem = (vsid << 7) | (pgidx >> 10); - } /* Initialize real address with an invalid value */ ctx->raddr = (target_phys_addr_t)-1ULL; if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx || @@ -889,9 +861,9 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); } else { LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx - " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx + " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, vsid, pgidx, + env->htab_base, env->htab_mask, vsid, ctx->ptem, ctx->hash[0]); /* Primary table lookup */ ret = find_pte(env, ctx, 0, rw, type, target_page_bits); @@ -902,8 +874,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx " pg_addr=" TARGET_FMT_plx "\n", env->htab_base, - env->htab_mask, vsid, pgidx, hash, - ctx->hash[1]); + env->htab_mask, vsid, ctx->ptem, ctx->hash[1]); ret2 = find_pte(env, ctx, 1, rw, type, target_page_bits); if (ret2 != -1)