From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37365) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xeifw-0000h9-Mq for qemu-devel@nongnu.org; Thu, 16 Oct 2014 06:53:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xeifs-0005LW-Aa for qemu-devel@nongnu.org; Thu, 16 Oct 2014 06:52:56 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:19469) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xeifs-0005LJ-1Q for qemu-devel@nongnu.org; Thu, 16 Oct 2014 06:52:52 -0400 Message-ID: <543FA37F.8080804@imgtec.com> Date: Thu, 16 Oct 2014 11:52:47 +0100 From: Yongbok Kim MIME-Version: 1.0 References: <1404806257-28048-1-git-send-email-leon.alrae@imgtec.com> <1404806257-28048-8-git-send-email-leon.alrae@imgtec.com> In-Reply-To: <1404806257-28048-8-git-send-email-leon.alrae@imgtec.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Leon Alrae , qemu-devel@nongnu.org Cc: aurelien@aurel32.net Hi Leon, As the issues below are all corrected in the PRPL already, Reviewed-by: Yongbok Kim Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: > For Standard TLB configuration (Config.MT=1): > > TLBINV invalidates a set of TLB entries based on ASID. The virtual address is > ignored in the entry match. TLB entries which have their G bit set to 1 are not > modified. > > TLBINVF causes all entries to be invalidated. > > Note that this commit introduces support for Config4.IE == 3 only (i.e. TLBINV* > instructions operate on entire MMU). > > Single TLB entry can be marked as invalid on TLB entry write by having > EntryHi.EHINV set to 1. > > Signed-off-by: Leon Alrae > --- > disas/mips.c | 2 + > target-mips/cpu.h | 7 ++++ > target-mips/helper.c | 2 +- > target-mips/helper.h | 2 + > target-mips/op_helper.c | 65 +++++++++++++++++++++++++++++++++++++---- > target-mips/translate.c | 22 ++++++++++++++ > target-mips/translate_init.c | 2 + > 7 files changed, 94 insertions(+), 8 deletions(-) > > diff --git a/disas/mips.c b/disas/mips.c > index e3e253f..ff2e4b3 100644 > --- a/disas/mips.c > +++ b/disas/mips.c > @@ -2410,6 +2410,8 @@ const struct mips_opcode mips_builtin_opcodes[] = > {"tlbp", "", 0x42000008, 0xffffffff, INSN_TLB, 0, I1 }, > {"tlbr", "", 0x42000001, 0xffffffff, INSN_TLB, 0, I1 }, > {"tlbwi", "", 0x42000002, 0xffffffff, INSN_TLB, 0, I1 }, > +{"tlbinv", "", 0x42000003, 0xffffffff, INSN_TLB, 0, I32 }, > +{"tlbinvf", "", 0x42000004, 0xffffffff, INSN_TLB, 0, I32 }, > {"tlbwr", "", 0x42000006, 0xffffffff, INSN_TLB, 0, I1 }, > {"tlti", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, > {"tlt", "s,t", 0x00000032, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 40ebca6..bc52222 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -34,6 +34,7 @@ struct r4k_tlb_t { > uint_fast16_t XI1:1; > uint_fast16_t RI0:1; > uint_fast16_t RI1:1; > + uint_fast16_t EHINV:1; > target_ulong PFN[2]; > }; > > @@ -47,6 +48,8 @@ struct CPUMIPSTLBContext { > void (*helper_tlbwr)(struct CPUMIPSState *env); > void (*helper_tlbp)(struct CPUMIPSState *env); > void (*helper_tlbr)(struct CPUMIPSState *env); > + void (*helper_tlbinv)(struct CPUMIPSState *env); > + void (*helper_tlbinvf)(struct CPUMIPSState *env); > union { > struct { > r4k_tlb_t tlb[MIPS_TLB_MAX]; > @@ -282,6 +285,7 @@ struct CPUMIPSState { > target_ulong CP0_BadVAddr; > int32_t CP0_Count; > target_ulong CP0_EntryHi; > +#define CP0EnHi_EHINV 10 > int32_t CP0_Compare; > int32_t CP0_Status; > #define CP0St_CU3 31 > @@ -393,6 +397,7 @@ struct CPUMIPSState { > uint32_t CP0_Config4; > uint32_t CP0_Config4_rw_bitmask; > #define CP0C4_M 31 > +#define CP0C4_IE 29 > #define CP0C4_KScrExist 16 > uint32_t CP0_Config5; > uint32_t CP0_Config5_rw_bitmask; > @@ -528,6 +533,8 @@ void r4k_helper_tlbwi(CPUMIPSState *env); > void r4k_helper_tlbwr(CPUMIPSState *env); > void r4k_helper_tlbp(CPUMIPSState *env); > void r4k_helper_tlbr(CPUMIPSState *env); > +void r4k_helper_tlbinv(CPUMIPSState *env); > +void r4k_helper_tlbinvf(CPUMIPSState *env); > > void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, > bool is_write, bool is_exec, int unused, > diff --git a/target-mips/helper.c b/target-mips/helper.c > index fed28b4..5d72438 100644 > --- a/target-mips/helper.c > +++ b/target-mips/helper.c > @@ -83,7 +83,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, > #endif > > /* Check ASID, virtual page number & size */ > - if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { > + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { > /* TLB match */ > int n = !!(address & mask & ~(mask >> 1)); > /* Check access rights */ > diff --git a/target-mips/helper.h b/target-mips/helper.h > index e7e0c8c..aea12a9 100644 > --- a/target-mips/helper.h > +++ b/target-mips/helper.h > @@ -342,6 +342,8 @@ DEF_HELPER_1(tlbwi, void, env) > DEF_HELPER_1(tlbwr, void, env) > DEF_HELPER_1(tlbp, void, env) > DEF_HELPER_1(tlbr, void, env) > +DEF_HELPER_1(tlbinv, void, env) > +DEF_HELPER_1(tlbinvf, void, env) > DEF_HELPER_1(di, tl, env) > DEF_HELPER_1(ei, tl, env) > DEF_HELPER_1(eret, void, env) > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 3579bde..fa96bb3 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -1361,10 +1361,14 @@ void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1) > > void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) > { > - target_ulong old, val; > + target_ulong old, val, mask; > + mask = (TARGET_PAGE_MASK << 1) | 0xFF; > + if (env->CP0_Config4 & (1 << CP0C4_IE)) { (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) as you corrected it in PRPL > + mask |= 1 << CP0EnHi_EHINV; > + } > > /* 1k pages not implemented */ > - val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF); > + val = arg1 & mask; > #if defined(TARGET_MIPS64) > val &= env->SEGMask; > #endif > @@ -1858,6 +1862,11 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) > > /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ > tlb = &env->tlb->mmu.r4k.tlb[idx]; > + if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { > + tlb->EHINV = 1; > + return; > + } > + tlb->EHINV = 0; > tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); > #if defined(TARGET_MIPS64) > tlb->VPN &= env->SEGMask; > @@ -1879,6 +1888,31 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) > tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; > } > > +void r4k_helper_tlbinv(CPUMIPSState *env) > +{ > + int idx; > + r4k_tlb_t *tlb; > + uint8_t ASID = env->CP0_EntryHi & 0xFF; > + > + for (idx = 0; idx < env->tlb->nb_tlb; idx++) { > + tlb = &env->tlb->mmu.r4k.tlb[idx]; > + if (!tlb->G && tlb->ASID == ASID) { > + tlb->EHINV = 1; > + } > + } > + cpu_mips_tlb_flush(env, 1); > +} > + > +void r4k_helper_tlbinvf(CPUMIPSState *env) > +{ > + int idx; > + > + for (idx = 0; idx < env->tlb->nb_tlb; idx++) { > + env->tlb->mmu.r4k.tlb[idx].EHINV = 1; > + } > + cpu_mips_tlb_flush(env, 1); > +} > + > void r4k_helper_tlbwi(CPUMIPSState *env) > { > r4k_tlb_t *tlb; > @@ -1940,7 +1974,7 @@ void r4k_helper_tlbp(CPUMIPSState *env) > tag &= env->SEGMask; > #endif > /* Check ASID, virtual page number & size */ > - if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { > + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { > /* TLB match */ > env->CP0_Index = i; > break; > @@ -1984,16 +2018,23 @@ void r4k_helper_tlbr(CPUMIPSState *env) > > r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); > > - env->CP0_EntryHi = tlb->VPN | tlb->ASID; > - env->CP0_PageMask = tlb->PageMask; > - env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | > + if (tlb->EHINV) { > + env->CP0_EntryHi = 1 << CP0EnHi_EHINV; > + env->CP0_PageMask = 0; > + env->CP0_EntryLo0 = 0; > + env->CP0_EntryLo1 = 0; > + } else { > + env->CP0_EntryHi = tlb->VPN | tlb->ASID; > + env->CP0_PageMask = tlb->PageMask; > + env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | > ((target_ulong)tlb->RI0 << CP0EnLo_RI) | > ((target_ulong)tlb->XI0 << CP0EnLo_XI) | > (tlb->C0 << 3) | (tlb->PFN[0] >> 6); > - env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | > + env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | > ((target_ulong)tlb->RI1 << CP0EnLo_RI) | > ((target_ulong)tlb->XI1 << CP0EnLo_XI) | > (tlb->C1 << 3) | (tlb->PFN[1] >> 6); > + } > } > > void helper_tlbwi(CPUMIPSState *env) > @@ -2016,6 +2057,16 @@ void helper_tlbr(CPUMIPSState *env) > env->tlb->helper_tlbr(env); > } > > +void helper_tlbinv(CPUMIPSState *env) > +{ > + env->tlb->helper_tlbinv(env); > +} > + > +void helper_tlbinvf(CPUMIPSState *env) > +{ > + env->tlb->helper_tlbinvf(env); > +} > + > /* Specials */ > target_ulong helper_di(CPUMIPSState *env) > { > diff --git a/target-mips/translate.c b/target-mips/translate.c > index a8c8318..4179fea 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -901,6 +901,8 @@ enum { > enum { > OPC_TLBR = 0x01 | OPC_C0, > OPC_TLBWI = 0x02 | OPC_C0, > + OPC_TLBINV = 0x03 | OPC_C0, > + OPC_TLBINVF = 0x04 | OPC_C0, > OPC_TLBWR = 0x06 | OPC_C0, > OPC_TLBP = 0x08 | OPC_C0, > OPC_RFE = 0x10 | OPC_C0, > @@ -1177,6 +1179,7 @@ typedef struct DisasContext { > bool ulri; > int kscrexist; > bool rxi; > + bool ie; int ie; > } DisasContext; > > enum { > @@ -7560,6 +7563,24 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, > goto die; > gen_helper_tlbwi(cpu_env); > break; > + case OPC_TLBINV: > + opn = "tlbinv"; > + if (ctx->ie) { (ctx->ie >= 2) > + if (!env->tlb->helper_tlbinv) { > + goto die; > + } > + gen_helper_tlbinv(cpu_env); > + } /* treat as nop if TLBINV not supported */ > + break; > + case OPC_TLBINVF: > + opn = "tlbinvf"; > + if (ctx->ie) { (ctx->ie >= 2) > + if (!env->tlb->helper_tlbinvf) { > + goto die; > + } > + gen_helper_tlbinvf(cpu_env); > + } /* treat as nop if TLBINV not supported */ > + break; > case OPC_TLBWR: > opn = "tlbwr"; > if (!env->tlb->helper_tlbwr) > @@ -17554,6 +17575,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, > ctx.bstate = BS_NONE; > ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; > ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; > + ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 1; & 3 > /* Restore delay slot state from the tb context. */ > ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ > ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI); > diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c > index 779afff..bcfc46a 100644 > --- a/target-mips/translate_init.c > +++ b/target-mips/translate_init.c > @@ -657,6 +657,8 @@ static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def) > env->tlb->helper_tlbwr = r4k_helper_tlbwr; > env->tlb->helper_tlbp = r4k_helper_tlbp; > env->tlb->helper_tlbr = r4k_helper_tlbr; > + env->tlb->helper_tlbinv = r4k_helper_tlbinv; > + env->tlb->helper_tlbinvf = r4k_helper_tlbinvf; > } > > static void mmu_init (CPUMIPSState *env, const mips_def_t *def)