1 /* 2 * Software MMU support 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 16 * 17 */ 18 19 /* 20 * Generate inline load/store functions for all MMU modes (typically 21 * at least _user and _kernel) as well as _data versions, for all data 22 * sizes. 23 * 24 * Used by target op helpers. 25 * 26 * The syntax for the accessors is: 27 * 28 * load: cpu_ld{sign}{size}_{mmusuffix}(env, ptr) 29 * cpu_ld{sign}{size}_{mmusuffix}_ra(env, ptr, retaddr) 30 * cpu_ld{sign}{size}_mmuidx_ra(env, ptr, mmu_idx, retaddr) 31 * 32 * store: cpu_st{size}_{mmusuffix}(env, ptr, val) 33 * cpu_st{size}_{mmusuffix}_ra(env, ptr, val, retaddr) 34 * cpu_st{size}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr) 35 * 36 * sign is: 37 * (empty): for 32 and 64 bit sizes 38 * u : unsigned 39 * s : signed 40 * 41 * size is: 42 * b: 8 bits 43 * w: 16 bits 44 * l: 32 bits 45 * q: 64 bits 46 * 47 * mmusuffix is one of the generic suffixes "data" or "code", or "mmuidx". 48 * The "mmuidx" suffix carries an extra mmu_idx argument that specifies 49 * the index to use; the "data" and "code" suffixes take the index from 50 * cpu_mmu_index(). 51 */ 52 #ifndef CPU_LDST_H 53 #define CPU_LDST_H 54 55 #if defined(CONFIG_USER_ONLY) 56 /* sparc32plus has 64bit long but 32bit space address 57 * this can make bad result with g2h() and h2g() 58 */ 59 #if TARGET_VIRT_ADDR_SPACE_BITS <= 32 60 typedef uint32_t abi_ptr; 61 #define TARGET_ABI_FMT_ptr "%x" 62 #else 63 typedef uint64_t abi_ptr; 64 #define TARGET_ABI_FMT_ptr "%"PRIx64 65 #endif 66 67 /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ 68 #define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base)) 69 70 #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS 71 #define guest_addr_valid(x) (1) 72 #else 73 #define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX) 74 #endif 75 #define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base) 76 77 static inline int guest_range_valid(unsigned long start, unsigned long len) 78 { 79 return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1; 80 } 81 82 #define h2g_nocheck(x) ({ \ 83 unsigned long __ret = (unsigned long)(x) - guest_base; \ 84 (abi_ptr)__ret; \ 85 }) 86 87 #define h2g(x) ({ \ 88 /* Check if given address fits target address space */ \ 89 assert(h2g_valid(x)); \ 90 h2g_nocheck(x); \ 91 }) 92 #else 93 typedef target_ulong abi_ptr; 94 #define TARGET_ABI_FMT_ptr TARGET_ABI_FMT_lx 95 #endif 96 97 uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr); 98 uint32_t cpu_lduw_data(CPUArchState *env, abi_ptr ptr); 99 uint32_t cpu_ldl_data(CPUArchState *env, abi_ptr ptr); 100 uint64_t cpu_ldq_data(CPUArchState *env, abi_ptr ptr); 101 int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr); 102 int cpu_ldsw_data(CPUArchState *env, abi_ptr ptr); 103 104 uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 105 uint32_t cpu_lduw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 106 uint32_t cpu_ldl_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 107 uint64_t cpu_ldq_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 108 int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 109 int cpu_ldsw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); 110 111 void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val); 112 void cpu_stw_data(CPUArchState *env, abi_ptr ptr, uint32_t val); 113 void cpu_stl_data(CPUArchState *env, abi_ptr ptr, uint32_t val); 114 void cpu_stq_data(CPUArchState *env, abi_ptr ptr, uint64_t val); 115 116 void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr, 117 uint32_t val, uintptr_t retaddr); 118 void cpu_stw_data_ra(CPUArchState *env, abi_ptr ptr, 119 uint32_t val, uintptr_t retaddr); 120 void cpu_stl_data_ra(CPUArchState *env, abi_ptr ptr, 121 uint32_t val, uintptr_t retaddr); 122 void cpu_stq_data_ra(CPUArchState *env, abi_ptr ptr, 123 uint64_t val, uintptr_t retaddr); 124 125 #if defined(CONFIG_USER_ONLY) 126 127 extern __thread uintptr_t helper_retaddr; 128 129 static inline void set_helper_retaddr(uintptr_t ra) 130 { 131 helper_retaddr = ra; 132 /* 133 * Ensure that this write is visible to the SIGSEGV handler that 134 * may be invoked due to a subsequent invalid memory operation. 135 */ 136 signal_barrier(); 137 } 138 139 static inline void clear_helper_retaddr(void) 140 { 141 /* 142 * Ensure that previous memory operations have succeeded before 143 * removing the data visible to the signal handler. 144 */ 145 signal_barrier(); 146 helper_retaddr = 0; 147 } 148 149 /* 150 * Provide the same *_mmuidx_ra interface as for softmmu. 151 * The mmu_idx argument is ignored. 152 */ 153 154 static inline uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr, 155 int mmu_idx, uintptr_t ra) 156 { 157 return cpu_ldub_data_ra(env, addr, ra); 158 } 159 160 static inline uint32_t cpu_lduw_mmuidx_ra(CPUArchState *env, abi_ptr addr, 161 int mmu_idx, uintptr_t ra) 162 { 163 return cpu_lduw_data_ra(env, addr, ra); 164 } 165 166 static inline uint32_t cpu_ldl_mmuidx_ra(CPUArchState *env, abi_ptr addr, 167 int mmu_idx, uintptr_t ra) 168 { 169 return cpu_ldl_data_ra(env, addr, ra); 170 } 171 172 static inline uint64_t cpu_ldq_mmuidx_ra(CPUArchState *env, abi_ptr addr, 173 int mmu_idx, uintptr_t ra) 174 { 175 return cpu_ldq_data_ra(env, addr, ra); 176 } 177 178 static inline int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, 179 int mmu_idx, uintptr_t ra) 180 { 181 return cpu_ldsb_data_ra(env, addr, ra); 182 } 183 184 static inline int cpu_ldsw_mmuidx_ra(CPUArchState *env, abi_ptr addr, 185 int mmu_idx, uintptr_t ra) 186 { 187 return cpu_ldsw_data_ra(env, addr, ra); 188 } 189 190 static inline void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, 191 uint32_t val, int mmu_idx, uintptr_t ra) 192 { 193 cpu_stb_data_ra(env, addr, val, ra); 194 } 195 196 static inline void cpu_stw_mmuidx_ra(CPUArchState *env, abi_ptr addr, 197 uint32_t val, int mmu_idx, uintptr_t ra) 198 { 199 cpu_stw_data_ra(env, addr, val, ra); 200 } 201 202 static inline void cpu_stl_mmuidx_ra(CPUArchState *env, abi_ptr addr, 203 uint32_t val, int mmu_idx, uintptr_t ra) 204 { 205 cpu_stl_data_ra(env, addr, val, ra); 206 } 207 208 static inline void cpu_stq_mmuidx_ra(CPUArchState *env, abi_ptr addr, 209 uint64_t val, int mmu_idx, uintptr_t ra) 210 { 211 cpu_stq_data_ra(env, addr, val, ra); 212 } 213 214 #else 215 216 /* Needed for TCG_OVERSIZED_GUEST */ 217 #include "tcg/tcg.h" 218 219 static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry) 220 { 221 #if TCG_OVERSIZED_GUEST 222 return entry->addr_write; 223 #else 224 return atomic_read(&entry->addr_write); 225 #endif 226 } 227 228 /* Find the TLB index corresponding to the mmu_idx + address pair. */ 229 static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx, 230 target_ulong addr) 231 { 232 uintptr_t size_mask = env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS; 233 234 return (addr >> TARGET_PAGE_BITS) & size_mask; 235 } 236 237 /* Find the TLB entry corresponding to the mmu_idx + address pair. */ 238 static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx, 239 target_ulong addr) 240 { 241 return &env_tlb(env)->f[mmu_idx].table[tlb_index(env, mmu_idx, addr)]; 242 } 243 244 uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr, 245 int mmu_idx, uintptr_t ra); 246 uint32_t cpu_lduw_mmuidx_ra(CPUArchState *env, abi_ptr addr, 247 int mmu_idx, uintptr_t ra); 248 uint32_t cpu_ldl_mmuidx_ra(CPUArchState *env, abi_ptr addr, 249 int mmu_idx, uintptr_t ra); 250 uint64_t cpu_ldq_mmuidx_ra(CPUArchState *env, abi_ptr addr, 251 int mmu_idx, uintptr_t ra); 252 253 int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, 254 int mmu_idx, uintptr_t ra); 255 int cpu_ldsw_mmuidx_ra(CPUArchState *env, abi_ptr addr, 256 int mmu_idx, uintptr_t ra); 257 258 void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 259 int mmu_idx, uintptr_t retaddr); 260 void cpu_stw_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 261 int mmu_idx, uintptr_t retaddr); 262 void cpu_stl_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 263 int mmu_idx, uintptr_t retaddr); 264 void cpu_stq_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, 265 int mmu_idx, uintptr_t retaddr); 266 267 #endif /* defined(CONFIG_USER_ONLY) */ 268 269 uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr); 270 uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr); 271 uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr); 272 uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr); 273 274 static inline int cpu_ldsb_code(CPUArchState *env, abi_ptr addr) 275 { 276 return (int8_t)cpu_ldub_code(env, addr); 277 } 278 279 static inline int cpu_ldsw_code(CPUArchState *env, abi_ptr addr) 280 { 281 return (int16_t)cpu_lduw_code(env, addr); 282 } 283 284 /** 285 * tlb_vaddr_to_host: 286 * @env: CPUArchState 287 * @addr: guest virtual address to look up 288 * @access_type: 0 for read, 1 for write, 2 for execute 289 * @mmu_idx: MMU index to use for lookup 290 * 291 * Look up the specified guest virtual index in the TCG softmmu TLB. 292 * If we can translate a host virtual address suitable for direct RAM 293 * access, without causing a guest exception, then return it. 294 * Otherwise (TLB entry is for an I/O access, guest software 295 * TLB fill required, etc) return NULL. 296 */ 297 #ifdef CONFIG_USER_ONLY 298 static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 299 MMUAccessType access_type, int mmu_idx) 300 { 301 return g2h(addr); 302 } 303 #else 304 void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 305 MMUAccessType access_type, int mmu_idx); 306 #endif 307 308 #endif /* CPU_LDST_H */ 309