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