qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20190510' into staging

Add CPUClass::tlb_fill.
Improve tlb_vaddr_to_host for use by ARM SVE no-fault loads.

# gpg: Signature made Fri 10 May 2019 19:48:37 BST
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F

* remotes/rth/tags/pull-tcg-20190510: (27 commits)
tcg: Use tlb_fill probe from tlb_vaddr_to_host
tcg: Remove CPUClass::handle_mmu_fault
tcg: Use CPUClass::tlb_fill in cputlb.c
target/xtensa: Convert to CPUClass::tlb_fill
target/unicore32: Convert to CPUClass::tlb_fill
target/tricore: Convert to CPUClass::tlb_fill
target/tilegx: Convert to CPUClass::tlb_fill
target/sparc: Convert to CPUClass::tlb_fill
target/sh4: Convert to CPUClass::tlb_fill
target/s390x: Convert to CPUClass::tlb_fill
target/riscv: Convert to CPUClass::tlb_fill
target/ppc: Convert to CPUClass::tlb_fill
target/openrisc: Convert to CPUClass::tlb_fill
target/nios2: Convert to CPUClass::tlb_fill
target/moxie: Convert to CPUClass::tlb_fill
target/mips: Convert to CPUClass::tlb_fill
target/mips: Tidy control flow in mips_cpu_handle_mmu_fault
target/mips: Pass a valid error to raise_mmu_exception for user-only
target/microblaze: Convert to CPUClass::tlb_fill
target/m68k: Convert to CPUClass::tlb_fill
...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+865 -1128
+80 -8
accel/tcg/cputlb.c
··· 855 855 return ram_addr; 856 856 } 857 857 858 + /* 859 + * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the 860 + * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must 861 + * be discarded and looked up again (e.g. via tlb_entry()). 862 + */ 863 + static void tlb_fill(CPUState *cpu, target_ulong addr, int size, 864 + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 865 + { 866 + CPUClass *cc = CPU_GET_CLASS(cpu); 867 + bool ok; 868 + 869 + /* 870 + * This is not a probe, so only valid return is success; failure 871 + * should result in exception + longjmp to the cpu loop. 872 + */ 873 + ok = cc->tlb_fill(cpu, addr, size, access_type, mmu_idx, false, retaddr); 874 + assert(ok); 875 + } 876 + 858 877 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, 859 878 int mmu_idx, target_ulong addr, uintptr_t retaddr, 860 879 MMUAccessType access_type, int size) ··· 938 957 } 939 958 } 940 959 960 + static inline target_ulong tlb_read_ofs(CPUTLBEntry *entry, size_t ofs) 961 + { 962 + #if TCG_OVERSIZED_GUEST 963 + return *(target_ulong *)((uintptr_t)entry + ofs); 964 + #else 965 + /* ofs might correspond to .addr_write, so use atomic_read */ 966 + return atomic_read((target_ulong *)((uintptr_t)entry + ofs)); 967 + #endif 968 + } 969 + 941 970 /* Return true if ADDR is present in the victim tlb, and has been copied 942 971 back to the main tlb. */ 943 972 static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, ··· 948 977 assert_cpu_is_self(ENV_GET_CPU(env)); 949 978 for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) { 950 979 CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx]; 951 - target_ulong cmp; 952 - 953 - /* elt_ofs might correspond to .addr_write, so use atomic_read */ 954 - #if TCG_OVERSIZED_GUEST 955 - cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs); 956 - #else 957 - cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs)); 958 - #endif 980 + target_ulong cmp = tlb_read_ofs(vtlb, elt_ofs); 959 981 960 982 if (cmp == page) { 961 983 /* Found entry in victim tlb, swap tlb and iotlb. */ ··· 1037 1059 mmu_idx, retaddr); 1038 1060 } 1039 1061 } 1062 + } 1063 + 1064 + void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 1065 + MMUAccessType access_type, int mmu_idx) 1066 + { 1067 + CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); 1068 + uintptr_t tlb_addr, page; 1069 + size_t elt_ofs; 1070 + 1071 + switch (access_type) { 1072 + case MMU_DATA_LOAD: 1073 + elt_ofs = offsetof(CPUTLBEntry, addr_read); 1074 + break; 1075 + case MMU_DATA_STORE: 1076 + elt_ofs = offsetof(CPUTLBEntry, addr_write); 1077 + break; 1078 + case MMU_INST_FETCH: 1079 + elt_ofs = offsetof(CPUTLBEntry, addr_code); 1080 + break; 1081 + default: 1082 + g_assert_not_reached(); 1083 + } 1084 + 1085 + page = addr & TARGET_PAGE_MASK; 1086 + tlb_addr = tlb_read_ofs(entry, elt_ofs); 1087 + 1088 + if (!tlb_hit_page(tlb_addr, page)) { 1089 + uintptr_t index = tlb_index(env, mmu_idx, addr); 1090 + 1091 + if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page)) { 1092 + CPUState *cs = ENV_GET_CPU(env); 1093 + CPUClass *cc = CPU_GET_CLASS(cs); 1094 + 1095 + if (!cc->tlb_fill(cs, addr, 0, access_type, mmu_idx, true, 0)) { 1096 + /* Non-faulting page table read failed. */ 1097 + return NULL; 1098 + } 1099 + 1100 + /* TLB resize via tlb_fill may have moved the entry. */ 1101 + entry = tlb_entry(env, mmu_idx, addr); 1102 + } 1103 + tlb_addr = tlb_read_ofs(entry, elt_ofs); 1104 + } 1105 + 1106 + if (tlb_addr & ~TARGET_PAGE_MASK) { 1107 + /* IO access */ 1108 + return NULL; 1109 + } 1110 + 1111 + return (void *)((uintptr_t)addr + entry->addend); 1040 1112 } 1041 1113 1042 1114 /* Probe for a read-modify-write atomic operation. Do not allow unaligned
+9 -27
accel/tcg/user-exec.c
··· 63 63 { 64 64 CPUState *cpu = current_cpu; 65 65 CPUClass *cc; 66 - int ret; 67 66 unsigned long address = (unsigned long)info->si_addr; 67 + MMUAccessType access_type; 68 68 69 69 /* We must handle PC addresses from two different sources: 70 70 * a call return address and a signal frame address. ··· 147 147 are still valid segv ones */ 148 148 address = h2g_nocheck(address); 149 149 150 - cc = CPU_GET_CLASS(cpu); 151 - /* see if it is an MMU fault */ 152 - g_assert(cc->handle_mmu_fault); 153 - ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX); 154 - 155 - if (ret == 0) { 156 - /* The MMU fault was handled without causing real CPU fault. 157 - * Retain helper_retaddr for a possible second fault. 158 - */ 159 - return 1; 160 - } 161 - 162 - /* All other paths lead to cpu_exit; clear helper_retaddr 163 - * for next execution. 150 + /* 151 + * There is no way the target can handle this other than raising 152 + * an exception. Undo signal and retaddr state prior to longjmp. 164 153 */ 154 + sigprocmask(SIG_SETMASK, old_set, NULL); 165 155 helper_retaddr = 0; 166 156 167 - if (ret < 0) { 168 - return 0; /* not an MMU fault */ 169 - } 170 - 171 - /* Now we have a real cpu fault. */ 172 - cpu_restore_state(cpu, pc, true); 173 - 174 - sigprocmask(SIG_SETMASK, old_set, NULL); 175 - cpu_loop_exit(cpu); 176 - 177 - /* never comes here */ 178 - return 1; 157 + cc = CPU_GET_CLASS(cpu); 158 + access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD; 159 + cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc); 160 + g_assert_not_reached(); 179 161 } 180 162 181 163 #if defined(__i386__)
+10 -40
include/exec/cpu_ldst.h
··· 433 433 * @mmu_idx: MMU index to use for lookup 434 434 * 435 435 * Look up the specified guest virtual index in the TCG softmmu TLB. 436 - * If the TLB contains a host virtual address suitable for direct RAM 437 - * access, then return it. Otherwise (TLB miss, TLB entry is for an 438 - * I/O access, etc) return NULL. 439 - * 440 - * This is the equivalent of the initial fast-path code used by 441 - * TCG backends for guest load and store accesses. 436 + * If we can translate a host virtual address suitable for direct RAM 437 + * access, without causing a guest exception, then return it. 438 + * Otherwise (TLB entry is for an I/O access, guest software 439 + * TLB fill required, etc) return NULL. 442 440 */ 441 + #ifdef CONFIG_USER_ONLY 443 442 static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 444 - int access_type, int mmu_idx) 443 + MMUAccessType access_type, int mmu_idx) 445 444 { 446 - #if defined(CONFIG_USER_ONLY) 447 445 return g2h(addr); 448 - #else 449 - CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr); 450 - abi_ptr tlb_addr; 451 - uintptr_t haddr; 452 - 453 - switch (access_type) { 454 - case 0: 455 - tlb_addr = tlbentry->addr_read; 456 - break; 457 - case 1: 458 - tlb_addr = tlb_addr_write(tlbentry); 459 - break; 460 - case 2: 461 - tlb_addr = tlbentry->addr_code; 462 - break; 463 - default: 464 - g_assert_not_reached(); 465 - } 466 - 467 - if (!tlb_hit(tlb_addr, addr)) { 468 - /* TLB entry is for a different page */ 469 - return NULL; 470 - } 471 - 472 - if (tlb_addr & ~TARGET_PAGE_MASK) { 473 - /* IO access */ 474 - return NULL; 475 - } 476 - 477 - haddr = addr + tlbentry->addend; 478 - return (void *)haddr; 479 - #endif /* defined(CONFIG_USER_ONLY) */ 480 446 } 447 + #else 448 + void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 449 + MMUAccessType access_type, int mmu_idx); 450 + #endif 481 451 482 452 #endif /* CPU_LDST_H */
-9
include/exec/exec-all.h
··· 474 474 */ 475 475 struct MemoryRegionSection *iotlb_to_section(CPUState *cpu, 476 476 hwaddr index, MemTxAttrs attrs); 477 - 478 - /* 479 - * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the 480 - * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must 481 - * be discarded and looked up again (e.g. via tlb_entry()). 482 - */ 483 - void tlb_fill(CPUState *cpu, target_ulong addr, int size, 484 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); 485 - 486 477 #endif 487 478 488 479 #if defined(CONFIG_USER_ONLY)
+9 -3
include/qom/cpu.h
··· 117 117 * This always includes at least the program counter; some targets 118 118 * will need to do more. If this hook is not implemented then the 119 119 * default is to call @set_pc(tb->pc). 120 - * @handle_mmu_fault: Callback for handling an MMU fault. 120 + * @tlb_fill: Callback for handling a softmmu tlb miss or user-only 121 + * address fault. For system mode, if the access is valid, call 122 + * tlb_set_page and return true; if the access is invalid, and 123 + * probe is true, return false; otherwise raise an exception and 124 + * do not return. For user-only mode, always raise an exception 125 + * and do not return. 121 126 * @get_phys_page_debug: Callback for obtaining a physical address. 122 127 * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the 123 128 * associated memory transaction attributes to use for the access. ··· 189 194 Error **errp); 190 195 void (*set_pc)(CPUState *cpu, vaddr value); 191 196 void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); 192 - int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw, 193 - int mmu_index); 197 + bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, 198 + MMUAccessType access_type, int mmu_idx, 199 + bool probe, uintptr_t retaddr); 194 200 hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); 195 201 hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr, 196 202 MemTxAttrs *attrs);
+2 -3
target/alpha/cpu.c
··· 225 225 cc->set_pc = alpha_cpu_set_pc; 226 226 cc->gdb_read_register = alpha_cpu_gdb_read_register; 227 227 cc->gdb_write_register = alpha_cpu_gdb_write_register; 228 - #ifdef CONFIG_USER_ONLY 229 - cc->handle_mmu_fault = alpha_cpu_handle_mmu_fault; 230 - #else 228 + cc->tlb_fill = alpha_cpu_tlb_fill; 229 + #ifndef CONFIG_USER_ONLY 231 230 cc->do_transaction_failed = alpha_cpu_do_transaction_failed; 232 231 cc->do_unaligned_access = alpha_cpu_do_unaligned_access; 233 232 cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
+3 -2
target/alpha/cpu.h
··· 475 475 is returned if the signal was handled by the virtual CPU. */ 476 476 int cpu_alpha_signal_handler(int host_signum, void *pinfo, 477 477 void *puc); 478 - int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 479 - int mmu_idx); 478 + bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 479 + MMUAccessType access_type, int mmu_idx, 480 + bool probe, uintptr_t retaddr); 480 481 void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int); 481 482 void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t); 482 483
+15 -9
target/alpha/helper.c
··· 104 104 } 105 105 106 106 #if defined(CONFIG_USER_ONLY) 107 - int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 108 - int rw, int mmu_idx) 107 + bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 108 + MMUAccessType access_type, int mmu_idx, 109 + bool probe, uintptr_t retaddr) 109 110 { 110 111 AlphaCPU *cpu = ALPHA_CPU(cs); 111 112 112 113 cs->exception_index = EXCP_MMFAULT; 113 114 cpu->env.trap_arg0 = address; 114 - return 1; 115 + cpu_loop_exit_restore(cs, retaddr); 115 116 } 116 117 #else 117 118 /* Returns the OSF/1 entMM failure indication, or -1 on success. */ ··· 248 249 return (fail >= 0 ? -1 : phys); 249 250 } 250 251 251 - int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, int rw, 252 - int mmu_idx) 252 + bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 253 + MMUAccessType access_type, int mmu_idx, 254 + bool probe, uintptr_t retaddr) 253 255 { 254 256 AlphaCPU *cpu = ALPHA_CPU(cs); 255 257 CPUAlphaState *env = &cpu->env; 256 258 target_ulong phys; 257 259 int prot, fail; 258 260 259 - fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); 261 + fail = get_physical_address(env, addr, 1 << access_type, 262 + mmu_idx, &phys, &prot); 260 263 if (unlikely(fail >= 0)) { 264 + if (probe) { 265 + return false; 266 + } 261 267 cs->exception_index = EXCP_MMFAULT; 262 268 env->trap_arg0 = addr; 263 269 env->trap_arg1 = fail; 264 - env->trap_arg2 = (rw == 2 ? -1 : rw); 265 - return 1; 270 + env->trap_arg2 = (access_type == MMU_INST_FETCH ? -1 : access_type); 271 + cpu_loop_exit_restore(cs, retaddr); 266 272 } 267 273 268 274 tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, 269 275 prot, mmu_idx, TARGET_PAGE_SIZE); 270 - return 0; 276 + return true; 271 277 } 272 278 #endif /* USER_ONLY */ 273 279
-16
target/alpha/mem_helper.c
··· 62 62 env->error_code = 0; 63 63 cpu_loop_exit_restore(cs, retaddr); 64 64 } 65 - 66 - /* try to fill the TLB and return an exception if error. If retaddr is 67 - NULL, it means that the function was called in C code (i.e. not 68 - from generated code or from helper.c) */ 69 - /* XXX: fix it to restore all registers */ 70 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 71 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 72 - { 73 - int ret; 74 - 75 - ret = alpha_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 76 - if (unlikely(ret != 0)) { 77 - /* Exception index and error code are already set */ 78 - cpu_loop_exit_restore(cs, retaddr); 79 - } 80 - } 81 65 #endif /* CONFIG_USER_ONLY */
+2 -20
target/arm/cpu.c
··· 2133 2133 DEFINE_PROP_END_OF_LIST() 2134 2134 }; 2135 2135 2136 - #ifdef CONFIG_USER_ONLY 2137 - static int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 2138 - int rw, int mmu_idx) 2139 - { 2140 - ARMCPU *cpu = ARM_CPU(cs); 2141 - CPUARMState *env = &cpu->env; 2142 - 2143 - env->exception.vaddress = address; 2144 - if (rw == 2) { 2145 - cs->exception_index = EXCP_PREFETCH_ABORT; 2146 - } else { 2147 - cs->exception_index = EXCP_DATA_ABORT; 2148 - } 2149 - return 1; 2150 - } 2151 - #endif 2152 - 2153 2136 static gchar *arm_gdb_arch_name(CPUState *cs) 2154 2137 { 2155 2138 ARMCPU *cpu = ARM_CPU(cs); ··· 2182 2165 cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; 2183 2166 cc->gdb_read_register = arm_cpu_gdb_read_register; 2184 2167 cc->gdb_write_register = arm_cpu_gdb_write_register; 2185 - #ifdef CONFIG_USER_ONLY 2186 - cc->handle_mmu_fault = arm_cpu_handle_mmu_fault; 2187 - #else 2168 + #ifndef CONFIG_USER_ONLY 2188 2169 cc->do_interrupt = arm_cpu_do_interrupt; 2189 2170 cc->do_unaligned_access = arm_cpu_do_unaligned_access; 2190 2171 cc->do_transaction_failed = arm_cpu_do_transaction_failed; ··· 2209 2190 cc->disas_set_info = arm_disas_set_info; 2210 2191 #ifdef CONFIG_TCG 2211 2192 cc->tcg_initialize = arm_translate_init; 2193 + cc->tlb_fill = arm_cpu_tlb_fill; 2212 2194 #endif 2213 2195 } 2214 2196
+53 -37
target/arm/helper.c
··· 12596 12596 } 12597 12597 } 12598 12598 12599 - /* Walk the page table and (if the mapping exists) add the page 12600 - * to the TLB. Return false on success, or true on failure. Populate 12601 - * fsr with ARM DFSR/IFSR fault register format value on failure. 12602 - */ 12603 - bool arm_tlb_fill(CPUState *cs, vaddr address, 12604 - MMUAccessType access_type, int mmu_idx, 12605 - ARMMMUFaultInfo *fi) 12606 - { 12607 - ARMCPU *cpu = ARM_CPU(cs); 12608 - CPUARMState *env = &cpu->env; 12609 - hwaddr phys_addr; 12610 - target_ulong page_size; 12611 - int prot; 12612 - int ret; 12613 - MemTxAttrs attrs = {}; 12614 - 12615 - ret = get_phys_addr(env, address, access_type, 12616 - core_to_arm_mmu_idx(env, mmu_idx), &phys_addr, 12617 - &attrs, &prot, &page_size, fi, NULL); 12618 - if (!ret) { 12619 - /* 12620 - * Map a single [sub]page. Regions smaller than our declared 12621 - * target page size are handled specially, so for those we 12622 - * pass in the exact addresses. 12623 - */ 12624 - if (page_size >= TARGET_PAGE_SIZE) { 12625 - phys_addr &= TARGET_PAGE_MASK; 12626 - address &= TARGET_PAGE_MASK; 12627 - } 12628 - tlb_set_page_with_attrs(cs, address, phys_addr, attrs, 12629 - prot, mmu_idx, page_size); 12630 - return 0; 12631 - } 12632 - 12633 - return ret; 12634 - } 12635 - 12636 12599 hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, 12637 12600 MemTxAttrs *attrs) 12638 12601 { ··· 13110 13073 } 13111 13074 13112 13075 #endif 13076 + 13077 + bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 13078 + MMUAccessType access_type, int mmu_idx, 13079 + bool probe, uintptr_t retaddr) 13080 + { 13081 + ARMCPU *cpu = ARM_CPU(cs); 13082 + 13083 + #ifdef CONFIG_USER_ONLY 13084 + cpu->env.exception.vaddress = address; 13085 + if (access_type == MMU_INST_FETCH) { 13086 + cs->exception_index = EXCP_PREFETCH_ABORT; 13087 + } else { 13088 + cs->exception_index = EXCP_DATA_ABORT; 13089 + } 13090 + cpu_loop_exit_restore(cs, retaddr); 13091 + #else 13092 + hwaddr phys_addr; 13093 + target_ulong page_size; 13094 + int prot, ret; 13095 + MemTxAttrs attrs = {}; 13096 + ARMMMUFaultInfo fi = {}; 13097 + 13098 + /* 13099 + * Walk the page table and (if the mapping exists) add the page 13100 + * to the TLB. On success, return true. Otherwise, if probing, 13101 + * return false. Otherwise populate fsr with ARM DFSR/IFSR fault 13102 + * register format, and signal the fault. 13103 + */ 13104 + ret = get_phys_addr(&cpu->env, address, access_type, 13105 + core_to_arm_mmu_idx(&cpu->env, mmu_idx), 13106 + &phys_addr, &attrs, &prot, &page_size, &fi, NULL); 13107 + if (likely(!ret)) { 13108 + /* 13109 + * Map a single [sub]page. Regions smaller than our declared 13110 + * target page size are handled specially, so for those we 13111 + * pass in the exact addresses. 13112 + */ 13113 + if (page_size >= TARGET_PAGE_SIZE) { 13114 + phys_addr &= TARGET_PAGE_MASK; 13115 + address &= TARGET_PAGE_MASK; 13116 + } 13117 + tlb_set_page_with_attrs(cs, address, phys_addr, attrs, 13118 + prot, mmu_idx, page_size); 13119 + return true; 13120 + } else if (probe) { 13121 + return false; 13122 + } else { 13123 + /* now we have a real cpu fault */ 13124 + cpu_restore_state(cs, retaddr, true); 13125 + arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi); 13126 + } 13127 + #endif 13128 + } 13113 13129 13114 13130 void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) 13115 13131 {
+6 -4
target/arm/internals.h
··· 761 761 return result != MEMTX_DECODE_ERROR; 762 762 } 763 763 764 - /* Do a page table walk and add page to TLB if possible */ 765 - bool arm_tlb_fill(CPUState *cpu, vaddr address, 766 - MMUAccessType access_type, int mmu_idx, 767 - ARMMMUFaultInfo *fi); 764 + bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 765 + MMUAccessType access_type, int mmu_idx, 766 + bool probe, uintptr_t retaddr); 767 + 768 + void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, 769 + int mmu_idx, ARMMMUFaultInfo *fi) QEMU_NORETURN; 768 770 769 771 /* Return true if the stage 1 translation regime is using LPAE format page 770 772 * tables */
+4 -25
target/arm/op_helper.c
··· 126 126 return syn; 127 127 } 128 128 129 - static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, 130 - int mmu_idx, ARMMMUFaultInfo *fi) 129 + void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, 130 + int mmu_idx, ARMMMUFaultInfo *fi) 131 131 { 132 132 CPUARMState *env = &cpu->env; 133 133 int target_el; ··· 179 179 raise_exception(env, exc, syn, target_el); 180 180 } 181 181 182 - /* try to fill the TLB and return an exception if error. If retaddr is 183 - * NULL, it means that the function was called in C code (i.e. not 184 - * from generated code or from helper.c) 185 - */ 186 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 187 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 188 - { 189 - bool ret; 190 - ARMMMUFaultInfo fi = {}; 191 - 192 - ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fi); 193 - if (unlikely(ret)) { 194 - ARMCPU *cpu = ARM_CPU(cs); 195 - 196 - /* now we have a real cpu fault */ 197 - cpu_restore_state(cs, retaddr, true); 198 - 199 - deliver_fault(cpu, addr, access_type, mmu_idx, &fi); 200 - } 201 - } 202 - 203 182 /* Raise a data fault alignment exception for the specified virtual address */ 204 183 void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, 205 184 MMUAccessType access_type, ··· 212 191 cpu_restore_state(cs, retaddr, true); 213 192 214 193 fi.type = ARMFault_Alignment; 215 - deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); 194 + arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); 216 195 } 217 196 218 197 /* arm_cpu_do_transaction_failed: handle a memory system error response ··· 233 212 234 213 fi.ea = arm_extabort_type(response); 235 214 fi.type = ARMFault_SyncExternal; 236 - deliver_fault(cpu, addr, access_type, mmu_idx, &fi); 215 + arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi); 237 216 } 238 217 239 218 #endif /* !defined(CONFIG_USER_ONLY) */
+1 -5
target/arm/sve_helper.c
··· 4598 4598 * in the real world, obviously.) 4599 4599 * 4600 4600 * Then there are the annoying special cases with watchpoints... 4601 - * 4602 - * TODO: Add a form of tlb_fill that does not raise an exception, 4603 - * with a form of tlb_vaddr_to_host and a set of loads to match. 4604 - * The non_fault_vaddr_to_host would handle everything, usually, 4605 - * and the loads would handle the iomem path for watchpoints. 4601 + * TODO: Add a form of non-faulting loads using cc->tlb_fill(probe=true). 4606 4602 */ 4607 4603 host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); 4608 4604 split = max_for_page(addr, mem_off, mem_max);
+2 -3
target/cris/cpu.c
··· 269 269 cc->set_pc = cris_cpu_set_pc; 270 270 cc->gdb_read_register = cris_cpu_gdb_read_register; 271 271 cc->gdb_write_register = cris_cpu_gdb_write_register; 272 - #ifdef CONFIG_USER_ONLY 273 - cc->handle_mmu_fault = cris_cpu_handle_mmu_fault; 274 - #else 272 + cc->tlb_fill = cris_cpu_tlb_fill; 273 + #ifndef CONFIG_USER_ONLY 275 274 cc->get_phys_page_debug = cris_cpu_get_phys_page_debug; 276 275 dc->vmsd = &vmstate_cris_cpu; 277 276 #endif
+3 -2
target/cris/cpu.h
··· 281 281 return !!(env->pregs[PR_CCS] & U_FLAG); 282 282 } 283 283 284 - int cris_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 285 - int mmu_idx); 284 + bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 285 + MMUAccessType access_type, int mmu_idx, 286 + bool probe, uintptr_t retaddr); 286 287 287 288 /* Support function regs. */ 288 289 #define SFR_RW_GC_CFG 0][0
+31 -30
target/cris/helper.c
··· 24 24 #include "qemu/host-utils.h" 25 25 #include "exec/exec-all.h" 26 26 #include "exec/cpu_ldst.h" 27 + #include "exec/helper-proto.h" 27 28 28 29 29 30 //#define CRIS_HELPER_DEBUG ··· 53 54 cris_cpu_do_interrupt(cs); 54 55 } 55 56 56 - int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 57 - int mmu_idx) 57 + bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 58 + MMUAccessType access_type, int mmu_idx, 59 + bool probe, uintptr_t retaddr) 58 60 { 59 61 CRISCPU *cpu = CRIS_CPU(cs); 60 62 61 63 cs->exception_index = 0xaa; 62 64 cpu->env.pregs[PR_EDA] = address; 63 - cpu_dump_state(cs, stderr, 0); 64 - return 1; 65 + cpu_loop_exit_restore(cs, retaddr); 65 66 } 66 67 67 68 #else /* !CONFIG_USER_ONLY */ ··· 76 77 env->pregs[PR_CCS] = ccs; 77 78 } 78 79 79 - int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 80 - int mmu_idx) 80 + bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 81 + MMUAccessType access_type, int mmu_idx, 82 + bool probe, uintptr_t retaddr) 81 83 { 82 84 CRISCPU *cpu = CRIS_CPU(cs); 83 85 CPUCRISState *env = &cpu->env; 84 86 struct cris_mmu_result res; 85 87 int prot, miss; 86 - int r = -1; 87 88 target_ulong phy; 88 89 89 - qemu_log_mask(CPU_LOG_MMU, "%s addr=%" VADDR_PRIx " pc=%x rw=%x\n", 90 - __func__, address, env->pc, rw); 91 90 miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK, 92 - rw, mmu_idx, 0); 93 - if (miss) { 94 - if (cs->exception_index == EXCP_BUSFAULT) { 95 - cpu_abort(cs, 96 - "CRIS: Illegal recursive bus fault." 97 - "addr=%" VADDR_PRIx " rw=%d\n", 98 - address, rw); 99 - } 100 - 101 - env->pregs[PR_EDA] = address; 102 - cs->exception_index = EXCP_BUSFAULT; 103 - env->fault_vector = res.bf_vec; 104 - r = 1; 105 - } else { 91 + access_type, mmu_idx, 0); 92 + if (likely(!miss)) { 106 93 /* 107 94 * Mask off the cache selection bit. The ETRAX busses do not 108 95 * see the top bit. ··· 111 98 prot = res.prot; 112 99 tlb_set_page(cs, address & TARGET_PAGE_MASK, phy, 113 100 prot, mmu_idx, TARGET_PAGE_SIZE); 114 - r = 0; 101 + return true; 115 102 } 116 - if (r > 0) { 117 - qemu_log_mask(CPU_LOG_MMU, 118 - "%s returns %d irqreq=%x addr=%" VADDR_PRIx " phy=%x vec=%x" 119 - " pc=%x\n", __func__, r, cs->interrupt_request, address, 120 - res.phy, res.bf_vec, env->pc); 103 + 104 + if (probe) { 105 + return false; 121 106 } 122 - return r; 107 + 108 + if (cs->exception_index == EXCP_BUSFAULT) { 109 + cpu_abort(cs, "CRIS: Illegal recursive bus fault." 110 + "addr=%" VADDR_PRIx " access_type=%d\n", 111 + address, access_type); 112 + } 113 + 114 + env->pregs[PR_EDA] = address; 115 + cs->exception_index = EXCP_BUSFAULT; 116 + env->fault_vector = res.bf_vec; 117 + if (retaddr) { 118 + if (cpu_restore_state(cs, retaddr, true)) { 119 + /* Evaluate flags after retranslation. */ 120 + helper_top_evaluate_flags(env); 121 + } 122 + } 123 + cpu_loop_exit(cs); 123 124 } 124 125 125 126 void crisv10_cpu_do_interrupt(CPUState *cs)
-28
target/cris/op_helper.c
··· 37 37 #define D_LOG(...) do { } while (0) 38 38 #endif 39 39 40 - #if !defined(CONFIG_USER_ONLY) 41 - /* Try to fill the TLB and return an exception if error. If retaddr is 42 - NULL, it means that the function was called in C code (i.e. not 43 - from generated code or from helper.c) */ 44 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 45 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 46 - { 47 - CRISCPU *cpu = CRIS_CPU(cs); 48 - CPUCRISState *env = &cpu->env; 49 - int ret; 50 - 51 - D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__, 52 - env->pc, env->pregs[PR_EDA], (void *)retaddr); 53 - ret = cris_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 54 - if (unlikely(ret)) { 55 - if (retaddr) { 56 - /* now we have a real cpu fault */ 57 - if (cpu_restore_state(cs, retaddr, true)) { 58 - /* Evaluate flags after retranslation. */ 59 - helper_top_evaluate_flags(env); 60 - } 61 - } 62 - cpu_loop_exit(cs); 63 - } 64 - } 65 - 66 - #endif 67 - 68 40 void helper_raise_exception(CPUCRISState *env, uint32_t index) 69 41 { 70 42 CPUState *cs = CPU(cris_env_get_cpu(env));
+2 -3
target/hppa/cpu.c
··· 163 163 cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb; 164 164 cc->gdb_read_register = hppa_cpu_gdb_read_register; 165 165 cc->gdb_write_register = hppa_cpu_gdb_write_register; 166 - #ifdef CONFIG_USER_ONLY 167 - cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault; 168 - #else 166 + cc->tlb_fill = hppa_cpu_tlb_fill; 167 + #ifndef CONFIG_USER_ONLY 169 168 cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; 170 169 dc->vmsd = &vmstate_hppa_cpu; 171 170 #endif
+4 -4
target/hppa/cpu.h
··· 360 360 void hppa_cpu_do_interrupt(CPUState *cpu); 361 361 bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); 362 362 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int); 363 - #ifdef CONFIG_USER_ONLY 364 - int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, 365 - int rw, int midx); 366 - #else 363 + bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 364 + MMUAccessType access_type, int mmu_idx, 365 + bool probe, uintptr_t retaddr); 366 + #ifndef CONFIG_USER_ONLY 367 367 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, 368 368 int type, hwaddr *pphys, int *pprot); 369 369 extern const MemoryRegionOps hppa_io_eir_ops;
+11 -5
target/hppa/mem_helper.c
··· 25 25 #include "trace.h" 26 26 27 27 #ifdef CONFIG_USER_ONLY 28 - int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, 29 - int size, int rw, int mmu_idx) 28 + bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 29 + MMUAccessType access_type, int mmu_idx, 30 + bool probe, uintptr_t retaddr) 30 31 { 31 32 HPPACPU *cpu = HPPA_CPU(cs); 32 33 ··· 34 35 which would affect si_code. */ 35 36 cs->exception_index = EXCP_DMP; 36 37 cpu->env.cr[CR_IOR] = address; 37 - return 1; 38 + cpu_loop_exit_restore(cs, retaddr); 38 39 } 39 40 #else 40 41 static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr) ··· 213 214 return excp == EXCP_DTLB_MISS ? -1 : phys; 214 215 } 215 216 216 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 217 - MMUAccessType type, int mmu_idx, uintptr_t retaddr) 217 + bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 218 + MMUAccessType type, int mmu_idx, 219 + bool probe, uintptr_t retaddr) 218 220 { 219 221 HPPACPU *cpu = HPPA_CPU(cs); 220 222 CPUHPPAState *env = &cpu->env; ··· 236 238 excp = hppa_get_physical_address(env, addr, mmu_idx, 237 239 a_prot, &phys, &prot); 238 240 if (unlikely(excp >= 0)) { 241 + if (probe) { 242 + return false; 243 + } 239 244 trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx); 240 245 /* Failure. Raise the indicated exception. */ 241 246 cs->exception_index = excp; ··· 252 257 /* Success! Store the translation into the QEMU TLB. */ 253 258 tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, 254 259 prot, mmu_idx, TARGET_PAGE_SIZE); 260 + return true; 255 261 } 256 262 257 263 /* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */
+2 -3
target/i386/cpu.c
··· 5915 5915 cc->gdb_write_register = x86_cpu_gdb_write_register; 5916 5916 cc->get_arch_id = x86_cpu_get_arch_id; 5917 5917 cc->get_paging_enabled = x86_cpu_get_paging_enabled; 5918 - #ifdef CONFIG_USER_ONLY 5919 - cc->handle_mmu_fault = x86_cpu_handle_mmu_fault; 5920 - #else 5918 + #ifndef CONFIG_USER_ONLY 5921 5919 cc->asidx_from_attrs = x86_asidx_from_attrs; 5922 5920 cc->get_memory_mapping = x86_cpu_get_memory_mapping; 5923 5921 cc->get_phys_page_debug = x86_cpu_get_phys_page_debug; ··· 5942 5940 cc->cpu_exec_exit = x86_cpu_exec_exit; 5943 5941 #ifdef CONFIG_TCG 5944 5942 cc->tcg_initialize = tcg_x86_init; 5943 + cc->tlb_fill = x86_cpu_tlb_fill; 5945 5944 #endif 5946 5945 cc->disas_set_info = x86_disas_set_info; 5947 5946
+3 -2
target/i386/cpu.h
··· 1656 1656 void host_vendor_fms(char *vendor, int *family, int *model, int *stepping); 1657 1657 1658 1658 /* helper.c */ 1659 - int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr, int size, 1660 - int is_write, int mmu_idx); 1659 + bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 1660 + MMUAccessType access_type, int mmu_idx, 1661 + bool probe, uintptr_t retaddr); 1661 1662 void x86_cpu_set_a20(X86CPU *cpu, int a20_state); 1662 1663 1663 1664 #ifndef CONFIG_USER_ONLY
+31 -22
target/i386/excp_helper.c
··· 137 137 raise_interrupt2(env, exception_index, 0, 0, 0, retaddr); 138 138 } 139 139 140 - #if defined(CONFIG_USER_ONLY) 141 - int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, 142 - int is_write, int mmu_idx) 143 - { 144 - X86CPU *cpu = X86_CPU(cs); 145 - CPUX86State *env = &cpu->env; 146 - 147 - /* user mode only emulation */ 148 - is_write &= 1; 149 - env->cr[2] = addr; 150 - env->error_code = (is_write << PG_ERROR_W_BIT); 151 - env->error_code |= PG_ERROR_U_MASK; 152 - cs->exception_index = EXCP0E_PAGE; 153 - env->exception_is_int = 0; 154 - env->exception_next_eip = -1; 155 - return 1; 156 - } 157 - 158 - #else 159 - 140 + #if !defined(CONFIG_USER_ONLY) 160 141 static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, 161 142 int *prot) 162 143 { ··· 365 346 * 0 = nothing more to do 366 347 * 1 = generate PF fault 367 348 */ 368 - int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, 369 - int is_write1, int mmu_idx) 349 + static int handle_mmu_fault(CPUState *cs, vaddr addr, int size, 350 + int is_write1, int mmu_idx) 370 351 { 371 352 X86CPU *cpu = X86_CPU(cs); 372 353 CPUX86State *env = &cpu->env; ··· 691 672 return 1; 692 673 } 693 674 #endif 675 + 676 + bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 677 + MMUAccessType access_type, int mmu_idx, 678 + bool probe, uintptr_t retaddr) 679 + { 680 + X86CPU *cpu = X86_CPU(cs); 681 + CPUX86State *env = &cpu->env; 682 + 683 + #ifdef CONFIG_USER_ONLY 684 + /* user mode only emulation */ 685 + env->cr[2] = addr; 686 + env->error_code = (access_type == MMU_DATA_STORE) << PG_ERROR_W_BIT; 687 + env->error_code |= PG_ERROR_U_MASK; 688 + cs->exception_index = EXCP0E_PAGE; 689 + env->exception_is_int = 0; 690 + env->exception_next_eip = -1; 691 + cpu_loop_exit_restore(cs, retaddr); 692 + #else 693 + env->retaddr = retaddr; 694 + if (handle_mmu_fault(cs, addr, size, access_type, mmu_idx)) { 695 + /* FIXME: On error in get_hphys we have already jumped out. */ 696 + g_assert(!probe); 697 + raise_exception_err_ra(env, cs->exception_index, 698 + env->error_code, retaddr); 699 + } 700 + return true; 701 + #endif 702 + }
-21
target/i386/mem_helper.c
··· 191 191 raise_exception_ra(env, EXCP05_BOUND, GETPC()); 192 192 } 193 193 } 194 - 195 - #if !defined(CONFIG_USER_ONLY) 196 - /* try to fill the TLB and return an exception if error. If retaddr is 197 - * NULL, it means that the function was called in C code (i.e. not 198 - * from generated code or from helper.c) 199 - */ 200 - /* XXX: fix it to restore all registers */ 201 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 202 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 203 - { 204 - X86CPU *cpu = X86_CPU(cs); 205 - CPUX86State *env = &cpu->env; 206 - int ret; 207 - 208 - env->retaddr = retaddr; 209 - ret = x86_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 210 - if (ret) { 211 - raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr); 212 - } 213 - } 214 - #endif
+2 -3
target/lm32/cpu.c
··· 231 231 cc->set_pc = lm32_cpu_set_pc; 232 232 cc->gdb_read_register = lm32_cpu_gdb_read_register; 233 233 cc->gdb_write_register = lm32_cpu_gdb_write_register; 234 - #ifdef CONFIG_USER_ONLY 235 - cc->handle_mmu_fault = lm32_cpu_handle_mmu_fault; 236 - #else 234 + cc->tlb_fill = lm32_cpu_tlb_fill; 235 + #ifndef CONFIG_USER_ONLY 237 236 cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug; 238 237 cc->vmsd = &vmstate_lm32_cpu; 239 238 #endif
+3 -2
target/lm32/cpu.h
··· 261 261 #define cpu_list lm32_cpu_list 262 262 #define cpu_signal_handler cpu_lm32_signal_handler 263 263 264 - int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 265 - int mmu_idx); 264 + bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 265 + MMUAccessType access_type, int mmu_idx, 266 + bool probe, uintptr_t retaddr); 266 267 267 268 #include "exec/cpu-all.h" 268 269
+4 -4
target/lm32/helper.c
··· 25 25 #include "exec/semihost.h" 26 26 #include "exec/log.h" 27 27 28 - int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 29 - int mmu_idx) 28 + bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 29 + MMUAccessType access_type, int mmu_idx, 30 + bool probe, uintptr_t retaddr) 30 31 { 31 32 LM32CPU *cpu = LM32_CPU(cs); 32 33 CPULM32State *env = &cpu->env; ··· 40 41 } else { 41 42 tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); 42 43 } 43 - 44 - return 0; 44 + return true; 45 45 } 46 46 47 47 hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-16
target/lm32/op_helper.c
··· 143 143 { 144 144 return lm32_juart_get_jrx(env->juart_state); 145 145 } 146 - 147 - /* Try to fill the TLB and return an exception if error. If retaddr is 148 - * NULL, it means that the function was called in C code (i.e. not 149 - * from generated code or from helper.c) 150 - */ 151 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 152 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 153 - { 154 - int ret; 155 - 156 - ret = lm32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 157 - if (unlikely(ret)) { 158 - /* now we have a real cpu fault */ 159 - cpu_loop_exit_restore(cs, retaddr); 160 - } 161 - } 162 146 #endif 163 147
+1 -1
target/m68k/cpu.c
··· 269 269 cc->set_pc = m68k_cpu_set_pc; 270 270 cc->gdb_read_register = m68k_cpu_gdb_read_register; 271 271 cc->gdb_write_register = m68k_cpu_gdb_write_register; 272 - cc->handle_mmu_fault = m68k_cpu_handle_mmu_fault; 272 + cc->tlb_fill = m68k_cpu_tlb_fill; 273 273 #if defined(CONFIG_SOFTMMU) 274 274 cc->do_unassigned_access = m68k_cpu_unassigned_access; 275 275 cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
+3 -2
target/m68k/cpu.h
··· 542 542 return (env->sr & SR_S) == 0 ? 1 : 0; 543 543 } 544 544 545 - int m68k_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 546 - int mmu_idx); 545 + bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 546 + MMUAccessType access_type, int mmu_idx, 547 + bool probe, uintptr_t retaddr); 547 548 void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr, 548 549 bool is_write, bool is_exec, int is_asi, 549 550 unsigned size);
+42 -45
target/m68k/helper.c
··· 353 353 env->current_sp = new_sp; 354 354 } 355 355 356 - #if defined(CONFIG_USER_ONLY) 357 - 358 - int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 359 - int mmu_idx) 360 - { 361 - M68kCPU *cpu = M68K_CPU(cs); 362 - 363 - cs->exception_index = EXCP_ACCESS; 364 - cpu->env.mmu.ar = address; 365 - return 1; 366 - } 367 - 368 - #else 369 - 356 + #if !defined(CONFIG_USER_ONLY) 370 357 /* MMU: 68040 only */ 371 358 372 359 static void print_address_zone(uint32_t logical, uint32_t physical, ··· 795 782 return phys_addr; 796 783 } 797 784 798 - int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 799 - int mmu_idx) 785 + /* 786 + * Notify CPU of a pending interrupt. Prioritization and vectoring should 787 + * be handled by the interrupt controller. Real hardware only requests 788 + * the vector when the interrupt is acknowledged by the CPU. For 789 + * simplicity we calculate it when the interrupt is signalled. 790 + */ 791 + void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) 792 + { 793 + CPUState *cs = CPU(cpu); 794 + CPUM68KState *env = &cpu->env; 795 + 796 + env->pending_level = level; 797 + env->pending_vector = vector; 798 + if (level) { 799 + cpu_interrupt(cs, CPU_INTERRUPT_HARD); 800 + } else { 801 + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 802 + } 803 + } 804 + 805 + #endif 806 + 807 + bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 808 + MMUAccessType qemu_access_type, int mmu_idx, 809 + bool probe, uintptr_t retaddr) 800 810 { 801 811 M68kCPU *cpu = M68K_CPU(cs); 802 812 CPUM68KState *env = &cpu->env; 813 + 814 + #ifndef CONFIG_USER_ONLY 803 815 hwaddr physical; 804 816 int prot; 805 817 int access_type; ··· 812 824 address & TARGET_PAGE_MASK, 813 825 PAGE_READ | PAGE_WRITE | PAGE_EXEC, 814 826 mmu_idx, TARGET_PAGE_SIZE); 815 - return 0; 827 + return true; 816 828 } 817 829 818 - if (rw == 2) { 830 + if (qemu_access_type == MMU_INST_FETCH) { 819 831 access_type = ACCESS_CODE; 820 - rw = 0; 821 832 } else { 822 833 access_type = ACCESS_DATA; 823 - if (rw) { 834 + if (qemu_access_type == MMU_DATA_STORE) { 824 835 access_type |= ACCESS_STORE; 825 836 } 826 837 } 827 - 828 838 if (mmu_idx != MMU_USER_IDX) { 829 839 access_type |= ACCESS_SUPER; 830 840 } 831 841 832 842 ret = get_physical_address(&cpu->env, &physical, &prot, 833 843 address, access_type, &page_size); 834 - if (ret == 0) { 844 + if (likely(ret == 0)) { 835 845 address &= TARGET_PAGE_MASK; 836 846 physical += address & (page_size - 1); 837 847 tlb_set_page(cs, address, physical, 838 848 prot, mmu_idx, TARGET_PAGE_SIZE); 839 - return 0; 849 + return true; 840 850 } 851 + 852 + if (probe) { 853 + return false; 854 + } 855 + 841 856 /* page fault */ 842 857 env->mmu.ssw = M68K_ATC_040; 843 858 switch (size) { ··· 862 877 if (!(access_type & ACCESS_STORE)) { 863 878 env->mmu.ssw |= M68K_RW_040; 864 879 } 865 - env->mmu.ar = address; 866 - cs->exception_index = EXCP_ACCESS; 867 - return 1; 868 - } 869 - 870 - /* Notify CPU of a pending interrupt. Prioritization and vectoring should 871 - be handled by the interrupt controller. Real hardware only requests 872 - the vector when the interrupt is acknowledged by the CPU. For 873 - simplicitly we calculate it when the interrupt is signalled. */ 874 - void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) 875 - { 876 - CPUState *cs = CPU(cpu); 877 - CPUM68KState *env = &cpu->env; 880 + #endif 878 881 879 - env->pending_level = level; 880 - env->pending_vector = vector; 881 - if (level) { 882 - cpu_interrupt(cs, CPU_INTERRUPT_HARD); 883 - } else { 884 - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 885 - } 882 + cs->exception_index = EXCP_ACCESS; 883 + env->mmu.ar = address; 884 + cpu_loop_exit_restore(cs, retaddr); 886 885 } 887 - 888 - #endif 889 886 890 887 uint32_t HELPER(bitrev)(uint32_t x) 891 888 {
-15
target/m68k/op_helper.c
··· 36 36 37 37 #else 38 38 39 - /* Try to fill the TLB and return an exception if error. If retaddr is 40 - NULL, it means that the function was called in C code (i.e. not 41 - from generated code or from helper.c) */ 42 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 43 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 44 - { 45 - int ret; 46 - 47 - ret = m68k_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 48 - if (unlikely(ret)) { 49 - /* now we have a real cpu fault */ 50 - cpu_loop_exit_restore(cs, retaddr); 51 - } 52 - } 53 - 54 39 static void cf_rte(CPUM68KState *env) 55 40 { 56 41 uint32_t sp;
+2 -3
target/microblaze/cpu.c
··· 304 304 cc->set_pc = mb_cpu_set_pc; 305 305 cc->gdb_read_register = mb_cpu_gdb_read_register; 306 306 cc->gdb_write_register = mb_cpu_gdb_write_register; 307 - #ifdef CONFIG_USER_ONLY 308 - cc->handle_mmu_fault = mb_cpu_handle_mmu_fault; 309 - #else 307 + cc->tlb_fill = mb_cpu_tlb_fill; 308 + #ifndef CONFIG_USER_ONLY 310 309 cc->do_transaction_failed = mb_cpu_transaction_failed; 311 310 cc->get_phys_page_debug = mb_cpu_get_phys_page_debug; 312 311 #endif
+3 -2
target/microblaze/cpu.h
··· 374 374 return MMU_KERNEL_IDX; 375 375 } 376 376 377 - int mb_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 378 - int mmu_idx); 377 + bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 378 + MMUAccessType access_type, int mmu_idx, 379 + bool probe, uintptr_t retaddr); 379 380 380 381 #include "exec/cpu-all.h" 381 382
+50 -49
target/microblaze/helper.c
··· 38 38 env->regs[14] = env->sregs[SR_PC]; 39 39 } 40 40 41 - int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 42 - int mmu_idx) 41 + bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 42 + MMUAccessType access_type, int mmu_idx, 43 + bool probe, uintptr_t retaddr) 43 44 { 44 45 cs->exception_index = 0xaa; 45 - cpu_dump_state(cs, stderr, 0); 46 - return 1; 46 + cpu_loop_exit_restore(cs, retaddr); 47 47 } 48 48 49 49 #else /* !CONFIG_USER_ONLY */ 50 50 51 - int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 52 - int mmu_idx) 51 + bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 52 + MMUAccessType access_type, int mmu_idx, 53 + bool probe, uintptr_t retaddr) 53 54 { 54 55 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); 55 56 CPUMBState *env = &cpu->env; 57 + struct microblaze_mmu_lookup lu; 56 58 unsigned int hit; 57 - int r = 1; 58 59 int prot; 59 60 60 - /* Translate if the MMU is available and enabled. */ 61 - if (mmu_idx != MMU_NOMMU_IDX) { 62 - uint32_t vaddr, paddr; 63 - struct microblaze_mmu_lookup lu; 61 + if (mmu_idx == MMU_NOMMU_IDX) { 62 + /* MMU disabled or not available. */ 63 + address &= TARGET_PAGE_MASK; 64 + prot = PAGE_BITS; 65 + tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); 66 + return true; 67 + } 64 68 65 - hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx); 66 - if (hit) { 67 - vaddr = address & TARGET_PAGE_MASK; 68 - paddr = lu.paddr + vaddr - lu.vaddr; 69 + hit = mmu_translate(&env->mmu, &lu, address, access_type, mmu_idx); 70 + if (likely(hit)) { 71 + uint32_t vaddr = address & TARGET_PAGE_MASK; 72 + uint32_t paddr = lu.paddr + vaddr - lu.vaddr; 73 + 74 + qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n", 75 + mmu_idx, vaddr, paddr, lu.prot); 76 + tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); 77 + return true; 78 + } 69 79 70 - qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n", 71 - mmu_idx, vaddr, paddr, lu.prot); 72 - tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); 73 - r = 0; 74 - } else { 75 - env->sregs[SR_EAR] = address; 76 - qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", 77 - mmu_idx, address); 80 + /* TLB miss. */ 81 + if (probe) { 82 + return false; 83 + } 78 84 79 - switch (lu.err) { 80 - case ERR_PROT: 81 - env->sregs[SR_ESR] = rw == 2 ? 17 : 16; 82 - env->sregs[SR_ESR] |= (rw == 1) << 10; 83 - break; 84 - case ERR_MISS: 85 - env->sregs[SR_ESR] = rw == 2 ? 19 : 18; 86 - env->sregs[SR_ESR] |= (rw == 1) << 10; 87 - break; 88 - default: 89 - abort(); 90 - break; 91 - } 85 + qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", 86 + mmu_idx, address); 92 87 93 - if (cs->exception_index == EXCP_MMU) { 94 - cpu_abort(cs, "recursive faults\n"); 95 - } 88 + env->sregs[SR_EAR] = address; 89 + switch (lu.err) { 90 + case ERR_PROT: 91 + env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 17 : 16; 92 + env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; 93 + break; 94 + case ERR_MISS: 95 + env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 19 : 18; 96 + env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; 97 + break; 98 + default: 99 + abort(); 100 + } 96 101 97 - /* TLB miss. */ 98 - cs->exception_index = EXCP_MMU; 99 - } 100 - } else { 101 - /* MMU disabled or not available. */ 102 - address &= TARGET_PAGE_MASK; 103 - prot = PAGE_BITS; 104 - tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); 105 - r = 0; 102 + if (cs->exception_index == EXCP_MMU) { 103 + cpu_abort(cs, "recursive faults\n"); 106 104 } 107 - return r; 105 + 106 + /* TLB miss. */ 107 + cs->exception_index = EXCP_MMU; 108 + cpu_loop_exit_restore(cs, retaddr); 108 109 } 109 110 110 111 void mb_cpu_do_interrupt(CPUState *cs)
-19
target/microblaze/op_helper.c
··· 28 28 29 29 #define D(x) 30 30 31 - #if !defined(CONFIG_USER_ONLY) 32 - 33 - /* Try to fill the TLB and return an exception if error. If retaddr is 34 - * NULL, it means that the function was called in C code (i.e. not 35 - * from generated code or from helper.c) 36 - */ 37 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 38 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 39 - { 40 - int ret; 41 - 42 - ret = mb_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 43 - if (unlikely(ret)) { 44 - /* now we have a real cpu fault */ 45 - cpu_loop_exit_restore(cs, retaddr); 46 - } 47 - } 48 - #endif 49 - 50 31 void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) 51 32 { 52 33 int test = ctrl & STREAM_TEST;
+2 -3
target/mips/cpu.c
··· 197 197 cc->synchronize_from_tb = mips_cpu_synchronize_from_tb; 198 198 cc->gdb_read_register = mips_cpu_gdb_read_register; 199 199 cc->gdb_write_register = mips_cpu_gdb_write_register; 200 - #ifdef CONFIG_USER_ONLY 201 - cc->handle_mmu_fault = mips_cpu_handle_mmu_fault; 202 - #else 200 + #ifndef CONFIG_USER_ONLY 203 201 cc->do_unassigned_access = mips_cpu_unassigned_access; 204 202 cc->do_unaligned_access = mips_cpu_do_unaligned_access; 205 203 cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; ··· 208 206 cc->disas_set_info = mips_cpu_disas_set_info; 209 207 #ifdef CONFIG_TCG 210 208 cc->tcg_initialize = mips_tcg_init; 209 + cc->tlb_fill = mips_cpu_tlb_fill; 211 210 #endif 212 211 213 212 cc->gdb_num_core_regs = 73;
+35 -44
target/mips/helper.c
··· 874 874 #endif 875 875 #endif 876 876 877 - int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 878 - int mmu_idx) 877 + bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 878 + MMUAccessType access_type, int mmu_idx, 879 + bool probe, uintptr_t retaddr) 879 880 { 880 881 MIPSCPU *cpu = MIPS_CPU(cs); 881 882 CPUMIPSState *env = &cpu->env; 882 883 #if !defined(CONFIG_USER_ONLY) 883 884 hwaddr physical; 884 885 int prot; 885 - int access_type; 886 - #endif 887 - int ret = 0; 888 - 889 - #if 0 890 - log_cpu_state(cs, 0); 886 + int mips_access_type; 891 887 #endif 892 - qemu_log_mask(CPU_LOG_MMU, 893 - "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n", 894 - __func__, env->active_tc.PC, address, rw, mmu_idx); 888 + int ret = TLBRET_BADADDR; 895 889 896 890 /* data access */ 897 891 #if !defined(CONFIG_USER_ONLY) 898 892 /* XXX: put correct access by using cpu_restore_state() correctly */ 899 - access_type = ACCESS_INT; 900 - ret = get_physical_address(env, &physical, &prot, 901 - address, rw, access_type, mmu_idx); 893 + mips_access_type = ACCESS_INT; 894 + ret = get_physical_address(env, &physical, &prot, address, 895 + access_type, mips_access_type, mmu_idx); 902 896 switch (ret) { 903 897 case TLBRET_MATCH: 904 898 qemu_log_mask(CPU_LOG_MMU, ··· 915 909 tlb_set_page(cs, address & TARGET_PAGE_MASK, 916 910 physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 917 911 mmu_idx, TARGET_PAGE_SIZE); 918 - ret = 0; 919 - } else if (ret < 0) 920 - #endif 921 - { 922 - #if !defined(CONFIG_USER_ONLY) 912 + return true; 913 + } 923 914 #if !defined(TARGET_MIPS64) 924 - if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { 925 - /* 926 - * Memory reads during hardware page table walking are performed 927 - * as if they were kernel-mode load instructions. 928 - */ 929 - int mode = (env->hflags & MIPS_HFLAG_KSU); 930 - bool ret_walker; 931 - env->hflags &= ~MIPS_HFLAG_KSU; 932 - ret_walker = page_table_walk_refill(env, address, rw, mmu_idx); 933 - env->hflags |= mode; 934 - if (ret_walker) { 935 - ret = get_physical_address(env, &physical, &prot, 936 - address, rw, access_type, mmu_idx); 937 - if (ret == TLBRET_MATCH) { 938 - tlb_set_page(cs, address & TARGET_PAGE_MASK, 939 - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 940 - mmu_idx, TARGET_PAGE_SIZE); 941 - ret = 0; 942 - return ret; 943 - } 915 + if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { 916 + /* 917 + * Memory reads during hardware page table walking are performed 918 + * as if they were kernel-mode load instructions. 919 + */ 920 + int mode = (env->hflags & MIPS_HFLAG_KSU); 921 + bool ret_walker; 922 + env->hflags &= ~MIPS_HFLAG_KSU; 923 + ret_walker = page_table_walk_refill(env, address, access_type, mmu_idx); 924 + env->hflags |= mode; 925 + if (ret_walker) { 926 + ret = get_physical_address(env, &physical, &prot, address, 927 + access_type, mips_access_type, mmu_idx); 928 + if (ret == TLBRET_MATCH) { 929 + tlb_set_page(cs, address & TARGET_PAGE_MASK, 930 + physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 931 + mmu_idx, TARGET_PAGE_SIZE); 932 + return true; 944 933 } 945 934 } 935 + } 946 936 #endif 937 + if (probe) { 938 + return false; 939 + } 947 940 #endif 948 - raise_mmu_exception(env, address, rw, ret); 949 - ret = 1; 950 - } 951 941 952 - return ret; 942 + raise_mmu_exception(env, address, access_type, ret); 943 + do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); 953 944 } 954 945 955 - #if !defined(CONFIG_USER_ONLY) 946 + #ifndef CONFIG_USER_ONLY 956 947 hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) 957 948 { 958 949 hwaddr physical;
+3 -2
target/mips/internal.h
··· 202 202 void cpu_mips_stop_count(CPUMIPSState *env); 203 203 204 204 /* helper.c */ 205 - int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 206 - int mmu_idx); 205 + bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 206 + MMUAccessType access_type, int mmu_idx, 207 + bool probe, uintptr_t retaddr); 207 208 208 209 /* op_helper.c */ 209 210 uint32_t float_class_s(uint32_t arg, float_status *fst);
-15
target/mips/op_helper.c
··· 2669 2669 do_raise_exception_err(env, excp, error_code, retaddr); 2670 2670 } 2671 2671 2672 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 2673 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 2674 - { 2675 - int ret; 2676 - 2677 - ret = mips_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 2678 - if (ret) { 2679 - MIPSCPU *cpu = MIPS_CPU(cs); 2680 - CPUMIPSState *env = &cpu->env; 2681 - 2682 - do_raise_exception_err(env, cs->exception_index, 2683 - env->error_code, retaddr); 2684 - } 2685 - } 2686 - 2687 2672 void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, 2688 2673 bool is_write, bool is_exec, int unused, 2689 2674 unsigned size)
+2 -3
target/moxie/cpu.c
··· 112 112 cc->do_interrupt = moxie_cpu_do_interrupt; 113 113 cc->dump_state = moxie_cpu_dump_state; 114 114 cc->set_pc = moxie_cpu_set_pc; 115 - #ifdef CONFIG_USER_ONLY 116 - cc->handle_mmu_fault = moxie_cpu_handle_mmu_fault; 117 - #else 115 + cc->tlb_fill = moxie_cpu_tlb_fill; 116 + #ifndef CONFIG_USER_ONLY 118 117 cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug; 119 118 cc->vmsd = &vmstate_moxie_cpu; 120 119 #endif
+3 -2
target/moxie/cpu.h
··· 139 139 *flags = 0; 140 140 } 141 141 142 - int moxie_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, 143 - int rw, int mmu_idx); 142 + bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 143 + MMUAccessType access_type, int mmu_idx, 144 + bool probe, uintptr_t retaddr); 144 145 145 146 #endif /* MOXIE_CPU_H */
+13 -52
target/moxie/helper.c
··· 26 26 #include "qemu/host-utils.h" 27 27 #include "exec/helper-proto.h" 28 28 29 - /* Try to fill the TLB and return an exception if error. If retaddr is 30 - NULL, it means that the function was called in C code (i.e. not 31 - from generated code or from helper.c) */ 32 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 33 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 34 - { 35 - int ret; 36 - 37 - ret = moxie_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 38 - if (unlikely(ret)) { 39 - cpu_loop_exit_restore(cs, retaddr); 40 - } 41 - } 42 - 43 29 void helper_raise_exception(CPUMoxieState *env, int ex) 44 30 { 45 31 CPUState *cs = CPU(moxie_env_get_cpu(env)); ··· 85 71 cpu_loop_exit(cs); 86 72 } 87 73 88 - #if defined(CONFIG_USER_ONLY) 89 - 90 - void moxie_cpu_do_interrupt(CPUState *cs) 91 - { 92 - CPUState *cs = CPU(moxie_env_get_cpu(env)); 93 - 94 - cs->exception_index = -1; 95 - } 96 - 97 - int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 98 - int rw, int mmu_idx) 99 - { 100 - MoxieCPU *cpu = MOXIE_CPU(cs); 101 - 102 - cs->exception_index = 0xaa; 103 - cpu->env.debug1 = address; 104 - cpu_dump_state(cs, stderr, 0); 105 - return 1; 106 - } 107 - 108 - #else /* !CONFIG_USER_ONLY */ 109 - 110 - int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 111 - int rw, int mmu_idx) 74 + bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 75 + MMUAccessType access_type, int mmu_idx, 76 + bool probe, uintptr_t retaddr) 112 77 { 113 78 MoxieCPU *cpu = MOXIE_CPU(cs); 114 79 CPUMoxieState *env = &cpu->env; 115 80 MoxieMMUResult res; 116 81 int prot, miss; 117 - target_ulong phy; 118 - int r = 1; 119 82 120 83 address &= TARGET_PAGE_MASK; 121 84 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 122 - miss = moxie_mmu_translate(&res, env, address, rw, mmu_idx); 123 - if (miss) { 124 - /* handle the miss. */ 125 - phy = 0; 126 - cs->exception_index = MOXIE_EX_MMU_MISS; 127 - } else { 128 - phy = res.phy; 129 - r = 0; 85 + miss = moxie_mmu_translate(&res, env, address, access_type, mmu_idx); 86 + if (likely(!miss)) { 87 + tlb_set_page(cs, address, res.phy, prot, mmu_idx, TARGET_PAGE_SIZE); 88 + return true; 89 + } 90 + if (probe) { 91 + return false; 130 92 } 131 - tlb_set_page(cs, address, phy, prot, mmu_idx, TARGET_PAGE_SIZE); 132 - return r; 93 + 94 + cs->exception_index = MOXIE_EX_MMU_MISS; 95 + cpu_loop_exit_restore(cs, retaddr); 133 96 } 134 - 135 97 136 98 void moxie_cpu_do_interrupt(CPUState *cs) 137 99 { ··· 156 118 } 157 119 return phy; 158 120 } 159 - #endif
+2 -3
target/nios2/cpu.c
··· 200 200 cc->dump_state = nios2_cpu_dump_state; 201 201 cc->set_pc = nios2_cpu_set_pc; 202 202 cc->disas_set_info = nios2_cpu_disas_set_info; 203 - #ifdef CONFIG_USER_ONLY 204 - cc->handle_mmu_fault = nios2_cpu_handle_mmu_fault; 205 - #else 203 + cc->tlb_fill = nios2_cpu_tlb_fill; 204 + #ifndef CONFIG_USER_ONLY 206 205 cc->do_unaligned_access = nios2_cpu_do_unaligned_access; 207 206 cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug; 208 207 #endif
+3 -2
target/nios2/cpu.h
··· 253 253 MMU_SUPERVISOR_IDX; 254 254 } 255 255 256 - int nios2_cpu_handle_mmu_fault(CPUState *env, vaddr address, int size, 257 - int rw, int mmu_idx); 256 + bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 257 + MMUAccessType access_type, int mmu_idx, 258 + bool probe, uintptr_t retaddr); 258 259 259 260 static inline int cpu_interrupts_enabled(CPUNios2State *env) 260 261 {
+80 -90
target/nios2/helper.c
··· 38 38 env->regs[R_EA] = env->regs[R_PC] + 4; 39 39 } 40 40 41 - int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 42 - int rw, int mmu_idx) 41 + bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 42 + MMUAccessType access_type, int mmu_idx, 43 + bool probe, uintptr_t retaddr) 43 44 { 44 45 cs->exception_index = 0xaa; 45 - /* Page 0x1000 is kuser helper */ 46 - if (address < 0x1000 || address >= 0x2000) { 47 - cpu_dump_state(cs, stderr, 0); 48 - } 49 - return 1; 46 + cpu_loop_exit_restore(cs, retaddr); 50 47 } 51 48 52 49 #else /* !CONFIG_USER_ONLY */ ··· 203 200 } 204 201 } 205 202 206 - static int cpu_nios2_handle_virtual_page( 207 - CPUState *cs, target_ulong address, int rw, int mmu_idx) 208 - { 209 - Nios2CPU *cpu = NIOS2_CPU(cs); 210 - CPUNios2State *env = &cpu->env; 211 - target_ulong vaddr, paddr; 212 - Nios2MMULookup lu; 213 - unsigned int hit; 214 - hit = mmu_translate(env, &lu, address, rw, mmu_idx); 215 - if (hit) { 216 - vaddr = address & TARGET_PAGE_MASK; 217 - paddr = lu.paddr + vaddr - lu.vaddr; 218 - 219 - if (((rw == 0) && (lu.prot & PAGE_READ)) || 220 - ((rw == 1) && (lu.prot & PAGE_WRITE)) || 221 - ((rw == 2) && (lu.prot & PAGE_EXEC))) { 222 - 223 - tlb_set_page(cs, vaddr, paddr, lu.prot, 224 - mmu_idx, TARGET_PAGE_SIZE); 225 - return 0; 226 - } else { 227 - /* Permission violation */ 228 - cs->exception_index = (rw == 0) ? EXCP_TLBR : 229 - ((rw == 1) ? EXCP_TLBW : 230 - EXCP_TLBX); 231 - } 232 - } else { 233 - cs->exception_index = EXCP_TLBD; 234 - } 235 - 236 - if (rw == 2) { 237 - env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D; 238 - } else { 239 - env->regs[CR_TLBMISC] |= CR_TLBMISC_D; 240 - } 241 - env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK; 242 - env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK; 243 - env->mmu.pteaddr_wr = env->regs[CR_PTEADDR]; 244 - env->regs[CR_BADADDR] = address; 245 - return 1; 246 - } 247 - 248 - int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 249 - int rw, int mmu_idx) 250 - { 251 - Nios2CPU *cpu = NIOS2_CPU(cs); 252 - CPUNios2State *env = &cpu->env; 253 - 254 - if (cpu->mmu_present) { 255 - if (MMU_SUPERVISOR_IDX == mmu_idx) { 256 - if (address >= 0xC0000000) { 257 - /* Kernel physical page - TLB bypassed */ 258 - address &= TARGET_PAGE_MASK; 259 - tlb_set_page(cs, address, address, PAGE_BITS, 260 - mmu_idx, TARGET_PAGE_SIZE); 261 - } else if (address >= 0x80000000) { 262 - /* Kernel virtual page */ 263 - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); 264 - } else { 265 - /* User virtual page */ 266 - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); 267 - } 268 - } else { 269 - if (address >= 0x80000000) { 270 - /* Illegal access from user mode */ 271 - cs->exception_index = EXCP_SUPERA; 272 - env->regs[CR_BADADDR] = address; 273 - return 1; 274 - } else { 275 - /* User virtual page */ 276 - return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx); 277 - } 278 - } 279 - } else { 280 - /* No MMU */ 281 - address &= TARGET_PAGE_MASK; 282 - tlb_set_page(cs, address, address, PAGE_BITS, 283 - mmu_idx, TARGET_PAGE_SIZE); 284 - } 285 - 286 - return 0; 287 - } 288 - 289 203 hwaddr nios2_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 290 204 { 291 205 Nios2CPU *cpu = NIOS2_CPU(cs); ··· 320 234 env->regs[CR_BADADDR] = addr; 321 235 env->regs[CR_EXCEPTION] = EXCP_UNALIGN << 2; 322 236 helper_raise_exception(env, EXCP_UNALIGN); 237 + } 238 + 239 + bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 240 + MMUAccessType access_type, int mmu_idx, 241 + bool probe, uintptr_t retaddr) 242 + { 243 + Nios2CPU *cpu = NIOS2_CPU(cs); 244 + CPUNios2State *env = &cpu->env; 245 + unsigned int excp = EXCP_TLBD; 246 + target_ulong vaddr, paddr; 247 + Nios2MMULookup lu; 248 + unsigned int hit; 249 + 250 + if (!cpu->mmu_present) { 251 + /* No MMU */ 252 + address &= TARGET_PAGE_MASK; 253 + tlb_set_page(cs, address, address, PAGE_BITS, 254 + mmu_idx, TARGET_PAGE_SIZE); 255 + return true; 256 + } 257 + 258 + if (MMU_SUPERVISOR_IDX == mmu_idx) { 259 + if (address >= 0xC0000000) { 260 + /* Kernel physical page - TLB bypassed */ 261 + address &= TARGET_PAGE_MASK; 262 + tlb_set_page(cs, address, address, PAGE_BITS, 263 + mmu_idx, TARGET_PAGE_SIZE); 264 + return true; 265 + } 266 + } else { 267 + if (address >= 0x80000000) { 268 + /* Illegal access from user mode */ 269 + if (probe) { 270 + return false; 271 + } 272 + cs->exception_index = EXCP_SUPERA; 273 + env->regs[CR_BADADDR] = address; 274 + cpu_loop_exit_restore(cs, retaddr); 275 + } 276 + } 277 + 278 + /* Virtual page. */ 279 + hit = mmu_translate(env, &lu, address, access_type, mmu_idx); 280 + if (hit) { 281 + vaddr = address & TARGET_PAGE_MASK; 282 + paddr = lu.paddr + vaddr - lu.vaddr; 283 + 284 + if (((access_type == MMU_DATA_LOAD) && (lu.prot & PAGE_READ)) || 285 + ((access_type == MMU_DATA_STORE) && (lu.prot & PAGE_WRITE)) || 286 + ((access_type == MMU_INST_FETCH) && (lu.prot & PAGE_EXEC))) { 287 + tlb_set_page(cs, vaddr, paddr, lu.prot, 288 + mmu_idx, TARGET_PAGE_SIZE); 289 + return true; 290 + } 291 + 292 + /* Permission violation */ 293 + excp = (access_type == MMU_DATA_LOAD ? EXCP_TLBR : 294 + access_type == MMU_DATA_STORE ? EXCP_TLBW : EXCP_TLBX); 295 + } 296 + 297 + if (probe) { 298 + return false; 299 + } 300 + 301 + if (access_type == MMU_INST_FETCH) { 302 + env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D; 303 + } else { 304 + env->regs[CR_TLBMISC] |= CR_TLBMISC_D; 305 + } 306 + env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK; 307 + env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK; 308 + env->mmu.pteaddr_wr = env->regs[CR_PTEADDR]; 309 + 310 + cs->exception_index = excp; 311 + env->regs[CR_BADADDR] = address; 312 + cpu_loop_exit_restore(cs, retaddr); 323 313 } 324 314 #endif /* !CONFIG_USER_ONLY */
-12
target/nios2/mmu.c
··· 36 36 #define MMU_LOG(x) 37 37 #endif 38 38 39 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 40 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 41 - { 42 - int ret; 43 - 44 - ret = nios2_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 45 - if (unlikely(ret)) { 46 - /* now we have a real cpu fault */ 47 - cpu_loop_exit_restore(cs, retaddr); 48 - } 49 - } 50 - 51 39 void mmu_read_debug(CPUNios2State *env, uint32_t rn) 52 40 { 53 41 switch (rn) {
+2 -3
target/openrisc/cpu.c
··· 149 149 cc->set_pc = openrisc_cpu_set_pc; 150 150 cc->gdb_read_register = openrisc_cpu_gdb_read_register; 151 151 cc->gdb_write_register = openrisc_cpu_gdb_write_register; 152 - #ifdef CONFIG_USER_ONLY 153 - cc->handle_mmu_fault = openrisc_cpu_handle_mmu_fault; 154 - #else 152 + cc->tlb_fill = openrisc_cpu_tlb_fill; 153 + #ifndef CONFIG_USER_ONLY 155 154 cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug; 156 155 dc->vmsd = &vmstate_openrisc_cpu; 157 156 #endif
+3 -2
target/openrisc/cpu.h
··· 344 344 int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); 345 345 int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); 346 346 void openrisc_translate_init(void); 347 - int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, 348 - int rw, int mmu_idx); 347 + bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 348 + MMUAccessType access_type, int mmu_idx, 349 + bool probe, uintptr_t retaddr); 349 350 int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc); 350 351 int print_insn_or1k(bfd_vma addr, disassemble_info *info); 351 352
+33 -36
target/openrisc/mmu.c
··· 107 107 cpu->env.lock_addr = -1; 108 108 } 109 109 110 - int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 111 - int rw, int mmu_idx) 110 + bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 111 + MMUAccessType access_type, int mmu_idx, 112 + bool probe, uintptr_t retaddr) 112 113 { 113 - #ifdef CONFIG_USER_ONLY 114 114 OpenRISCCPU *cpu = OPENRISC_CPU(cs); 115 - raise_mmu_exception(cpu, address, EXCP_DPF); 116 - return 1; 117 - #else 118 - g_assert_not_reached(); 115 + int excp = EXCP_DPF; 116 + 117 + #ifndef CONFIG_USER_ONLY 118 + int prot; 119 + hwaddr phys_addr; 120 + 121 + if (mmu_idx == MMU_NOMMU_IDX) { 122 + /* The mmu is disabled; lookups never fail. */ 123 + get_phys_nommu(&phys_addr, &prot, addr); 124 + excp = 0; 125 + } else { 126 + bool super = mmu_idx == MMU_SUPERVISOR_IDX; 127 + int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC 128 + : access_type == MMU_DATA_STORE ? PAGE_WRITE 129 + : PAGE_READ); 130 + excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super); 131 + } 132 + 133 + if (likely(excp == 0)) { 134 + tlb_set_page(cs, addr & TARGET_PAGE_MASK, 135 + phys_addr & TARGET_PAGE_MASK, prot, 136 + mmu_idx, TARGET_PAGE_SIZE); 137 + return true; 138 + } 139 + if (probe) { 140 + return false; 141 + } 119 142 #endif 143 + 144 + raise_mmu_exception(cpu, addr, excp); 145 + cpu_loop_exit_restore(cs, retaddr); 120 146 } 121 147 122 148 #ifndef CONFIG_USER_ONLY ··· 151 177 get_phys_nommu(&phys_addr, &prot, addr); 152 178 return phys_addr; 153 179 } 154 - } 155 - 156 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 157 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 158 - { 159 - OpenRISCCPU *cpu = OPENRISC_CPU(cs); 160 - int prot, excp; 161 - hwaddr phys_addr; 162 - 163 - if (mmu_idx == MMU_NOMMU_IDX) { 164 - /* The mmu is disabled; lookups never fail. */ 165 - get_phys_nommu(&phys_addr, &prot, addr); 166 - excp = 0; 167 - } else { 168 - bool super = mmu_idx == MMU_SUPERVISOR_IDX; 169 - int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC 170 - : access_type == MMU_DATA_STORE ? PAGE_WRITE 171 - : PAGE_READ); 172 - excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super); 173 - } 174 - 175 - if (unlikely(excp)) { 176 - raise_mmu_exception(cpu, addr, excp); 177 - cpu_loop_exit_restore(cs, retaddr); 178 - } 179 - 180 - tlb_set_page(cs, addr & TARGET_PAGE_MASK, 181 - phys_addr & TARGET_PAGE_MASK, prot, 182 - mmu_idx, TARGET_PAGE_SIZE); 183 180 } 184 181 #endif
+3 -4
target/ppc/cpu.h
··· 1311 1311 * is returned if the signal was handled by the virtual CPU. 1312 1312 */ 1313 1313 int cpu_ppc_signal_handler(int host_signum, void *pinfo, void *puc); 1314 - #if defined(CONFIG_USER_ONLY) 1315 - int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 1316 - int mmu_idx); 1317 - #endif 1314 + bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 1315 + MMUAccessType access_type, int mmu_idx, 1316 + bool probe, uintptr_t retaddr); 1318 1317 1319 1318 #if !defined(CONFIG_USER_ONLY) 1320 1319 void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
+7 -9
target/ppc/mmu_helper.c
··· 3057 3057 3058 3058 /*****************************************************************************/ 3059 3059 3060 - /* 3061 - * try to fill the TLB and return an exception if error. If retaddr is 3062 - * NULL, it means that the function was called in C code (i.e. not 3063 - * from generated code or from helper.c) 3064 - * 3065 - * XXX: fix it to restore all registers 3066 - */ 3067 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 3068 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 3060 + bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 3061 + MMUAccessType access_type, int mmu_idx, 3062 + bool probe, uintptr_t retaddr) 3069 3063 { 3070 3064 PowerPCCPU *cpu = POWERPC_CPU(cs); 3071 3065 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); ··· 3078 3072 ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx); 3079 3073 } 3080 3074 if (unlikely(ret != 0)) { 3075 + if (probe) { 3076 + return false; 3077 + } 3081 3078 raise_exception_err_ra(env, cs->exception_index, env->error_code, 3082 3079 retaddr); 3083 3080 } 3081 + return true; 3084 3082 }
+2 -3
target/ppc/translate_init.inc.c
··· 10592 10592 cc->gdb_read_register = ppc_cpu_gdb_read_register; 10593 10593 cc->gdb_write_register = ppc_cpu_gdb_write_register; 10594 10594 cc->do_unaligned_access = ppc_cpu_do_unaligned_access; 10595 - #ifdef CONFIG_USER_ONLY 10596 - cc->handle_mmu_fault = ppc_cpu_handle_mmu_fault; 10597 - #else 10595 + #ifndef CONFIG_USER_ONLY 10598 10596 cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; 10599 10597 cc->vmsd = &vmstate_ppc_cpu; 10600 10598 #endif ··· 10624 10622 #endif 10625 10623 #ifdef CONFIG_TCG 10626 10624 cc->tcg_initialize = ppc_translate_init; 10625 + cc->tlb_fill = ppc_cpu_tlb_fill; 10627 10626 #endif 10628 10627 cc->disas_set_info = ppc_disas_set_info; 10629 10628
+8 -6
target/ppc/user_only_helper.c
··· 20 20 21 21 #include "qemu/osdep.h" 22 22 #include "cpu.h" 23 + #include "exec/exec-all.h" 23 24 24 - int ppc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 25 - int mmu_idx) 25 + 26 + bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 27 + MMUAccessType access_type, int mmu_idx, 28 + bool probe, uintptr_t retaddr) 26 29 { 27 30 PowerPCCPU *cpu = POWERPC_CPU(cs); 28 31 CPUPPCState *env = &cpu->env; 29 32 int exception, error_code; 30 33 31 - if (rw == 2) { 34 + if (access_type == MMU_INST_FETCH) { 32 35 exception = POWERPC_EXCP_ISI; 33 36 error_code = 0x40000000; 34 37 } else { 35 38 exception = POWERPC_EXCP_DSI; 36 39 error_code = 0x40000000; 37 - if (rw) { 40 + if (access_type == MMU_DATA_STORE) { 38 41 error_code |= 0x02000000; 39 42 } 40 43 env->spr[SPR_DAR] = address; ··· 42 45 } 43 46 cs->exception_index = exception; 44 47 env->error_code = error_code; 45 - 46 - return 1; 48 + cpu_loop_exit_restore(cs, retaddr); 47 49 }
+2 -3
target/riscv/cpu.c
··· 355 355 #endif 356 356 cc->gdb_stop_before_watchpoint = true; 357 357 cc->disas_set_info = riscv_cpu_disas_set_info; 358 - #ifdef CONFIG_USER_ONLY 359 - cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault; 360 - #else 358 + #ifndef CONFIG_USER_ONLY 361 359 cc->do_unaligned_access = riscv_cpu_do_unaligned_access; 362 360 cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; 363 361 #endif 364 362 #ifdef CONFIG_TCG 365 363 cc->tcg_initialize = riscv_translate_init; 364 + cc->tlb_fill = riscv_cpu_tlb_fill; 366 365 #endif 367 366 /* For now, mark unmigratable: */ 368 367 cc->vmsd = &vmstate_riscv_cpu;
+3 -2
target/riscv/cpu.h
··· 261 261 void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, 262 262 MMUAccessType access_type, int mmu_idx, 263 263 uintptr_t retaddr); 264 - int riscv_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, 265 - int rw, int mmu_idx); 264 + bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 265 + MMUAccessType access_type, int mmu_idx, 266 + bool probe, uintptr_t retaddr); 266 267 char *riscv_isa_string(RISCVCPU *cpu); 267 268 void riscv_cpu_list(void); 268 269
+20 -30
target/riscv/cpu_helper.c
··· 378 378 env->badaddr = addr; 379 379 riscv_raise_exception(env, cs->exception_index, retaddr); 380 380 } 381 - 382 - /* called by qemu's softmmu to fill the qemu tlb */ 383 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 384 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 385 - { 386 - int ret; 387 - ret = riscv_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 388 - if (ret == TRANSLATE_FAIL) { 389 - RISCVCPU *cpu = RISCV_CPU(cs); 390 - CPURISCVState *env = &cpu->env; 391 - riscv_raise_exception(env, cs->exception_index, retaddr); 392 - } 393 - } 394 - 395 381 #endif 396 382 397 - int riscv_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 398 - int rw, int mmu_idx) 383 + bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 384 + MMUAccessType access_type, int mmu_idx, 385 + bool probe, uintptr_t retaddr) 399 386 { 387 + #ifndef CONFIG_USER_ONLY 400 388 RISCVCPU *cpu = RISCV_CPU(cs); 401 389 CPURISCVState *env = &cpu->env; 402 - #if !defined(CONFIG_USER_ONLY) 403 390 hwaddr pa = 0; 404 391 int prot; 405 - #endif 406 392 int ret = TRANSLATE_FAIL; 407 393 408 - qemu_log_mask(CPU_LOG_MMU, 409 - "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx \ 410 - %d\n", __func__, env->pc, address, rw, mmu_idx); 394 + qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n", 395 + __func__, address, access_type, mmu_idx); 396 + 397 + ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx); 411 398 412 - #if !defined(CONFIG_USER_ONLY) 413 - ret = get_physical_address(env, &pa, &prot, address, rw, mmu_idx); 414 399 qemu_log_mask(CPU_LOG_MMU, 415 - "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx 416 - " prot %d\n", __func__, address, ret, pa, prot); 400 + "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx 401 + " prot %d\n", __func__, address, ret, pa, prot); 402 + 417 403 if (riscv_feature(env, RISCV_FEATURE_PMP) && 418 - !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << rw)) { 404 + !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { 419 405 ret = TRANSLATE_FAIL; 420 406 } 421 407 if (ret == TRANSLATE_SUCCESS) { 422 408 tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, 423 409 prot, mmu_idx, TARGET_PAGE_SIZE); 424 - } else if (ret == TRANSLATE_FAIL) { 425 - raise_mmu_exception(env, address, rw); 410 + return true; 411 + } else if (probe) { 412 + return false; 413 + } else { 414 + raise_mmu_exception(env, address, access_type); 415 + riscv_raise_exception(env, cs->exception_index, retaddr); 426 416 } 427 417 #else 428 - switch (rw) { 418 + switch (access_type) { 429 419 case MMU_INST_FETCH: 430 420 cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT; 431 421 break; ··· 436 426 cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT; 437 427 break; 438 428 } 429 + cpu_loop_exit_restore(cs, retaddr); 439 430 #endif 440 - return ret; 441 431 } 442 432 443 433 /*
+2 -3
target/s390x/cpu.c
··· 478 478 cc->set_pc = s390_cpu_set_pc; 479 479 cc->gdb_read_register = s390_cpu_gdb_read_register; 480 480 cc->gdb_write_register = s390_cpu_gdb_write_register; 481 - #ifdef CONFIG_USER_ONLY 482 - cc->handle_mmu_fault = s390_cpu_handle_mmu_fault; 483 - #else 481 + #ifndef CONFIG_USER_ONLY 484 482 cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; 485 483 cc->vmsd = &vmstate_s390_cpu; 486 484 cc->write_elf64_note = s390_cpu_write_elf64_note; ··· 493 491 cc->disas_set_info = s390_cpu_disas_set_info; 494 492 #ifdef CONFIG_TCG 495 493 cc->tcg_initialize = s390x_translate_init; 494 + cc->tlb_fill = s390_cpu_tlb_fill; 496 495 #endif 497 496 498 497 cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
+44 -23
target/s390x/excp_helper.c
··· 74 74 cs->exception_index = -1; 75 75 } 76 76 77 - int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 78 - int rw, int mmu_idx) 77 + bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 78 + MMUAccessType access_type, int mmu_idx, 79 + bool probe, uintptr_t retaddr) 79 80 { 80 81 S390CPU *cpu = S390_CPU(cs); 81 82 ··· 83 84 /* On real machines this value is dropped into LowMem. Since this 84 85 is userland, simply put this someplace that cpu_loop can find it. */ 85 86 cpu->env.__excp_addr = address; 86 - return 1; 87 + cpu_loop_exit_restore(cs, retaddr); 87 88 } 88 89 89 90 #else /* !CONFIG_USER_ONLY */ ··· 102 103 } 103 104 } 104 105 105 - int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size, 106 - int rw, int mmu_idx) 106 + bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 107 + MMUAccessType access_type, int mmu_idx, 108 + bool probe, uintptr_t retaddr) 107 109 { 108 110 S390CPU *cpu = S390_CPU(cs); 109 111 CPUS390XState *env = &cpu->env; 110 112 target_ulong vaddr, raddr; 111 113 uint64_t asc; 112 - int prot; 114 + int prot, fail; 113 115 114 116 qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", 115 - __func__, orig_vaddr, rw, mmu_idx); 117 + __func__, address, access_type, mmu_idx); 116 118 117 - vaddr = orig_vaddr; 119 + vaddr = address; 118 120 119 121 if (mmu_idx < MMU_REAL_IDX) { 120 122 asc = cpu_mmu_idx_to_asc(mmu_idx); ··· 122 124 if (!(env->psw.mask & PSW_MASK_64)) { 123 125 vaddr &= 0x7fffffff; 124 126 } 125 - if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) { 126 - return 1; 127 - } 127 + fail = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, true); 128 128 } else if (mmu_idx == MMU_REAL_IDX) { 129 129 /* 31-Bit mode */ 130 130 if (!(env->psw.mask & PSW_MASK_64)) { 131 131 vaddr &= 0x7fffffff; 132 132 } 133 - if (mmu_translate_real(env, vaddr, rw, &raddr, &prot)) { 134 - return 1; 135 - } 133 + fail = mmu_translate_real(env, vaddr, access_type, &raddr, &prot); 136 134 } else { 137 - abort(); 135 + g_assert_not_reached(); 138 136 } 139 137 140 138 /* check out of RAM access */ 141 - if (!address_space_access_valid(&address_space_memory, raddr, 142 - TARGET_PAGE_SIZE, rw, 139 + if (!fail && 140 + !address_space_access_valid(&address_space_memory, raddr, 141 + TARGET_PAGE_SIZE, access_type, 143 142 MEMTXATTRS_UNSPECIFIED)) { 144 143 qemu_log_mask(CPU_LOG_MMU, 145 144 "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", 146 145 __func__, (uint64_t)raddr, (uint64_t)ram_size); 147 146 trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO); 148 - return 1; 147 + fail = 1; 148 + } 149 + 150 + if (!fail) { 151 + qemu_log_mask(CPU_LOG_MMU, 152 + "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", 153 + __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); 154 + tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot, 155 + mmu_idx, TARGET_PAGE_SIZE); 156 + return true; 157 + } 158 + if (probe) { 159 + return false; 149 160 } 150 161 151 - qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", 152 - __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); 162 + cpu_restore_state(cs, retaddr, true); 153 163 154 - tlb_set_page(cs, orig_vaddr & TARGET_PAGE_MASK, raddr, prot, 155 - mmu_idx, TARGET_PAGE_SIZE); 164 + /* 165 + * The ILC value for code accesses is undefined. The important 166 + * thing here is to *not* leave env->int_pgm_ilen set to ILEN_AUTO, 167 + * which would cause do_program_interrupt to attempt to read from 168 + * env->psw.addr again. C.f. the condition in trigger_page_fault, 169 + * but is not universally applied. 170 + * 171 + * ??? If we remove ILEN_AUTO, by moving the computation of ILEN 172 + * into cpu_restore_state, then we may remove this entirely. 173 + */ 174 + if (access_type == MMU_INST_FETCH) { 175 + env->int_pgm_ilen = 2; 176 + } 156 177 157 - return 0; 178 + cpu_loop_exit(cs); 158 179 } 159 180 160 181 static void do_program_interrupt(CPUS390XState *env)
+3 -2
target/s390x/internal.h
··· 263 263 void s390x_cpu_debug_excp_handler(CPUState *cs); 264 264 void s390_cpu_do_interrupt(CPUState *cpu); 265 265 bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req); 266 - int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 267 - int mmu_idx); 266 + bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 267 + MMUAccessType access_type, int mmu_idx, 268 + bool probe, uintptr_t retaddr); 268 269 void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, 269 270 MMUAccessType access_type, 270 271 int mmu_idx, uintptr_t retaddr);
-16
target/s390x/mem_helper.c
··· 33 33 34 34 /*****************************************************************************/ 35 35 /* Softmmu support */ 36 - #if !defined(CONFIG_USER_ONLY) 37 - 38 - /* try to fill the TLB and return an exception if error. If retaddr is 39 - NULL, it means that the function was called in C code (i.e. not 40 - from generated code or from helper.c) */ 41 - /* XXX: fix it to restore all registers */ 42 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 43 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 44 - { 45 - int ret = s390_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 46 - if (unlikely(ret != 0)) { 47 - cpu_loop_exit_restore(cs, retaddr); 48 - } 49 - } 50 - 51 - #endif 52 36 53 37 /* #define DEBUG_HELPER */ 54 38 #ifdef DEBUG_HELPER
+2 -3
target/sh4/cpu.c
··· 229 229 cc->synchronize_from_tb = superh_cpu_synchronize_from_tb; 230 230 cc->gdb_read_register = superh_cpu_gdb_read_register; 231 231 cc->gdb_write_register = superh_cpu_gdb_write_register; 232 - #ifdef CONFIG_USER_ONLY 233 - cc->handle_mmu_fault = superh_cpu_handle_mmu_fault; 234 - #else 232 + cc->tlb_fill = superh_cpu_tlb_fill; 233 + #ifndef CONFIG_USER_ONLY 235 234 cc->do_unaligned_access = superh_cpu_do_unaligned_access; 236 235 cc->get_phys_page_debug = superh_cpu_get_phys_page_debug; 237 236 #endif
+3 -2
target/sh4/cpu.h
··· 243 243 void sh4_translate_init(void); 244 244 int cpu_sh4_signal_handler(int host_signum, void *pinfo, 245 245 void *puc); 246 - int superh_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 247 - int mmu_idx); 246 + bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 247 + MMUAccessType access_type, int mmu_idx, 248 + bool probe, uintptr_t retaddr); 248 249 249 250 void sh4_cpu_list(void); 250 251 #if !defined(CONFIG_USER_ONLY)
+88 -101
target/sh4/helper.c
··· 27 27 #include "hw/sh4/sh_intc.h" 28 28 #endif 29 29 30 - #if defined(CONFIG_USER_ONLY) 31 - 32 - void superh_cpu_do_interrupt(CPUState *cs) 33 - { 34 - cs->exception_index = -1; 35 - } 36 - 37 - int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 38 - int mmu_idx) 39 - { 40 - SuperHCPU *cpu = SUPERH_CPU(cs); 41 - CPUSH4State *env = &cpu->env; 42 - 43 - env->tea = address; 44 - cs->exception_index = -1; 45 - switch (rw) { 46 - case 0: 47 - cs->exception_index = 0x0a0; 48 - break; 49 - case 1: 50 - cs->exception_index = 0x0c0; 51 - break; 52 - case 2: 53 - cs->exception_index = 0x0a0; 54 - break; 55 - } 56 - return 1; 57 - } 58 - 59 - int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) 60 - { 61 - /* For user mode, only U0 area is cacheable. */ 62 - return !(addr & 0x80000000); 63 - } 64 - 65 - #else /* !CONFIG_USER_ONLY */ 66 - 67 30 #define MMU_OK 0 68 31 #define MMU_ITLB_MISS (-1) 69 32 #define MMU_ITLB_MULTIPLE (-2) ··· 78 41 #define MMU_IADDR_ERROR (-11) 79 42 #define MMU_DADDR_ERROR_READ (-12) 80 43 #define MMU_DADDR_ERROR_WRITE (-13) 44 + 45 + #if defined(CONFIG_USER_ONLY) 46 + 47 + void superh_cpu_do_interrupt(CPUState *cs) 48 + { 49 + cs->exception_index = -1; 50 + } 51 + 52 + int cpu_sh4_is_cached(CPUSH4State *env, target_ulong addr) 53 + { 54 + /* For user mode, only U0 area is cacheable. */ 55 + return !(addr & 0x80000000); 56 + } 57 + 58 + #else /* !CONFIG_USER_ONLY */ 81 59 82 60 void superh_cpu_do_interrupt(CPUState *cs) 83 61 { ··· 458 436 return get_mmu_address(env, physical, prot, address, rw, access_type); 459 437 } 460 438 461 - int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 462 - int mmu_idx) 463 - { 464 - SuperHCPU *cpu = SUPERH_CPU(cs); 465 - CPUSH4State *env = &cpu->env; 466 - target_ulong physical; 467 - int prot, ret, access_type; 468 - 469 - access_type = ACCESS_INT; 470 - ret = 471 - get_physical_address(env, &physical, &prot, address, rw, 472 - access_type); 473 - 474 - if (ret != MMU_OK) { 475 - env->tea = address; 476 - if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) { 477 - env->pteh = (env->pteh & PTEH_ASID_MASK) | 478 - (address & PTEH_VPN_MASK); 479 - } 480 - switch (ret) { 481 - case MMU_ITLB_MISS: 482 - case MMU_DTLB_MISS_READ: 483 - cs->exception_index = 0x040; 484 - break; 485 - case MMU_DTLB_MULTIPLE: 486 - case MMU_ITLB_MULTIPLE: 487 - cs->exception_index = 0x140; 488 - break; 489 - case MMU_ITLB_VIOLATION: 490 - cs->exception_index = 0x0a0; 491 - break; 492 - case MMU_DTLB_MISS_WRITE: 493 - cs->exception_index = 0x060; 494 - break; 495 - case MMU_DTLB_INITIAL_WRITE: 496 - cs->exception_index = 0x080; 497 - break; 498 - case MMU_DTLB_VIOLATION_READ: 499 - cs->exception_index = 0x0a0; 500 - break; 501 - case MMU_DTLB_VIOLATION_WRITE: 502 - cs->exception_index = 0x0c0; 503 - break; 504 - case MMU_IADDR_ERROR: 505 - case MMU_DADDR_ERROR_READ: 506 - cs->exception_index = 0x0e0; 507 - break; 508 - case MMU_DADDR_ERROR_WRITE: 509 - cs->exception_index = 0x100; 510 - break; 511 - default: 512 - cpu_abort(cs, "Unhandled MMU fault"); 513 - } 514 - return 1; 515 - } 516 - 517 - address &= TARGET_PAGE_MASK; 518 - physical &= TARGET_PAGE_MASK; 519 - 520 - tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); 521 - return 0; 522 - } 523 - 524 439 hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 525 440 { 526 441 SuperHCPU *cpu = SUPERH_CPU(cs); ··· 745 660 if (needs_tlb_flush) { 746 661 tlb_flush_page(CPU(sh_env_get_cpu(s)), vpn << 10); 747 662 } 748 - 749 663 } else { 750 664 int index = (addr & 0x00003f00) >> 8; 751 665 tlb_t * entry = &s->utlb[index]; ··· 885 799 } 886 800 return false; 887 801 } 802 + 803 + bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 804 + MMUAccessType access_type, int mmu_idx, 805 + bool probe, uintptr_t retaddr) 806 + { 807 + SuperHCPU *cpu = SUPERH_CPU(cs); 808 + CPUSH4State *env = &cpu->env; 809 + int ret; 810 + 811 + #ifdef CONFIG_USER_ONLY 812 + ret = (access_type == MMU_DATA_STORE ? MMU_DTLB_VIOLATION_WRITE : 813 + access_type == MMU_INST_FETCH ? MMU_ITLB_VIOLATION : 814 + MMU_DTLB_VIOLATION_READ); 815 + #else 816 + target_ulong physical; 817 + int prot, sh_access_type; 818 + 819 + sh_access_type = ACCESS_INT; 820 + ret = get_physical_address(env, &physical, &prot, address, 821 + access_type, sh_access_type); 822 + 823 + if (ret == MMU_OK) { 824 + address &= TARGET_PAGE_MASK; 825 + physical &= TARGET_PAGE_MASK; 826 + tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); 827 + return true; 828 + } 829 + if (probe) { 830 + return false; 831 + } 832 + 833 + if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) { 834 + env->pteh = (env->pteh & PTEH_ASID_MASK) | (address & PTEH_VPN_MASK); 835 + } 836 + #endif 837 + 838 + env->tea = address; 839 + switch (ret) { 840 + case MMU_ITLB_MISS: 841 + case MMU_DTLB_MISS_READ: 842 + cs->exception_index = 0x040; 843 + break; 844 + case MMU_DTLB_MULTIPLE: 845 + case MMU_ITLB_MULTIPLE: 846 + cs->exception_index = 0x140; 847 + break; 848 + case MMU_ITLB_VIOLATION: 849 + cs->exception_index = 0x0a0; 850 + break; 851 + case MMU_DTLB_MISS_WRITE: 852 + cs->exception_index = 0x060; 853 + break; 854 + case MMU_DTLB_INITIAL_WRITE: 855 + cs->exception_index = 0x080; 856 + break; 857 + case MMU_DTLB_VIOLATION_READ: 858 + cs->exception_index = 0x0a0; 859 + break; 860 + case MMU_DTLB_VIOLATION_WRITE: 861 + cs->exception_index = 0x0c0; 862 + break; 863 + case MMU_IADDR_ERROR: 864 + case MMU_DADDR_ERROR_READ: 865 + cs->exception_index = 0x0e0; 866 + break; 867 + case MMU_DADDR_ERROR_WRITE: 868 + cs->exception_index = 0x100; 869 + break; 870 + default: 871 + cpu_abort(cs, "Unhandled MMU fault"); 872 + } 873 + cpu_loop_exit_restore(cs, retaddr); 874 + }
-12
target/sh4/op_helper.c
··· 41 41 cpu_loop_exit_restore(cs, retaddr); 42 42 } 43 43 44 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 45 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 46 - { 47 - int ret; 48 - 49 - ret = superh_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 50 - if (ret) { 51 - /* now we have a real cpu fault */ 52 - cpu_loop_exit_restore(cs, retaddr); 53 - } 54 - } 55 - 56 44 #endif 57 45 58 46 void helper_ldtlb(CPUSH4State *env)
+2 -3
target/sparc/cpu.c
··· 875 875 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; 876 876 cc->gdb_read_register = sparc_cpu_gdb_read_register; 877 877 cc->gdb_write_register = sparc_cpu_gdb_write_register; 878 - #ifdef CONFIG_USER_ONLY 879 - cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault; 880 - #else 878 + cc->tlb_fill = sparc_cpu_tlb_fill; 879 + #ifndef CONFIG_USER_ONLY 881 880 cc->do_unassigned_access = sparc_cpu_unassigned_access; 882 881 cc->do_unaligned_access = sparc_cpu_do_unaligned_access; 883 882 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
+3 -2
target/sparc/cpu.h
··· 579 579 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu); 580 580 void sparc_cpu_list(void); 581 581 /* mmu_helper.c */ 582 - int sparc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 583 - int mmu_idx); 582 + bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 583 + MMUAccessType access_type, int mmu_idx, 584 + bool probe, uintptr_t retaddr); 584 585 target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev); 585 586 void dump_mmu(CPUSPARCState *env); 586 587
-15
target/sparc/ldst_helper.c
··· 1924 1924 #endif 1925 1925 cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr); 1926 1926 } 1927 - 1928 - /* try to fill the TLB and return an exception if error. If retaddr is 1929 - NULL, it means that the function was called in C code (i.e. not 1930 - from generated code or from helper.c) */ 1931 - /* XXX: fix it to restore all registers */ 1932 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 1933 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 1934 - { 1935 - int ret; 1936 - 1937 - ret = sparc_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 1938 - if (ret) { 1939 - cpu_loop_exit_restore(cs, retaddr); 1940 - } 1941 - } 1942 1927 #endif
+37 -21
target/sparc/mmu_helper.c
··· 27 27 28 28 #if defined(CONFIG_USER_ONLY) 29 29 30 - int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 31 - int mmu_idx) 30 + bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 31 + MMUAccessType access_type, int mmu_idx, 32 + bool probe, uintptr_t retaddr) 32 33 { 33 34 SPARCCPU *cpu = SPARC_CPU(cs); 34 35 CPUSPARCState *env = &cpu->env; 35 36 36 - if (rw & 2) { 37 + if (access_type == MMU_INST_FETCH) { 37 38 cs->exception_index = TT_TFAULT; 38 39 } else { 39 40 cs->exception_index = TT_DFAULT; ··· 43 44 env->mmuregs[4] = address; 44 45 #endif 45 46 } 46 - return 1; 47 + cpu_loop_exit_restore(cs, retaddr); 47 48 } 48 49 49 50 #else ··· 208 209 } 209 210 210 211 /* Perform address translation */ 211 - int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 212 - int mmu_idx) 212 + bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 213 + MMUAccessType access_type, int mmu_idx, 214 + bool probe, uintptr_t retaddr) 213 215 { 214 216 SPARCCPU *cpu = SPARC_CPU(cs); 215 217 CPUSPARCState *env = &cpu->env; ··· 218 220 target_ulong page_size; 219 221 int error_code = 0, prot, access_index; 220 222 223 + /* 224 + * TODO: If we ever need tlb_vaddr_to_host for this target, 225 + * then we must figure out how to manipulate FSR and FAR 226 + * when both MMU_NF and probe are set. In the meantime, 227 + * do not support this use case. 228 + */ 229 + assert(!probe); 230 + 221 231 address &= TARGET_PAGE_MASK; 222 232 error_code = get_physical_address(env, &paddr, &prot, &access_index, 223 - address, rw, mmu_idx, &page_size); 233 + address, access_type, 234 + mmu_idx, &page_size); 224 235 vaddr = address; 225 - if (error_code == 0) { 236 + if (likely(error_code == 0)) { 226 237 qemu_log_mask(CPU_LOG_MMU, 227 - "Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr " 228 - TARGET_FMT_lx "\n", address, paddr, vaddr); 238 + "Translate at %" VADDR_PRIx " -> " 239 + TARGET_FMT_plx ", vaddr " TARGET_FMT_lx "\n", 240 + address, paddr, vaddr); 229 241 tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size); 230 - return 0; 242 + return true; 231 243 } 232 244 233 245 if (env->mmuregs[3]) { /* Fault status register */ ··· 243 255 switching to normal mode. */ 244 256 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 245 257 tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE); 246 - return 0; 258 + return true; 247 259 } else { 248 - if (rw & 2) { 260 + if (access_type == MMU_INST_FETCH) { 249 261 cs->exception_index = TT_TFAULT; 250 262 } else { 251 263 cs->exception_index = TT_DFAULT; 252 264 } 253 - return 1; 265 + cpu_loop_exit_restore(cs, retaddr); 254 266 } 255 267 } 256 268 ··· 713 725 } 714 726 715 727 /* Perform address translation */ 716 - int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 717 - int mmu_idx) 728 + bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 729 + MMUAccessType access_type, int mmu_idx, 730 + bool probe, uintptr_t retaddr) 718 731 { 719 732 SPARCCPU *cpu = SPARC_CPU(cs); 720 733 CPUSPARCState *env = &cpu->env; ··· 725 738 726 739 address &= TARGET_PAGE_MASK; 727 740 error_code = get_physical_address(env, &paddr, &prot, &access_index, 728 - address, rw, mmu_idx, &page_size); 729 - if (error_code == 0) { 741 + address, access_type, 742 + mmu_idx, &page_size); 743 + if (likely(error_code == 0)) { 730 744 vaddr = address; 731 745 732 746 trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl, ··· 734 748 env->dmmu.mmu_secondary_context); 735 749 736 750 tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size); 737 - return 0; 751 + return true; 738 752 } 739 - /* XXX */ 740 - return 1; 753 + if (probe) { 754 + return false; 755 + } 756 + cpu_loop_exit_restore(cs, retaddr); 741 757 } 742 758 743 759 void dump_mmu(CPUSPARCState *env)
+6 -4
target/tilegx/cpu.c
··· 25 25 #include "hw/qdev-properties.h" 26 26 #include "linux-user/syscall_defs.h" 27 27 #include "qemu/qemu-print.h" 28 + #include "exec/exec-all.h" 28 29 29 30 static void tilegx_cpu_dump_state(CPUState *cs, FILE *f, int flags) 30 31 { ··· 111 112 cs->exception_index = -1; 112 113 } 113 114 114 - static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 115 - int rw, int mmu_idx) 115 + static bool tilegx_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 116 + MMUAccessType access_type, int mmu_idx, 117 + bool probe, uintptr_t retaddr) 116 118 { 117 119 TileGXCPU *cpu = TILEGX_CPU(cs); 118 120 ··· 122 124 cpu->env.signo = TARGET_SIGSEGV; 123 125 cpu->env.sigcode = 0; 124 126 125 - return 1; 127 + cpu_loop_exit_restore(cs, retaddr); 126 128 } 127 129 128 130 static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ··· 152 154 cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt; 153 155 cc->dump_state = tilegx_cpu_dump_state; 154 156 cc->set_pc = tilegx_cpu_set_pc; 155 - cc->handle_mmu_fault = tilegx_cpu_handle_mmu_fault; 157 + cc->tlb_fill = tilegx_cpu_tlb_fill; 156 158 cc->gdb_num_core_regs = 0; 157 159 cc->tcg_initialize = tilegx_tcg_init; 158 160 }
+1
target/tricore/cpu.c
··· 166 166 cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; 167 167 cc->get_phys_page_attrs_debug = tricore_cpu_get_phys_page_attrs_debug; 168 168 cc->tcg_initialize = tricore_tcg_init; 169 + cc->tlb_fill = tricore_cpu_tlb_fill; 169 170 } 170 171 171 172 #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
+3 -3
target/tricore/cpu.h
··· 417 417 #define CPU_RESOLVING_TYPE TYPE_TRICORE_CPU 418 418 419 419 /* helpers.c */ 420 - int cpu_tricore_handle_mmu_fault(CPUState *cpu, target_ulong address, 421 - int rw, int mmu_idx); 422 - #define cpu_handle_mmu_fault cpu_tricore_handle_mmu_fault 420 + bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 421 + MMUAccessType access_type, int mmu_idx, 422 + bool probe, uintptr_t retaddr); 423 423 424 424 #endif /* TRICORE_CPU_H */
+14 -9
target/tricore/helper.c
··· 50 50 { 51 51 } 52 52 53 - int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address, 54 - int rw, int mmu_idx) 53 + bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 54 + MMUAccessType rw, int mmu_idx, 55 + bool probe, uintptr_t retaddr) 55 56 { 56 57 TriCoreCPU *cpu = TRICORE_CPU(cs); 57 58 CPUTriCoreState *env = &cpu->env; ··· 64 65 access_type = ACCESS_INT; 65 66 ret = get_physical_address(env, &physical, &prot, 66 67 address, rw, access_type); 67 - qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx 68 - " prot %d\n", __func__, address, ret, physical, prot); 68 + 69 + qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " 70 + TARGET_FMT_plx " prot %d\n", 71 + __func__, (target_ulong)address, ret, physical, prot); 69 72 70 73 if (ret == TLBRET_MATCH) { 71 74 tlb_set_page(cs, address & TARGET_PAGE_MASK, 72 75 physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 73 76 mmu_idx, TARGET_PAGE_SIZE); 74 - ret = 0; 75 - } else if (ret < 0) { 77 + return true; 78 + } else { 79 + assert(ret < 0); 80 + if (probe) { 81 + return false; 82 + } 76 83 raise_mmu_exception(env, address, rw, ret); 77 - ret = 1; 84 + cpu_loop_exit_restore(cs, retaddr); 78 85 } 79 - 80 - return ret; 81 86 } 82 87 83 88 static void tricore_cpu_list_entry(gpointer data, gpointer user_data)
-26
target/tricore/op_helper.c
··· 2793 2793 { 2794 2794 return psw_read(env); 2795 2795 } 2796 - 2797 - 2798 - static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 2799 - uint32_t exception, 2800 - int error_code, 2801 - uintptr_t pc) 2802 - { 2803 - CPUState *cs = CPU(tricore_env_get_cpu(env)); 2804 - cs->exception_index = exception; 2805 - env->error_code = error_code; 2806 - /* now we have a real cpu fault */ 2807 - cpu_loop_exit_restore(cs, pc); 2808 - } 2809 - 2810 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 2811 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 2812 - { 2813 - int ret; 2814 - ret = cpu_tricore_handle_mmu_fault(cs, addr, access_type, mmu_idx); 2815 - if (ret) { 2816 - TriCoreCPU *cpu = TRICORE_CPU(cs); 2817 - CPUTriCoreState *env = &cpu->env; 2818 - do_raise_exception_err(env, cs->exception_index, 2819 - env->error_code, retaddr); 2820 - } 2821 - }
+1 -4
target/unicore32/cpu.c
··· 138 138 cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt; 139 139 cc->dump_state = uc32_cpu_dump_state; 140 140 cc->set_pc = uc32_cpu_set_pc; 141 - #ifdef CONFIG_USER_ONLY 142 - cc->handle_mmu_fault = uc32_cpu_handle_mmu_fault; 143 - #else 141 + cc->tlb_fill = uc32_cpu_tlb_fill; 144 142 cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug; 145 - #endif 146 143 cc->tcg_initialize = uc32_translate_init; 147 144 dc->vmsd = &vmstate_uc32_cpu; 148 145 }
+3 -2
target/unicore32/cpu.h
··· 178 178 } 179 179 } 180 180 181 - int uc32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, 182 - int mmu_idx); 181 + bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 182 + MMUAccessType access_type, int mmu_idx, 183 + bool probe, uintptr_t retaddr); 183 184 void uc32_translate_init(void); 184 185 void switch_mode(CPUUniCore32State *, int); 185 186
-23
target/unicore32/helper.c
··· 215 215 } 216 216 #endif 217 217 218 - #ifdef CONFIG_USER_ONLY 219 - void switch_mode(CPUUniCore32State *env, int mode) 220 - { 221 - UniCore32CPU *cpu = uc32_env_get_cpu(env); 222 - 223 - if (mode != ASR_MODE_USER) { 224 - cpu_abort(CPU(cpu), "Tried to switch out of user mode\n"); 225 - } 226 - } 227 - 228 - void uc32_cpu_do_interrupt(CPUState *cs) 229 - { 230 - cpu_abort(cs, "NO interrupt in user mode\n"); 231 - } 232 - 233 - int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 234 - int access_type, int mmu_idx) 235 - { 236 - cpu_abort(cs, "NO mmu fault in user mode\n"); 237 - return 1; 238 - } 239 - #endif 240 - 241 218 bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 242 219 { 243 220 if (interrupt_request & CPU_INTERRUPT_HARD) {
-14
target/unicore32/op_helper.c
··· 242 242 return ((uint32_t)x >> shift) | (x << (32 - shift)); 243 243 } 244 244 } 245 - 246 - #ifndef CONFIG_USER_ONLY 247 - void tlb_fill(CPUState *cs, target_ulong addr, int size, 248 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 249 - { 250 - int ret; 251 - 252 - ret = uc32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); 253 - if (unlikely(ret)) { 254 - /* now we have a real cpu fault */ 255 - cpu_loop_exit_restore(cs, retaddr); 256 - } 257 - } 258 - #endif
+9 -4
target/unicore32/softmmu.c
··· 215 215 return code; 216 216 } 217 217 218 - int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, 219 - int access_type, int mmu_idx) 218 + bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 219 + MMUAccessType access_type, int mmu_idx, 220 + bool probe, uintptr_t retaddr) 220 221 { 221 222 UniCore32CPU *cpu = UNICORE32_CPU(cs); 222 223 CPUUniCore32State *env = &cpu->env; ··· 257 258 phys_addr &= TARGET_PAGE_MASK; 258 259 address &= TARGET_PAGE_MASK; 259 260 tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size); 260 - return 0; 261 + return true; 262 + } 263 + 264 + if (probe) { 265 + return false; 261 266 } 262 267 263 268 env->cp0.c3_faultstatus = ret; ··· 267 272 } else { 268 273 cs->exception_index = UC32_EXCP_DTRAP; 269 274 } 270 - return ret; 275 + cpu_loop_exit_restore(cs, retaddr); 271 276 } 272 277 273 278 hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+2 -3
target/xtensa/cpu.c
··· 181 181 cc->gdb_read_register = xtensa_cpu_gdb_read_register; 182 182 cc->gdb_write_register = xtensa_cpu_gdb_write_register; 183 183 cc->gdb_stop_before_watchpoint = true; 184 - #ifdef CONFIG_USER_ONLY 185 - cc->handle_mmu_fault = xtensa_cpu_handle_mmu_fault; 186 - #else 184 + cc->tlb_fill = xtensa_cpu_tlb_fill; 185 + #ifndef CONFIG_USER_ONLY 187 186 cc->do_unaligned_access = xtensa_cpu_do_unaligned_access; 188 187 cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; 189 188 cc->do_transaction_failed = xtensa_cpu_do_transaction_failed;
+3 -2
target/xtensa/cpu.h
··· 552 552 #define ENV_OFFSET offsetof(XtensaCPU, env) 553 553 554 554 555 - int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int size, 556 - int mmu_idx); 555 + bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 556 + MMUAccessType access_type, int mmu_idx, 557 + bool probe, uintptr_t retaddr); 557 558 void xtensa_cpu_do_interrupt(CPUState *cpu); 558 559 bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request); 559 560 void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
+20 -13
target/xtensa/helper.c
··· 240 240 241 241 #ifdef CONFIG_USER_ONLY 242 242 243 - int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 244 - int mmu_idx) 243 + bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 244 + MMUAccessType access_type, int mmu_idx, 245 + bool probe, uintptr_t retaddr) 245 246 { 246 247 XtensaCPU *cpu = XTENSA_CPU(cs); 247 248 CPUXtensaState *env = &cpu->env; 248 249 249 250 qemu_log_mask(CPU_LOG_INT, 250 251 "%s: rw = %d, address = 0x%08" VADDR_PRIx ", size = %d\n", 251 - __func__, rw, address, size); 252 + __func__, access_type, address, size); 252 253 env->sregs[EXCVADDR] = address; 253 - env->sregs[EXCCAUSE] = rw ? STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE; 254 + env->sregs[EXCCAUSE] = (access_type == MMU_DATA_STORE ? 255 + STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE); 254 256 cs->exception_index = EXC_USER; 255 - return 1; 257 + cpu_loop_exit_restore(cs, retaddr); 256 258 } 257 259 258 260 #else ··· 273 275 } 274 276 } 275 277 276 - void tlb_fill(CPUState *cs, target_ulong vaddr, int size, 277 - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) 278 + bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 279 + MMUAccessType access_type, int mmu_idx, 280 + bool probe, uintptr_t retaddr) 278 281 { 279 282 XtensaCPU *cpu = XTENSA_CPU(cs); 280 283 CPUXtensaState *env = &cpu->env; 281 284 uint32_t paddr; 282 285 uint32_t page_size; 283 286 unsigned access; 284 - int ret = xtensa_get_physical_addr(env, true, vaddr, access_type, mmu_idx, 285 - &paddr, &page_size, &access); 287 + int ret = xtensa_get_physical_addr(env, true, address, access_type, 288 + mmu_idx, &paddr, &page_size, &access); 286 289 287 - qemu_log_mask(CPU_LOG_MMU, "%s(%08x, %d, %d) -> %08x, ret = %d\n", 288 - __func__, vaddr, access_type, mmu_idx, paddr, ret); 290 + qemu_log_mask(CPU_LOG_MMU, "%s(%08" VADDR_PRIx 291 + ", %d, %d) -> %08x, ret = %d\n", 292 + __func__, address, access_type, mmu_idx, paddr, ret); 289 293 290 294 if (ret == 0) { 291 295 tlb_set_page(cs, 292 - vaddr & TARGET_PAGE_MASK, 296 + address & TARGET_PAGE_MASK, 293 297 paddr & TARGET_PAGE_MASK, 294 298 access, mmu_idx, page_size); 299 + return true; 300 + } else if (probe) { 301 + return false; 295 302 } else { 296 303 cpu_restore_state(cs, retaddr, true); 297 - HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr); 304 + HELPER(exception_cause_vaddr)(env, env->pc, ret, address); 298 305 } 299 306 } 300 307