From e41c94529740cc26ac6d6eea4bb8b6f77466f5e4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 14:51:11 +0700 Subject: target/alpha: Convert to CPUClass::tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/alpha/cpu.c | 5 ++--- target/alpha/cpu.h | 5 +++-- target/alpha/helper.c | 30 +++++++++++++++++++++--------- target/alpha/mem_helper.c | 16 ---------------- 4 files changed, 26 insertions(+), 30 deletions(-) (limited to 'target') diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c index ad3588a..7c81be4 100644 --- a/target/alpha/cpu.c +++ b/target/alpha/cpu.c @@ -225,9 +225,8 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = alpha_cpu_set_pc; cc->gdb_read_register = alpha_cpu_gdb_read_register; cc->gdb_write_register = alpha_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = alpha_cpu_handle_mmu_fault; -#else + cc->tlb_fill = alpha_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_transaction_failed = alpha_cpu_do_transaction_failed; cc->do_unaligned_access = alpha_cpu_do_unaligned_access; cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug; diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index 63bf361..cf09112 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -475,8 +475,9 @@ void alpha_cpu_list(void); is returned if the signal was handled by the virtual CPU. */ int cpu_alpha_signal_handler(int host_signum, void *pinfo, void *puc); -int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int); void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t); diff --git a/target/alpha/helper.c b/target/alpha/helper.c index 7201576..929a217 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -104,14 +104,15 @@ void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val) } #if defined(CONFIG_USER_ONLY) -int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { AlphaCPU *cpu = ALPHA_CPU(cs); cs->exception_index = EXCP_MMFAULT; cpu->env.trap_arg0 = address; - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else /* Returns the OSF/1 entMM failure indication, or -1 on success. */ @@ -248,26 +249,37 @@ hwaddr alpha_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return (fail >= 0 ? -1 : phys); } -int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, int rw, - int mmu_idx) +bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { AlphaCPU *cpu = ALPHA_CPU(cs); CPUAlphaState *env = &cpu->env; target_ulong phys; int prot, fail; - fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); + fail = get_physical_address(env, addr, 1 << access_type, + mmu_idx, &phys, &prot); if (unlikely(fail >= 0)) { + if (probe) { + return false; + } cs->exception_index = EXCP_MMFAULT; env->trap_arg0 = addr; env->trap_arg1 = fail; - env->trap_arg2 = (rw == 2 ? -1 : rw); - return 1; + env->trap_arg2 = (access_type == MMU_INST_FETCH ? -1 : access_type); + cpu_loop_exit_restore(cs, retaddr); } tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + alpha_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } #endif /* USER_ONLY */ diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c index 011bc73..934faa1 100644 --- a/target/alpha/mem_helper.c +++ b/target/alpha/mem_helper.c @@ -62,20 +62,4 @@ void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, env->error_code = 0; cpu_loop_exit_restore(cs, retaddr); } - -/* try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = alpha_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret != 0)) { - /* Exception index and error code are already set */ - cpu_loop_exit_restore(cs, retaddr); - } -} #endif /* CONFIG_USER_ONLY */ -- cgit v1.1 From 7350d553b5066abdc662045d7db5cdb73d0f9d53 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:12:58 +0700 Subject: target/arm: Convert to CPUClass::tlb_fill Cc: qemu-arm@nongnu.org Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/arm/cpu.c | 22 ++---------- target/arm/helper.c | 98 +++++++++++++++++++++++++++++++------------------- target/arm/internals.h | 10 +++--- target/arm/op_helper.c | 29 +++------------ 4 files changed, 73 insertions(+), 86 deletions(-) (limited to 'target') diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a181fa8..8eee1d8 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2133,23 +2133,6 @@ static Property arm_cpu_properties[] = { DEFINE_PROP_END_OF_LIST() }; -#ifdef CONFIG_USER_ONLY -static int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - - env->exception.vaddress = address; - if (rw == 2) { - cs->exception_index = EXCP_PREFETCH_ABORT; - } else { - cs->exception_index = EXCP_DATA_ABORT; - } - return 1; -} -#endif - static gchar *arm_gdb_arch_name(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); @@ -2182,9 +2165,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; cc->gdb_read_register = arm_cpu_gdb_read_register; cc->gdb_write_register = arm_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = arm_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->do_interrupt = arm_cpu_do_interrupt; cc->do_unaligned_access = arm_cpu_do_unaligned_access; cc->do_transaction_failed = arm_cpu_do_transaction_failed; @@ -2209,6 +2190,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->disas_set_info = arm_disas_set_info; #ifdef CONFIG_TCG cc->tcg_initialize = arm_translate_init; + cc->tlb_fill = arm_cpu_tlb_fill; #endif } diff --git a/target/arm/helper.c b/target/arm/helper.c index 1e6eb0d..f1a2b94 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -12596,43 +12596,6 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address, } } -/* Walk the page table and (if the mapping exists) add the page - * to the TLB. Return false on success, or true on failure. Populate - * fsr with ARM DFSR/IFSR fault register format value on failure. - */ -bool arm_tlb_fill(CPUState *cs, vaddr address, - MMUAccessType access_type, int mmu_idx, - ARMMMUFaultInfo *fi) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - hwaddr phys_addr; - target_ulong page_size; - int prot; - int ret; - MemTxAttrs attrs = {}; - - ret = get_phys_addr(env, address, access_type, - core_to_arm_mmu_idx(env, mmu_idx), &phys_addr, - &attrs, &prot, &page_size, fi, NULL); - if (!ret) { - /* - * Map a single [sub]page. Regions smaller than our declared - * target page size are handled specially, so for those we - * pass in the exact addresses. - */ - if (page_size >= TARGET_PAGE_SIZE) { - phys_addr &= TARGET_PAGE_MASK; - address &= TARGET_PAGE_MASK; - } - tlb_set_page_with_attrs(cs, address, phys_addr, attrs, - prot, mmu_idx, page_size); - return 0; - } - - return ret; -} - hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, MemTxAttrs *attrs) { @@ -13111,6 +13074,67 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) #endif +bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + ARMCPU *cpu = ARM_CPU(cs); + +#ifdef CONFIG_USER_ONLY + cpu->env.exception.vaddress = address; + if (access_type == MMU_INST_FETCH) { + cs->exception_index = EXCP_PREFETCH_ABORT; + } else { + cs->exception_index = EXCP_DATA_ABORT; + } + cpu_loop_exit_restore(cs, retaddr); +#else + hwaddr phys_addr; + target_ulong page_size; + int prot, ret; + MemTxAttrs attrs = {}; + ARMMMUFaultInfo fi = {}; + + /* + * Walk the page table and (if the mapping exists) add the page + * to the TLB. On success, return true. Otherwise, if probing, + * return false. Otherwise populate fsr with ARM DFSR/IFSR fault + * register format, and signal the fault. + */ + ret = get_phys_addr(&cpu->env, address, access_type, + core_to_arm_mmu_idx(&cpu->env, mmu_idx), + &phys_addr, &attrs, &prot, &page_size, &fi, NULL); + if (likely(!ret)) { + /* + * Map a single [sub]page. Regions smaller than our declared + * target page size are handled specially, so for those we + * pass in the exact addresses. + */ + if (page_size >= TARGET_PAGE_SIZE) { + phys_addr &= TARGET_PAGE_MASK; + address &= TARGET_PAGE_MASK; + } + tlb_set_page_with_attrs(cs, address, phys_addr, attrs, + prot, mmu_idx, page_size); + return true; + } else if (probe) { + return false; + } else { + /* now we have a real cpu fault */ + cpu_restore_state(cs, retaddr, true); + arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi); + } +#endif +} + +#ifndef CONFIG_USER_ONLY +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + arm_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); +} +#endif + void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) { /* Implement DC ZVA, which zeroes a fixed-length block of memory. diff --git a/target/arm/internals.h b/target/arm/internals.h index 587a1dd..5a02f45 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -761,10 +761,12 @@ static inline bool arm_extabort_type(MemTxResult result) return result != MEMTX_DECODE_ERROR; } -/* Do a page table walk and add page to TLB if possible */ -bool arm_tlb_fill(CPUState *cpu, vaddr address, - MMUAccessType access_type, int mmu_idx, - ARMMMUFaultInfo *fi); +bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); + +void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, + int mmu_idx, ARMMMUFaultInfo *fi) QEMU_NORETURN; /* Return true if the stage 1 translation regime is using LPAE format page * tables */ diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 8698b4d..8ee15a4 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -126,8 +126,8 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn, return syn; } -static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, - int mmu_idx, ARMMMUFaultInfo *fi) +void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, + int mmu_idx, ARMMMUFaultInfo *fi) { CPUARMState *env = &cpu->env; int target_el; @@ -179,27 +179,6 @@ static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, raise_exception(env, exc, syn, target_el); } -/* try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - bool ret; - ARMMMUFaultInfo fi = {}; - - ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fi); - if (unlikely(ret)) { - ARMCPU *cpu = ARM_CPU(cs); - - /* now we have a real cpu fault */ - cpu_restore_state(cs, retaddr, true); - - deliver_fault(cpu, addr, access_type, mmu_idx, &fi); - } -} - /* Raise a data fault alignment exception for the specified virtual address */ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, MMUAccessType access_type, @@ -212,7 +191,7 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, cpu_restore_state(cs, retaddr, true); fi.type = ARMFault_Alignment; - deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); + arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); } /* arm_cpu_do_transaction_failed: handle a memory system error response @@ -233,7 +212,7 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, fi.ea = arm_extabort_type(response); fi.type = ARMFault_SyncExternal; - deliver_fault(cpu, addr, access_type, mmu_idx, &fi); + arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi); } #endif /* !defined(CONFIG_USER_ONLY) */ -- cgit v1.1 From c038ec934632c0916c9a835a1c778b30ead88f7c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:24:13 +0700 Subject: target/cris: Convert to CPUClass::tlb_fill Remove dumping of cpu state. Remove logging of PC, as that value is garbage until cpu_restore_state. Cc: Edgar E. Iglesias Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/cris/cpu.c | 5 ++-- target/cris/cpu.h | 5 ++-- target/cris/helper.c | 67 +++++++++++++++++++++++++++---------------------- target/cris/op_helper.c | 28 --------------------- 4 files changed, 42 insertions(+), 63 deletions(-) (limited to 'target') diff --git a/target/cris/cpu.c b/target/cris/cpu.c index 75729bf..4e5288a 100644 --- a/target/cris/cpu.c +++ b/target/cris/cpu.c @@ -269,9 +269,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = cris_cpu_set_pc; cc->gdb_read_register = cris_cpu_gdb_read_register; cc->gdb_write_register = cris_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = cris_cpu_handle_mmu_fault; -#else + cc->tlb_fill = cris_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = cris_cpu_get_phys_page_debug; dc->vmsd = &vmstate_cris_cpu; #endif diff --git a/target/cris/cpu.h b/target/cris/cpu.h index 0fbe771..857de79 100644 --- a/target/cris/cpu.h +++ b/target/cris/cpu.h @@ -281,8 +281,9 @@ static inline int cpu_mmu_index (CPUCRISState *env, bool ifetch) return !!(env->pregs[PR_CCS] & U_FLAG); } -int cris_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); /* Support function regs. */ #define SFR_RW_GC_CFG 0][0 diff --git a/target/cris/helper.c b/target/cris/helper.c index 3939603..6946483 100644 --- a/target/cris/helper.c +++ b/target/cris/helper.c @@ -24,6 +24,7 @@ #include "qemu/host-utils.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "exec/helper-proto.h" //#define CRIS_HELPER_DEBUG @@ -53,15 +54,15 @@ void crisv10_cpu_do_interrupt(CPUState *cs) cris_cpu_do_interrupt(cs); } -int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { CRISCPU *cpu = CRIS_CPU(cs); cs->exception_index = 0xaa; cpu->env.pregs[PR_EDA] = address; - cpu_dump_state(cs, stderr, 0); - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else /* !CONFIG_USER_ONLY */ @@ -76,33 +77,19 @@ static void cris_shift_ccs(CPUCRISState *env) env->pregs[PR_CCS] = ccs; } -int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { CRISCPU *cpu = CRIS_CPU(cs); CPUCRISState *env = &cpu->env; struct cris_mmu_result res; int prot, miss; - int r = -1; target_ulong phy; - qemu_log_mask(CPU_LOG_MMU, "%s addr=%" VADDR_PRIx " pc=%x rw=%x\n", - __func__, address, env->pc, rw); miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK, - rw, mmu_idx, 0); - if (miss) { - if (cs->exception_index == EXCP_BUSFAULT) { - cpu_abort(cs, - "CRIS: Illegal recursive bus fault." - "addr=%" VADDR_PRIx " rw=%d\n", - address, rw); - } - - env->pregs[PR_EDA] = address; - cs->exception_index = EXCP_BUSFAULT; - env->fault_vector = res.bf_vec; - r = 1; - } else { + access_type, mmu_idx, 0); + if (likely(!miss)) { /* * Mask off the cache selection bit. The ETRAX busses do not * see the top bit. @@ -111,15 +98,35 @@ int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, prot = res.prot; tlb_set_page(cs, address & TARGET_PAGE_MASK, phy, prot, mmu_idx, TARGET_PAGE_SIZE); - r = 0; + return true; + } + + if (probe) { + return false; + } + + if (cs->exception_index == EXCP_BUSFAULT) { + cpu_abort(cs, "CRIS: Illegal recursive bus fault." + "addr=%" VADDR_PRIx " access_type=%d\n", + address, access_type); } - if (r > 0) { - qemu_log_mask(CPU_LOG_MMU, - "%s returns %d irqreq=%x addr=%" VADDR_PRIx " phy=%x vec=%x" - " pc=%x\n", __func__, r, cs->interrupt_request, address, - res.phy, res.bf_vec, env->pc); + + env->pregs[PR_EDA] = address; + cs->exception_index = EXCP_BUSFAULT; + env->fault_vector = res.bf_vec; + if (retaddr) { + if (cpu_restore_state(cs, retaddr, true)) { + /* Evaluate flags after retranslation. */ + helper_top_evaluate_flags(env); + } } - return r; + cpu_loop_exit(cs); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + cris_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } void crisv10_cpu_do_interrupt(CPUState *cs) diff --git a/target/cris/op_helper.c b/target/cris/op_helper.c index 0ee3a31..26a395b 100644 --- a/target/cris/op_helper.c +++ b/target/cris/op_helper.c @@ -37,34 +37,6 @@ #define D_LOG(...) do { } while (0) #endif -#if !defined(CONFIG_USER_ONLY) -/* Try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - CRISCPU *cpu = CRIS_CPU(cs); - CPUCRISState *env = &cpu->env; - int ret; - - D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__, - env->pc, env->pregs[PR_EDA], (void *)retaddr); - ret = cris_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - if (retaddr) { - /* now we have a real cpu fault */ - if (cpu_restore_state(cs, retaddr, true)) { - /* Evaluate flags after retranslation. */ - helper_top_evaluate_flags(env); - } - } - cpu_loop_exit(cs); - } -} - -#endif - void helper_raise_exception(CPUCRISState *env, uint32_t index) { CPUState *cs = CPU(cris_env_get_cpu(env)); -- cgit v1.1 From 3c7bef03c54f9b731539b8037ba0160402a3a2a6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:30:10 +0700 Subject: target/hppa: Convert to CPUClass::tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 5 ++--- target/hppa/cpu.h | 8 ++++---- target/hppa/mem_helper.c | 22 +++++++++++++++++----- 3 files changed, 23 insertions(+), 12 deletions(-) (limited to 'target') diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index e64f485..9717ea1 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -163,9 +163,8 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb; cc->gdb_read_register = hppa_cpu_gdb_read_register; cc->gdb_write_register = hppa_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault; -#else + cc->tlb_fill = hppa_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; dc->vmsd = &vmstate_hppa_cpu; #endif diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 923346a..c1e0215 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -360,10 +360,10 @@ int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void hppa_cpu_do_interrupt(CPUState *cpu); bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); void hppa_cpu_dump_state(CPUState *cs, FILE *f, int); -#ifdef CONFIG_USER_ONLY -int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int midx); -#else +bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); +#ifndef CONFIG_USER_ONLY int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot); extern const MemoryRegionOps hppa_io_eir_ops; diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 77fb544..5cee0c1 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -25,8 +25,9 @@ #include "trace.h" #ifdef CONFIG_USER_ONLY -int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, - int size, int rw, int mmu_idx) +bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { HPPACPU *cpu = HPPA_CPU(cs); @@ -34,7 +35,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, which would affect si_code. */ cs->exception_index = EXCP_DMP; cpu->env.cr[CR_IOR] = address; - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr) @@ -213,8 +214,9 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return excp == EXCP_DTLB_MISS ? -1 : phys; } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType type, int mmu_idx, uintptr_t retaddr) +bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType type, int mmu_idx, + bool probe, uintptr_t retaddr) { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; @@ -236,6 +238,9 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size, excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, &phys, &prot); if (unlikely(excp >= 0)) { + if (probe) { + return false; + } trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx); /* Failure. Raise the indicated exception. */ cs->exception_index = excp; @@ -252,6 +257,13 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size, /* Success! Store the translation into the QEMU TLB. */ tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); + return true; +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType type, int mmu_idx, uintptr_t retaddr) +{ + hppa_cpu_tlb_fill(cs, addr, size, type, mmu_idx, false, retaddr); } /* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */ -- cgit v1.1 From 5d0044212c375c0696baef7bba13699277dac5b5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:39:50 +0700 Subject: target/i386: Convert to CPUClass::tlb_fill We do not support probing, but we do not need it yet either. Cc: Paolo Bonzini Cc: Eduardo Habkost Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/i386/cpu.c | 5 ++-- target/i386/cpu.h | 5 ++-- target/i386/excp_helper.c | 61 ++++++++++++++++++++++++++++++----------------- target/i386/mem_helper.c | 21 ---------------- 4 files changed, 44 insertions(+), 48 deletions(-) (limited to 'target') diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 722c551..2df56fa 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5915,9 +5915,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->gdb_write_register = x86_cpu_gdb_write_register; cc->get_arch_id = x86_cpu_get_arch_id; cc->get_paging_enabled = x86_cpu_get_paging_enabled; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = x86_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->asidx_from_attrs = x86_asidx_from_attrs; cc->get_memory_mapping = x86_cpu_get_memory_mapping; cc->get_phys_page_debug = x86_cpu_get_phys_page_debug; @@ -5942,6 +5940,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->cpu_exec_exit = x86_cpu_exec_exit; #ifdef CONFIG_TCG cc->tcg_initialize = tcg_x86_init; + cc->tlb_fill = x86_cpu_tlb_fill; #endif cc->disas_set_info = x86_disas_set_info; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 0128910..fce6660 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1656,8 +1656,9 @@ void host_cpuid(uint32_t function, uint32_t count, void host_vendor_fms(char *vendor, int *family, int *model, int *stepping); /* helper.c */ -int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr, int size, - int is_write, int mmu_idx); +bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void x86_cpu_set_a20(X86CPU *cpu, int a20_state); #ifndef CONFIG_USER_ONLY diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c index 49231f6..68bf8e3 100644 --- a/target/i386/excp_helper.c +++ b/target/i386/excp_helper.c @@ -137,26 +137,7 @@ void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr raise_interrupt2(env, exception_index, 0, 0, 0, retaddr); } -#if defined(CONFIG_USER_ONLY) -int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, - int is_write, int mmu_idx) -{ - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - - /* user mode only emulation */ - is_write &= 1; - env->cr[2] = addr; - env->error_code = (is_write << PG_ERROR_W_BIT); - env->error_code |= PG_ERROR_U_MASK; - cs->exception_index = EXCP0E_PAGE; - env->exception_is_int = 0; - env->exception_next_eip = -1; - return 1; -} - -#else - +#if !defined(CONFIG_USER_ONLY) static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, int *prot) { @@ -365,8 +346,8 @@ static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, * 0 = nothing more to do * 1 = generate PF fault */ -int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, - int is_write1, int mmu_idx) +static int handle_mmu_fault(CPUState *cs, vaddr addr, int size, + int is_write1, int mmu_idx) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; @@ -691,3 +672,39 @@ do_check_protect_pse36: return 1; } #endif + +bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + +#ifdef CONFIG_USER_ONLY + /* user mode only emulation */ + env->cr[2] = addr; + env->error_code = (access_type == MMU_DATA_STORE) << PG_ERROR_W_BIT; + env->error_code |= PG_ERROR_U_MASK; + cs->exception_index = EXCP0E_PAGE; + env->exception_is_int = 0; + env->exception_next_eip = -1; + cpu_loop_exit_restore(cs, retaddr); +#else + env->retaddr = retaddr; + if (handle_mmu_fault(cs, addr, size, access_type, mmu_idx)) { + /* FIXME: On error in get_hphys we have already jumped out. */ + g_assert(!probe); + raise_exception_err_ra(env, cs->exception_index, + env->error_code, retaddr); + } + return true; +#endif +} + +#if !defined(CONFIG_USER_ONLY) +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + x86_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); +} +#endif diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c index 6cc53bc..1885df2 100644 --- a/target/i386/mem_helper.c +++ b/target/i386/mem_helper.c @@ -191,24 +191,3 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v) raise_exception_ra(env, EXCP05_BOUND, GETPC()); } } - -#if !defined(CONFIG_USER_ONLY) -/* try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - int ret; - - env->retaddr = retaddr; - ret = x86_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (ret) { - raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr); - } -} -#endif -- cgit v1.1 From ae0d4c0b52f030533dfba98188f61a28f9e87592 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:45:45 +0700 Subject: target/lm32: Convert to CPUClass::tlb_fill Cc: Michael Walle Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/lm32/cpu.c | 5 ++--- target/lm32/cpu.h | 5 +++-- target/lm32/helper.c | 12 +++++++++--- target/lm32/op_helper.c | 16 ---------------- 4 files changed, 14 insertions(+), 24 deletions(-) (limited to 'target') diff --git a/target/lm32/cpu.c b/target/lm32/cpu.c index 282da19..57c50c1 100644 --- a/target/lm32/cpu.c +++ b/target/lm32/cpu.c @@ -231,9 +231,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = lm32_cpu_set_pc; cc->gdb_read_register = lm32_cpu_gdb_read_register; cc->gdb_write_register = lm32_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = lm32_cpu_handle_mmu_fault; -#else + cc->tlb_fill = lm32_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug; cc->vmsd = &vmstate_lm32_cpu; #endif diff --git a/target/lm32/cpu.h b/target/lm32/cpu.h index 9b1e6c2..d224d44 100644 --- a/target/lm32/cpu.h +++ b/target/lm32/cpu.h @@ -261,8 +261,9 @@ bool lm32_cpu_do_semihosting(CPUState *cs); #define cpu_list lm32_cpu_list #define cpu_signal_handler cpu_lm32_signal_handler -int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); #include "exec/cpu-all.h" diff --git a/target/lm32/helper.c b/target/lm32/helper.c index a039a99..1db9a55 100644 --- a/target/lm32/helper.c +++ b/target/lm32/helper.c @@ -25,8 +25,9 @@ #include "exec/semihost.h" #include "exec/log.h" -int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { LM32CPU *cpu = LM32_CPU(cs); CPULM32State *env = &cpu->env; @@ -40,8 +41,13 @@ int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, } else { tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); } + return true; +} - return 0; +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + lm32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) diff --git a/target/lm32/op_helper.c b/target/lm32/op_helper.c index 234d55e..be12b11 100644 --- a/target/lm32/op_helper.c +++ b/target/lm32/op_helper.c @@ -143,21 +143,5 @@ uint32_t HELPER(rcsr_jrx)(CPULM32State *env) { return lm32_juart_get_jrx(env->juart_state); } - -/* Try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = lm32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} #endif -- cgit v1.1 From fe5f7b1b3a2317f598687218c348b54e02a75e1f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 15:55:10 +0700 Subject: target/m68k: Convert to CPUClass::tlb_fill Cc: Laurent Vivier Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/m68k/cpu.c | 2 +- target/m68k/cpu.h | 5 +-- target/m68k/helper.c | 87 ++++++++++++++++++++++++++----------------------- target/m68k/op_helper.c | 15 --------- 4 files changed, 50 insertions(+), 59 deletions(-) (limited to 'target') diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 582e3a7..6f441bc 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -269,7 +269,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) cc->set_pc = m68k_cpu_set_pc; cc->gdb_read_register = m68k_cpu_gdb_read_register; cc->gdb_write_register = m68k_cpu_gdb_write_register; - cc->handle_mmu_fault = m68k_cpu_handle_mmu_fault; + cc->tlb_fill = m68k_cpu_tlb_fill; #if defined(CONFIG_SOFTMMU) cc->do_unassigned_access = m68k_cpu_unassigned_access; cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index ad41608..683d3e2 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -542,8 +542,9 @@ static inline int cpu_mmu_index (CPUM68KState *env, bool ifetch) return (env->sr & SR_S) == 0 ? 1 : 0; } -int m68k_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write, bool is_exec, int is_asi, unsigned size); diff --git a/target/m68k/helper.c b/target/m68k/helper.c index d958a34..862f955 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -353,20 +353,7 @@ void m68k_switch_sp(CPUM68KState *env) env->current_sp = new_sp; } -#if defined(CONFIG_USER_ONLY) - -int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) -{ - M68kCPU *cpu = M68K_CPU(cs); - - cs->exception_index = EXCP_ACCESS; - cpu->env.mmu.ar = address; - return 1; -} - -#else - +#if !defined(CONFIG_USER_ONLY) /* MMU: 68040 only */ static void print_address_zone(uint32_t logical, uint32_t physical, @@ -795,11 +782,36 @@ hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return phys_addr; } -int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +/* + * Notify CPU of a pending interrupt. Prioritization and vectoring should + * be handled by the interrupt controller. Real hardware only requests + * the vector when the interrupt is acknowledged by the CPU. For + * simplicity we calculate it when the interrupt is signalled. + */ +void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) +{ + CPUState *cs = CPU(cpu); + CPUM68KState *env = &cpu->env; + + env->pending_level = level; + env->pending_vector = vector; + if (level) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + +#endif + +bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType qemu_access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { M68kCPU *cpu = M68K_CPU(cs); CPUM68KState *env = &cpu->env; + +#ifndef CONFIG_USER_ONLY hwaddr physical; int prot; int access_type; @@ -812,32 +824,35 @@ int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, address & TARGET_PAGE_MASK, PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; } - if (rw == 2) { + if (qemu_access_type == MMU_INST_FETCH) { access_type = ACCESS_CODE; - rw = 0; } else { access_type = ACCESS_DATA; - if (rw) { + if (qemu_access_type == MMU_DATA_STORE) { access_type |= ACCESS_STORE; } } - if (mmu_idx != MMU_USER_IDX) { access_type |= ACCESS_SUPER; } ret = get_physical_address(&cpu->env, &physical, &prot, address, access_type, &page_size); - if (ret == 0) { + if (likely(ret == 0)) { address &= TARGET_PAGE_MASK; physical += address & (page_size - 1); tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; } + + if (probe) { + return false; + } + /* page fault */ env->mmu.ssw = M68K_ATC_040; switch (size) { @@ -862,29 +877,19 @@ int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, if (!(access_type & ACCESS_STORE)) { env->mmu.ssw |= M68K_RW_040; } - env->mmu.ar = address; +#endif + cs->exception_index = EXCP_ACCESS; - return 1; + env->mmu.ar = address; + cpu_loop_exit_restore(cs, retaddr); } -/* Notify CPU of a pending interrupt. Prioritization and vectoring should - be handled by the interrupt controller. Real hardware only requests - the vector when the interrupt is acknowledged by the CPU. For - simplicitly we calculate it when the interrupt is signalled. */ -void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) +#ifndef CONFIG_USER_ONLY +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - CPUState *cs = CPU(cpu); - CPUM68KState *env = &cpu->env; - - env->pending_level = level; - env->pending_vector = vector; - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } + m68k_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } - #endif uint32_t HELPER(bitrev)(uint32_t x) diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 76f4399..d421614 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -36,21 +36,6 @@ static inline void do_interrupt_m68k_hardirq(CPUM68KState *env) #else -/* Try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = m68k_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} - static void cf_rte(CPUM68KState *env) { uint32_t sp; -- cgit v1.1 From f429d607c7196497dd70b5994b824a3460d7e8df Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 16:06:02 +0700 Subject: target/microblaze: Convert to CPUClass::tlb_fill Cc: Edgar E. Iglesias Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/microblaze/cpu.c | 5 +- target/microblaze/cpu.h | 5 +- target/microblaze/helper.c | 107 ++++++++++++++++++++++-------------------- target/microblaze/op_helper.c | 19 -------- 4 files changed, 62 insertions(+), 74 deletions(-) (limited to 'target') diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 5596cd5..0ea5499 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -304,9 +304,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = mb_cpu_set_pc; cc->gdb_read_register = mb_cpu_gdb_read_register; cc->gdb_write_register = mb_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = mb_cpu_handle_mmu_fault; -#else + cc->tlb_fill = mb_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_transaction_failed = mb_cpu_transaction_failed; cc->get_phys_page_debug = mb_cpu_get_phys_page_debug; #endif diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index f20e796..7a9fb8f 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -374,8 +374,9 @@ static inline int cpu_mmu_index (CPUMBState *env, bool ifetch) return MMU_KERNEL_IDX; } -int mb_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); #include "exec/cpu-all.h" diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c index 9848e31..a523c77 100644 --- a/target/microblaze/helper.c +++ b/target/microblaze/helper.c @@ -38,73 +38,80 @@ void mb_cpu_do_interrupt(CPUState *cs) env->regs[14] = env->sregs[SR_PC]; } -int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { cs->exception_index = 0xaa; - cpu_dump_state(cs, stderr, 0); - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else /* !CONFIG_USER_ONLY */ -int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; + struct microblaze_mmu_lookup lu; unsigned int hit; - int r = 1; int prot; - /* Translate if the MMU is available and enabled. */ - if (mmu_idx != MMU_NOMMU_IDX) { - uint32_t vaddr, paddr; - struct microblaze_mmu_lookup lu; - - hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx); - if (hit) { - vaddr = address & TARGET_PAGE_MASK; - paddr = lu.paddr + vaddr - lu.vaddr; - - qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n", - mmu_idx, vaddr, paddr, lu.prot); - tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); - r = 0; - } else { - env->sregs[SR_EAR] = address; - qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", - mmu_idx, address); - - switch (lu.err) { - case ERR_PROT: - env->sregs[SR_ESR] = rw == 2 ? 17 : 16; - env->sregs[SR_ESR] |= (rw == 1) << 10; - break; - case ERR_MISS: - env->sregs[SR_ESR] = rw == 2 ? 19 : 18; - env->sregs[SR_ESR] |= (rw == 1) << 10; - break; - default: - abort(); - break; - } - - if (cs->exception_index == EXCP_MMU) { - cpu_abort(cs, "recursive faults\n"); - } - - /* TLB miss. */ - cs->exception_index = EXCP_MMU; - } - } else { + if (mmu_idx == MMU_NOMMU_IDX) { /* MMU disabled or not available. */ address &= TARGET_PAGE_MASK; prot = PAGE_BITS; tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); - r = 0; + return true; } - return r; + + hit = mmu_translate(&env->mmu, &lu, address, access_type, mmu_idx); + if (likely(hit)) { + uint32_t vaddr = address & TARGET_PAGE_MASK; + uint32_t paddr = lu.paddr + vaddr - lu.vaddr; + + qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n", + mmu_idx, vaddr, paddr, lu.prot); + tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); + return true; + } + + /* TLB miss. */ + if (probe) { + return false; + } + + qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", + mmu_idx, address); + + env->sregs[SR_EAR] = address; + switch (lu.err) { + case ERR_PROT: + env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 17 : 16; + env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; + break; + case ERR_MISS: + env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 19 : 18; + env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; + break; + default: + abort(); + } + + if (cs->exception_index == EXCP_MMU) { + cpu_abort(cs, "recursive faults\n"); + } + + /* TLB miss. */ + cs->exception_index = EXCP_MMU; + cpu_loop_exit_restore(cs, retaddr); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + mb_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } void mb_cpu_do_interrupt(CPUState *cs) diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index e23dcfd..b5dbb90 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -28,25 +28,6 @@ #define D(x) -#if !defined(CONFIG_USER_ONLY) - -/* Try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = mb_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} -#endif - void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) { int test = ctrl & STREAM_TEST; -- cgit v1.1 From 995ffde9622c01f5b307cab47f9bd7962ac09db2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 1 May 2019 22:32:31 -0700 Subject: target/mips: Pass a valid error to raise_mmu_exception for user-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At present we give ret = 0, or TLBRET_MATCH. This gets matched by the default case, which falls through to TLBRET_BADADDR. However, it makes more sense to use a proper value. All of the tlb-related exceptions are handled identically in cpu_loop.c, so TLBRET_BADADDR is as good as any other. Retain it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'target') diff --git a/target/mips/helper.c b/target/mips/helper.c index c44cdca..cc7be77 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -884,7 +884,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, int prot; int access_type; #endif - int ret = 0; + int ret = TLBRET_BADADDR; #if 0 log_cpu_state(cs, 0); -- cgit v1.1 From e38f4eb63020075432cb77bf48398187809cf4a3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 1 May 2019 22:38:44 -0700 Subject: target/mips: Tidy control flow in mips_cpu_handle_mmu_fault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the only non-negative TLBRET_* value is TLBRET_MATCH, the subsequent test for ret < 0 is useless. Use early return to allow subsequent blocks to be unindented. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/helper.c | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) (limited to 'target') diff --git a/target/mips/helper.c b/target/mips/helper.c index cc7be77..86e622e 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -915,41 +915,35 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); - ret = 0; - } else if (ret < 0) -#endif - { -#if !defined(CONFIG_USER_ONLY) + return 0; + } #if !defined(TARGET_MIPS64) - if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { - /* - * Memory reads during hardware page table walking are performed - * as if they were kernel-mode load instructions. - */ - int mode = (env->hflags & MIPS_HFLAG_KSU); - bool ret_walker; - env->hflags &= ~MIPS_HFLAG_KSU; - ret_walker = page_table_walk_refill(env, address, rw, mmu_idx); - env->hflags |= mode; - if (ret_walker) { - ret = get_physical_address(env, &physical, &prot, - address, rw, access_type, mmu_idx); - if (ret == TLBRET_MATCH) { - tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, - mmu_idx, TARGET_PAGE_SIZE); - ret = 0; - return ret; - } + if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { + /* + * Memory reads during hardware page table walking are performed + * as if they were kernel-mode load instructions. + */ + int mode = (env->hflags & MIPS_HFLAG_KSU); + bool ret_walker; + env->hflags &= ~MIPS_HFLAG_KSU; + ret_walker = page_table_walk_refill(env, address, rw, mmu_idx); + env->hflags |= mode; + if (ret_walker) { + ret = get_physical_address(env, &physical, &prot, + address, rw, access_type, mmu_idx); + if (ret == TLBRET_MATCH) { + tlb_set_page(cs, address & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + mmu_idx, TARGET_PAGE_SIZE); + return 0; } } + } #endif #endif - raise_mmu_exception(env, address, rw, ret); - ret = 1; - } - return ret; + raise_mmu_exception(env, address, rw, ret); + return 1; } #if !defined(CONFIG_USER_ONLY) -- cgit v1.1 From 931d019f5b2e7bbacb162869497123be402ddd86 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 16:22:13 +0700 Subject: target/mips: Convert to CPUClass::tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note that env->active_tc.PC is removed from the qemu_log as that value is garbage. The PC isn't recovered until cpu_restore_state, called from cpu_loop_exit_restore, called from do_raise_exception_err. Cc: Aleksandar Markovic Cc: Aleksandar Rikalo Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/cpu.c | 5 ++--- target/mips/helper.c | 45 ++++++++++++++++++++++++--------------------- target/mips/internal.h | 5 +++-- target/mips/op_helper.c | 15 --------------- 4 files changed, 29 insertions(+), 41 deletions(-) (limited to 'target') diff --git a/target/mips/cpu.c b/target/mips/cpu.c index e217fb3..a330586 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -197,9 +197,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->synchronize_from_tb = mips_cpu_synchronize_from_tb; cc->gdb_read_register = mips_cpu_gdb_read_register; cc->gdb_write_register = mips_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = mips_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->do_unassigned_access = mips_cpu_unassigned_access; cc->do_unaligned_access = mips_cpu_do_unaligned_access; cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; @@ -208,6 +206,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->disas_set_info = mips_cpu_disas_set_info; #ifdef CONFIG_TCG cc->tcg_initialize = mips_tcg_init; + cc->tlb_fill = mips_cpu_tlb_fill; #endif cc->gdb_num_core_regs = 73; diff --git a/target/mips/helper.c b/target/mips/helper.c index 86e622e..3a4917c 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -874,31 +874,25 @@ refill: #endif #endif -int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; #if !defined(CONFIG_USER_ONLY) hwaddr physical; int prot; - int access_type; + int mips_access_type; #endif int ret = TLBRET_BADADDR; -#if 0 - log_cpu_state(cs, 0); -#endif - qemu_log_mask(CPU_LOG_MMU, - "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n", - __func__, env->active_tc.PC, address, rw, mmu_idx); - /* data access */ #if !defined(CONFIG_USER_ONLY) /* XXX: put correct access by using cpu_restore_state() correctly */ - access_type = ACCESS_INT; - ret = get_physical_address(env, &physical, &prot, - address, rw, access_type, mmu_idx); + mips_access_type = ACCESS_INT; + ret = get_physical_address(env, &physical, &prot, address, + access_type, mips_access_type, mmu_idx); switch (ret) { case TLBRET_MATCH: qemu_log_mask(CPU_LOG_MMU, @@ -915,7 +909,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; } #if !defined(TARGET_MIPS64) if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { @@ -926,27 +920,36 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, int mode = (env->hflags & MIPS_HFLAG_KSU); bool ret_walker; env->hflags &= ~MIPS_HFLAG_KSU; - ret_walker = page_table_walk_refill(env, address, rw, mmu_idx); + ret_walker = page_table_walk_refill(env, address, access_type, mmu_idx); env->hflags |= mode; if (ret_walker) { - ret = get_physical_address(env, &physical, &prot, - address, rw, access_type, mmu_idx); + ret = get_physical_address(env, &physical, &prot, address, + access_type, mips_access_type, mmu_idx); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; } } } #endif + if (probe) { + return false; + } #endif - raise_mmu_exception(env, address, rw, ret); - return 1; + raise_mmu_exception(env, address, access_type, ret); + do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); +} + +#ifndef CONFIG_USER_ONLY +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + mips_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } -#if !defined(CONFIG_USER_ONLY) hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) { hwaddr physical; diff --git a/target/mips/internal.h b/target/mips/internal.h index 286e388..b2b41a5 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -202,8 +202,9 @@ void cpu_mips_start_count(CPUMIPSState *env); void cpu_mips_stop_count(CPUMIPSState *env); /* helper.c */ -int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); /* op_helper.c */ uint32_t float_class_s(uint32_t arg, float_status *fst); diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 0f272a5..6d86912 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -2669,21 +2669,6 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr, do_raise_exception_err(env, excp, error_code, retaddr); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = mips_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (ret) { - MIPSCPU *cpu = MIPS_CPU(cs); - CPUMIPSState *env = &cpu->env; - - do_raise_exception_err(env, cs->exception_index, - env->error_code, retaddr); - } -} - void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write, bool is_exec, int unused, unsigned size) -- cgit v1.1 From ccfd61fc6bda50456d54b915ddcdc248751b3098 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 16:30:06 +0700 Subject: target/moxie: Convert to CPUClass::tlb_fill Remove the user-only functions, as we don't have a user-only config. Fix the unconditional call to tlb_set_page, even if the translation failed. Cc: Anthony Green Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/moxie/cpu.c | 5 ++--- target/moxie/cpu.h | 5 +++-- target/moxie/helper.c | 61 ++++++++++++--------------------------------------- 3 files changed, 19 insertions(+), 52 deletions(-) (limited to 'target') diff --git a/target/moxie/cpu.c b/target/moxie/cpu.c index 46434e6..02b2b47 100644 --- a/target/moxie/cpu.c +++ b/target/moxie/cpu.c @@ -112,9 +112,8 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data) cc->do_interrupt = moxie_cpu_do_interrupt; cc->dump_state = moxie_cpu_dump_state; cc->set_pc = moxie_cpu_set_pc; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = moxie_cpu_handle_mmu_fault; -#else + cc->tlb_fill = moxie_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug; cc->vmsd = &vmstate_moxie_cpu; #endif diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h index f3b6d83..a63a96b 100644 --- a/target/moxie/cpu.h +++ b/target/moxie/cpu.h @@ -139,7 +139,8 @@ static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc, *flags = 0; } -int moxie_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int mmu_idx); +bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); #endif /* MOXIE_CPU_H */ diff --git a/target/moxie/helper.c b/target/moxie/helper.c index 287a452..216cef0 100644 --- a/target/moxie/helper.c +++ b/target/moxie/helper.c @@ -26,18 +26,10 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" -/* Try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ void tlb_fill(CPUState *cs, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - int ret; - - ret = moxie_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - cpu_loop_exit_restore(cs, retaddr); - } + moxie_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } void helper_raise_exception(CPUMoxieState *env, int ex) @@ -85,53 +77,29 @@ void helper_debug(CPUMoxieState *env) cpu_loop_exit(cs); } -#if defined(CONFIG_USER_ONLY) - -void moxie_cpu_do_interrupt(CPUState *cs) -{ - CPUState *cs = CPU(moxie_env_get_cpu(env)); - - cs->exception_index = -1; -} - -int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) -{ - MoxieCPU *cpu = MOXIE_CPU(cs); - - cs->exception_index = 0xaa; - cpu->env.debug1 = address; - cpu_dump_state(cs, stderr, 0); - return 1; -} - -#else /* !CONFIG_USER_ONLY */ - -int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { MoxieCPU *cpu = MOXIE_CPU(cs); CPUMoxieState *env = &cpu->env; MoxieMMUResult res; int prot, miss; - target_ulong phy; - int r = 1; address &= TARGET_PAGE_MASK; prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - miss = moxie_mmu_translate(&res, env, address, rw, mmu_idx); - if (miss) { - /* handle the miss. */ - phy = 0; - cs->exception_index = MOXIE_EX_MMU_MISS; - } else { - phy = res.phy; - r = 0; + miss = moxie_mmu_translate(&res, env, address, access_type, mmu_idx); + if (likely(!miss)) { + tlb_set_page(cs, address, res.phy, prot, mmu_idx, TARGET_PAGE_SIZE); + return true; + } + if (probe) { + return false; } - tlb_set_page(cs, address, phy, prot, mmu_idx, TARGET_PAGE_SIZE); - return r; -} + cs->exception_index = MOXIE_EX_MMU_MISS; + cpu_loop_exit_restore(cs, retaddr); +} void moxie_cpu_do_interrupt(CPUState *cs) { @@ -156,4 +124,3 @@ hwaddr moxie_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) } return phy; } -#endif -- cgit v1.1 From 0137c93ff8cbcebf8f8b1bc354b5928016387eef Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 16:47:37 +0700 Subject: target/nios2: Convert to CPUClass::tlb_fill Remove the leftover debugging cpu_dump_state. Cc: Chris Wulff Cc: Marek Vasut Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/nios2/cpu.c | 5 +- target/nios2/cpu.h | 5 +- target/nios2/helper.c | 176 ++++++++++++++++++++++++-------------------------- target/nios2/mmu.c | 12 ---- 4 files changed, 91 insertions(+), 107 deletions(-) (limited to 'target') diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index fbfaa2c..186af49 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -200,9 +200,8 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data) cc->dump_state = nios2_cpu_dump_state; cc->set_pc = nios2_cpu_set_pc; cc->disas_set_info = nios2_cpu_disas_set_info; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = nios2_cpu_handle_mmu_fault; -#else + cc->tlb_fill = nios2_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_unaligned_access = nios2_cpu_do_unaligned_access; cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug; #endif diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 881e7d5..60a916b 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -252,8 +252,9 @@ static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch) MMU_SUPERVISOR_IDX; } -int nios2_cpu_handle_mmu_fault(CPUState *env, vaddr address, int size, - int rw, int mmu_idx); +bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); static inline int cpu_interrupts_enabled(CPUNios2State *env) { diff --git a/target/nios2/helper.c b/target/nios2/helper.c index e01fc1f..eb2eed7 100644 --- a/target/nios2/helper.c +++ b/target/nios2/helper.c @@ -38,15 +38,12 @@ void nios2_cpu_do_interrupt(CPUState *cs) env->regs[R_EA] = env->regs[R_PC] + 4; } -int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { cs->exception_index = 0xaa; - /* Page 0x1000 is kuser helper */ - if (address < 0x1000 || address >= 0x2000) { - cpu_dump_state(cs, stderr, 0); - } - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else /* !CONFIG_USER_ONLY */ @@ -203,89 +200,6 @@ void nios2_cpu_do_interrupt(CPUState *cs) } } -static int cpu_nios2_handle_virtual_page( - CPUState *cs, target_ulong address, int rw, int mmu_idx) -{ - Nios2CPU *cpu = NIOS2_CPU(cs); - CPUNios2State *env = &cpu->env; - target_ulong vaddr, paddr; - Nios2MMULookup lu; - unsigned int hit; - hit = mmu_translate(env, &lu, address, rw, mmu_idx); - if (hit) { - vaddr = address & TARGET_PAGE_MASK; - paddr = lu.paddr + vaddr - lu.vaddr; - - if (((rw == 0) && (lu.prot & PAGE_READ)) || - ((rw == 1) && (lu.prot & PAGE_WRITE)) || - ((rw == 2) && (lu.prot & PAGE_EXEC))) { - - tlb_set_page(cs, vaddr, paddr, lu.prot, - mmu_idx, TARGET_PAGE_SIZE); - return 0; - } else { - /* Permission violation */ - cs->exception_index = (rw == 0) ? EXCP_TLBR : - ((rw == 1) ? EXCP_TLBW : - EXCP_TLBX); - } - } else { - cs->exception_index = EXCP_TLBD; - } - - if (rw == 2) { - env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D; - } else { - env->regs[CR_TLBMISC] |= CR_TLBMISC_D; - } - env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK; - env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK; - env->mmu.pteaddr_wr = env->regs[CR_PTEADDR]; - env->regs[CR_BADADDR] = address; - return 1; -} - -int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) -{ - Nios2CPU *cpu = NIOS2_CPU(cs); - CPUNios2State *env = &cpu->env; - - if (cpu->mmu_present) { - if (MMU_SUPERVISOR_IDX == mmu_idx) { - if (address >= 0xC0000000) { - /* Kernel physical page - TLB bypassed */ - address &= TARGET_PAGE_MASK; - tlb_set_page(cs, address, address, PAGE_BITS, - mmu_idx, TARGET_PAGE_SIZE); - } else if (address >= 0x80000000) { - /* Kernel virtual page */ - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); - } else { - /* User virtual page */ - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); - } - } else { - if (address >= 0x80000000) { - /* Illegal access from user mode */ - cs->exception_index = EXCP_SUPERA; - env->regs[CR_BADADDR] = address; - return 1; - } else { - /* User virtual page */ - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); - } - } - } else { - /* No MMU */ - address &= TARGET_PAGE_MASK; - tlb_set_page(cs, address, address, PAGE_BITS, - mmu_idx, TARGET_PAGE_SIZE); - } - - return 0; -} - hwaddr nios2_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { Nios2CPU *cpu = NIOS2_CPU(cs); @@ -321,4 +235,86 @@ void nios2_cpu_do_unaligned_access(CPUState *cs, vaddr addr, env->regs[CR_EXCEPTION] = EXCP_UNALIGN << 2; helper_raise_exception(env, EXCP_UNALIGN); } + +bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + Nios2CPU *cpu = NIOS2_CPU(cs); + CPUNios2State *env = &cpu->env; + unsigned int excp = EXCP_TLBD; + target_ulong vaddr, paddr; + Nios2MMULookup lu; + unsigned int hit; + + if (!cpu->mmu_present) { + /* No MMU */ + address &= TARGET_PAGE_MASK; + tlb_set_page(cs, address, address, PAGE_BITS, + mmu_idx, TARGET_PAGE_SIZE); + return true; + } + + if (MMU_SUPERVISOR_IDX == mmu_idx) { + if (address >= 0xC0000000) { + /* Kernel physical page - TLB bypassed */ + address &= TARGET_PAGE_MASK; + tlb_set_page(cs, address, address, PAGE_BITS, + mmu_idx, TARGET_PAGE_SIZE); + return true; + } + } else { + if (address >= 0x80000000) { + /* Illegal access from user mode */ + if (probe) { + return false; + } + cs->exception_index = EXCP_SUPERA; + env->regs[CR_BADADDR] = address; + cpu_loop_exit_restore(cs, retaddr); + } + } + + /* Virtual page. */ + hit = mmu_translate(env, &lu, address, access_type, mmu_idx); + if (hit) { + vaddr = address & TARGET_PAGE_MASK; + paddr = lu.paddr + vaddr - lu.vaddr; + + if (((access_type == MMU_DATA_LOAD) && (lu.prot & PAGE_READ)) || + ((access_type == MMU_DATA_STORE) && (lu.prot & PAGE_WRITE)) || + ((access_type == MMU_INST_FETCH) && (lu.prot & PAGE_EXEC))) { + tlb_set_page(cs, vaddr, paddr, lu.prot, + mmu_idx, TARGET_PAGE_SIZE); + return true; + } + + /* Permission violation */ + excp = (access_type == MMU_DATA_LOAD ? EXCP_TLBR : + access_type == MMU_DATA_STORE ? EXCP_TLBW : EXCP_TLBX); + } + + if (probe) { + return false; + } + + if (access_type == MMU_INST_FETCH) { + env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D; + } else { + env->regs[CR_TLBMISC] |= CR_TLBMISC_D; + } + env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK; + env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK; + env->mmu.pteaddr_wr = env->regs[CR_PTEADDR]; + + cs->exception_index = excp; + env->regs[CR_BADADDR] = address; + cpu_loop_exit_restore(cs, retaddr); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + nios2_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); +} #endif /* !CONFIG_USER_ONLY */ diff --git a/target/nios2/mmu.c b/target/nios2/mmu.c index 5acf442..47fa474 100644 --- a/target/nios2/mmu.c +++ b/target/nios2/mmu.c @@ -36,18 +36,6 @@ #define MMU_LOG(x) #endif -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = nios2_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} - void mmu_read_debug(CPUNios2State *env, uint32_t rn) { switch (rn) { -- cgit v1.1 From 35e911ae2fdf12aebecf6e7d8704b11f8514dfe3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 16:55:37 +0700 Subject: target/openrisc: Convert to CPUClass::tlb_fill Cc: Stafford Horne Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/openrisc/cpu.c | 5 ++-- target/openrisc/cpu.h | 5 ++-- target/openrisc/mmu.c | 65 +++++++++++++++++++++++++++------------------------ 3 files changed, 39 insertions(+), 36 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index d125236..3816bae 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -149,9 +149,8 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = openrisc_cpu_set_pc; cc->gdb_read_register = openrisc_cpu_gdb_read_register; cc->gdb_write_register = openrisc_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = openrisc_cpu_handle_mmu_fault; -#else + cc->tlb_fill = openrisc_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug; dc->vmsd = &vmstate_openrisc_cpu; #endif diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 88a8c70..9473d94 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -344,8 +344,9 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void openrisc_translate_init(void); -int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int mmu_idx); +bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc); int print_insn_or1k(bfd_vma addr, disassemble_info *info); diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 5dec68d..94c65a2 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -107,16 +107,42 @@ static void raise_mmu_exception(OpenRISCCPU *cpu, target_ulong address, cpu->env.lock_addr = -1; } -int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { -#ifdef CONFIG_USER_ONLY OpenRISCCPU *cpu = OPENRISC_CPU(cs); - raise_mmu_exception(cpu, address, EXCP_DPF); - return 1; -#else - g_assert_not_reached(); + int excp = EXCP_DPF; + +#ifndef CONFIG_USER_ONLY + int prot; + hwaddr phys_addr; + + if (mmu_idx == MMU_NOMMU_IDX) { + /* The mmu is disabled; lookups never fail. */ + get_phys_nommu(&phys_addr, &prot, addr); + excp = 0; + } else { + bool super = mmu_idx == MMU_SUPERVISOR_IDX; + int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC + : access_type == MMU_DATA_STORE ? PAGE_WRITE + : PAGE_READ); + excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super); + } + + if (likely(excp == 0)) { + tlb_set_page(cs, addr & TARGET_PAGE_MASK, + phys_addr & TARGET_PAGE_MASK, prot, + mmu_idx, TARGET_PAGE_SIZE); + return true; + } + if (probe) { + return false; + } #endif + + raise_mmu_exception(cpu, addr, excp); + cpu_loop_exit_restore(cs, retaddr); } #ifndef CONFIG_USER_ONLY @@ -156,29 +182,6 @@ 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) { - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - int prot, excp; - hwaddr phys_addr; - - if (mmu_idx == MMU_NOMMU_IDX) { - /* The mmu is disabled; lookups never fail. */ - get_phys_nommu(&phys_addr, &prot, addr); - excp = 0; - } else { - bool super = mmu_idx == MMU_SUPERVISOR_IDX; - int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC - : access_type == MMU_DATA_STORE ? PAGE_WRITE - : PAGE_READ); - excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super); - } - - if (unlikely(excp)) { - raise_mmu_exception(cpu, addr, excp); - cpu_loop_exit_restore(cs, retaddr); - } - - tlb_set_page(cs, addr & TARGET_PAGE_MASK, - phys_addr & TARGET_PAGE_MASK, prot, - mmu_idx, TARGET_PAGE_SIZE); + openrisc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, 0, retaddr); } #endif -- cgit v1.1 From 351bc97ecfa4b7ef1f1fc9cc32de3541b2130000 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 17:03:41 +0700 Subject: target/ppc: Convert to CPUClass::tlb_fill Cc: qemu-ppc@nongnu.org Acked-by: David Gibson Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/ppc/cpu.h | 7 +++---- target/ppc/mmu_helper.c | 22 +++++++++++++--------- target/ppc/translate_init.inc.c | 5 ++--- target/ppc/user_only_helper.c | 14 ++++++++------ 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'target') diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 5e7cf54..d7f23ad 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1311,10 +1311,9 @@ void ppc_translate_init(void); * is returned if the signal was handled by the virtual CPU. */ int cpu_ppc_signal_handler(int host_signum, void *pinfo, void *puc); -#if defined(CONFIG_USER_ONLY) -int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); -#endif +bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); #if !defined(CONFIG_USER_ONLY) void ppc_store_sdr1(CPUPPCState *env, target_ulong value); diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 1dbc9ac..afcca50 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -3057,15 +3057,9 @@ void helper_check_tlb_flush_global(CPUPPCState *env) /*****************************************************************************/ -/* - * try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - * - * XXX: fix it to restore all registers - */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); @@ -3078,7 +3072,17 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size, ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx); } if (unlikely(ret != 0)) { + if (probe) { + return false; + } raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr); } + return true; +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + ppc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 0394a9d..ad5e14b 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -10592,9 +10592,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_read_register = ppc_cpu_gdb_read_register; cc->gdb_write_register = ppc_cpu_gdb_write_register; cc->do_unaligned_access = ppc_cpu_do_unaligned_access; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = ppc_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; cc->vmsd = &vmstate_ppc_cpu; #endif @@ -10624,6 +10622,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) #endif #ifdef CONFIG_TCG cc->tcg_initialize = ppc_translate_init; + cc->tlb_fill = ppc_cpu_tlb_fill; #endif cc->disas_set_info = ppc_disas_set_info; diff --git a/target/ppc/user_only_helper.c b/target/ppc/user_only_helper.c index 2f1477f..683c033 100644 --- a/target/ppc/user_only_helper.c +++ b/target/ppc/user_only_helper.c @@ -20,21 +20,24 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "exec/exec-all.h" -int ppc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) + +bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; int exception, error_code; - if (rw == 2) { + if (access_type == MMU_INST_FETCH) { exception = POWERPC_EXCP_ISI; error_code = 0x40000000; } else { exception = POWERPC_EXCP_DSI; error_code = 0x40000000; - if (rw) { + if (access_type == MMU_DATA_STORE) { error_code |= 0x02000000; } env->spr[SPR_DAR] = address; @@ -42,6 +45,5 @@ int ppc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, } cs->exception_index = exception; env->error_code = error_code; - - return 1; + cpu_loop_exit_restore(cs, retaddr); } -- cgit v1.1 From 8a4ca3c10a96be6ed7f023b685b688c4d409bbcb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 17:12:38 +0700 Subject: target/riscv: Convert to CPUClass::tlb_fill Note that env->pc is removed from the qemu_log as that value is garbage. The PC isn't recovered until cpu_restore_state, called from cpu_loop_exit_restore, called from riscv_raise_exception. Cc: qemu-riscv@nongnu.org Cc: Palmer Dabbelt Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson --- target/riscv/cpu.c | 5 ++--- target/riscv/cpu.h | 5 +++-- target/riscv/cpu_helper.c | 46 +++++++++++++++++++++------------------------- 3 files changed, 26 insertions(+), 30 deletions(-) (limited to 'target') diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1bcf4ea..b767570 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -355,14 +355,13 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) #endif cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = riscv_cpu_disas_set_info; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; #endif #ifdef CONFIG_TCG cc->tcg_initialize = riscv_translate_init; + cc->tlb_fill = riscv_cpu_tlb_fill; #endif /* For now, mark unmigratable: */ cc->vmsd = &vmstate_riscv_cpu; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7d9f489..c17184f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -261,8 +261,9 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); -int riscv_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int mmu_idx); +bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); void riscv_cpu_list(void); diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index b17f169..2535435 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -379,53 +379,49 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, riscv_raise_exception(env, cs->exception_index, retaddr); } -/* called by qemu's softmmu to fill the qemu tlb */ void tlb_fill(CPUState *cs, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - int ret; - ret = riscv_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (ret == TRANSLATE_FAIL) { - RISCVCPU *cpu = RISCV_CPU(cs); - CPURISCVState *env = &cpu->env; - riscv_raise_exception(env, cs->exception_index, retaddr); - } + riscv_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } - #endif -int riscv_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { +#ifndef CONFIG_USER_ONLY RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; -#if !defined(CONFIG_USER_ONLY) hwaddr pa = 0; int prot; -#endif int ret = TRANSLATE_FAIL; - qemu_log_mask(CPU_LOG_MMU, - "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx \ - %d\n", __func__, env->pc, address, rw, mmu_idx); + qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n", + __func__, address, access_type, mmu_idx); + + ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx); -#if !defined(CONFIG_USER_ONLY) - ret = get_physical_address(env, &pa, &prot, address, rw, mmu_idx); qemu_log_mask(CPU_LOG_MMU, - "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx - " prot %d\n", __func__, address, ret, pa, prot); + "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx + " prot %d\n", __func__, address, ret, pa, prot); + if (riscv_feature(env, RISCV_FEATURE_PMP) && - !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << rw)) { + !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { ret = TRANSLATE_FAIL; } if (ret == TRANSLATE_SUCCESS) { tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); - } else if (ret == TRANSLATE_FAIL) { - raise_mmu_exception(env, address, rw); + return true; + } else if (probe) { + return false; + } else { + raise_mmu_exception(env, address, access_type); + riscv_raise_exception(env, cs->exception_index, retaddr); } #else - switch (rw) { + switch (access_type) { case MMU_INST_FETCH: cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT; break; @@ -436,8 +432,8 @@ int riscv_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT; break; } + cpu_loop_exit_restore(cs, retaddr); #endif - return ret; } /* -- cgit v1.1 From 82851985ccae8dec5078819ce8851da7b785e7cf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 18:02:09 +0700 Subject: target/s390x: Convert to CPUClass::tlb_fill Cc: qemu-s390x@nongnu.org Cc: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Richard Henderson --- target/s390x/cpu.c | 5 ++-- target/s390x/excp_helper.c | 73 +++++++++++++++++++++++++++++++--------------- target/s390x/internal.h | 5 ++-- target/s390x/mem_helper.c | 16 ---------- 4 files changed, 55 insertions(+), 44 deletions(-) (limited to 'target') diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index b58ef0a..b1df63d 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -478,9 +478,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->set_pc = s390_cpu_set_pc; cc->gdb_read_register = s390_cpu_gdb_read_register; cc->gdb_write_register = s390_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = s390_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; cc->vmsd = &vmstate_s390_cpu; cc->write_elf64_note = s390_cpu_write_elf64_note; @@ -493,6 +491,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->disas_set_info = s390_cpu_disas_set_info; #ifdef CONFIG_TCG cc->tcg_initialize = s390x_translate_init; + cc->tlb_fill = s390_cpu_tlb_fill; #endif cc->gdb_num_core_regs = S390_NUM_CORE_REGS; diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index f84bfb1..a4e134b 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -74,8 +74,9 @@ void s390_cpu_do_interrupt(CPUState *cs) cs->exception_index = -1; } -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { S390CPU *cpu = S390_CPU(cs); @@ -83,7 +84,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, /* On real machines this value is dropped into LowMem. Since this is userland, simply put this someplace that cpu_loop can find it. */ cpu->env.__excp_addr = address; - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else /* !CONFIG_USER_ONLY */ @@ -102,19 +103,20 @@ static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx) } } -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size, - int rw, int mmu_idx) +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; target_ulong vaddr, raddr; uint64_t asc; - int prot; + int prot, fail; qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", - __func__, orig_vaddr, rw, mmu_idx); + __func__, address, access_type, mmu_idx); - vaddr = orig_vaddr; + vaddr = address; if (mmu_idx < MMU_REAL_IDX) { asc = cpu_mmu_idx_to_asc(mmu_idx); @@ -122,39 +124,64 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size, if (!(env->psw.mask & PSW_MASK_64)) { vaddr &= 0x7fffffff; } - if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) { - return 1; - } + fail = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, true); } else if (mmu_idx == MMU_REAL_IDX) { /* 31-Bit mode */ if (!(env->psw.mask & PSW_MASK_64)) { vaddr &= 0x7fffffff; } - if (mmu_translate_real(env, vaddr, rw, &raddr, &prot)) { - return 1; - } + fail = mmu_translate_real(env, vaddr, access_type, &raddr, &prot); } else { - abort(); + g_assert_not_reached(); } /* check out of RAM access */ - if (!address_space_access_valid(&address_space_memory, raddr, - TARGET_PAGE_SIZE, rw, + if (!fail && + !address_space_access_valid(&address_space_memory, raddr, + TARGET_PAGE_SIZE, access_type, MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(CPU_LOG_MMU, "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)raddr, (uint64_t)ram_size); trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO); - return 1; + fail = 1; } - qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", - __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); + if (!fail) { + qemu_log_mask(CPU_LOG_MMU, + "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", + __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); + tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot, + mmu_idx, TARGET_PAGE_SIZE); + return true; + } + if (probe) { + return false; + } - tlb_set_page(cs, orig_vaddr & TARGET_PAGE_MASK, raddr, prot, - mmu_idx, TARGET_PAGE_SIZE); + cpu_restore_state(cs, retaddr, true); + + /* + * The ILC value for code accesses is undefined. The important + * thing here is to *not* leave env->int_pgm_ilen set to ILEN_AUTO, + * which would cause do_program_interrupt to attempt to read from + * env->psw.addr again. C.f. the condition in trigger_page_fault, + * but is not universally applied. + * + * ??? If we remove ILEN_AUTO, by moving the computation of ILEN + * into cpu_restore_state, then we may remove this entirely. + */ + if (access_type == MMU_INST_FETCH) { + env->int_pgm_ilen = 2; + } - return 0; + cpu_loop_exit(cs); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + s390_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } static void do_program_interrupt(CPUS390XState *env) diff --git a/target/s390x/internal.h b/target/s390x/internal.h index 26575f2..56534b3 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -263,8 +263,9 @@ ObjectClass *s390_cpu_class_by_name(const char *name); void s390x_cpu_debug_excp_handler(CPUState *cs); void s390_cpu_do_interrupt(CPUState *cpu); bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req); -int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3f76a8a..ffd5f02 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -33,22 +33,6 @@ /*****************************************************************************/ /* Softmmu support */ -#if !defined(CONFIG_USER_ONLY) - -/* try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret = s390_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret != 0)) { - cpu_loop_exit_restore(cs, retaddr); - } -} - -#endif /* #define DEBUG_HELPER */ #ifdef DEBUG_HELPER -- cgit v1.1 From f98bce2b9c82cd9708c20c973de527ef7706cf23 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 22:18:39 +0700 Subject: target/sh4: Convert to CPUClass::tlb_fill Cc: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/sh4/cpu.c | 5 +- target/sh4/cpu.h | 5 +- target/sh4/helper.c | 197 ++++++++++++++++++++++++------------------------- target/sh4/op_helper.c | 12 --- 4 files changed, 101 insertions(+), 118 deletions(-) (limited to 'target') diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index da27990..c4736a0 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -229,9 +229,8 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data) cc->synchronize_from_tb = superh_cpu_synchronize_from_tb; cc->gdb_read_register = superh_cpu_gdb_read_register; cc->gdb_write_register = superh_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = superh_cpu_handle_mmu_fault; -#else + cc->tlb_fill = superh_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_unaligned_access = superh_cpu_do_unaligned_access; cc->get_phys_page_debug = superh_cpu_get_phys_page_debug; #endif diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 1be36fe..547194a 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -243,8 +243,9 @@ void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, void sh4_translate_init(void); int cpu_sh4_signal_handler(int host_signum, void *pinfo, void *puc); -int superh_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void sh4_cpu_list(void); #if !defined(CONFIG_USER_ONLY) diff --git a/target/sh4/helper.c b/target/sh4/helper.c index fa51269..1517a61 100644 --- a/target/sh4/helper.c +++ b/target/sh4/helper.c @@ -27,43 +27,6 @@ #include "hw/sh4/sh_intc.h" #endif -#if defined(CONFIG_USER_ONLY) - -void superh_cpu_do_interrupt(CPUState *cs) -{ - cs->exception_index = -1; -} - -int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) -{ - SuperHCPU *cpu = SUPERH_CPU(cs); - CPUSH4State *env = &cpu->env; - - env->tea = address; - cs->exception_index = -1; - switch (rw) { - case 0: - cs->exception_index = 0x0a0; - break; - case 1: - cs->exception_index = 0x0c0; - break; - case 2: - cs->exception_index = 0x0a0; - break; - } - return 1; -} - -int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) -{ - /* For user mode, only U0 area is cacheable. */ - return !(addr & 0x80000000); -} - -#else /* !CONFIG_USER_ONLY */ - #define MMU_OK 0 #define MMU_ITLB_MISS (-1) #define MMU_ITLB_MULTIPLE (-2) @@ -79,6 +42,21 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) #define MMU_DADDR_ERROR_READ (-12) #define MMU_DADDR_ERROR_WRITE (-13) +#if defined(CONFIG_USER_ONLY) + +void superh_cpu_do_interrupt(CPUState *cs) +{ + cs->exception_index = -1; +} + +int cpu_sh4_is_cached(CPUSH4State *env, target_ulong addr) +{ + /* For user mode, only U0 area is cacheable. */ + return !(addr & 0x80000000); +} + +#else /* !CONFIG_USER_ONLY */ + void superh_cpu_do_interrupt(CPUState *cs) { SuperHCPU *cpu = SUPERH_CPU(cs); @@ -458,69 +436,6 @@ static int get_physical_address(CPUSH4State * env, target_ulong * physical, return get_mmu_address(env, physical, prot, address, rw, access_type); } -int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) -{ - SuperHCPU *cpu = SUPERH_CPU(cs); - CPUSH4State *env = &cpu->env; - target_ulong physical; - int prot, ret, access_type; - - access_type = ACCESS_INT; - ret = - get_physical_address(env, &physical, &prot, address, rw, - access_type); - - if (ret != MMU_OK) { - env->tea = address; - if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) { - env->pteh = (env->pteh & PTEH_ASID_MASK) | - (address & PTEH_VPN_MASK); - } - switch (ret) { - case MMU_ITLB_MISS: - case MMU_DTLB_MISS_READ: - cs->exception_index = 0x040; - break; - case MMU_DTLB_MULTIPLE: - case MMU_ITLB_MULTIPLE: - cs->exception_index = 0x140; - break; - case MMU_ITLB_VIOLATION: - cs->exception_index = 0x0a0; - break; - case MMU_DTLB_MISS_WRITE: - cs->exception_index = 0x060; - break; - case MMU_DTLB_INITIAL_WRITE: - cs->exception_index = 0x080; - break; - case MMU_DTLB_VIOLATION_READ: - cs->exception_index = 0x0a0; - break; - case MMU_DTLB_VIOLATION_WRITE: - cs->exception_index = 0x0c0; - break; - case MMU_IADDR_ERROR: - case MMU_DADDR_ERROR_READ: - cs->exception_index = 0x0e0; - break; - case MMU_DADDR_ERROR_WRITE: - cs->exception_index = 0x100; - break; - default: - cpu_abort(cs, "Unhandled MMU fault"); - } - return 1; - } - - address &= TARGET_PAGE_MASK; - physical &= TARGET_PAGE_MASK; - - tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); - return 0; -} - hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { SuperHCPU *cpu = SUPERH_CPU(cs); @@ -745,7 +660,6 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, if (needs_tlb_flush) { tlb_flush_page(CPU(sh_env_get_cpu(s)), vpn << 10); } - } else { int index = (addr & 0x00003f00) >> 8; tlb_t * entry = &s->utlb[index]; @@ -885,3 +799,84 @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request) } return false; } + +bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + SuperHCPU *cpu = SUPERH_CPU(cs); + CPUSH4State *env = &cpu->env; + int ret; + +#ifdef CONFIG_USER_ONLY + ret = (access_type == MMU_DATA_STORE ? MMU_DTLB_VIOLATION_WRITE : + access_type == MMU_INST_FETCH ? MMU_ITLB_VIOLATION : + MMU_DTLB_VIOLATION_READ); +#else + target_ulong physical; + int prot, sh_access_type; + + sh_access_type = ACCESS_INT; + ret = get_physical_address(env, &physical, &prot, address, + access_type, sh_access_type); + + if (ret == MMU_OK) { + address &= TARGET_PAGE_MASK; + physical &= TARGET_PAGE_MASK; + tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); + return true; + } + if (probe) { + return false; + } + + if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) { + env->pteh = (env->pteh & PTEH_ASID_MASK) | (address & PTEH_VPN_MASK); + } +#endif + + env->tea = address; + switch (ret) { + case MMU_ITLB_MISS: + case MMU_DTLB_MISS_READ: + cs->exception_index = 0x040; + break; + case MMU_DTLB_MULTIPLE: + case MMU_ITLB_MULTIPLE: + cs->exception_index = 0x140; + break; + case MMU_ITLB_VIOLATION: + cs->exception_index = 0x0a0; + break; + case MMU_DTLB_MISS_WRITE: + cs->exception_index = 0x060; + break; + case MMU_DTLB_INITIAL_WRITE: + cs->exception_index = 0x080; + break; + case MMU_DTLB_VIOLATION_READ: + cs->exception_index = 0x0a0; + break; + case MMU_DTLB_VIOLATION_WRITE: + cs->exception_index = 0x0c0; + break; + case MMU_IADDR_ERROR: + case MMU_DADDR_ERROR_READ: + cs->exception_index = 0x0e0; + break; + case MMU_DADDR_ERROR_WRITE: + cs->exception_index = 0x100; + break; + default: + cpu_abort(cs, "Unhandled MMU fault"); + } + cpu_loop_exit_restore(cs, retaddr); +} + +#ifndef CONFIG_USER_ONLY +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + superh_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); +} +#endif diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index 28027f9..bd5d782 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -41,18 +41,6 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr, cpu_loop_exit_restore(cs, retaddr); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = superh_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (ret) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} - #endif void helper_ldtlb(CPUSH4State *env) -- cgit v1.1 From e84942f2ceaa79430414f2cb68d77c044dadca96 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 07:16:41 +0700 Subject: target/sparc: Convert to CPUClass::tlb_fill Cc: Artyom Tarasenko Cc: Mark Cave-Ayland Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/sparc/cpu.c | 5 ++-- target/sparc/cpu.h | 5 ++-- target/sparc/ldst_helper.c | 11 +-------- target/sparc/mmu_helper.c | 58 +++++++++++++++++++++++++++++----------------- 4 files changed, 43 insertions(+), 36 deletions(-) (limited to 'target') diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 4654c2a..f93ce72 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -875,9 +875,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; cc->gdb_read_register = sparc_cpu_gdb_read_register; cc->gdb_write_register = sparc_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault; -#else + cc->tlb_fill = sparc_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_unassigned_access = sparc_cpu_unassigned_access; cc->do_unaligned_access = sparc_cpu_do_unaligned_access; cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug; diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 85b9665..f31e853 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -579,8 +579,9 @@ void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t) QEMU_NORETURN; void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu); void sparc_cpu_list(void); /* mmu_helper.c */ -int sparc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev); void dump_mmu(CPUSPARCState *env); diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index a7fcb84..2558c08 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -1925,18 +1925,9 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr); } -/* try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ void tlb_fill(CPUState *cs, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - int ret; - - ret = sparc_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (ret) { - cpu_loop_exit_restore(cs, retaddr); - } + sparc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } #endif diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index afcc5b6..facc0c6 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -27,13 +27,14 @@ #if defined(CONFIG_USER_ONLY) -int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; - if (rw & 2) { + if (access_type == MMU_INST_FETCH) { cs->exception_index = TT_TFAULT; } else { cs->exception_index = TT_DFAULT; @@ -43,7 +44,7 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, env->mmuregs[4] = address; #endif } - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else @@ -208,8 +209,9 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical, } /* Perform address translation */ -int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; @@ -218,16 +220,26 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, target_ulong page_size; int error_code = 0, prot, access_index; + /* + * TODO: If we ever need tlb_vaddr_to_host for this target, + * then we must figure out how to manipulate FSR and FAR + * when both MMU_NF and probe are set. In the meantime, + * do not support this use case. + */ + assert(!probe); + address &= TARGET_PAGE_MASK; error_code = get_physical_address(env, &paddr, &prot, &access_index, - address, rw, mmu_idx, &page_size); + address, access_type, + mmu_idx, &page_size); vaddr = address; - if (error_code == 0) { + if (likely(error_code == 0)) { qemu_log_mask(CPU_LOG_MMU, - "Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr " - TARGET_FMT_lx "\n", address, paddr, vaddr); + "Translate at %" VADDR_PRIx " -> " + TARGET_FMT_plx ", vaddr " TARGET_FMT_lx "\n", + address, paddr, vaddr); tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size); - return 0; + return true; } if (env->mmuregs[3]) { /* Fault status register */ @@ -243,14 +255,14 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, switching to normal mode. */ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE); - return 0; + return true; } else { - if (rw & 2) { + if (access_type == MMU_INST_FETCH) { cs->exception_index = TT_TFAULT; } else { cs->exception_index = TT_DFAULT; } - return 1; + cpu_loop_exit_restore(cs, retaddr); } } @@ -713,8 +725,9 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical, } /* Perform address translation */ -int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; @@ -725,8 +738,9 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, address &= TARGET_PAGE_MASK; error_code = get_physical_address(env, &paddr, &prot, &access_index, - address, rw, mmu_idx, &page_size); - if (error_code == 0) { + address, access_type, + mmu_idx, &page_size); + if (likely(error_code == 0)) { vaddr = address; trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl, @@ -734,10 +748,12 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, env->dmmu.mmu_secondary_context); tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size); - return 0; + return true; } - /* XXX */ - return 1; + if (probe) { + return false; + } + cpu_loop_exit_restore(cs, retaddr); } void dump_mmu(CPUSPARCState *env) -- cgit v1.1 From 7bfe4e2562dec95396ff10cdbd07f8af1ab634d2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 07:19:26 +0700 Subject: target/tilegx: Convert to CPUClass::tlb_fill Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/tilegx/cpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'target') diff --git a/target/tilegx/cpu.c b/target/tilegx/cpu.c index b9d3710..b209c55 100644 --- a/target/tilegx/cpu.c +++ b/target/tilegx/cpu.c @@ -25,6 +25,7 @@ #include "hw/qdev-properties.h" #include "linux-user/syscall_defs.h" #include "qemu/qemu-print.h" +#include "exec/exec-all.h" static void tilegx_cpu_dump_state(CPUState *cs, FILE *f, int flags) { @@ -111,8 +112,9 @@ static void tilegx_cpu_do_interrupt(CPUState *cs) cs->exception_index = -1; } -static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) +static bool tilegx_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { TileGXCPU *cpu = TILEGX_CPU(cs); @@ -122,7 +124,7 @@ static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, cpu->env.signo = TARGET_SIGSEGV; cpu->env.sigcode = 0; - return 1; + cpu_loop_exit_restore(cs, retaddr); } static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) @@ -152,7 +154,7 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data) cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt; cc->dump_state = tilegx_cpu_dump_state; cc->set_pc = tilegx_cpu_set_pc; - cc->handle_mmu_fault = tilegx_cpu_handle_mmu_fault; + cc->tlb_fill = tilegx_cpu_tlb_fill; cc->gdb_num_core_regs = 0; cc->tcg_initialize = tilegx_tcg_init; } -- cgit v1.1 From 68d6eee73c0a0ea38660fb41f805dd2ec5209b89 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 07:27:29 +0700 Subject: target/tricore: Convert to CPUClass::tlb_fill Acked-by: Bastian Koppelmann Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/tricore/cpu.c | 1 + target/tricore/cpu.h | 6 +++--- target/tricore/helper.c | 27 +++++++++++++++++++-------- target/tricore/op_helper.c | 26 -------------------------- 4 files changed, 23 insertions(+), 37 deletions(-) (limited to 'target') diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index e8d37e4..ea1199d 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -166,6 +166,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; cc->get_phys_page_attrs_debug = tricore_cpu_get_phys_page_attrs_debug; cc->tcg_initialize = tricore_tcg_init; + cc->tlb_fill = tricore_cpu_tlb_fill; } #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \ diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index 64d1a9c..287f432 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -417,8 +417,8 @@ static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, target_ulong *pc, #define CPU_RESOLVING_TYPE TYPE_TRICORE_CPU /* helpers.c */ -int cpu_tricore_handle_mmu_fault(CPUState *cpu, target_ulong address, - int rw, int mmu_idx); -#define cpu_handle_mmu_fault cpu_tricore_handle_mmu_fault +bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); #endif /* TRICORE_CPU_H */ diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 78ee87c..ed184fe 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -50,8 +50,9 @@ static void raise_mmu_exception(CPUTriCoreState *env, target_ulong address, { } -int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address, - int rw, int mmu_idx) +bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType rw, int mmu_idx, + bool probe, uintptr_t retaddr) { TriCoreCPU *cpu = TRICORE_CPU(cs); CPUTriCoreState *env = &cpu->env; @@ -64,20 +65,30 @@ int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address, access_type = ACCESS_INT; ret = get_physical_address(env, &physical, &prot, address, rw, access_type); - qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx - " prot %d\n", __func__, address, ret, physical, prot); + + qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, (target_ulong)address, ret, physical, prot); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); - ret = 0; - } else if (ret < 0) { + return true; + } else { + assert(ret < 0); + if (probe) { + return false; + } raise_mmu_exception(env, address, rw, ret); - ret = 1; + cpu_loop_exit_restore(cs, retaddr); } +} - return ret; +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + tricore_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } static void tricore_cpu_list_entry(gpointer data, gpointer user_data) diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index ed9dc0c..601e92f 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -2793,29 +2793,3 @@ uint32_t helper_psw_read(CPUTriCoreState *env) { return psw_read(env); } - - -static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, - uint32_t exception, - int error_code, - uintptr_t pc) -{ - CPUState *cs = CPU(tricore_env_get_cpu(env)); - cs->exception_index = exception; - env->error_code = error_code; - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, pc); -} - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - ret = cpu_tricore_handle_mmu_fault(cs, addr, access_type, mmu_idx); - if (ret) { - TriCoreCPU *cpu = TRICORE_CPU(cs); - CPUTriCoreState *env = &cpu->env; - do_raise_exception_err(env, cs->exception_index, - env->error_code, retaddr); - } -} -- cgit v1.1 From c5d417da4a5be88e8da9523dcc38d2efc1898081 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 07:34:20 +0700 Subject: target/unicore32: Convert to CPUClass::tlb_fill Remove the user-only functions, as we no longer have a user-only config. Cc: Guan Xuetao Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/unicore32/cpu.c | 5 +---- target/unicore32/cpu.h | 5 +++-- target/unicore32/helper.c | 23 ----------------------- target/unicore32/op_helper.c | 14 -------------- target/unicore32/softmmu.c | 19 +++++++++++++++---- 5 files changed, 19 insertions(+), 47 deletions(-) (limited to 'target') diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c index 2b49d1c..3f57c50 100644 --- a/target/unicore32/cpu.c +++ b/target/unicore32/cpu.c @@ -138,11 +138,8 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data) cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt; cc->dump_state = uc32_cpu_dump_state; cc->set_pc = uc32_cpu_set_pc; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = uc32_cpu_handle_mmu_fault; -#else + cc->tlb_fill = uc32_cpu_tlb_fill; cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug; -#endif cc->tcg_initialize = uc32_translate_init; dc->vmsd = &vmstate_uc32_cpu; } diff --git a/target/unicore32/cpu.h b/target/unicore32/cpu.h index 24abe5e..f052ee0 100644 --- a/target/unicore32/cpu.h +++ b/target/unicore32/cpu.h @@ -178,8 +178,9 @@ static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc } } -int uc32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, - int mmu_idx); +bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void uc32_translate_init(void); void switch_mode(CPUUniCore32State *, int); diff --git a/target/unicore32/helper.c b/target/unicore32/helper.c index a5ff2dd..0d4914b 100644 --- a/target/unicore32/helper.c +++ b/target/unicore32/helper.c @@ -215,29 +215,6 @@ void helper_cp1_putc(target_ulong x) } #endif -#ifdef CONFIG_USER_ONLY -void switch_mode(CPUUniCore32State *env, int mode) -{ - UniCore32CPU *cpu = uc32_env_get_cpu(env); - - if (mode != ASR_MODE_USER) { - cpu_abort(CPU(cpu), "Tried to switch out of user mode\n"); - } -} - -void uc32_cpu_do_interrupt(CPUState *cs) -{ - cpu_abort(cs, "NO interrupt in user mode\n"); -} - -int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int access_type, int mmu_idx) -{ - cpu_abort(cs, "NO mmu fault in user mode\n"); - return 1; -} -#endif - bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { if (interrupt_request & CPU_INTERRUPT_HARD) { diff --git a/target/unicore32/op_helper.c b/target/unicore32/op_helper.c index e0a1588..797ba60 100644 --- a/target/unicore32/op_helper.c +++ b/target/unicore32/op_helper.c @@ -242,17 +242,3 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) return ((uint32_t)x >> shift) | (x << (32 - shift)); } } - -#ifndef CONFIG_USER_ONLY -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = uc32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); - if (unlikely(ret)) { - /* now we have a real cpu fault */ - cpu_loop_exit_restore(cs, retaddr); - } -} -#endif diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c index 00c7e0d..13678df 100644 --- a/target/unicore32/softmmu.c +++ b/target/unicore32/softmmu.c @@ -215,8 +215,9 @@ do_fault: return code; } -int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int access_type, int mmu_idx) +bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { UniCore32CPU *cpu = UNICORE32_CPU(cs); CPUUniCore32State *env = &cpu->env; @@ -257,7 +258,11 @@ int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, phys_addr &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK; tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size); - return 0; + return true; + } + + if (probe) { + return false; } env->cp0.c3_faultstatus = ret; @@ -267,7 +272,13 @@ int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, } else { cs->exception_index = UC32_EXCP_DTRAP; } - return ret; + cpu_loop_exit_restore(cs, retaddr); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + uc32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); } hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -- cgit v1.1 From b008c45612f652edb8cae8ec9620a3f57b2500e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 07:46:30 +0700 Subject: target/xtensa: Convert to CPUClass::tlb_fill Cc: Max Filippov Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/xtensa/cpu.c | 5 ++--- target/xtensa/cpu.h | 5 +++-- target/xtensa/helper.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 18 deletions(-) (limited to 'target') diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index a54dbe4..da12363 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -181,9 +181,8 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_read_register = xtensa_cpu_gdb_read_register; cc->gdb_write_register = xtensa_cpu_gdb_write_register; cc->gdb_stop_before_watchpoint = true; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = xtensa_cpu_handle_mmu_fault; -#else + cc->tlb_fill = xtensa_cpu_tlb_fill; +#ifndef CONFIG_USER_ONLY cc->do_unaligned_access = xtensa_cpu_do_unaligned_access; cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; cc->do_transaction_failed = xtensa_cpu_do_transaction_failed; diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 5d23e134..68d89f8 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -552,8 +552,9 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env) #define ENV_OFFSET offsetof(XtensaCPU, env) -int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int size, - int mmu_idx); +bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); void xtensa_cpu_do_interrupt(CPUState *cpu); bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request); void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 5f37f37..5c94f93 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -240,19 +240,21 @@ void xtensa_cpu_list(void) #ifdef CONFIG_USER_ONLY -int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, - int mmu_idx) +bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; qemu_log_mask(CPU_LOG_INT, "%s: rw = %d, address = 0x%08" VADDR_PRIx ", size = %d\n", - __func__, rw, address, size); + __func__, access_type, address, size); env->sregs[EXCVADDR] = address; - env->sregs[EXCCAUSE] = rw ? STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE; + env->sregs[EXCCAUSE] = (access_type == MMU_DATA_STORE ? + STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE); cs->exception_index = EXC_USER; - return 1; + cpu_loop_exit_restore(cs, retaddr); } #else @@ -273,31 +275,42 @@ void xtensa_cpu_do_unaligned_access(CPUState *cs, } } -void tlb_fill(CPUState *cs, target_ulong vaddr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) { XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; uint32_t paddr; uint32_t page_size; unsigned access; - int ret = xtensa_get_physical_addr(env, true, vaddr, access_type, mmu_idx, - &paddr, &page_size, &access); + int ret = xtensa_get_physical_addr(env, true, address, access_type, + mmu_idx, &paddr, &page_size, &access); - qemu_log_mask(CPU_LOG_MMU, "%s(%08x, %d, %d) -> %08x, ret = %d\n", - __func__, vaddr, access_type, mmu_idx, paddr, ret); + qemu_log_mask(CPU_LOG_MMU, "%s(%08" VADDR_PRIx + ", %d, %d) -> %08x, ret = %d\n", + __func__, address, access_type, mmu_idx, paddr, ret); if (ret == 0) { tlb_set_page(cs, - vaddr & TARGET_PAGE_MASK, + address & TARGET_PAGE_MASK, paddr & TARGET_PAGE_MASK, access, mmu_idx, page_size); + return true; + } else if (probe) { + return false; } else { cpu_restore_state(cs, retaddr, true); - HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr); + HELPER(exception_cause_vaddr)(env, env->pc, ret, address); } } +void tlb_fill(CPUState *cs, target_ulong vaddr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + xtensa_cpu_tlb_fill(cs, vaddr, size, access_type, mmu_idx, false, retaddr); +} + void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, int mmu_idx, MemTxAttrs attrs, -- cgit v1.1 From c319dc13579a92937bffe02ad2c9f1a550e73973 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 09:07:11 +0700 Subject: tcg: Use CPUClass::tlb_fill in cputlb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can now use the CPUClass hook instead of a named function. Create a static tlb_fill function to avoid other changes within cputlb.c. This also isolates the asserts within. Remove the named tlb_fill function from all of the targets. Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/alpha/helper.c | 6 ------ target/arm/helper.c | 8 -------- target/cris/helper.c | 6 ------ target/hppa/mem_helper.c | 6 ------ target/i386/excp_helper.c | 8 -------- target/lm32/helper.c | 6 ------ target/m68k/helper.c | 8 -------- target/microblaze/helper.c | 6 ------ target/mips/helper.c | 6 ------ target/moxie/helper.c | 6 ------ target/nios2/helper.c | 6 ------ target/openrisc/mmu.c | 6 ------ target/ppc/mmu_helper.c | 6 ------ target/riscv/cpu_helper.c | 6 ------ target/s390x/excp_helper.c | 6 ------ target/sh4/helper.c | 8 -------- target/sparc/ldst_helper.c | 6 ------ target/tricore/helper.c | 6 ------ target/unicore32/softmmu.c | 6 ------ target/xtensa/helper.c | 6 ------ 20 files changed, 128 deletions(-) (limited to 'target') diff --git a/target/alpha/helper.c b/target/alpha/helper.c index 929a217..5fe9c87 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -275,12 +275,6 @@ bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - alpha_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} #endif /* USER_ONLY */ void alpha_cpu_do_interrupt(CPUState *cs) diff --git a/target/arm/helper.c b/target/arm/helper.c index f1a2b94..e2d5c8e 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -13127,14 +13127,6 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, #endif } -#ifndef CONFIG_USER_ONLY -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - arm_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} -#endif - void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) { /* Implement DC ZVA, which zeroes a fixed-length block of memory. diff --git a/target/cris/helper.c b/target/cris/helper.c index 6946483..b5159b8 100644 --- a/target/cris/helper.c +++ b/target/cris/helper.c @@ -123,12 +123,6 @@ bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit(cs); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - cris_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - void crisv10_cpu_do_interrupt(CPUState *cs) { CRISCPU *cpu = CRIS_CPU(cs); diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 5cee0c1..0fd3ac6 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -260,12 +260,6 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, return true; } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType type, int mmu_idx, uintptr_t retaddr) -{ - hppa_cpu_tlb_fill(cs, addr, size, type, mmu_idx, false, retaddr); -} - /* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */ void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg) { diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c index 68bf8e3..fa1ead6 100644 --- a/target/i386/excp_helper.c +++ b/target/i386/excp_helper.c @@ -700,11 +700,3 @@ bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, return true; #endif } - -#if !defined(CONFIG_USER_ONLY) -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - x86_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} -#endif diff --git a/target/lm32/helper.c b/target/lm32/helper.c index 1db9a55..20ea17b 100644 --- a/target/lm32/helper.c +++ b/target/lm32/helper.c @@ -44,12 +44,6 @@ bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, return true; } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - lm32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { LM32CPU *cpu = LM32_CPU(cs); diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 862f955..9fc9e64 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -884,14 +884,6 @@ bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit_restore(cs, retaddr); } -#ifndef CONFIG_USER_ONLY -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - m68k_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} -#endif - uint32_t HELPER(bitrev)(uint32_t x) { x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau); diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c index a523c77..ab2ceeb 100644 --- a/target/microblaze/helper.c +++ b/target/microblaze/helper.c @@ -108,12 +108,6 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit_restore(cs, retaddr); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - mb_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - void mb_cpu_do_interrupt(CPUState *cs) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); diff --git a/target/mips/helper.c b/target/mips/helper.c index 3a4917c..9799f2e 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -944,12 +944,6 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } #ifndef CONFIG_USER_ONLY -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - mips_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) { hwaddr physical; diff --git a/target/moxie/helper.c b/target/moxie/helper.c index 216cef0..f5c1d41 100644 --- a/target/moxie/helper.c +++ b/target/moxie/helper.c @@ -26,12 +26,6 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - moxie_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - void helper_raise_exception(CPUMoxieState *env, int ex) { CPUState *cs = CPU(moxie_env_get_cpu(env)); diff --git a/target/nios2/helper.c b/target/nios2/helper.c index eb2eed7..ffb83fc 100644 --- a/target/nios2/helper.c +++ b/target/nios2/helper.c @@ -311,10 +311,4 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, env->regs[CR_BADADDR] = address; cpu_loop_exit_restore(cs, retaddr); } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - nios2_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} #endif /* !CONFIG_USER_ONLY */ diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 94c65a2..a73b12a 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -178,10 +178,4 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return phys_addr; } } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - openrisc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, 0, retaddr); -} #endif diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index afcca50..e605efa 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -3080,9 +3080,3 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, } return true; } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - ppc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 2535435..41d6db4 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -378,12 +378,6 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, env->badaddr = addr; riscv_raise_exception(env, cs->exception_index, retaddr); } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - riscv_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} #endif bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index a4e134b..3a467b7 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -178,12 +178,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit(cs); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - s390_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - static void do_program_interrupt(CPUS390XState *env) { uint64_t mask, addr; diff --git a/target/sh4/helper.c b/target/sh4/helper.c index 1517a61..fda195e 100644 --- a/target/sh4/helper.c +++ b/target/sh4/helper.c @@ -872,11 +872,3 @@ bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } cpu_loop_exit_restore(cs, retaddr); } - -#ifndef CONFIG_USER_ONLY -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - superh_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} -#endif diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index 2558c08..b4bf6fa 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -1924,10 +1924,4 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, #endif cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr); } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - sparc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} #endif diff --git a/target/tricore/helper.c b/target/tricore/helper.c index ed184fe..a680336 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -85,12 +85,6 @@ bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - tricore_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - static void tricore_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *oc = data; diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c index 13678df..27f218a 100644 --- a/target/unicore32/softmmu.c +++ b/target/unicore32/softmmu.c @@ -275,12 +275,6 @@ bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit_restore(cs, retaddr); } -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - uc32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr); -} - hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { error_report("function uc32_cpu_get_phys_page_debug not " diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 5c94f93..efb966b 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -305,12 +305,6 @@ bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } -void tlb_fill(CPUState *cs, target_ulong vaddr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - xtensa_cpu_tlb_fill(cs, vaddr, size, access_type, mmu_idx, false, retaddr); -} - void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, int mmu_idx, MemTxAttrs attrs, -- cgit v1.1 From 4811e9095c0491bc6f5450e5012c9c4796b9e59d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 10:16:56 +0700 Subject: tcg: Use tlb_fill probe from tlb_vaddr_to_host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the existing users would continue around a loop which would fault the tlb entry in via a normal load/store. But for AArch64 SVE we have an existing emulation bug wherein we would mark the first element of a no-fault vector load as faulted (within the FFR, not via exception) just because we did not have its address in the TLB. Now we can properly only mark it as faulted if there really is no valid, readable translation, while still not raising an exception. (Note that beyond the first element of the vector, the hardware may report a fault for any reason whatsoever; with at least one element loaded, forward progress is guaranteed.) Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target/arm/sve_helper.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'target') diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index bc84725..fd434c6 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -4598,11 +4598,7 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, * in the real world, obviously.) * * Then there are the annoying special cases with watchpoints... - * - * TODO: Add a form of tlb_fill that does not raise an exception, - * with a form of tlb_vaddr_to_host and a set of loads to match. - * The non_fault_vaddr_to_host would handle everything, usually, - * and the loads would handle the iomem path for watchpoints. + * TODO: Add a form of non-faulting loads using cc->tlb_fill(probe=true). */ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); split = max_for_page(addr, mem_off, mem_max); -- cgit v1.1