1 /* 2 * PowerPC MMU, TLB and BAT emulation helpers for QEMU. 3 * 4 * Copyright (c) 2003-2007 Jocelyn Mayer 5 * Copyright (c) 2013 David Gibson, IBM Corporation 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "exec/exec-all.h" 24 #include "exec/page-protection.h" 25 #include "sysemu/kvm.h" 26 #include "kvm_ppc.h" 27 #include "internal.h" 28 #include "mmu-hash32.h" 29 #include "mmu-books.h" 30 #include "exec/log.h" 31 32 /* #define DEBUG_BATS */ 33 34 #ifdef DEBUG_BATS 35 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) 36 #else 37 # define LOG_BATS(...) do { } while (0) 38 #endif 39 40 static int ppc_hash32_pp_prot(int key, int pp, int nx) 41 { 42 int prot; 43 44 if (key == 0) { 45 switch (pp) { 46 case 0x0: 47 case 0x1: 48 case 0x2: 49 prot = PAGE_READ | PAGE_WRITE; 50 break; 51 52 case 0x3: 53 prot = PAGE_READ; 54 break; 55 56 default: 57 abort(); 58 } 59 } else { 60 switch (pp) { 61 case 0x0: 62 prot = 0; 63 break; 64 65 case 0x1: 66 case 0x3: 67 prot = PAGE_READ; 68 break; 69 70 case 0x2: 71 prot = PAGE_READ | PAGE_WRITE; 72 break; 73 74 default: 75 abort(); 76 } 77 } 78 if (nx == 0) { 79 prot |= PAGE_EXEC; 80 } 81 82 return prot; 83 } 84 85 static int ppc_hash32_pte_prot(int mmu_idx, 86 target_ulong sr, ppc_hash_pte32_t pte) 87 { 88 unsigned pp, key; 89 90 key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS)); 91 pp = pte.pte1 & HPTE32_R_PP; 92 93 return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX)); 94 } 95 96 static target_ulong hash32_bat_size(int mmu_idx, 97 target_ulong batu, target_ulong batl) 98 { 99 if ((mmuidx_pr(mmu_idx) && !(batu & BATU32_VP)) 100 || (!mmuidx_pr(mmu_idx) && !(batu & BATU32_VS))) { 101 return 0; 102 } 103 104 return BATU32_BEPI & ~((batu & BATU32_BL) << 15); 105 } 106 107 static int hash32_bat_prot(PowerPCCPU *cpu, 108 target_ulong batu, target_ulong batl) 109 { 110 int pp, prot; 111 112 prot = 0; 113 pp = batl & BATL32_PP; 114 if (pp != 0) { 115 prot = PAGE_READ | PAGE_EXEC; 116 if (pp == 0x2) { 117 prot |= PAGE_WRITE; 118 } 119 } 120 return prot; 121 } 122 123 static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, 124 MMUAccessType access_type, int *prot, 125 int mmu_idx) 126 { 127 CPUPPCState *env = &cpu->env; 128 target_ulong *BATlt, *BATut; 129 bool ifetch = access_type == MMU_INST_FETCH; 130 int i; 131 132 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, 133 ifetch ? 'I' : 'D', ea); 134 if (ifetch) { 135 BATlt = env->IBAT[1]; 136 BATut = env->IBAT[0]; 137 } else { 138 BATlt = env->DBAT[1]; 139 BATut = env->DBAT[0]; 140 } 141 for (i = 0; i < env->nb_BATs; i++) { 142 target_ulong batu = BATut[i]; 143 target_ulong batl = BATlt[i]; 144 target_ulong mask; 145 146 mask = hash32_bat_size(mmu_idx, batu, batl); 147 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx 148 " BATl " TARGET_FMT_lx "\n", __func__, 149 ifetch ? 'I' : 'D', i, ea, batu, batl); 150 151 if (mask && ((ea & mask) == (batu & BATU32_BEPI))) { 152 hwaddr raddr = (batl & mask) | (ea & ~mask); 153 154 *prot = hash32_bat_prot(cpu, batu, batl); 155 156 return raddr & TARGET_PAGE_MASK; 157 } 158 } 159 160 /* No hit */ 161 #if defined(DEBUG_BATS) 162 if (qemu_log_enabled()) { 163 target_ulong *BATu, *BATl; 164 target_ulong BEPIl, BEPIu, bl; 165 166 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea); 167 for (i = 0; i < 4; i++) { 168 BATu = &BATut[i]; 169 BATl = &BATlt[i]; 170 BEPIu = *BATu & BATU32_BEPIU; 171 BEPIl = *BATu & BATU32_BEPIL; 172 bl = (*BATu & 0x00001FFC) << 15; 173 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx 174 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " 175 TARGET_FMT_lx " " TARGET_FMT_lx "\n", 176 __func__, ifetch ? 'I' : 'D', i, ea, 177 *BATu, *BATl, BEPIu, BEPIl, bl); 178 } 179 } 180 #endif 181 182 return -1; 183 } 184 185 static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, 186 target_ulong eaddr, 187 MMUAccessType access_type, 188 hwaddr *raddr, int *prot, int mmu_idx, 189 bool guest_visible) 190 { 191 CPUState *cs = CPU(cpu); 192 CPUPPCState *env = &cpu->env; 193 int key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS)); 194 195 qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); 196 197 if (access_type == MMU_INST_FETCH) { 198 /* No code fetch is allowed in direct-store areas */ 199 if (guest_visible) { 200 cs->exception_index = POWERPC_EXCP_ISI; 201 env->error_code = 0x10000000; 202 } 203 return false; 204 } 205 206 /* 207 * From ppc_cpu_get_phys_page_debug, env->access_type is not set. 208 * Assume ACCESS_INT for that case. 209 */ 210 switch (guest_visible ? env->access_type : ACCESS_INT) { 211 case ACCESS_INT: 212 /* Integer load/store : only access allowed */ 213 break; 214 case ACCESS_FLOAT: 215 /* Floating point load/store */ 216 cs->exception_index = POWERPC_EXCP_ALIGN; 217 env->error_code = POWERPC_EXCP_ALIGN_FP; 218 env->spr[SPR_DAR] = eaddr; 219 return false; 220 case ACCESS_RES: 221 /* lwarx, ldarx or srwcx. */ 222 env->error_code = 0; 223 env->spr[SPR_DAR] = eaddr; 224 if (access_type == MMU_DATA_STORE) { 225 env->spr[SPR_DSISR] = 0x06000000; 226 } else { 227 env->spr[SPR_DSISR] = 0x04000000; 228 } 229 return false; 230 case ACCESS_CACHE: 231 /* 232 * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi 233 * 234 * Should make the instruction do no-op. As it already do 235 * no-op, it's quite easy :-) 236 */ 237 *raddr = eaddr; 238 return true; 239 case ACCESS_EXT: 240 /* eciwx or ecowx */ 241 cs->exception_index = POWERPC_EXCP_DSI; 242 env->error_code = 0; 243 env->spr[SPR_DAR] = eaddr; 244 if (access_type == MMU_DATA_STORE) { 245 env->spr[SPR_DSISR] = 0x06100000; 246 } else { 247 env->spr[SPR_DSISR] = 0x04100000; 248 } 249 return false; 250 default: 251 cpu_abort(cs, "ERROR: insn should not need address translation\n"); 252 } 253 254 *prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ; 255 if (check_prot_access_type(*prot, access_type)) { 256 *raddr = eaddr; 257 return true; 258 } 259 260 if (guest_visible) { 261 cs->exception_index = POWERPC_EXCP_DSI; 262 env->error_code = 0; 263 env->spr[SPR_DAR] = eaddr; 264 if (access_type == MMU_DATA_STORE) { 265 env->spr[SPR_DSISR] = 0x0a000000; 266 } else { 267 env->spr[SPR_DSISR] = 0x08000000; 268 } 269 } 270 return false; 271 } 272 273 hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash) 274 { 275 target_ulong mask = ppc_hash32_hpt_mask(cpu); 276 277 return (hash * HASH_PTEG_SIZE_32) & mask; 278 } 279 280 static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off, 281 bool secondary, target_ulong ptem, 282 ppc_hash_pte32_t *pte) 283 { 284 hwaddr pte_offset = pteg_off; 285 target_ulong pte0, pte1; 286 int i; 287 288 for (i = 0; i < HPTES_PER_GROUP; i++) { 289 pte0 = ppc_hash32_load_hpte0(cpu, pte_offset); 290 /* 291 * pte0 contains the valid bit and must be read before pte1, 292 * otherwise we might see an old pte1 with a new valid bit and 293 * thus an inconsistent hpte value 294 */ 295 smp_rmb(); 296 pte1 = ppc_hash32_load_hpte1(cpu, pte_offset); 297 298 if ((pte0 & HPTE32_V_VALID) 299 && (secondary == !!(pte0 & HPTE32_V_SECONDARY)) 300 && HPTE32_V_COMPARE(pte0, ptem)) { 301 pte->pte0 = pte0; 302 pte->pte1 = pte1; 303 return pte_offset; 304 } 305 306 pte_offset += HASH_PTE_SIZE_32; 307 } 308 309 return -1; 310 } 311 312 static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1) 313 { 314 target_ulong base = ppc_hash32_hpt_base(cpu); 315 hwaddr offset = pte_offset + 6; 316 317 /* The HW performs a non-atomic byte update */ 318 stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01); 319 } 320 321 static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1) 322 { 323 target_ulong base = ppc_hash32_hpt_base(cpu); 324 hwaddr offset = pte_offset + 7; 325 326 /* The HW performs a non-atomic byte update */ 327 stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80); 328 } 329 330 static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu, 331 target_ulong sr, target_ulong eaddr, 332 ppc_hash_pte32_t *pte) 333 { 334 hwaddr pteg_off, pte_offset; 335 hwaddr hash; 336 uint32_t vsid, pgidx, ptem; 337 338 vsid = sr & SR32_VSID; 339 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS; 340 hash = vsid ^ pgidx; 341 ptem = (vsid << 7) | (pgidx >> 10); 342 343 /* Page address translation */ 344 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx 345 " htab_mask " HWADDR_FMT_plx 346 " hash " HWADDR_FMT_plx "\n", 347 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); 348 349 /* Primary PTEG lookup */ 350 qemu_log_mask(CPU_LOG_MMU, "0 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx 351 " vsid=%" PRIx32 " ptem=%" PRIx32 352 " hash=" HWADDR_FMT_plx "\n", 353 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 354 vsid, ptem, hash); 355 pteg_off = get_pteg_offset32(cpu, hash); 356 pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte); 357 if (pte_offset == -1) { 358 /* Secondary PTEG lookup */ 359 qemu_log_mask(CPU_LOG_MMU, "1 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx 360 " vsid=%" PRIx32 " api=%" PRIx32 361 " hash=" HWADDR_FMT_plx "\n", ppc_hash32_hpt_base(cpu), 362 ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash); 363 pteg_off = get_pteg_offset32(cpu, ~hash); 364 pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte); 365 } 366 367 return pte_offset; 368 } 369 370 static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte, 371 target_ulong eaddr) 372 { 373 hwaddr rpn = pte.pte1 & HPTE32_R_RPN; 374 hwaddr mask = ~TARGET_PAGE_MASK; 375 376 return (rpn & ~mask) | (eaddr & mask); 377 } 378 379 bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, 380 hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, 381 bool guest_visible) 382 { 383 CPUState *cs = CPU(cpu); 384 CPUPPCState *env = &cpu->env; 385 target_ulong sr; 386 hwaddr pte_offset; 387 ppc_hash_pte32_t pte; 388 int prot; 389 hwaddr raddr; 390 391 /* There are no hash32 large pages. */ 392 *psizep = TARGET_PAGE_BITS; 393 394 /* 1. Handle real mode accesses */ 395 if (mmuidx_real(mmu_idx)) { 396 /* Translation is off */ 397 *raddrp = eaddr; 398 *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 399 return true; 400 } 401 402 /* 2. Check Block Address Translation entries (BATs) */ 403 if (env->nb_BATs != 0) { 404 raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx); 405 if (raddr != -1) { 406 if (!check_prot_access_type(*protp, access_type)) { 407 if (guest_visible) { 408 if (access_type == MMU_INST_FETCH) { 409 cs->exception_index = POWERPC_EXCP_ISI; 410 env->error_code = 0x08000000; 411 } else { 412 cs->exception_index = POWERPC_EXCP_DSI; 413 env->error_code = 0; 414 env->spr[SPR_DAR] = eaddr; 415 if (access_type == MMU_DATA_STORE) { 416 env->spr[SPR_DSISR] = 0x0a000000; 417 } else { 418 env->spr[SPR_DSISR] = 0x08000000; 419 } 420 } 421 } 422 return false; 423 } 424 *raddrp = raddr; 425 return true; 426 } 427 } 428 429 /* 3. Look up the Segment Register */ 430 sr = env->sr[eaddr >> 28]; 431 432 /* 4. Handle direct store segments */ 433 if (sr & SR32_T) { 434 return ppc_hash32_direct_store(cpu, sr, eaddr, access_type, 435 raddrp, protp, mmu_idx, guest_visible); 436 } 437 438 /* 5. Check for segment level no-execute violation */ 439 if (access_type == MMU_INST_FETCH && (sr & SR32_NX)) { 440 if (guest_visible) { 441 cs->exception_index = POWERPC_EXCP_ISI; 442 env->error_code = 0x10000000; 443 } 444 return false; 445 } 446 447 /* 6. Locate the PTE in the hash table */ 448 pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte); 449 if (pte_offset == -1) { 450 if (guest_visible) { 451 if (access_type == MMU_INST_FETCH) { 452 cs->exception_index = POWERPC_EXCP_ISI; 453 env->error_code = 0x40000000; 454 } else { 455 cs->exception_index = POWERPC_EXCP_DSI; 456 env->error_code = 0; 457 env->spr[SPR_DAR] = eaddr; 458 if (access_type == MMU_DATA_STORE) { 459 env->spr[SPR_DSISR] = 0x42000000; 460 } else { 461 env->spr[SPR_DSISR] = 0x40000000; 462 } 463 } 464 } 465 return false; 466 } 467 qemu_log_mask(CPU_LOG_MMU, 468 "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); 469 470 /* 7. Check access permissions */ 471 472 prot = ppc_hash32_pte_prot(mmu_idx, sr, pte); 473 474 if (!check_prot_access_type(prot, access_type)) { 475 /* Access right violation */ 476 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); 477 if (guest_visible) { 478 if (access_type == MMU_INST_FETCH) { 479 cs->exception_index = POWERPC_EXCP_ISI; 480 env->error_code = 0x08000000; 481 } else { 482 cs->exception_index = POWERPC_EXCP_DSI; 483 env->error_code = 0; 484 env->spr[SPR_DAR] = eaddr; 485 if (access_type == MMU_DATA_STORE) { 486 env->spr[SPR_DSISR] = 0x0a000000; 487 } else { 488 env->spr[SPR_DSISR] = 0x08000000; 489 } 490 } 491 } 492 return false; 493 } 494 495 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); 496 497 /* 8. Update PTE referenced and changed bits if necessary */ 498 499 if (!(pte.pte1 & HPTE32_R_R)) { 500 ppc_hash32_set_r(cpu, pte_offset, pte.pte1); 501 } 502 if (!(pte.pte1 & HPTE32_R_C)) { 503 if (access_type == MMU_DATA_STORE) { 504 ppc_hash32_set_c(cpu, pte_offset, pte.pte1); 505 } else { 506 /* 507 * Treat the page as read-only for now, so that a later write 508 * will pass through this function again to set the C bit 509 */ 510 prot &= ~PAGE_WRITE; 511 } 512 } 513 514 /* 9. Determine the real address from the PTE */ 515 516 *raddrp = ppc_hash32_pte_raddr(sr, pte, eaddr); 517 *protp = prot; 518 return true; 519 } 520