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