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