From patchwork Tue Mar 12 10:31:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 226997 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BD5B82C02AF for ; Tue, 12 Mar 2013 22:55:19 +1100 (EST) Received: from localhost ([::1]:33587 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFMer-0004ol-Id for incoming@patchwork.ozlabs.org; Tue, 12 Mar 2013 06:42:13 -0400 Received: from eggs.gnu.org ([208.118.235.92]:44408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFMVY-0000Ka-HH for qemu-devel@nongnu.org; Tue, 12 Mar 2013 06:33:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UFMV6-0004nD-5E for qemu-devel@nongnu.org; Tue, 12 Mar 2013 06:32:36 -0400 Received: from ozlabs.org ([203.10.76.45]:54799) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UFMV5-0004jy-Gg; Tue, 12 Mar 2013 06:32:08 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id B271F2C02C1; Tue, 12 Mar 2013 21:32:01 +1100 (EST) From: David Gibson To: agraf@suse.de Date: Tue, 12 Mar 2013 21:31:30 +1100 Message-Id: <1363084310-4115-29-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363084310-4115-1-git-send-email-david@gibson.dropbear.id.au> References: <1363084310-4115-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 203.10.76.45 Cc: David Gibson , qemu-ppc@nongnu.org, afaerber@suse.de, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 28/48] mmu-hash*: Remove permission checking from find_pte{32, 64}() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org find_pte{32,64}() are poorly named, since they both find a PTE and do permissions checking of it. This patch makes them only locate a matching PTE, moving the permission checking and other logic to the caller. We rename the resulting search functions ppc_hash{32,64}_htab_lookup(). Signed-off-by: David Gibson --- target-ppc/mmu-hash32.c | 45 +++++++++++++++++--------------- target-ppc/mmu-hash64.c | 65 +++++++++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index b7a26a2..8b403fe 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -374,19 +374,15 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off, return -1; } -static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, - target_ulong sr, target_ulong eaddr, int rwx) +static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env, + target_ulong sr, target_ulong eaddr, + ppc_hash_pte32_t *pte) { hwaddr pteg_off, pte_offset; - ppc_hash_pte32_t pte; hwaddr hash; uint32_t vsid, pgidx, ptem; - int ret; - ret = -1; /* No entry found */ vsid = sr & SR32_VSID; - ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) || - ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0; pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS; hash = vsid ^ pgidx; ptem = (vsid << 7) | (pgidx >> 10); @@ -402,7 +398,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, hash); pteg_off = get_pteg_offset32(env, hash); - pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, &pte); + pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, pte); if (pte_offset == -1) { /* Secondary PTEG lookup */ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx @@ -410,20 +406,10 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, ~hash); pteg_off = get_pteg_offset32(env, ~hash); - pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, &pte); + pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, pte); } - if (pte_offset != -1) { - ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx); - LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n", - ctx->raddr, ctx->prot, ret); - /* Update page flags */ - if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { - ppc_hash32_store_hpte1(env, pte_offset, pte.pte1); - } - } - - return ret; + return pte_offset; } static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, @@ -431,6 +417,8 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, { int ret; target_ulong sr; + hwaddr pte_offset; + ppc_hash_pte32_t pte; /* 1. Handle real mode accesses */ if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { @@ -462,7 +450,22 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, if ((rwx == 2) && ctx->nx) { return -3; } - ret = find_pte32(env, ctx, sr, eaddr, rwx); + + /* 6. Locate the PTE in the hash table */ + pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte); + if (pte_offset == -1) { + return -1; + } + LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); + + /* 7. Check access permissions */ + ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) || + ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0; + ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx); + /* Update page flags */ + if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { + ppc_hash32_store_hpte1(env, pte_offset, pte.pte1); + } return ret; } diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 36e2c84..a98e008 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -374,17 +374,14 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off, return -1; } -static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, - ppc_slb_t *slb, target_ulong eaddr, int rwx) +static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, + ppc_slb_t *slb, target_ulong eaddr, + ppc_hash_pte64_t *pte) { hwaddr pteg_off, pte_offset; - ppc_hash_pte64_t pte; uint64_t vsid, pageaddr, ptem; hwaddr hash; int segment_bits, target_page_bits; - int ret; - - ret = -1; /* No entry found */ if (slb->vsid & SLB_VSID_B) { vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T; @@ -396,8 +393,6 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, target_page_bits = (slb->vsid & SLB_VSID_L) ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; - ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP) - : (slb->vsid & SLB_VSID_KS)); pageaddr = eaddr & ((1ULL << segment_bits) - (1ULL << target_page_bits)); @@ -410,21 +405,19 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80)); - ret = -1; - /* Page address translation */ LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, hash); - /* Primary PTEG lookup */ LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, hash); pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask; - pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, &pte); + pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, pte); + if (pte_offset == -1) { /* Secondary PTEG lookup */ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx @@ -433,26 +426,10 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, env->htab_mask, vsid, ptem, ~hash); pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask; - pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, &pte); + pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, pte); } - if (pte_offset != -1) { - ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx); - LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n", - ctx->raddr, ctx->prot, ret); - /* Update page flags */ - if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { - ppc_hash64_store_hpte1(env, pte_offset, pte.pte1); - } - } - - /* We have a TLB that saves 4K pages, so let's - * split a huge page to 4k chunks */ - if (target_page_bits != TARGET_PAGE_BITS) { - ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1)) - & TARGET_PAGE_MASK; - } - return ret; + return pte_offset; } static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, @@ -460,6 +437,9 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, { int ret; ppc_slb_t *slb; + hwaddr pte_offset; + ppc_hash_pte64_t pte; + int target_page_bits; /* 1. Handle real mode accesses */ if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { @@ -482,8 +462,31 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, return -3; } - ret = find_pte64(env, ctx, slb, eaddr, rwx); + /* 4. Locate the PTE in the hash table */ + pte_offset = ppc_hash64_htab_lookup(env, slb, eaddr, &pte); + if (pte_offset == -1) { + return -1; + } + LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); + + /* 5. Check access permissions */ + ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP) + : (slb->vsid & SLB_VSID_KS)); + + ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx); + /* Update page flags */ + if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { + ppc_hash64_store_hpte1(env, pte_offset, pte.pte1); + } + /* We have a TLB that saves 4K pages, so let's + * split a huge page to 4k chunks */ + target_page_bits = (slb->vsid & SLB_VSID_L) + ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; + if (target_page_bits != TARGET_PAGE_BITS) { + ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1)) + & TARGET_PAGE_MASK; + } return ret; }