1 /* 2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU. 3 * 4 * Copyright (c) 2003-2007 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "qemu/units.h" 22 #include "cpu.h" 23 #include "sysemu/kvm.h" 24 #include "kvm_ppc.h" 25 #include "mmu-hash64.h" 26 #include "mmu-hash32.h" 27 #include "exec/exec-all.h" 28 #include "exec/page-protection.h" 29 #include "exec/log.h" 30 #include "helper_regs.h" 31 #include "qemu/error-report.h" 32 #include "qemu/qemu-print.h" 33 #include "internal.h" 34 #include "mmu-book3s-v3.h" 35 #include "mmu-radix64.h" 36 #include "mmu-booke.h" 37 38 /* #define DUMP_PAGE_TABLES */ 39 40 /* Context used internally during MMU translations */ 41 typedef struct { 42 hwaddr raddr; /* Real address */ 43 int prot; /* Protection bits */ 44 target_ulong ptem; /* Virtual segment ID | API */ 45 int key; /* Access key */ 46 } mmu_ctx_t; 47 48 void ppc_store_sdr1(CPUPPCState *env, target_ulong value) 49 { 50 PowerPCCPU *cpu = env_archcpu(env); 51 qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); 52 assert(!cpu->env.has_hv_mode || !cpu->vhyp); 53 #if defined(TARGET_PPC64) 54 if (mmu_is_64bit(env->mmu_model)) { 55 target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE; 56 target_ulong htabsize = value & SDR_64_HTABSIZE; 57 58 if (value & ~sdr_mask) { 59 qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx 60 " set in SDR1", value & ~sdr_mask); 61 value &= sdr_mask; 62 } 63 if (htabsize > 28) { 64 qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx 65 " stored in SDR1", htabsize); 66 return; 67 } 68 } 69 #endif /* defined(TARGET_PPC64) */ 70 /* FIXME: Should check for valid HTABMASK values in 32-bit case */ 71 env->spr[SPR_SDR1] = value; 72 } 73 74 /*****************************************************************************/ 75 /* PowerPC MMU emulation */ 76 77 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr, 78 int way, int is_code) 79 { 80 int nr; 81 82 /* Select TLB num in a way from address */ 83 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1); 84 /* Select TLB way */ 85 nr += env->tlb_per_way * way; 86 /* 6xx has separate TLBs for instructions and data */ 87 if (is_code) { 88 nr += env->nb_tlb; 89 } 90 91 return nr; 92 } 93 94 /* Software driven TLB helpers */ 95 96 static int ppc6xx_tlb_check(CPUPPCState *env, 97 mmu_ctx_t *ctx, target_ulong eaddr, 98 MMUAccessType access_type, bool nx) 99 { 100 ppc6xx_tlb_t *tlb; 101 target_ulong *pte1p; 102 int nr, best, way, ret; 103 104 best = -1; 105 ret = -1; /* No TLB found */ 106 for (way = 0; way < env->nb_ways; way++) { 107 nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH); 108 tlb = &env->tlb.tlb6[nr]; 109 /* This test "emulates" the PTE index match for hardware TLBs */ 110 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { 111 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx 112 " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n", 113 nr, env->nb_tlb, 114 pte_is_valid(tlb->pte0) ? "valid" : "inval", 115 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); 116 continue; 117 } 118 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " 119 TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n", 120 nr, env->nb_tlb, 121 pte_is_valid(tlb->pte0) ? "valid" : "inval", 122 tlb->EPN, eaddr, tlb->pte1, 123 access_type == MMU_DATA_STORE ? 'S' : 'L', 124 access_type == MMU_INST_FETCH ? 'I' : 'D'); 125 /* Check validity and table match */ 126 if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 || 127 (tlb->pte0 & PTE_PTEM_MASK) != ctx->ptem) { 128 continue; 129 } 130 /* all matches should have equal RPN, WIMG & PP */ 131 if (ctx->raddr != (hwaddr)-1ULL && 132 (ctx->raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) { 133 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n"); 134 /* TLB inconsistency */ 135 continue; 136 } 137 /* Keep the matching PTE information */ 138 best = nr; 139 ctx->raddr = tlb->pte1; 140 ctx->prot = ppc_hash32_prot(ctx->key, tlb->pte1 & HPTE32_R_PP, nx); 141 if (check_prot_access_type(ctx->prot, access_type)) { 142 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); 143 ret = 0; 144 break; 145 } else { 146 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); 147 ret = -2; 148 } 149 } 150 if (best != -1) { 151 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx 152 " prot=%01x ret=%d\n", 153 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); 154 /* Update page flags */ 155 pte1p = &env->tlb.tlb6[best].pte1; 156 *pte1p |= 0x00000100; /* Update accessed flag */ 157 if (!(*pte1p & 0x00000080)) { 158 if (access_type == MMU_DATA_STORE && ret == 0) { 159 /* Update changed flag */ 160 *pte1p |= 0x00000080; 161 } else { 162 /* Force page fault for first write access */ 163 ctx->prot &= ~PAGE_WRITE; 164 } 165 } 166 } 167 #if defined(DUMP_PAGE_TABLES) 168 if (qemu_loglevel_mask(CPU_LOG_MMU)) { 169 CPUState *cs = env_cpu(env); 170 hwaddr base = ppc_hash32_hpt_base(env_archcpu(env)); 171 hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80; 172 uint32_t a0, a1, a2, a3; 173 174 qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n", 175 base, len); 176 for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) { 177 a0 = ldl_phys(cs->as, curaddr); 178 a1 = ldl_phys(cs->as, curaddr + 4); 179 a2 = ldl_phys(cs->as, curaddr + 8); 180 a3 = ldl_phys(cs->as, curaddr + 12); 181 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) { 182 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n", 183 curaddr, a0, a1, a2, a3); 184 } 185 } 186 } 187 #endif 188 return ret; 189 } 190 191 /* Perform BAT hit & translation */ 192 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, 193 int *validp, int *protp, target_ulong *BATu, 194 target_ulong *BATl) 195 { 196 target_ulong bl; 197 int pp, valid, prot; 198 199 bl = (*BATu & 0x00001FFC) << 15; 200 valid = 0; 201 prot = 0; 202 if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) || 203 (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) { 204 valid = 1; 205 pp = *BATl & 0x00000003; 206 if (pp != 0) { 207 prot = PAGE_READ | PAGE_EXEC; 208 if (pp == 0x2) { 209 prot |= PAGE_WRITE; 210 } 211 } 212 } 213 *blp = bl; 214 *validp = valid; 215 *protp = prot; 216 } 217 218 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, 219 target_ulong virtual, MMUAccessType access_type) 220 { 221 target_ulong *BATlt, *BATut, *BATu, *BATl; 222 target_ulong BEPIl, BEPIu, bl; 223 int i, valid, prot; 224 int ret = -1; 225 bool ifetch = access_type == MMU_INST_FETCH; 226 227 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__, 228 ifetch ? 'I' : 'D', virtual); 229 if (ifetch) { 230 BATlt = env->IBAT[1]; 231 BATut = env->IBAT[0]; 232 } else { 233 BATlt = env->DBAT[1]; 234 BATut = env->DBAT[0]; 235 } 236 for (i = 0; i < env->nb_BATs; i++) { 237 BATu = &BATut[i]; 238 BATl = &BATlt[i]; 239 BEPIu = *BATu & 0xF0000000; 240 BEPIl = *BATu & 0x0FFE0000; 241 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); 242 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " 243 TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, 244 ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); 245 if ((virtual & 0xF0000000) == BEPIu && 246 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { 247 /* BAT matches */ 248 if (valid != 0) { 249 /* Get physical address */ 250 ctx->raddr = (*BATl & 0xF0000000) | 251 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | 252 (virtual & 0x0001F000); 253 /* Compute access rights */ 254 ctx->prot = prot; 255 if (check_prot_access_type(ctx->prot, access_type)) { 256 qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx 257 " prot=%c%c\n", i, ctx->raddr, 258 ctx->prot & PAGE_READ ? 'R' : '-', 259 ctx->prot & PAGE_WRITE ? 'W' : '-'); 260 ret = 0; 261 } else { 262 ret = -2; 263 } 264 break; 265 } 266 } 267 } 268 if (ret < 0) { 269 if (qemu_log_enabled()) { 270 qemu_log_mask(CPU_LOG_MMU, "no BAT match for " 271 TARGET_FMT_lx ":\n", virtual); 272 for (i = 0; i < 4; i++) { 273 BATu = &BATut[i]; 274 BATl = &BATlt[i]; 275 BEPIu = *BATu & 0xF0000000; 276 BEPIl = *BATu & 0x0FFE0000; 277 bl = (*BATu & 0x00001FFC) << 15; 278 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx 279 " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx 280 "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " " 281 TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', 282 i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl); 283 } 284 } 285 } 286 /* No hit */ 287 return ret; 288 } 289 290 static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, 291 target_ulong eaddr, hwaddr *hashp, 292 MMUAccessType access_type, int type) 293 { 294 PowerPCCPU *cpu = env_archcpu(env); 295 hwaddr hash; 296 target_ulong vsid, sr, pgidx; 297 bool pr, ds, nx; 298 299 /* First try to find a BAT entry if there are any */ 300 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) { 301 return 0; 302 } 303 304 /* Perform segment based translation when no BATs matched */ 305 pr = FIELD_EX64(env->msr, MSR, PR); 306 307 sr = env->sr[eaddr >> 28]; 308 ctx->key = (((sr & 0x20000000) && pr) || 309 ((sr & 0x40000000) && !pr)) ? 1 : 0; 310 ds = sr & SR32_T; 311 nx = sr & SR32_NX; 312 vsid = sr & SR32_VSID; 313 qemu_log_mask(CPU_LOG_MMU, 314 "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx 315 " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx 316 " ir=%d dr=%d pr=%d %d t=%d\n", 317 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, 318 (int)FIELD_EX64(env->msr, MSR, IR), 319 (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0, 320 access_type == MMU_DATA_STORE, type); 321 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS; 322 hash = vsid ^ pgidx; 323 ctx->ptem = (vsid << 7) | (pgidx >> 10); 324 325 qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid " 326 TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid); 327 if (!ds) { 328 /* Check if instruction fetch is allowed, if needed */ 329 if (type == ACCESS_CODE && nx) { 330 qemu_log_mask(CPU_LOG_MMU, "No access allowed\n"); 331 return -3; 332 } 333 /* Page address translation */ 334 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask " 335 HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n", 336 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); 337 *hashp = hash; 338 339 /* Initialize real address with an invalid value */ 340 ctx->raddr = (hwaddr)-1ULL; 341 /* Software TLB search */ 342 return ppc6xx_tlb_check(env, ctx, eaddr, access_type, nx); 343 } 344 345 /* Direct-store segment : absolutely *BUGGY* for now */ 346 qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); 347 switch (type) { 348 case ACCESS_INT: 349 /* Integer load/store : only access allowed */ 350 break; 351 case ACCESS_CACHE: 352 /* 353 * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi 354 * 355 * Should make the instruction do no-op. As it already do 356 * no-op, it's quite easy :-) 357 */ 358 ctx->raddr = eaddr; 359 return 0; 360 case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */ 361 case ACCESS_FLOAT: /* Floating point load/store */ 362 case ACCESS_RES: /* lwarx, ldarx or srwcx. */ 363 case ACCESS_EXT: /* eciwx or ecowx */ 364 return -4; 365 } 366 if ((access_type == MMU_DATA_STORE || ctx->key != 1) && 367 (access_type == MMU_DATA_LOAD || ctx->key != 0)) { 368 ctx->raddr = eaddr; 369 return 2; 370 } 371 return -2; 372 } 373 374 static const char *book3e_tsize_to_str[32] = { 375 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", 376 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", 377 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G", 378 "1T", "2T" 379 }; 380 381 static void mmubooke_dump_mmu(CPUPPCState *env) 382 { 383 ppcemb_tlb_t *entry; 384 int i; 385 386 #ifdef CONFIG_KVM 387 if (kvm_enabled() && !env->kvm_sw_tlb) { 388 qemu_printf("Cannot access KVM TLB\n"); 389 return; 390 } 391 #endif 392 393 qemu_printf("\nTLB:\n"); 394 qemu_printf("Effective Physical Size PID Prot " 395 "Attr\n"); 396 397 entry = &env->tlb.tlbe[0]; 398 for (i = 0; i < env->nb_tlb; i++, entry++) { 399 hwaddr ea, pa; 400 target_ulong mask; 401 uint64_t size = (uint64_t)entry->size; 402 char size_buf[20]; 403 404 /* Check valid flag */ 405 if (!(entry->prot & PAGE_VALID)) { 406 continue; 407 } 408 409 mask = ~(entry->size - 1); 410 ea = entry->EPN & mask; 411 pa = entry->RPN & mask; 412 /* Extend the physical address to 36 bits */ 413 pa |= (hwaddr)(entry->RPN & 0xF) << 32; 414 if (size >= 1 * MiB) { 415 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB); 416 } else { 417 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB); 418 } 419 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n", 420 (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID, 421 entry->prot, entry->attr); 422 } 423 424 } 425 426 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset, 427 int tlbsize) 428 { 429 ppcmas_tlb_t *entry; 430 int i; 431 432 qemu_printf("\nTLB%d:\n", tlbn); 433 qemu_printf("Effective Physical Size TID TS SRWX" 434 " URWX WIMGE U0123\n"); 435 436 entry = &env->tlb.tlbm[offset]; 437 for (i = 0; i < tlbsize; i++, entry++) { 438 hwaddr ea, pa, size; 439 int tsize; 440 441 if (!(entry->mas1 & MAS1_VALID)) { 442 continue; 443 } 444 445 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; 446 size = 1024ULL << tsize; 447 ea = entry->mas2 & ~(size - 1); 448 pa = entry->mas7_3 & ~(size - 1); 449 450 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c" 451 " U%c%c%c %c%c%c%c%c U%c%c%c%c\n", 452 (uint64_t)ea, (uint64_t)pa, 453 book3e_tsize_to_str[tsize], 454 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT, 455 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT, 456 entry->mas7_3 & MAS3_SR ? 'R' : '-', 457 entry->mas7_3 & MAS3_SW ? 'W' : '-', 458 entry->mas7_3 & MAS3_SX ? 'X' : '-', 459 entry->mas7_3 & MAS3_UR ? 'R' : '-', 460 entry->mas7_3 & MAS3_UW ? 'W' : '-', 461 entry->mas7_3 & MAS3_UX ? 'X' : '-', 462 entry->mas2 & MAS2_W ? 'W' : '-', 463 entry->mas2 & MAS2_I ? 'I' : '-', 464 entry->mas2 & MAS2_M ? 'M' : '-', 465 entry->mas2 & MAS2_G ? 'G' : '-', 466 entry->mas2 & MAS2_E ? 'E' : '-', 467 entry->mas7_3 & MAS3_U0 ? '0' : '-', 468 entry->mas7_3 & MAS3_U1 ? '1' : '-', 469 entry->mas7_3 & MAS3_U2 ? '2' : '-', 470 entry->mas7_3 & MAS3_U3 ? '3' : '-'); 471 } 472 } 473 474 static void mmubooke206_dump_mmu(CPUPPCState *env) 475 { 476 int offset = 0; 477 int i; 478 479 #ifdef CONFIG_KVM 480 if (kvm_enabled() && !env->kvm_sw_tlb) { 481 qemu_printf("Cannot access KVM TLB\n"); 482 return; 483 } 484 #endif 485 486 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 487 int size = booke206_tlb_size(env, i); 488 489 if (size == 0) { 490 continue; 491 } 492 493 mmubooke206_dump_one_tlb(env, i, offset, size); 494 offset += size; 495 } 496 } 497 498 static void mmu6xx_dump_BATs(CPUPPCState *env, int type) 499 { 500 target_ulong *BATlt, *BATut, *BATu, *BATl; 501 target_ulong BEPIl, BEPIu, bl; 502 int i; 503 504 switch (type) { 505 case ACCESS_CODE: 506 BATlt = env->IBAT[1]; 507 BATut = env->IBAT[0]; 508 break; 509 default: 510 BATlt = env->DBAT[1]; 511 BATut = env->DBAT[0]; 512 break; 513 } 514 515 for (i = 0; i < env->nb_BATs; i++) { 516 BATu = &BATut[i]; 517 BATl = &BATlt[i]; 518 BEPIu = *BATu & 0xF0000000; 519 BEPIl = *BATu & 0x0FFE0000; 520 bl = (*BATu & 0x00001FFC) << 15; 521 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx 522 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " 523 TARGET_FMT_lx " " TARGET_FMT_lx "\n", 524 type == ACCESS_CODE ? "code" : "data", i, 525 *BATu, *BATl, BEPIu, BEPIl, bl); 526 } 527 } 528 529 static void mmu6xx_dump_mmu(CPUPPCState *env) 530 { 531 PowerPCCPU *cpu = env_archcpu(env); 532 ppc6xx_tlb_t *tlb; 533 target_ulong sr; 534 int type, way, entry, i; 535 536 qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu)); 537 qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu)); 538 539 qemu_printf("\nSegment registers:\n"); 540 for (i = 0; i < 32; i++) { 541 sr = env->sr[i]; 542 if (sr & 0x80000000) { 543 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x " 544 "CNTLR_SPEC=0x%05x\n", i, 545 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 546 sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF), 547 (uint32_t)(sr & 0xFFFFF)); 548 } else { 549 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i, 550 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 551 sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0, 552 (uint32_t)(sr & 0x00FFFFFF)); 553 } 554 } 555 556 qemu_printf("\nBATs:\n"); 557 mmu6xx_dump_BATs(env, ACCESS_INT); 558 mmu6xx_dump_BATs(env, ACCESS_CODE); 559 560 qemu_printf("\nTLBs [EPN EPN + SIZE]\n"); 561 for (type = 0; type < 2; type++) { 562 for (way = 0; way < env->nb_ways; way++) { 563 for (entry = env->nb_tlb * type + env->tlb_per_way * way; 564 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1)); 565 entry++) { 566 567 tlb = &env->tlb.tlb6[entry]; 568 qemu_printf("%s TLB %02d/%02d way:%d %s [" 569 TARGET_FMT_lx " " TARGET_FMT_lx "]\n", 570 type ? "code" : "data", entry % env->nb_tlb, 571 env->nb_tlb, way, 572 pte_is_valid(tlb->pte0) ? "valid" : "inval", 573 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE); 574 } 575 } 576 } 577 } 578 579 void dump_mmu(CPUPPCState *env) 580 { 581 switch (env->mmu_model) { 582 case POWERPC_MMU_BOOKE: 583 mmubooke_dump_mmu(env); 584 break; 585 case POWERPC_MMU_BOOKE206: 586 mmubooke206_dump_mmu(env); 587 break; 588 case POWERPC_MMU_SOFT_6xx: 589 mmu6xx_dump_mmu(env); 590 break; 591 #if defined(TARGET_PPC64) 592 case POWERPC_MMU_64B: 593 case POWERPC_MMU_2_03: 594 case POWERPC_MMU_2_06: 595 case POWERPC_MMU_2_07: 596 dump_slb(env_archcpu(env)); 597 break; 598 case POWERPC_MMU_3_00: 599 if (ppc64_v3_radix(env_archcpu(env))) { 600 qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n", 601 __func__); 602 } else { 603 dump_slb(env_archcpu(env)); 604 } 605 break; 606 #endif 607 default: 608 qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__); 609 } 610 } 611 612 613 static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr, 614 MMUAccessType access_type, 615 hwaddr *raddrp, int *psizep, int *protp) 616 { 617 CPUPPCState *env = &cpu->env; 618 619 if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR) 620 : !FIELD_EX64(env->msr, MSR, DR)) { 621 *raddrp = eaddr; 622 *protp = PAGE_RWX; 623 *psizep = TARGET_PAGE_BITS; 624 return true; 625 } else if (env->mmu_model == POWERPC_MMU_REAL) { 626 cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n"); 627 } 628 return false; 629 } 630 631 static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr, 632 MMUAccessType access_type, 633 hwaddr *raddrp, int *psizep, int *protp, 634 int mmu_idx, bool guest_visible) 635 { 636 CPUState *cs = CPU(cpu); 637 CPUPPCState *env = &cpu->env; 638 int ret; 639 640 if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 641 return true; 642 } 643 644 ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type); 645 if (ret == 0) { 646 *psizep = TARGET_PAGE_BITS; 647 return true; 648 } else if (!guest_visible) { 649 return false; 650 } 651 652 log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 653 if (access_type == MMU_INST_FETCH) { 654 switch (ret) { 655 case -1: 656 /* No matches in page tables or TLB */ 657 cs->exception_index = POWERPC_EXCP_ITLB; 658 env->error_code = 0; 659 env->spr[SPR_40x_DEAR] = eaddr; 660 env->spr[SPR_40x_ESR] = 0x00000000; 661 break; 662 case -2: 663 /* Access rights violation */ 664 cs->exception_index = POWERPC_EXCP_ISI; 665 env->error_code = 0x08000000; 666 break; 667 default: 668 g_assert_not_reached(); 669 } 670 } else { 671 switch (ret) { 672 case -1: 673 /* No matches in page tables or TLB */ 674 cs->exception_index = POWERPC_EXCP_DTLB; 675 env->error_code = 0; 676 env->spr[SPR_40x_DEAR] = eaddr; 677 if (access_type == MMU_DATA_STORE) { 678 env->spr[SPR_40x_ESR] = 0x00800000; 679 } else { 680 env->spr[SPR_40x_ESR] = 0x00000000; 681 } 682 break; 683 case -2: 684 /* Access rights violation */ 685 cs->exception_index = POWERPC_EXCP_DSI; 686 env->error_code = 0; 687 env->spr[SPR_40x_DEAR] = eaddr; 688 if (access_type == MMU_DATA_STORE) { 689 env->spr[SPR_40x_ESR] |= 0x00800000; 690 } 691 break; 692 default: 693 g_assert_not_reached(); 694 } 695 } 696 return false; 697 } 698 699 static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr, 700 MMUAccessType access_type, 701 hwaddr *raddrp, int *psizep, int *protp, 702 int mmu_idx, bool guest_visible) 703 { 704 CPUState *cs = CPU(cpu); 705 CPUPPCState *env = &cpu->env; 706 mmu_ctx_t ctx; 707 hwaddr hash = 0; /* init to 0 to avoid used uninit warning */ 708 int type, ret; 709 710 if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 711 return true; 712 } 713 714 if (access_type == MMU_INST_FETCH) { 715 /* code access */ 716 type = ACCESS_CODE; 717 } else if (guest_visible) { 718 /* data access */ 719 type = env->access_type; 720 } else { 721 type = ACCESS_INT; 722 } 723 724 ctx.prot = 0; 725 ret = mmu6xx_get_physical_address(env, &ctx, eaddr, &hash, 726 access_type, type); 727 if (ret == 0) { 728 *raddrp = ctx.raddr; 729 *protp = ctx.prot; 730 *psizep = TARGET_PAGE_BITS; 731 return true; 732 } else if (!guest_visible) { 733 return false; 734 } 735 736 log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 737 if (type == ACCESS_CODE) { 738 switch (ret) { 739 case -1: 740 /* No matches in page tables or TLB */ 741 cs->exception_index = POWERPC_EXCP_IFTLB; 742 env->error_code = 1 << 18; 743 env->spr[SPR_IMISS] = eaddr; 744 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; 745 goto tlb_miss; 746 case -2: 747 /* Access rights violation */ 748 cs->exception_index = POWERPC_EXCP_ISI; 749 env->error_code = 0x08000000; 750 break; 751 case -3: 752 /* No execute protection violation */ 753 cs->exception_index = POWERPC_EXCP_ISI; 754 env->error_code = 0x10000000; 755 break; 756 case -4: 757 /* Direct store exception */ 758 /* No code fetch is allowed in direct-store areas */ 759 cs->exception_index = POWERPC_EXCP_ISI; 760 env->error_code = 0x10000000; 761 break; 762 } 763 } else { 764 switch (ret) { 765 case -1: 766 /* No matches in page tables or TLB */ 767 if (access_type == MMU_DATA_STORE) { 768 cs->exception_index = POWERPC_EXCP_DSTLB; 769 env->error_code = 1 << 16; 770 } else { 771 cs->exception_index = POWERPC_EXCP_DLTLB; 772 env->error_code = 0; 773 } 774 env->spr[SPR_DMISS] = eaddr; 775 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; 776 tlb_miss: 777 env->error_code |= ctx.key << 19; 778 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) + 779 get_pteg_offset32(cpu, hash); 780 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) + 781 get_pteg_offset32(cpu, ~hash); 782 break; 783 case -2: 784 /* Access rights violation */ 785 cs->exception_index = POWERPC_EXCP_DSI; 786 env->error_code = 0; 787 env->spr[SPR_DAR] = eaddr; 788 if (access_type == MMU_DATA_STORE) { 789 env->spr[SPR_DSISR] = 0x0A000000; 790 } else { 791 env->spr[SPR_DSISR] = 0x08000000; 792 } 793 break; 794 case -4: 795 /* Direct store exception */ 796 switch (type) { 797 case ACCESS_FLOAT: 798 /* Floating point load/store */ 799 cs->exception_index = POWERPC_EXCP_ALIGN; 800 env->error_code = POWERPC_EXCP_ALIGN_FP; 801 env->spr[SPR_DAR] = eaddr; 802 break; 803 case ACCESS_RES: 804 /* lwarx, ldarx or stwcx. */ 805 cs->exception_index = POWERPC_EXCP_DSI; 806 env->error_code = 0; 807 env->spr[SPR_DAR] = eaddr; 808 if (access_type == MMU_DATA_STORE) { 809 env->spr[SPR_DSISR] = 0x06000000; 810 } else { 811 env->spr[SPR_DSISR] = 0x04000000; 812 } 813 break; 814 case ACCESS_EXT: 815 /* eciwx or ecowx */ 816 cs->exception_index = POWERPC_EXCP_DSI; 817 env->error_code = 0; 818 env->spr[SPR_DAR] = eaddr; 819 if (access_type == MMU_DATA_STORE) { 820 env->spr[SPR_DSISR] = 0x06100000; 821 } else { 822 env->spr[SPR_DSISR] = 0x04100000; 823 } 824 break; 825 default: 826 printf("DSI: invalid exception (%d)\n", ret); 827 cs->exception_index = POWERPC_EXCP_PROGRAM; 828 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; 829 env->spr[SPR_DAR] = eaddr; 830 break; 831 } 832 break; 833 } 834 } 835 return false; 836 } 837 838 /*****************************************************************************/ 839 840 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, 841 hwaddr *raddrp, int *psizep, int *protp, 842 int mmu_idx, bool guest_visible) 843 { 844 switch (cpu->env.mmu_model) { 845 #if defined(TARGET_PPC64) 846 case POWERPC_MMU_3_00: 847 if (ppc64_v3_radix(cpu)) { 848 return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp, 849 psizep, protp, mmu_idx, guest_visible); 850 } 851 /* fall through */ 852 case POWERPC_MMU_64B: 853 case POWERPC_MMU_2_03: 854 case POWERPC_MMU_2_06: 855 case POWERPC_MMU_2_07: 856 return ppc_hash64_xlate(cpu, eaddr, access_type, 857 raddrp, psizep, protp, mmu_idx, guest_visible); 858 #endif 859 860 case POWERPC_MMU_32B: 861 return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp, 862 psizep, protp, mmu_idx, guest_visible); 863 case POWERPC_MMU_BOOKE: 864 case POWERPC_MMU_BOOKE206: 865 return ppc_booke_xlate(cpu, eaddr, access_type, raddrp, 866 psizep, protp, mmu_idx, guest_visible); 867 case POWERPC_MMU_SOFT_4xx: 868 return ppc_40x_xlate(cpu, eaddr, access_type, raddrp, 869 psizep, protp, mmu_idx, guest_visible); 870 case POWERPC_MMU_SOFT_6xx: 871 return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp, 872 psizep, protp, mmu_idx, guest_visible); 873 case POWERPC_MMU_REAL: 874 return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, 875 protp); 876 case POWERPC_MMU_MPC8xx: 877 cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n"); 878 default: 879 cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n"); 880 } 881 } 882 883 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 884 { 885 PowerPCCPU *cpu = POWERPC_CPU(cs); 886 hwaddr raddr; 887 int s, p; 888 889 /* 890 * Some MMUs have separate TLBs for code and data. If we only 891 * try an MMU_DATA_LOAD, we may not be able to read instructions 892 * mapped by code TLBs, so we also try a MMU_INST_FETCH. 893 */ 894 if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 895 ppc_env_mmu_index(&cpu->env, false), false) || 896 ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 897 ppc_env_mmu_index(&cpu->env, true), false)) { 898 return raddr & TARGET_PAGE_MASK; 899 } 900 return -1; 901 } 902