From c3513c836e4c19cd7a2a7f691995fdef587cec72 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 27 Jun 2018 08:40:23 -0700 Subject: target/openrisc: Fix mtspr shadow gprs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missing break when this feature was added in 89e71e873d ("target/openrisc: implement shadow registers"). This was causing strange issues as we get writes into the translation block jump cache and other bits of state. Fixes: 89e71e873d ("target/openrisc: implement shadow registers") Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index b284064381..2f337363ec 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -98,6 +98,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */ idx = (spr - 1024); env->shadow_gpr[idx / 32][idx % 32] = rb; + break; case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); -- cgit 1.4.1 From c28fa81f915b03834b00187e43604e42768f15fa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 23 May 2018 07:13:26 -0700 Subject: target/openrisc: Form the spr index from tcg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than pass base+offset to the helper, pass the full index. In most cases the base is r0 and optimization yields a constant. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/helper.h | 4 ++-- target/openrisc/sys_helper.c | 9 +++------ target/openrisc/translate.c | 16 +++++++++------- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index e37dabc77a..9db9bf3963 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -56,5 +56,5 @@ FOP_CMP(le) DEF_HELPER_FLAGS_1(rfe, 0, void, env) /* sys */ -DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl) -DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl) +DEF_HELPER_FLAGS_3(mtspr, 0, void, env, tl, tl) +DEF_HELPER_FLAGS_3(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl) diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 2f337363ec..2c959f63f4 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -27,13 +27,11 @@ #define TO_SPR(group, number) (((group) << 11) + (number)) -void HELPER(mtspr)(CPUOpenRISCState *env, - target_ulong ra, target_ulong rb, target_ulong offset) +void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) { #ifndef CONFIG_USER_ONLY OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); - int spr = (ra | offset); int idx; switch (spr) { @@ -202,13 +200,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env, #endif } -target_ulong HELPER(mfspr)(CPUOpenRISCState *env, - target_ulong rd, target_ulong ra, uint32_t offset) +target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, + target_ulong spr) { #ifndef CONFIG_USER_ONLY OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); - int spr = (ra | offset); int idx; switch (spr) { diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 59605aacca..64b5e84630 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -865,9 +865,10 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) if (is_user(dc)) { gen_illegal_exception(dc); } else { - TCGv_i32 ti = tcg_const_i32(a->k); - gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti); - tcg_temp_free_i32(ti); + TCGv spr = tcg_temp_new(); + tcg_gen_ori_tl(spr, cpu_R[a->a], a->k); + gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr); + tcg_temp_free(spr); } return true; } @@ -877,7 +878,7 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) if (is_user(dc)) { gen_illegal_exception(dc); } else { - TCGv_i32 ti; + TCGv spr; /* For SR, we will need to exit the TB to recognize the new * exception state. For NPC, in theory this counts as a branch @@ -892,9 +893,10 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) } dc->base.is_jmp = DISAS_EXIT; - ti = tcg_const_i32(a->k); - gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti); - tcg_temp_free_i32(ti); + spr = tcg_temp_new(); + tcg_gen_ori_tl(spr, cpu_R[a->a], a->k); + gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]); + tcg_temp_free(spr); } return true; } -- cgit 1.4.1 From 455d45d22cc3b2c29c7840f2478647a0a3d9d8b4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 16:28:33 -0700 Subject: target/openrisc: Merge tlb allocation into CPUOpenRISCState There is no reason to allocate this separately. This was probably copied from target/mips which makes the same mistake. While doing so, move tlb into the clear-on-reset range. While not all of the TLB bits are guaranteed zero on reset, all of the valid bits are cleared, and the rest of the bits are unspecified. Therefore clearing the whole of the TLB is correct. Reviewed-by: Stafford Horne Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.h | 6 ++++-- target/openrisc/interrupt.c | 4 ++-- target/openrisc/interrupt_helper.c | 8 ++++---- target/openrisc/machine.c | 15 ++++++--------- target/openrisc/mmu.c | 34 ++++++++++++++++------------------ target/openrisc/sys_helper.c | 28 ++++++++++++++-------------- 6 files changed, 46 insertions(+), 49 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index c871d6bfe1..96b7f58659 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -301,6 +301,10 @@ typedef struct CPUOpenRISCState { uint32_t dflag; /* In delay slot (boolean) */ +#ifndef CONFIG_USER_ONLY + CPUOpenRISCTLBContext tlb; +#endif + /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; @@ -310,8 +314,6 @@ typedef struct CPUOpenRISCState { uint32_t cpucfgr; /* CPU configure register */ #ifndef CONFIG_USER_ONLY - CPUOpenRISCTLBContext * tlb; - QEMUTimer *timer; uint32_t ttmr; /* Timer tick mode register */ int is_counting; diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index 25351d5de3..2d0b55afa9 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -63,8 +63,8 @@ void openrisc_cpu_do_interrupt(CPUState *cs) env->sr &= ~SR_TEE; env->pmr &= ~PMR_DME; env->pmr &= ~PMR_SME; - env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; - env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; + env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; + env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; env->lock_addr = -1; if (exception > 0 && exception < EXCP_NR) { diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index b865738f8b..dc97b38704 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -36,18 +36,18 @@ void HELPER(rfe)(CPUOpenRISCState *env) #ifndef CONFIG_USER_ONLY if (cpu->env.sr & SR_DME) { - cpu->env.tlb->cpu_openrisc_map_address_data = + cpu->env.tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_data; } else { - cpu->env.tlb->cpu_openrisc_map_address_data = + cpu->env.tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; } if (cpu->env.sr & SR_IME) { - cpu->env.tlb->cpu_openrisc_map_address_code = + cpu->env.tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_code; } else { - cpu->env.tlb->cpu_openrisc_map_address_code = + cpu->env.tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; } diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index 0a793eb14d..c10d28b055 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -30,18 +30,18 @@ static int env_post_load(void *opaque, int version_id) /* Restore MMU handlers */ if (env->sr & SR_DME) { - env->tlb->cpu_openrisc_map_address_data = + env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_data; } else { - env->tlb->cpu_openrisc_map_address_data = + env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; } if (env->sr & SR_IME) { - env->tlb->cpu_openrisc_map_address_code = + env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_code; } else { - env->tlb->cpu_openrisc_map_address_code = + env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; } @@ -77,10 +77,6 @@ static const VMStateDescription vmstate_cpu_tlb = { } }; -#define VMSTATE_CPU_TLB(_f, _s) \ - VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_tlb, CPUOpenRISCTLBContext) - - static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) { CPUOpenRISCState *env = opaque; @@ -143,7 +139,8 @@ static const VMStateDescription vmstate_env = { VMSTATE_UINT32(fpcsr, CPUOpenRISCState), VMSTATE_UINT64(mac, CPUOpenRISCState), - VMSTATE_CPU_TLB(tlb, CPUOpenRISCState), + VMSTATE_STRUCT(tlb, CPUOpenRISCState, 1, + vmstate_cpu_tlb, CPUOpenRISCTLBContext), VMSTATE_TIMER_PTR(timer, CPUOpenRISCState), VMSTATE_UINT32(ttmr, CPUOpenRISCState), diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 2bd782f89b..5665bb7cc9 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -46,19 +46,19 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, int idx = vpn & ITLB_MASK; int right = 0; - if ((cpu->env.tlb->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { + if ((cpu->env.tlb.itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { return TLBRET_NOMATCH; } - if (!(cpu->env.tlb->itlb[0][idx].mr & 1)) { + if (!(cpu->env.tlb.itlb[0][idx].mr & 1)) { return TLBRET_INVALID; } if (cpu->env.sr & SR_SM) { /* supervisor mode */ - if (cpu->env.tlb->itlb[0][idx].tr & SXE) { + if (cpu->env.tlb.itlb[0][idx].tr & SXE) { right |= PAGE_EXEC; } } else { - if (cpu->env.tlb->itlb[0][idx].tr & UXE) { + if (cpu->env.tlb.itlb[0][idx].tr & UXE) { right |= PAGE_EXEC; } } @@ -67,7 +67,7 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, return TLBRET_BADADDR; } - *physical = (cpu->env.tlb->itlb[0][idx].tr & TARGET_PAGE_MASK) | + *physical = (cpu->env.tlb.itlb[0][idx].tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1)); *prot = right; return TLBRET_MATCH; @@ -81,25 +81,25 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, int idx = vpn & DTLB_MASK; int right = 0; - if ((cpu->env.tlb->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { + if ((cpu->env.tlb.dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { return TLBRET_NOMATCH; } - if (!(cpu->env.tlb->dtlb[0][idx].mr & 1)) { + if (!(cpu->env.tlb.dtlb[0][idx].mr & 1)) { return TLBRET_INVALID; } if (cpu->env.sr & SR_SM) { /* supervisor mode */ - if (cpu->env.tlb->dtlb[0][idx].tr & SRE) { + if (cpu->env.tlb.dtlb[0][idx].tr & SRE) { right |= PAGE_READ; } - if (cpu->env.tlb->dtlb[0][idx].tr & SWE) { + if (cpu->env.tlb.dtlb[0][idx].tr & SWE) { right |= PAGE_WRITE; } } else { - if (cpu->env.tlb->dtlb[0][idx].tr & URE) { + if (cpu->env.tlb.dtlb[0][idx].tr & URE) { right |= PAGE_READ; } - if (cpu->env.tlb->dtlb[0][idx].tr & UWE) { + if (cpu->env.tlb.dtlb[0][idx].tr & UWE) { right |= PAGE_WRITE; } } @@ -111,7 +111,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, return TLBRET_BADADDR; } - *physical = (cpu->env.tlb->dtlb[0][idx].tr & TARGET_PAGE_MASK) | + *physical = (cpu->env.tlb.dtlb[0][idx].tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1)); *prot = right; return TLBRET_MATCH; @@ -126,10 +126,10 @@ static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu, if (rw == MMU_INST_FETCH) { /* ITLB */ *physical = 0; - ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical, + ret = cpu->env.tlb.cpu_openrisc_map_address_code(cpu, physical, prot, address, rw); } else { /* DTLB */ - ret = cpu->env.tlb->cpu_openrisc_map_address_data(cpu, physical, + ret = cpu->env.tlb.cpu_openrisc_map_address_data(cpu, physical, prot, address, rw); } @@ -247,9 +247,7 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) void cpu_openrisc_mmu_init(OpenRISCCPU *cpu) { - cpu->env.tlb = g_malloc0(sizeof(CPUOpenRISCTLBContext)); - - cpu->env.tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; - cpu->env.tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; + cpu->env.tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; + cpu->env.tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; } #endif diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 2c959f63f4..ff315f6f1a 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -61,18 +61,18 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) } cpu_set_sr(env, rb); if (env->sr & SR_DME) { - env->tlb->cpu_openrisc_map_address_data = + env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_data; } else { - env->tlb->cpu_openrisc_map_address_data = + env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; } if (env->sr & SR_IME) { - env->tlb->cpu_openrisc_map_address_code = + env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_code; } else { - env->tlb->cpu_openrisc_map_address_code = + env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; } break; @@ -101,14 +101,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK); + tlb_flush_page(cs, env->tlb.dtlb[0][idx].mr & TARGET_PAGE_MASK); } - env->tlb->dtlb[0][idx].mr = rb; + env->tlb.dtlb[0][idx].mr = rb; break; case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); - env->tlb->dtlb[0][idx].tr = rb; + env->tlb.dtlb[0][idx].tr = rb; break; case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ @@ -120,14 +120,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK); + tlb_flush_page(cs, env->tlb.itlb[0][idx].mr & TARGET_PAGE_MASK); } - env->tlb->itlb[0][idx].mr = rb; + env->tlb.itlb[0][idx].mr = rb; break; case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); - env->tlb->itlb[0][idx].tr = rb; + env->tlb.itlb[0][idx].tr = rb; break; case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ @@ -259,11 +259,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); - return env->tlb->dtlb[0][idx].mr; + return env->tlb.dtlb[0][idx].mr; case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); - return env->tlb->dtlb[0][idx].tr; + return env->tlb.dtlb[0][idx].tr; case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ @@ -275,11 +275,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); - return env->tlb->itlb[0][idx].mr; + return env->tlb.itlb[0][idx].mr; case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); - return env->tlb->itlb[0][idx].tr; + return env->tlb.itlb[0][idx].tr; case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ -- cgit 1.4.1 From 23d45ebdb198378ae580c98ac898aa4b615059fd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 16:51:19 -0700 Subject: target/openrisc: Remove indirect function calls for mmu There is no reason to use an indirect branch instead of simply testing the SR bits that control mmu state. Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.c | 4 --- target/openrisc/cpu.h | 11 ------ target/openrisc/interrupt.c | 2 -- target/openrisc/interrupt_helper.c | 25 ++------------ target/openrisc/machine.c | 26 --------------- target/openrisc/mmu.c | 68 ++++++++++++++++---------------------- target/openrisc/sys_helper.c | 15 --------- 7 files changed, 32 insertions(+), 119 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index fa8e342ff7..b92de51ecf 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -92,10 +92,6 @@ static void openrisc_cpu_initfn(Object *obj) OpenRISCCPU *cpu = OPENRISC_CPU(obj); cs->env_ptr = &cpu->env; - -#ifndef CONFIG_USER_ONLY - cpu_openrisc_mmu_init(cpu); -#endif } /* CPU models */ diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 96b7f58659..a27adad085 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -379,17 +379,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu); void cpu_openrisc_timer_update(OpenRISCCPU *cpu); void cpu_openrisc_count_start(OpenRISCCPU *cpu); void cpu_openrisc_count_stop(OpenRISCCPU *cpu); - -void cpu_openrisc_mmu_init(OpenRISCCPU *cpu); -int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); -int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); -int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); #endif #define OPENRISC_CPU_TYPE_SUFFIX "-" TYPE_OPENRISC_CPU diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index 2d0b55afa9..23abcf29ed 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -63,8 +63,6 @@ void openrisc_cpu_do_interrupt(CPUState *cs) env->sr &= ~SR_TEE; env->pmr &= ~PMR_DME; env->pmr &= ~PMR_SME; - env->tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; - env->tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; env->lock_addr = -1; if (exception > 0 && exception < EXCP_NR) { diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index dc97b38704..a2e9003969 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -29,31 +29,12 @@ void HELPER(rfe)(CPUOpenRISCState *env) #ifndef CONFIG_USER_ONLY int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^ (cpu->env.esr & (SR_SM | SR_IME | SR_DME)); -#endif - cpu->env.pc = cpu->env.epcr; - cpu_set_sr(&cpu->env, cpu->env.esr); - cpu->env.lock_addr = -1; - -#ifndef CONFIG_USER_ONLY - if (cpu->env.sr & SR_DME) { - cpu->env.tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_data; - } else { - cpu->env.tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_nommu; - } - - if (cpu->env.sr & SR_IME) { - cpu->env.tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_code; - } else { - cpu->env.tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_nommu; - } - if (need_flush_tlb) { CPUState *cs = CPU(cpu); tlb_flush(cs); } #endif + cpu->env.pc = cpu->env.epcr; + cpu->env.lock_addr = -1; + cpu_set_sr(&cpu->env, cpu->env.esr); } diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index c10d28b055..73e0abcfd7 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -24,31 +24,6 @@ #include "hw/boards.h" #include "migration/cpu.h" -static int env_post_load(void *opaque, int version_id) -{ - CPUOpenRISCState *env = opaque; - - /* Restore MMU handlers */ - if (env->sr & SR_DME) { - env->tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_data; - } else { - env->tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_nommu; - } - - if (env->sr & SR_IME) { - env->tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_code; - } else { - env->tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_nommu; - } - - - return 0; -} - static const VMStateDescription vmstate_tlb_entry = { .name = "tlb_entry", .version_id = 1, @@ -102,7 +77,6 @@ static const VMStateDescription vmstate_env = { .name = "env", .version_id = 6, .minimum_version_id = 6, - .post_load = env_post_load, .fields = (VMStateField[]) { VMSTATE_UINTTL_2DARRAY(shadow_gpr, CPUOpenRISCState, 16, 32), VMSTATE_UINTTL(pc, CPUOpenRISCState), diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 5665bb7cc9..b2effaa6d7 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -29,18 +29,16 @@ #endif #ifndef CONFIG_USER_ONLY -int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) +static inline int get_phys_nommu(hwaddr *physical, int *prot, + target_ulong address) { *physical = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } -int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) +static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot, + target_ulong address, int rw, bool supervisor) { int vpn = address >> TARGET_PAGE_BITS; int idx = vpn & ITLB_MASK; @@ -52,8 +50,7 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, if (!(cpu->env.tlb.itlb[0][idx].mr & 1)) { return TLBRET_INVALID; } - - if (cpu->env.sr & SR_SM) { /* supervisor mode */ + if (supervisor) { if (cpu->env.tlb.itlb[0][idx].tr & SXE) { right |= PAGE_EXEC; } @@ -62,7 +59,6 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, right |= PAGE_EXEC; } } - if ((rw & 2) && ((right & PAGE_EXEC) == 0)) { return TLBRET_BADADDR; } @@ -73,9 +69,8 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, return TLBRET_MATCH; } -int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) +static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot, + target_ulong address, int rw, bool supervisor) { int vpn = address >> TARGET_PAGE_BITS; int idx = vpn & DTLB_MASK; @@ -87,8 +82,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, if (!(cpu->env.tlb.dtlb[0][idx].mr & 1)) { return TLBRET_INVALID; } - - if (cpu->env.sr & SR_SM) { /* supervisor mode */ + if (supervisor) { if (cpu->env.tlb.dtlb[0][idx].tr & SRE) { right |= PAGE_READ; } @@ -117,20 +111,24 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, return TLBRET_MATCH; } -static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, - int rw) +static int get_phys_addr(OpenRISCCPU *cpu, hwaddr *physical, + int *prot, target_ulong address, int rw) { - int ret = TLBRET_MATCH; - - if (rw == MMU_INST_FETCH) { /* ITLB */ - *physical = 0; - ret = cpu->env.tlb.cpu_openrisc_map_address_code(cpu, physical, - prot, address, rw); - } else { /* DTLB */ - ret = cpu->env.tlb.cpu_openrisc_map_address_data(cpu, physical, - prot, address, rw); + bool supervisor = (cpu->env.sr & SR_SM) != 0; + int ret; + + /* Assume nommu results for a moment. */ + ret = get_phys_nommu(physical, prot, address); + + /* Overwrite with TLB lookup if enabled. */ + if (rw == MMU_INST_FETCH) { + if (cpu->env.sr & SR_IME) { + ret = get_phys_code(cpu, physical, prot, address, rw, supervisor); + } + } else { + if (cpu->env.sr & SR_DME) { + ret = get_phys_data(cpu, physical, prot, address, rw, supervisor); + } } return ret; @@ -186,8 +184,7 @@ int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, hwaddr physical = 0; int prot = 0; - ret = cpu_openrisc_get_phys_addr(cpu, &physical, &prot, - address, rw); + ret = get_phys_addr(cpu, &physical, &prot, address, rw); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, @@ -225,17 +222,16 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) /* Check memory for any kind of address, since during debug the gdb can ask for anything, check data tlb for address */ - miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0); + miss = get_phys_addr(cpu, &phys_addr, &prot, addr, 0); /* Check instruction tlb */ if (miss) { - miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, - MMU_INST_FETCH); + miss = get_phys_addr(cpu, &phys_addr, &prot, addr, MMU_INST_FETCH); } /* Last, fall back to a plain address */ if (miss) { - miss = cpu_openrisc_get_phys_nommu(cpu, &phys_addr, &prot, addr, 0); + miss = get_phys_nommu(&phys_addr, &prot, addr); } if (miss) { @@ -244,10 +240,4 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return phys_addr; } } - -void cpu_openrisc_mmu_init(OpenRISCCPU *cpu) -{ - cpu->env.tlb.cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; - cpu->env.tlb.cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; -} #endif diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index ff315f6f1a..9b4339b34e 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -60,21 +60,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) tlb_flush(cs); } cpu_set_sr(env, rb); - if (env->sr & SR_DME) { - env->tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_data; - } else { - env->tlb.cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_nommu; - } - - if (env->sr & SR_IME) { - env->tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_code; - } else { - env->tlb.cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_nommu; - } break; case TO_SPR(0, 18): /* PPC */ -- cgit 1.4.1 From 2acaa2331b96ee92f0df213784f9b6454c3d5edc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 19:36:27 -0700 Subject: target/openrisc: Reduce tlb to a single dimension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While we had defines for *_WAYS, we didn't define more than 1. Reduce the complexity by eliminating this unused dimension. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.h | 6 ++---- target/openrisc/machine.c | 6 ++---- target/openrisc/mmu.c | 30 ++++++++++++++++-------------- target/openrisc/sys_helper.c | 20 ++++++++++---------- 4 files changed, 30 insertions(+), 32 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index a27adad085..eaf6cdd40e 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -222,10 +222,8 @@ enum { /* TLB size */ enum { - DTLB_WAYS = 1, DTLB_SIZE = 64, DTLB_MASK = (DTLB_SIZE-1), - ITLB_WAYS = 1, ITLB_SIZE = 64, ITLB_MASK = (ITLB_SIZE-1), }; @@ -256,8 +254,8 @@ typedef struct OpenRISCTLBEntry { #ifndef CONFIG_USER_ONLY typedef struct CPUOpenRISCTLBContext { - OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE]; - OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE]; + OpenRISCTLBEntry itlb[ITLB_SIZE]; + OpenRISCTLBEntry dtlb[DTLB_SIZE]; int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu, hwaddr *physical, diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index 73e0abcfd7..b795b56dc6 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -42,11 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_STRUCT_2DARRAY(itlb, CPUOpenRISCTLBContext, - ITLB_WAYS, ITLB_SIZE, 0, + VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0, vmstate_tlb_entry, OpenRISCTLBEntry), - VMSTATE_STRUCT_2DARRAY(dtlb, CPUOpenRISCTLBContext, - DTLB_WAYS, DTLB_SIZE, 0, + VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0, vmstate_tlb_entry, OpenRISCTLBEntry), VMSTATE_END_OF_LIST() } diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 9b4b5cf04f..856969a7f2 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -43,19 +43,21 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot, int vpn = address >> TARGET_PAGE_BITS; int idx = vpn & ITLB_MASK; int right = 0; + uint32_t mr = cpu->env.tlb.itlb[idx].mr; + uint32_t tr = cpu->env.tlb.itlb[idx].tr; - if ((cpu->env.tlb.itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { + if ((mr >> TARGET_PAGE_BITS) != vpn) { return TLBRET_NOMATCH; } - if (!(cpu->env.tlb.itlb[0][idx].mr & 1)) { + if (!(mr & 1)) { return TLBRET_INVALID; } if (supervisor) { - if (cpu->env.tlb.itlb[0][idx].tr & SXE) { + if (tr & SXE) { right |= PAGE_EXEC; } } else { - if (cpu->env.tlb.itlb[0][idx].tr & UXE) { + if (tr & UXE) { right |= PAGE_EXEC; } } @@ -63,8 +65,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot, return TLBRET_BADADDR; } - *physical = (cpu->env.tlb.itlb[0][idx].tr & TARGET_PAGE_MASK) | - (address & (TARGET_PAGE_SIZE-1)); + *physical = (tr & TARGET_PAGE_MASK) | (address & ~TARGET_PAGE_MASK); *prot = right; return TLBRET_MATCH; } @@ -75,25 +76,27 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot, int vpn = address >> TARGET_PAGE_BITS; int idx = vpn & DTLB_MASK; int right = 0; + uint32_t mr = cpu->env.tlb.dtlb[idx].mr; + uint32_t tr = cpu->env.tlb.dtlb[idx].tr; - if ((cpu->env.tlb.dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { + if ((mr >> TARGET_PAGE_BITS) != vpn) { return TLBRET_NOMATCH; } - if (!(cpu->env.tlb.dtlb[0][idx].mr & 1)) { + if (!(mr & 1)) { return TLBRET_INVALID; } if (supervisor) { - if (cpu->env.tlb.dtlb[0][idx].tr & SRE) { + if (tr & SRE) { right |= PAGE_READ; } - if (cpu->env.tlb.dtlb[0][idx].tr & SWE) { + if (tr & SWE) { right |= PAGE_WRITE; } } else { - if (cpu->env.tlb.dtlb[0][idx].tr & URE) { + if (tr & URE) { right |= PAGE_READ; } - if (cpu->env.tlb.dtlb[0][idx].tr & UWE) { + if (tr & UWE) { right |= PAGE_WRITE; } } @@ -105,8 +108,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot, return TLBRET_BADADDR; } - *physical = (cpu->env.tlb.dtlb[0][idx].tr & TARGET_PAGE_MASK) | - (address & (TARGET_PAGE_SIZE-1)); + *physical = (tr & TARGET_PAGE_MASK) | (address & ~TARGET_PAGE_MASK); *prot = right; return TLBRET_MATCH; } diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 9b4339b34e..7f458b0d17 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -86,14 +86,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb.dtlb[0][idx].mr & TARGET_PAGE_MASK); + tlb_flush_page(cs, env->tlb.dtlb[idx].mr & TARGET_PAGE_MASK); } - env->tlb.dtlb[0][idx].mr = rb; + env->tlb.dtlb[idx].mr = rb; break; case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); - env->tlb.dtlb[0][idx].tr = rb; + env->tlb.dtlb[idx].tr = rb; break; case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ @@ -105,14 +105,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb.itlb[0][idx].mr & TARGET_PAGE_MASK); + tlb_flush_page(cs, env->tlb.itlb[idx].mr & TARGET_PAGE_MASK); } - env->tlb.itlb[0][idx].mr = rb; + env->tlb.itlb[idx].mr = rb; break; case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); - env->tlb.itlb[0][idx].tr = rb; + env->tlb.itlb[idx].tr = rb; break; case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ @@ -244,11 +244,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); - return env->tlb.dtlb[0][idx].mr; + return env->tlb.dtlb[idx].mr; case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); - return env->tlb.dtlb[0][idx].tr; + return env->tlb.dtlb[idx].tr; case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ @@ -260,11 +260,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); - return env->tlb.itlb[0][idx].mr; + return env->tlb.itlb[idx].mr; case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); - return env->tlb.itlb[0][idx].tr; + return env->tlb.itlb[idx].tr; case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ -- cgit 1.4.1 From fffde6695f4be3cf484f068f24e894280d7360ea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 19:45:51 -0700 Subject: target/openrisc: Fix tlb flushing in mtspr The previous code was confused, avoiding the flush of the old entry if the new entry is invalid. We need to flush the old page if the old entry is valid and the new page if the new entry is valid. This bug was masked by over-flushing elsewhere. Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 7f458b0d17..c9702cd26c 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -32,6 +32,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) #ifndef CONFIG_USER_ONLY OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); + target_ulong mr; int idx; switch (spr) { @@ -85,12 +86,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); - if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb.dtlb[idx].mr & TARGET_PAGE_MASK); + mr = env->tlb.dtlb[idx].mr; + if (mr & 1) { + tlb_flush_page(cs, mr & TARGET_PAGE_MASK); + } + if (rb & 1) { + tlb_flush_page(cs, rb & TARGET_PAGE_MASK); } env->tlb.dtlb[idx].mr = rb; break; - case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); env->tlb.dtlb[idx].tr = rb; @@ -102,14 +106,18 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ break; + case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); - if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb.itlb[idx].mr & TARGET_PAGE_MASK); + mr = env->tlb.itlb[idx].mr; + if (mr & 1) { + tlb_flush_page(cs, mr & TARGET_PAGE_MASK); + } + if (rb & 1) { + tlb_flush_page(cs, rb & TARGET_PAGE_MASK); } env->tlb.itlb[idx].mr = rb; break; - case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); env->tlb.itlb[idx].tr = rb; @@ -121,6 +129,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ break; + case TO_SPR(5, 1): /* MACLO */ env->mac = deposit64(env->mac, 0, 32, rb); break; -- cgit 1.4.1 From b9bed1b9ab37a6ae62e88a52cbcbd2ad81aa1056 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 19:51:00 -0700 Subject: target/openrisc: Fix cpu_mmu_index The code in cpu_mmu_index does not properly honor SR_DME. This bug has workarounds elsewhere in that we flush the tlb more often than necessary, on the state changes that should be reflected in a change of mmu_index. Fixing this means that we can respect the mmu_index that is given to tlb_flush. Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.h | 23 +++++++++++++++-------- target/openrisc/interrupt.c | 4 ---- target/openrisc/interrupt_helper.c | 15 +++------------ target/openrisc/mmu.c | 33 ++++++++++++++++++++++++++++++--- target/openrisc/sys_helper.c | 4 ---- target/openrisc/translate.c | 2 +- 6 files changed, 49 insertions(+), 32 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index eaf6cdd40e..c3a968ec4d 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -385,9 +385,12 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu); #include "exec/cpu-all.h" -#define TB_FLAGS_DFLAG 1 -#define TB_FLAGS_R0_0 2 +#define TB_FLAGS_SM SR_SM +#define TB_FLAGS_DME SR_DME +#define TB_FLAGS_IME SR_IME #define TB_FLAGS_OVE SR_OVE +#define TB_FLAGS_DFLAG 2 /* reuse SR_TEE */ +#define TB_FLAGS_R0_0 4 /* reuse SR_IEE */ static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i) { @@ -405,17 +408,21 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, { *pc = env->pc; *cs_base = 0; - *flags = (env->dflag - | (cpu_get_gpr(env, 0) == 0 ? TB_FLAGS_R0_0 : 0) - | (env->sr & SR_OVE)); + *flags = (env->dflag ? TB_FLAGS_DFLAG : 0) + | (cpu_get_gpr(env, 0) ? 0 : TB_FLAGS_R0_0) + | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE)); } static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) { - if (!(env->sr & SR_IME)) { - return MMU_NOMMU_IDX; + int ret = MMU_NOMMU_IDX; /* mmu is disabled */ + + if (env->sr & (ifetch ? SR_IME : SR_DME)) { + /* The mmu is enabled; test supervisor state. */ + ret = env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX; } - return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX; + + return ret; } static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index 23abcf29ed..138ad17f00 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -51,10 +51,6 @@ void openrisc_cpu_do_interrupt(CPUState *cs) env->eear = env->pc; } - /* For machine-state changed between user-mode and supervisor mode, - we need flush TLB when we enter&exit EXCP. */ - tlb_flush(cs); - env->esr = cpu_get_sr(env); env->sr &= ~SR_DME; env->sr &= ~SR_IME; diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index a2e9003969..9c5489f5f7 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -25,16 +25,7 @@ void HELPER(rfe)(CPUOpenRISCState *env) { - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); -#ifndef CONFIG_USER_ONLY - int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^ - (cpu->env.esr & (SR_SM | SR_IME | SR_DME)); - if (need_flush_tlb) { - CPUState *cs = CPU(cpu); - tlb_flush(cs); - } -#endif - cpu->env.pc = cpu->env.epcr; - cpu->env.lock_addr = -1; - cpu_set_sr(&cpu->env, cpu->env.esr); + env->pc = env->epcr; + env->lock_addr = -1; + cpu_set_sr(env, env->esr); } diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 856969a7f2..b293b64e98 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -246,9 +246,36 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) void tlb_fill(CPUState *cs, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - int ret = openrisc_cpu_handle_mmu_fault(cs, addr, size, - access_type, mmu_idx); - if (ret) { + OpenRISCCPU *cpu = OPENRISC_CPU(cs); + int ret, prot = 0; + hwaddr physical = 0; + + if (mmu_idx == MMU_NOMMU_IDX) { + ret = get_phys_nommu(&physical, &prot, addr); + } else { + bool super = mmu_idx == MMU_SUPERVISOR_IDX; + if (access_type == MMU_INST_FETCH) { + ret = get_phys_code(cpu, &physical, &prot, addr, 2, super); + } else { + ret = get_phys_data(cpu, &physical, &prot, addr, + access_type == MMU_DATA_STORE, super); + } + } + + if (ret == TLBRET_MATCH) { + tlb_set_page(cs, addr & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot, + mmu_idx, TARGET_PAGE_SIZE); + } else if (ret < 0) { + int rw; + if (access_type == MMU_INST_FETCH) { + rw = 2; + } else if (access_type == MMU_DATA_STORE) { + rw = 1; + } else { + rw = 0; + } + cpu_openrisc_raise_mmu_exception(cpu, addr, rw, ret); /* Raise Exception. */ cpu_loop_exit_restore(cs, retaddr); } diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index c9702cd26c..852b219f9b 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -56,10 +56,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) break; case TO_SPR(0, 17): /* SR */ - if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^ - (rb & (SR_IME | SR_DME | SR_SM))) { - tlb_flush(cs); - } cpu_set_sr(env, rb); break; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 64b5e84630..a271cd3903 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -55,7 +55,7 @@ static inline bool is_user(DisasContext *dc) #ifdef CONFIG_USER_ONLY return true; #else - return dc->mem_idx == MMU_USER_IDX; + return !(dc->tb_flags & TB_FLAGS_SM); #endif } -- cgit 1.4.1 From 56c3a1415653bd485b06e718c6f14e32dcfe59b3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 May 2018 20:18:20 -0700 Subject: target/openrisc: Use identical sizes for ITLB and DTLB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sizes are already the same, however, we can improve things if they are identical by design. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.h | 10 ++++------ target/openrisc/machine.c | 4 ++-- target/openrisc/mmu.c | 4 ++-- target/openrisc/sys_helper.c | 16 ++++++++-------- 4 files changed, 16 insertions(+), 18 deletions(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index c3a968ec4d..47e94659e1 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -222,10 +222,8 @@ enum { /* TLB size */ enum { - DTLB_SIZE = 64, - DTLB_MASK = (DTLB_SIZE-1), - ITLB_SIZE = 64, - ITLB_MASK = (ITLB_SIZE-1), + TLB_SIZE = 64, + TLB_MASK = TLB_SIZE - 1, }; /* TLB prot */ @@ -254,8 +252,8 @@ typedef struct OpenRISCTLBEntry { #ifndef CONFIG_USER_ONLY typedef struct CPUOpenRISCTLBContext { - OpenRISCTLBEntry itlb[ITLB_SIZE]; - OpenRISCTLBEntry dtlb[DTLB_SIZE]; + OpenRISCTLBEntry itlb[TLB_SIZE]; + OpenRISCTLBEntry dtlb[TLB_SIZE]; int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu, hwaddr *physical, diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index b795b56dc6..3fc837b925 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -42,9 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0, + VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, TLB_SIZE, 0, vmstate_tlb_entry, OpenRISCTLBEntry), - VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0, + VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, TLB_SIZE, 0, vmstate_tlb_entry, OpenRISCTLBEntry), VMSTATE_END_OF_LIST() } diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index b293b64e98..a4613e9ae4 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -41,7 +41,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot, target_ulong address, int rw, bool supervisor) { int vpn = address >> TARGET_PAGE_BITS; - int idx = vpn & ITLB_MASK; + int idx = vpn & TLB_MASK; int right = 0; uint32_t mr = cpu->env.tlb.itlb[idx].mr; uint32_t tr = cpu->env.tlb.itlb[idx].tr; @@ -74,7 +74,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot, target_ulong address, int rw, bool supervisor) { int vpn = address >> TARGET_PAGE_BITS; - int idx = vpn & DTLB_MASK; + int idx = vpn & TLB_MASK; int right = 0; uint32_t mr = cpu->env.tlb.dtlb[idx].mr; uint32_t tr = cpu->env.tlb.dtlb[idx].tr; diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 852b219f9b..541615bfb3 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -80,7 +80,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) env->shadow_gpr[idx / 32][idx % 32] = rb; break; - case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ + case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); mr = env->tlb.dtlb[idx].mr; if (mr & 1) { @@ -91,7 +91,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) } env->tlb.dtlb[idx].mr = rb; break; - case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ + case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); env->tlb.dtlb[idx].tr = rb; break; @@ -103,7 +103,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ break; - case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ + case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); mr = env->tlb.itlb[idx].mr; if (mr & 1) { @@ -114,7 +114,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) } env->tlb.itlb[idx].mr = rb; break; - case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ + case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); env->tlb.itlb[idx].tr = rb; break; @@ -247,11 +247,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, idx = (spr - 1024); return env->shadow_gpr[idx / 32][idx % 32]; - case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ + case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); return env->tlb.dtlb[idx].mr; - case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ + case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); return env->tlb.dtlb[idx].tr; @@ -263,11 +263,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ break; - case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ + case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); return env->tlb.itlb[idx].mr; - case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ + case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); return env->tlb.itlb[idx].tr; -- cgit 1.4.1 From dfc84745bbaa0fea2abc8575dd349f6e4bb7edc7 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 1 Jul 2018 17:02:54 +0900 Subject: target/openrisc: Fix writes to interrupt mask register The interrupt controller mask register (PICMR) allows writing any value to any of the 32 interrupt mask bits. Writing a 0 masks the interrupt writing a 1 unmasks (enables) the the interrupt. For some reason the old code was or'ing the write values to the PICMR meaning it was not possible to ever mask a interrupt once it was enabled. I have tested this by running linux 4.18 and my regular checks, I don't see any issues. Reported-by: Davidson Francis Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 541615bfb3..b66a45c1e0 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -142,7 +142,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) } break; case TO_SPR(9, 0): /* PICMR */ - env->picmr |= rb; + env->picmr = rb; break; case TO_SPR(9, 2): /* PICSR */ env->picsr &= ~rb; -- cgit 1.4.1