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