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