From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:42485) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RoSMZ-0005M9-RD for qemu-devel@nongnu.org; Fri, 20 Jan 2012 23:15:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RoSMX-0000Lv-D1 for qemu-devel@nongnu.org; Fri, 20 Jan 2012 23:15:35 -0500 From: Alexander Graf Date: Sat, 21 Jan 2012 05:15:30 +0100 Message-Id: <1327119330-29304-9-git-send-email-agraf@suse.de> In-Reply-To: <1327119330-29304-1-git-send-email-agraf@suse.de> References: <1327119330-29304-1-git-send-email-agraf@suse.de> Subject: [Qemu-devel] [PATCH 8/8] PPC: booke206: Implement tlbilx List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-ppc@nongnu.org Cc: Scott Wood , qemu-devel Developers The PowerPC 2.06 BookE ISA defines an opcode called "tlbilx" which is used to flush TLB entries. It's the recommended way of flushing in virtualized environments. So far we got away without implementing it, but Linux for e500mc uses this instruction, so we better add it :). Signed-off-by: Alexander Graf --- v1 -> v2: - remove sas/ts check - isize is only valid for mav 2.0 --- target-ppc/helper.h | 1 + target-ppc/op_helper.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/translate.c | 25 ++++++++++++++++++ 3 files changed, 90 insertions(+), 0 deletions(-) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 470e42f..1635767 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -336,6 +336,7 @@ DEF_HELPER_0(booke206_tlbre, void) DEF_HELPER_0(booke206_tlbwe, void) DEF_HELPER_1(booke206_tlbsx, void, tl) DEF_HELPER_1(booke206_tlbivax, void, tl) +DEF_HELPER_2(booke206_tlbilx, void, tl, i32) DEF_HELPER_1(booke206_tlbflush, void, i32) DEF_HELPER_2(booke_setpid, void, i32, tl) DEF_HELPER_1(6xx_tlbd, void, tl) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 2c8a96f..29c3870 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -4406,6 +4406,70 @@ void helper_booke206_tlbivax(target_ulong address) } } +void helper_booke206_tlbilx(target_ulong address, uint32_t t) +{ + int tlb_size; + int i, j; + ppcmas_tlb_t *tlb = env->tlb.tlbm; + int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); + int pid = tid >> MAS6_SPID_SHIFT; + int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS; + int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0; + /* XXX check for unsupported isize and raise an invalid opcode then */ + int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK; + /* XXX implement MAV2 handling */ + bool mav2 = false; + + /* XXX missing LPID handling */ + switch (t) { + case 0: + /* flush all */ + booke206_flush_tlb(env, -1, 1); + break; + case 1: + /* flush by pid */ + for (i = 0; i < BOOKE206_MAX_TLBN; i++) { + tlb_size = booke206_tlb_size(env, i); + for (j = 0; j < tlb_size; j++) { + if (!(tlb[j].mas1 & MAS1_IPROT) && + ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) { + tlb[j].mas1 &= ~MAS1_VALID; + } + } + tlb += booke206_tlb_size(env, i); + } + tlb_flush(env, 1); + break; + case 3: + /* flush by pid and ea */ + for (i = 0; i < BOOKE206_MAX_TLBN; i++) { + int ways = booke206_tlb_ways(env, i); + + for (j = 0; j < ways; j++) { + tlb = booke206_get_tlbm(env, i, address, j); + if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) || + (tlb->mas1 & MAS1_IPROT) || + ((tlb->mas1 & MAS1_IND) != ind) || + ((tlb->mas8 & MAS8_TGS) != sgs)) { + continue; + } + if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) { + /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */ + continue; + } + /* XXX e500mc doesn't match SAS, but other cores might */ + tlb->mas1 &= ~MAS1_VALID; + } + } + tlb_flush(env, 1); + break; + default: + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | + POWERPC_EXCP_INVAL_INVAL); + } +} + void helper_booke206_tlbflush(uint32_t type) { int flags = 0; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index adde65b..7ceb210 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6110,6 +6110,29 @@ static void gen_tlbivax_booke206(DisasContext *ctx) #endif } +static void gen_tlbilx_booke206(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); +#else + TCGv t0; + TCGv_i32 t1; + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_const_i32((ctx->opcode >> 21) & 0x3); + gen_addr_reg_index(ctx, t0); + + gen_helper_booke206_tlbilx(t0, t1); + + tcg_temp_free(t0); + tcg_temp_free_i32(t1); +#endif +} + /* wrtee */ static void gen_wrtee(DisasContext *ctx) @@ -8574,6 +8597,8 @@ GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_NONE, PPC2_BOOKE206), GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001, PPC_NONE, PPC2_BOOKE206), +GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001, + PPC_NONE, PPC2_BOOKE206), GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE), GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE), GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC), -- 1.6.0.2