1 /* 2 * Software MMU support (per-target) 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.1 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}{end}_{mmusuffix}(env, ptr) 29 * cpu_ld{sign}{size}{end}_{mmusuffix}_ra(env, ptr, retaddr) 30 * cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmu_idx, retaddr) 31 * cpu_ld{sign}{size}{end}_mmu(env, ptr, oi, retaddr) 32 * 33 * store: cpu_st{size}{end}_{mmusuffix}(env, ptr, val) 34 * cpu_st{size}{end}_{mmusuffix}_ra(env, ptr, val, retaddr) 35 * cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr) 36 * cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr) 37 * 38 * sign is: 39 * (empty): for 32 and 64 bit sizes 40 * u : unsigned 41 * s : signed 42 * 43 * size is: 44 * b: 8 bits 45 * w: 16 bits 46 * l: 32 bits 47 * q: 64 bits 48 * 49 * end is: 50 * (empty): for target native endian, or for 8 bit access 51 * _be: for forced big endian 52 * _le: for forced little endian 53 * 54 * mmusuffix is one of the generic suffixes "data" or "code", or "mmuidx". 55 * The "mmuidx" suffix carries an extra mmu_idx argument that specifies 56 * the index to use; the "data" and "code" suffixes take the index from 57 * cpu_mmu_index(). 58 * 59 * The "mmu" suffix carries the full MemOpIdx, with both mmu_idx and the 60 * MemOp including alignment requirements. The alignment will be enforced. 61 */ 62 #ifndef ACCEL_TCG_CPU_LDST_H 63 #define ACCEL_TCG_CPU_LDST_H 64 65 #ifndef CONFIG_TCG 66 #error Can only include this header with TCG 67 #endif 68 69 #include "exec/cpu-common.h" 70 #include "accel/tcg/cpu-ldst-common.h" 71 #include "accel/tcg/cpu-mmu-index.h" 72 #include "exec/abi_ptr.h" 73 74 #if defined(CONFIG_USER_ONLY) 75 #include "user/guest-host.h" 76 #endif /* CONFIG_USER_ONLY */ 77 78 static inline uint32_t 79 cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr, int mmu_idx, uintptr_t ra) 80 { 81 MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); 82 return cpu_ldb_mmu(env, addr, oi, ra); 83 } 84 85 static inline int 86 cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, int mmu_idx, uintptr_t ra) 87 { 88 return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra); 89 } 90 91 static inline uint32_t 92 cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, 93 int mmu_idx, uintptr_t ra) 94 { 95 MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx); 96 return cpu_ldw_mmu(env, addr, oi, ra); 97 } 98 99 static inline int 100 cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, 101 int mmu_idx, uintptr_t ra) 102 { 103 return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra); 104 } 105 106 static inline uint32_t 107 cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, 108 int mmu_idx, uintptr_t ra) 109 { 110 MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx); 111 return cpu_ldl_mmu(env, addr, oi, ra); 112 } 113 114 static inline uint64_t 115 cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, 116 int mmu_idx, uintptr_t ra) 117 { 118 MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx); 119 return cpu_ldq_mmu(env, addr, oi, ra); 120 } 121 122 static inline uint32_t 123 cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, 124 int mmu_idx, uintptr_t ra) 125 { 126 MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx); 127 return cpu_ldw_mmu(env, addr, oi, ra); 128 } 129 130 static inline int 131 cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, 132 int mmu_idx, uintptr_t ra) 133 { 134 return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra); 135 } 136 137 static inline uint32_t 138 cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, 139 int mmu_idx, uintptr_t ra) 140 { 141 MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx); 142 return cpu_ldl_mmu(env, addr, oi, ra); 143 } 144 145 static inline uint64_t 146 cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, 147 int mmu_idx, uintptr_t ra) 148 { 149 MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx); 150 return cpu_ldq_mmu(env, addr, oi, ra); 151 } 152 153 static inline void 154 cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 155 int mmu_idx, uintptr_t ra) 156 { 157 MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); 158 cpu_stb_mmu(env, addr, val, oi, ra); 159 } 160 161 static inline void 162 cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 163 int mmu_idx, uintptr_t ra) 164 { 165 MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx); 166 cpu_stw_mmu(env, addr, val, oi, ra); 167 } 168 169 static inline void 170 cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 171 int mmu_idx, uintptr_t ra) 172 { 173 MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx); 174 cpu_stl_mmu(env, addr, val, oi, ra); 175 } 176 177 static inline void 178 cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, 179 int mmu_idx, uintptr_t ra) 180 { 181 MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx); 182 cpu_stq_mmu(env, addr, val, oi, ra); 183 } 184 185 static inline void 186 cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 187 int mmu_idx, uintptr_t ra) 188 { 189 MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx); 190 cpu_stw_mmu(env, addr, val, oi, ra); 191 } 192 193 static inline void 194 cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, 195 int mmu_idx, uintptr_t ra) 196 { 197 MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx); 198 cpu_stl_mmu(env, addr, val, oi, ra); 199 } 200 201 static inline void 202 cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, 203 int mmu_idx, uintptr_t ra) 204 { 205 MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx); 206 cpu_stq_mmu(env, addr, val, oi, ra); 207 } 208 209 /*--------------------------*/ 210 211 static inline uint32_t 212 cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 213 { 214 int mmu_index = cpu_mmu_index(env_cpu(env), false); 215 return cpu_ldub_mmuidx_ra(env, addr, mmu_index, ra); 216 } 217 218 static inline int 219 cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 220 { 221 return (int8_t)cpu_ldub_data_ra(env, addr, ra); 222 } 223 224 static inline uint32_t 225 cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 226 { 227 int mmu_index = cpu_mmu_index(env_cpu(env), false); 228 return cpu_lduw_be_mmuidx_ra(env, addr, mmu_index, ra); 229 } 230 231 static inline int 232 cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 233 { 234 return (int16_t)cpu_lduw_be_data_ra(env, addr, ra); 235 } 236 237 static inline uint32_t 238 cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 239 { 240 int mmu_index = cpu_mmu_index(env_cpu(env), false); 241 return cpu_ldl_be_mmuidx_ra(env, addr, mmu_index, ra); 242 } 243 244 static inline uint64_t 245 cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 246 { 247 int mmu_index = cpu_mmu_index(env_cpu(env), false); 248 return cpu_ldq_be_mmuidx_ra(env, addr, mmu_index, ra); 249 } 250 251 static inline uint32_t 252 cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 253 { 254 int mmu_index = cpu_mmu_index(env_cpu(env), false); 255 return cpu_lduw_le_mmuidx_ra(env, addr, mmu_index, ra); 256 } 257 258 static inline int 259 cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 260 { 261 return (int16_t)cpu_lduw_le_data_ra(env, addr, ra); 262 } 263 264 static inline uint32_t 265 cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 266 { 267 int mmu_index = cpu_mmu_index(env_cpu(env), false); 268 return cpu_ldl_le_mmuidx_ra(env, addr, mmu_index, ra); 269 } 270 271 static inline uint64_t 272 cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) 273 { 274 int mmu_index = cpu_mmu_index(env_cpu(env), false); 275 return cpu_ldq_le_mmuidx_ra(env, addr, mmu_index, ra); 276 } 277 278 static inline void 279 cpu_stb_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) 280 { 281 int mmu_index = cpu_mmu_index(env_cpu(env), false); 282 cpu_stb_mmuidx_ra(env, addr, val, mmu_index, ra); 283 } 284 285 static inline void 286 cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) 287 { 288 int mmu_index = cpu_mmu_index(env_cpu(env), false); 289 cpu_stw_be_mmuidx_ra(env, addr, val, mmu_index, ra); 290 } 291 292 static inline void 293 cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) 294 { 295 int mmu_index = cpu_mmu_index(env_cpu(env), false); 296 cpu_stl_be_mmuidx_ra(env, addr, val, mmu_index, ra); 297 } 298 299 static inline void 300 cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr, uint64_t val, uintptr_t ra) 301 { 302 int mmu_index = cpu_mmu_index(env_cpu(env), false); 303 cpu_stq_be_mmuidx_ra(env, addr, val, mmu_index, ra); 304 } 305 306 static inline void 307 cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) 308 { 309 int mmu_index = cpu_mmu_index(env_cpu(env), false); 310 cpu_stw_le_mmuidx_ra(env, addr, val, mmu_index, ra); 311 } 312 313 static inline void 314 cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) 315 { 316 int mmu_index = cpu_mmu_index(env_cpu(env), false); 317 cpu_stl_le_mmuidx_ra(env, addr, val, mmu_index, ra); 318 } 319 320 static inline void 321 cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr, uint64_t val, uintptr_t ra) 322 { 323 int mmu_index = cpu_mmu_index(env_cpu(env), false); 324 cpu_stq_le_mmuidx_ra(env, addr, val, mmu_index, ra); 325 } 326 327 /*--------------------------*/ 328 329 static inline uint32_t 330 cpu_ldub_data(CPUArchState *env, abi_ptr addr) 331 { 332 return cpu_ldub_data_ra(env, addr, 0); 333 } 334 335 static inline int 336 cpu_ldsb_data(CPUArchState *env, abi_ptr addr) 337 { 338 return (int8_t)cpu_ldub_data(env, addr); 339 } 340 341 static inline uint32_t 342 cpu_lduw_be_data(CPUArchState *env, abi_ptr addr) 343 { 344 return cpu_lduw_be_data_ra(env, addr, 0); 345 } 346 347 static inline int 348 cpu_ldsw_be_data(CPUArchState *env, abi_ptr addr) 349 { 350 return (int16_t)cpu_lduw_be_data(env, addr); 351 } 352 353 static inline uint32_t 354 cpu_ldl_be_data(CPUArchState *env, abi_ptr addr) 355 { 356 return cpu_ldl_be_data_ra(env, addr, 0); 357 } 358 359 static inline uint64_t 360 cpu_ldq_be_data(CPUArchState *env, abi_ptr addr) 361 { 362 return cpu_ldq_be_data_ra(env, addr, 0); 363 } 364 365 static inline uint32_t 366 cpu_lduw_le_data(CPUArchState *env, abi_ptr addr) 367 { 368 return cpu_lduw_le_data_ra(env, addr, 0); 369 } 370 371 static inline int 372 cpu_ldsw_le_data(CPUArchState *env, abi_ptr addr) 373 { 374 return (int16_t)cpu_lduw_le_data(env, addr); 375 } 376 377 static inline uint32_t 378 cpu_ldl_le_data(CPUArchState *env, abi_ptr addr) 379 { 380 return cpu_ldl_le_data_ra(env, addr, 0); 381 } 382 383 static inline uint64_t 384 cpu_ldq_le_data(CPUArchState *env, abi_ptr addr) 385 { 386 return cpu_ldq_le_data_ra(env, addr, 0); 387 } 388 389 static inline void 390 cpu_stb_data(CPUArchState *env, abi_ptr addr, uint32_t val) 391 { 392 cpu_stb_data_ra(env, addr, val, 0); 393 } 394 395 static inline void 396 cpu_stw_be_data(CPUArchState *env, abi_ptr addr, uint32_t val) 397 { 398 cpu_stw_be_data_ra(env, addr, val, 0); 399 } 400 401 static inline void 402 cpu_stl_be_data(CPUArchState *env, abi_ptr addr, uint32_t val) 403 { 404 cpu_stl_be_data_ra(env, addr, val, 0); 405 } 406 407 static inline void 408 cpu_stq_be_data(CPUArchState *env, abi_ptr addr, uint64_t val) 409 { 410 cpu_stq_be_data_ra(env, addr, val, 0); 411 } 412 413 static inline void 414 cpu_stw_le_data(CPUArchState *env, abi_ptr addr, uint32_t val) 415 { 416 cpu_stw_le_data_ra(env, addr, val, 0); 417 } 418 419 static inline void 420 cpu_stl_le_data(CPUArchState *env, abi_ptr addr, uint32_t val) 421 { 422 cpu_stl_le_data_ra(env, addr, val, 0); 423 } 424 425 static inline void 426 cpu_stq_le_data(CPUArchState *env, abi_ptr addr, uint64_t val) 427 { 428 cpu_stq_le_data_ra(env, addr, val, 0); 429 } 430 431 #if TARGET_BIG_ENDIAN 432 # define cpu_lduw_data cpu_lduw_be_data 433 # define cpu_ldsw_data cpu_ldsw_be_data 434 # define cpu_ldl_data cpu_ldl_be_data 435 # define cpu_ldq_data cpu_ldq_be_data 436 # define cpu_lduw_data_ra cpu_lduw_be_data_ra 437 # define cpu_ldsw_data_ra cpu_ldsw_be_data_ra 438 # define cpu_ldl_data_ra cpu_ldl_be_data_ra 439 # define cpu_ldq_data_ra cpu_ldq_be_data_ra 440 # define cpu_lduw_mmuidx_ra cpu_lduw_be_mmuidx_ra 441 # define cpu_ldsw_mmuidx_ra cpu_ldsw_be_mmuidx_ra 442 # define cpu_ldl_mmuidx_ra cpu_ldl_be_mmuidx_ra 443 # define cpu_ldq_mmuidx_ra cpu_ldq_be_mmuidx_ra 444 # define cpu_stw_data cpu_stw_be_data 445 # define cpu_stl_data cpu_stl_be_data 446 # define cpu_stq_data cpu_stq_be_data 447 # define cpu_stw_data_ra cpu_stw_be_data_ra 448 # define cpu_stl_data_ra cpu_stl_be_data_ra 449 # define cpu_stq_data_ra cpu_stq_be_data_ra 450 # define cpu_stw_mmuidx_ra cpu_stw_be_mmuidx_ra 451 # define cpu_stl_mmuidx_ra cpu_stl_be_mmuidx_ra 452 # define cpu_stq_mmuidx_ra cpu_stq_be_mmuidx_ra 453 #else 454 # define cpu_lduw_data cpu_lduw_le_data 455 # define cpu_ldsw_data cpu_ldsw_le_data 456 # define cpu_ldl_data cpu_ldl_le_data 457 # define cpu_ldq_data cpu_ldq_le_data 458 # define cpu_lduw_data_ra cpu_lduw_le_data_ra 459 # define cpu_ldsw_data_ra cpu_ldsw_le_data_ra 460 # define cpu_ldl_data_ra cpu_ldl_le_data_ra 461 # define cpu_ldq_data_ra cpu_ldq_le_data_ra 462 # define cpu_lduw_mmuidx_ra cpu_lduw_le_mmuidx_ra 463 # define cpu_ldsw_mmuidx_ra cpu_ldsw_le_mmuidx_ra 464 # define cpu_ldl_mmuidx_ra cpu_ldl_le_mmuidx_ra 465 # define cpu_ldq_mmuidx_ra cpu_ldq_le_mmuidx_ra 466 # define cpu_stw_data cpu_stw_le_data 467 # define cpu_stl_data cpu_stl_le_data 468 # define cpu_stq_data cpu_stq_le_data 469 # define cpu_stw_data_ra cpu_stw_le_data_ra 470 # define cpu_stl_data_ra cpu_stl_le_data_ra 471 # define cpu_stq_data_ra cpu_stq_le_data_ra 472 # define cpu_stw_mmuidx_ra cpu_stw_le_mmuidx_ra 473 # define cpu_stl_mmuidx_ra cpu_stl_le_mmuidx_ra 474 # define cpu_stq_mmuidx_ra cpu_stq_le_mmuidx_ra 475 #endif 476 477 static inline uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr) 478 { 479 CPUState *cs = env_cpu(env); 480 MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(cs, true)); 481 return cpu_ldb_code_mmu(env, addr, oi, 0); 482 } 483 484 static inline uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr) 485 { 486 CPUState *cs = env_cpu(env); 487 MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(cs, true)); 488 return cpu_ldw_code_mmu(env, addr, oi, 0); 489 } 490 491 static inline uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr) 492 { 493 CPUState *cs = env_cpu(env); 494 MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(cs, true)); 495 return cpu_ldl_code_mmu(env, addr, oi, 0); 496 } 497 498 static inline uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr) 499 { 500 CPUState *cs = env_cpu(env); 501 MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(cs, true)); 502 return cpu_ldq_code_mmu(env, addr, oi, 0); 503 } 504 505 /** 506 * tlb_vaddr_to_host: 507 * @env: CPUArchState 508 * @addr: guest virtual address to look up 509 * @access_type: 0 for read, 1 for write, 2 for execute 510 * @mmu_idx: MMU index to use for lookup 511 * 512 * Look up the specified guest virtual index in the TCG softmmu TLB. 513 * If we can translate a host virtual address suitable for direct RAM 514 * access, without causing a guest exception, then return it. 515 * Otherwise (TLB entry is for an I/O access, guest software 516 * TLB fill required, etc) return NULL. 517 */ 518 #ifdef CONFIG_USER_ONLY 519 static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, 520 MMUAccessType access_type, int mmu_idx) 521 { 522 return g2h(env_cpu(env), addr); 523 } 524 #else 525 void *tlb_vaddr_to_host(CPUArchState *env, vaddr addr, 526 MMUAccessType access_type, int mmu_idx); 527 #endif 528 529 #endif /* ACCEL_TCG_CPU_LDST_H */ 530