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/log.h" 29 #include "helper_regs.h" 30 #include "qemu/error-report.h" 31 #include "qemu/main-loop.h" 32 #include "qemu/qemu-print.h" 33 #include "internal.h" 34 #include "mmu-book3s-v3.h" 35 #include "mmu-radix64.h" 36 #include "exec/helper-proto.h" 37 #include "exec/cpu_ldst.h" 38 39 /* #define FLUSH_ALL_TLBS */ 40 41 /*****************************************************************************/ 42 /* PowerPC MMU emulation */ 43 44 /* Software driven TLB helpers */ 45 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env) 46 { 47 ppc6xx_tlb_t *tlb; 48 int nr, max; 49 50 /* LOG_SWTLB("Invalidate all TLBs\n"); */ 51 /* Invalidate all defined software TLB */ 52 max = env->nb_tlb; 53 if (env->id_tlbs == 1) { 54 max *= 2; 55 } 56 for (nr = 0; nr < max; nr++) { 57 tlb = &env->tlb.tlb6[nr]; 58 pte_invalidate(&tlb->pte0); 59 } 60 tlb_flush(env_cpu(env)); 61 } 62 63 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env, 64 target_ulong eaddr, 65 int is_code, int match_epn) 66 { 67 #if !defined(FLUSH_ALL_TLBS) 68 CPUState *cs = env_cpu(env); 69 ppc6xx_tlb_t *tlb; 70 int way, nr; 71 72 /* Invalidate ITLB + DTLB, all ways */ 73 for (way = 0; way < env->nb_ways; way++) { 74 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code); 75 tlb = &env->tlb.tlb6[nr]; 76 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) { 77 qemu_log_mask(CPU_LOG_MMU, "TLB invalidate %d/%d " 78 TARGET_FMT_lx "\n", nr, env->nb_tlb, eaddr); 79 pte_invalidate(&tlb->pte0); 80 tlb_flush_page(cs, tlb->EPN); 81 } 82 } 83 #else 84 /* XXX: PowerPC specification say this is valid as well */ 85 ppc6xx_tlb_invalidate_all(env); 86 #endif 87 } 88 89 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env, 90 target_ulong eaddr, int is_code) 91 { 92 ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0); 93 } 94 95 static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way, 96 int is_code, target_ulong pte0, target_ulong pte1) 97 { 98 ppc6xx_tlb_t *tlb; 99 int nr; 100 101 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code); 102 tlb = &env->tlb.tlb6[nr]; 103 qemu_log_mask(CPU_LOG_MMU, "Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " 104 TARGET_FMT_lx " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, 105 EPN, pte0, pte1); 106 /* Invalidate any pending reference in QEMU for this virtual address */ 107 ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1); 108 tlb->pte0 = pte0; 109 tlb->pte1 = pte1; 110 tlb->EPN = EPN; 111 /* Store last way for LRU mechanism */ 112 env->last_way = way; 113 } 114 115 /* Generic TLB search function for PowerPC embedded implementations */ 116 static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, 117 uint32_t pid) 118 { 119 ppcemb_tlb_t *tlb; 120 hwaddr raddr; 121 int i, ret; 122 123 /* Default return value is no match */ 124 ret = -1; 125 for (i = 0; i < env->nb_tlb; i++) { 126 tlb = &env->tlb.tlbe[i]; 127 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) { 128 ret = i; 129 break; 130 } 131 } 132 133 return ret; 134 } 135 136 /* Helpers specific to PowerPC 40x implementations */ 137 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env) 138 { 139 ppcemb_tlb_t *tlb; 140 int i; 141 142 for (i = 0; i < env->nb_tlb; i++) { 143 tlb = &env->tlb.tlbe[i]; 144 tlb->prot &= ~PAGE_VALID; 145 } 146 tlb_flush(env_cpu(env)); 147 } 148 149 static void booke206_flush_tlb(CPUPPCState *env, int flags, 150 const int check_iprot) 151 { 152 int tlb_size; 153 int i, j; 154 ppcmas_tlb_t *tlb = env->tlb.tlbm; 155 156 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 157 if (flags & (1 << i)) { 158 tlb_size = booke206_tlb_size(env, i); 159 for (j = 0; j < tlb_size; j++) { 160 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) { 161 tlb[j].mas1 &= ~MAS1_VALID; 162 } 163 } 164 } 165 tlb += booke206_tlb_size(env, i); 166 } 167 168 tlb_flush(env_cpu(env)); 169 } 170 171 static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, 172 target_ulong eaddr, MMUAccessType access_type, 173 int type) 174 { 175 return get_physical_address_wtlb(env, ctx, eaddr, access_type, type, 0); 176 } 177 178 179 180 /*****************************************************************************/ 181 /* BATs management */ 182 #if !defined(FLUSH_ALL_TLBS) 183 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu, 184 target_ulong mask) 185 { 186 CPUState *cs = env_cpu(env); 187 target_ulong base, end, page; 188 189 base = BATu & ~0x0001FFFF; 190 end = base + mask + 0x00020000; 191 if (((end - base) >> TARGET_PAGE_BITS) > 1024) { 192 /* Flushing 1024 4K pages is slower than a complete flush */ 193 qemu_log_mask(CPU_LOG_MMU, "Flush all BATs\n"); 194 tlb_flush(cs); 195 qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); 196 return; 197 } 198 qemu_log_mask(CPU_LOG_MMU, "Flush BAT from " TARGET_FMT_lx 199 " to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", 200 base, end, mask); 201 for (page = base; page != end; page += TARGET_PAGE_SIZE) { 202 tlb_flush_page(cs, page); 203 } 204 qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); 205 } 206 #endif 207 208 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr, 209 target_ulong value) 210 { 211 qemu_log_mask(CPU_LOG_MMU, "Set %cBAT%d%c to " TARGET_FMT_lx " (" 212 TARGET_FMT_lx ")\n", ID, nr, ul == 0 ? 'u' : 'l', 213 value, env->nip); 214 } 215 216 void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value) 217 { 218 target_ulong mask; 219 220 dump_store_bat(env, 'I', 0, nr, value); 221 if (env->IBAT[0][nr] != value) { 222 mask = (value << 15) & 0x0FFE0000UL; 223 #if !defined(FLUSH_ALL_TLBS) 224 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 225 #endif 226 /* 227 * When storing valid upper BAT, mask BEPI and BRPN and 228 * invalidate all TLBs covered by this BAT 229 */ 230 mask = (value << 15) & 0x0FFE0000UL; 231 env->IBAT[0][nr] = (value & 0x00001FFFUL) | 232 (value & ~0x0001FFFFUL & ~mask); 233 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) | 234 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask); 235 #if !defined(FLUSH_ALL_TLBS) 236 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 237 #else 238 tlb_flush(env_cpu(env)); 239 #endif 240 } 241 } 242 243 void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value) 244 { 245 dump_store_bat(env, 'I', 1, nr, value); 246 env->IBAT[1][nr] = value; 247 } 248 249 void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value) 250 { 251 target_ulong mask; 252 253 dump_store_bat(env, 'D', 0, nr, value); 254 if (env->DBAT[0][nr] != value) { 255 /* 256 * When storing valid upper BAT, mask BEPI and BRPN and 257 * invalidate all TLBs covered by this BAT 258 */ 259 mask = (value << 15) & 0x0FFE0000UL; 260 #if !defined(FLUSH_ALL_TLBS) 261 do_invalidate_BAT(env, env->DBAT[0][nr], mask); 262 #endif 263 mask = (value << 15) & 0x0FFE0000UL; 264 env->DBAT[0][nr] = (value & 0x00001FFFUL) | 265 (value & ~0x0001FFFFUL & ~mask); 266 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) | 267 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask); 268 #if !defined(FLUSH_ALL_TLBS) 269 do_invalidate_BAT(env, env->DBAT[0][nr], mask); 270 #else 271 tlb_flush(env_cpu(env)); 272 #endif 273 } 274 } 275 276 void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value) 277 { 278 dump_store_bat(env, 'D', 1, nr, value); 279 env->DBAT[1][nr] = value; 280 } 281 282 void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value) 283 { 284 target_ulong mask; 285 #if defined(FLUSH_ALL_TLBS) 286 int do_inval; 287 #endif 288 289 dump_store_bat(env, 'I', 0, nr, value); 290 if (env->IBAT[0][nr] != value) { 291 #if defined(FLUSH_ALL_TLBS) 292 do_inval = 0; 293 #endif 294 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; 295 if (env->IBAT[1][nr] & 0x40) { 296 /* Invalidate BAT only if it is valid */ 297 #if !defined(FLUSH_ALL_TLBS) 298 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 299 #else 300 do_inval = 1; 301 #endif 302 } 303 /* 304 * When storing valid upper BAT, mask BEPI and BRPN and 305 * invalidate all TLBs covered by this BAT 306 */ 307 env->IBAT[0][nr] = (value & 0x00001FFFUL) | 308 (value & ~0x0001FFFFUL & ~mask); 309 env->DBAT[0][nr] = env->IBAT[0][nr]; 310 if (env->IBAT[1][nr] & 0x40) { 311 #if !defined(FLUSH_ALL_TLBS) 312 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 313 #else 314 do_inval = 1; 315 #endif 316 } 317 #if defined(FLUSH_ALL_TLBS) 318 if (do_inval) { 319 tlb_flush(env_cpu(env)); 320 } 321 #endif 322 } 323 } 324 325 void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value) 326 { 327 #if !defined(FLUSH_ALL_TLBS) 328 target_ulong mask; 329 #else 330 int do_inval; 331 #endif 332 333 dump_store_bat(env, 'I', 1, nr, value); 334 if (env->IBAT[1][nr] != value) { 335 #if defined(FLUSH_ALL_TLBS) 336 do_inval = 0; 337 #endif 338 if (env->IBAT[1][nr] & 0x40) { 339 #if !defined(FLUSH_ALL_TLBS) 340 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; 341 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 342 #else 343 do_inval = 1; 344 #endif 345 } 346 if (value & 0x40) { 347 #if !defined(FLUSH_ALL_TLBS) 348 mask = (value << 17) & 0x0FFE0000UL; 349 do_invalidate_BAT(env, env->IBAT[0][nr], mask); 350 #else 351 do_inval = 1; 352 #endif 353 } 354 env->IBAT[1][nr] = value; 355 env->DBAT[1][nr] = value; 356 #if defined(FLUSH_ALL_TLBS) 357 if (do_inval) { 358 tlb_flush(env_cpu(env)); 359 } 360 #endif 361 } 362 } 363 364 /*****************************************************************************/ 365 /* TLB management */ 366 void ppc_tlb_invalidate_all(CPUPPCState *env) 367 { 368 #if defined(TARGET_PPC64) 369 if (mmu_is_64bit(env->mmu_model)) { 370 env->tlb_need_flush = 0; 371 tlb_flush(env_cpu(env)); 372 } else 373 #endif /* defined(TARGET_PPC64) */ 374 switch (env->mmu_model) { 375 case POWERPC_MMU_SOFT_6xx: 376 ppc6xx_tlb_invalidate_all(env); 377 break; 378 case POWERPC_MMU_SOFT_4xx: 379 ppc4xx_tlb_invalidate_all(env); 380 break; 381 case POWERPC_MMU_REAL: 382 cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n"); 383 break; 384 case POWERPC_MMU_MPC8xx: 385 /* XXX: TODO */ 386 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n"); 387 break; 388 case POWERPC_MMU_BOOKE: 389 tlb_flush(env_cpu(env)); 390 break; 391 case POWERPC_MMU_BOOKE206: 392 booke206_flush_tlb(env, -1, 0); 393 break; 394 case POWERPC_MMU_32B: 395 case POWERPC_MMU_601: 396 env->tlb_need_flush = 0; 397 tlb_flush(env_cpu(env)); 398 break; 399 default: 400 /* XXX: TODO */ 401 cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model); 402 break; 403 } 404 } 405 406 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) 407 { 408 #if !defined(FLUSH_ALL_TLBS) 409 addr &= TARGET_PAGE_MASK; 410 #if defined(TARGET_PPC64) 411 if (mmu_is_64bit(env->mmu_model)) { 412 /* tlbie invalidate TLBs for all segments */ 413 /* 414 * XXX: given the fact that there are too many segments to invalidate, 415 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU, 416 * we just invalidate all TLBs 417 */ 418 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; 419 } else 420 #endif /* defined(TARGET_PPC64) */ 421 switch (env->mmu_model) { 422 case POWERPC_MMU_SOFT_6xx: 423 ppc6xx_tlb_invalidate_virt(env, addr, 0); 424 if (env->id_tlbs == 1) { 425 ppc6xx_tlb_invalidate_virt(env, addr, 1); 426 } 427 break; 428 case POWERPC_MMU_32B: 429 case POWERPC_MMU_601: 430 /* 431 * Actual CPUs invalidate entire congruence classes based on 432 * the geometry of their TLBs and some OSes take that into 433 * account, we just mark the TLB to be flushed later (context 434 * synchronizing event or sync instruction on 32-bit). 435 */ 436 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; 437 break; 438 default: 439 /* Should never reach here with other MMU models */ 440 assert(0); 441 } 442 #else 443 ppc_tlb_invalidate_all(env); 444 #endif 445 } 446 447 /*****************************************************************************/ 448 /* Special registers manipulation */ 449 450 /* Segment registers load and store */ 451 target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num) 452 { 453 #if defined(TARGET_PPC64) 454 if (mmu_is_64bit(env->mmu_model)) { 455 /* XXX */ 456 return 0; 457 } 458 #endif 459 return env->sr[sr_num]; 460 } 461 462 void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value) 463 { 464 qemu_log_mask(CPU_LOG_MMU, 465 "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, 466 (int)srnum, value, env->sr[srnum]); 467 #if defined(TARGET_PPC64) 468 if (mmu_is_64bit(env->mmu_model)) { 469 PowerPCCPU *cpu = env_archcpu(env); 470 uint64_t esid, vsid; 471 472 /* ESID = srnum */ 473 esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V; 474 475 /* VSID = VSID */ 476 vsid = (value & 0xfffffff) << 12; 477 /* flags = flags */ 478 vsid |= ((value >> 27) & 0xf) << 8; 479 480 ppc_store_slb(cpu, srnum, esid, vsid); 481 } else 482 #endif 483 if (env->sr[srnum] != value) { 484 env->sr[srnum] = value; 485 /* 486 * Invalidating 256MB of virtual memory in 4kB pages is way 487 * longer than flushing the whole TLB. 488 */ 489 #if !defined(FLUSH_ALL_TLBS) && 0 490 { 491 target_ulong page, end; 492 /* Invalidate 256 MB of virtual memory */ 493 page = (16 << 20) * srnum; 494 end = page + (16 << 20); 495 for (; page != end; page += TARGET_PAGE_SIZE) { 496 tlb_flush_page(env_cpu(env), page); 497 } 498 } 499 #else 500 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; 501 #endif 502 } 503 } 504 505 /* TLB management */ 506 void helper_tlbia(CPUPPCState *env) 507 { 508 ppc_tlb_invalidate_all(env); 509 } 510 511 void helper_tlbie(CPUPPCState *env, target_ulong addr) 512 { 513 ppc_tlb_invalidate_one(env, addr); 514 } 515 516 void helper_tlbiva(CPUPPCState *env, target_ulong addr) 517 { 518 /* tlbiva instruction only exists on BookE */ 519 assert(env->mmu_model == POWERPC_MMU_BOOKE); 520 /* XXX: TODO */ 521 cpu_abort(env_cpu(env), "BookE MMU model is not implemented\n"); 522 } 523 524 /* Software driven TLBs management */ 525 /* PowerPC 602/603 software TLB load instructions helpers */ 526 static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code) 527 { 528 target_ulong RPN, CMP, EPN; 529 int way; 530 531 RPN = env->spr[SPR_RPA]; 532 if (is_code) { 533 CMP = env->spr[SPR_ICMP]; 534 EPN = env->spr[SPR_IMISS]; 535 } else { 536 CMP = env->spr[SPR_DCMP]; 537 EPN = env->spr[SPR_DMISS]; 538 } 539 way = (env->spr[SPR_SRR1] >> 17) & 1; 540 (void)EPN; /* avoid a compiler warning */ 541 qemu_log_mask(CPU_LOG_MMU, "%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx 542 " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", 543 __func__, new_EPN, EPN, CMP, RPN, way); 544 /* Store this TLB */ 545 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK), 546 way, is_code, CMP, RPN); 547 } 548 549 void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN) 550 { 551 do_6xx_tlb(env, EPN, 0); 552 } 553 554 void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN) 555 { 556 do_6xx_tlb(env, EPN, 1); 557 } 558 559 /*****************************************************************************/ 560 /* PowerPC 601 specific instructions (POWER bridge) */ 561 562 target_ulong helper_rac(CPUPPCState *env, target_ulong addr) 563 { 564 mmu_ctx_t ctx; 565 int nb_BATs; 566 target_ulong ret = 0; 567 568 /* 569 * We don't have to generate many instances of this instruction, 570 * as rac is supervisor only. 571 * 572 * XXX: FIX THIS: Pretend we have no BAT 573 */ 574 nb_BATs = env->nb_BATs; 575 env->nb_BATs = 0; 576 if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) { 577 ret = ctx.raddr; 578 } 579 env->nb_BATs = nb_BATs; 580 return ret; 581 } 582 583 static inline target_ulong booke_tlb_to_page_size(int size) 584 { 585 return 1024 << (2 * size); 586 } 587 588 static inline int booke_page_size_to_tlb(target_ulong page_size) 589 { 590 int size; 591 592 switch (page_size) { 593 case 0x00000400UL: 594 size = 0x0; 595 break; 596 case 0x00001000UL: 597 size = 0x1; 598 break; 599 case 0x00004000UL: 600 size = 0x2; 601 break; 602 case 0x00010000UL: 603 size = 0x3; 604 break; 605 case 0x00040000UL: 606 size = 0x4; 607 break; 608 case 0x00100000UL: 609 size = 0x5; 610 break; 611 case 0x00400000UL: 612 size = 0x6; 613 break; 614 case 0x01000000UL: 615 size = 0x7; 616 break; 617 case 0x04000000UL: 618 size = 0x8; 619 break; 620 case 0x10000000UL: 621 size = 0x9; 622 break; 623 case 0x40000000UL: 624 size = 0xA; 625 break; 626 #if defined(TARGET_PPC64) 627 case 0x000100000000ULL: 628 size = 0xB; 629 break; 630 case 0x000400000000ULL: 631 size = 0xC; 632 break; 633 case 0x001000000000ULL: 634 size = 0xD; 635 break; 636 case 0x004000000000ULL: 637 size = 0xE; 638 break; 639 case 0x010000000000ULL: 640 size = 0xF; 641 break; 642 #endif 643 default: 644 size = -1; 645 break; 646 } 647 648 return size; 649 } 650 651 /* Helpers for 4xx TLB management */ 652 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */ 653 654 #define PPC4XX_TLBHI_V 0x00000040 655 #define PPC4XX_TLBHI_E 0x00000020 656 #define PPC4XX_TLBHI_SIZE_MIN 0 657 #define PPC4XX_TLBHI_SIZE_MAX 7 658 #define PPC4XX_TLBHI_SIZE_DEFAULT 1 659 #define PPC4XX_TLBHI_SIZE_SHIFT 7 660 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007 661 662 #define PPC4XX_TLBLO_EX 0x00000200 663 #define PPC4XX_TLBLO_WR 0x00000100 664 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF 665 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00 666 667 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry) 668 { 669 ppcemb_tlb_t *tlb; 670 target_ulong ret; 671 int size; 672 673 entry &= PPC4XX_TLB_ENTRY_MASK; 674 tlb = &env->tlb.tlbe[entry]; 675 ret = tlb->EPN; 676 if (tlb->prot & PAGE_VALID) { 677 ret |= PPC4XX_TLBHI_V; 678 } 679 size = booke_page_size_to_tlb(tlb->size); 680 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) { 681 size = PPC4XX_TLBHI_SIZE_DEFAULT; 682 } 683 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; 684 env->spr[SPR_40x_PID] = tlb->PID; 685 return ret; 686 } 687 688 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry) 689 { 690 ppcemb_tlb_t *tlb; 691 target_ulong ret; 692 693 entry &= PPC4XX_TLB_ENTRY_MASK; 694 tlb = &env->tlb.tlbe[entry]; 695 ret = tlb->RPN; 696 if (tlb->prot & PAGE_EXEC) { 697 ret |= PPC4XX_TLBLO_EX; 698 } 699 if (tlb->prot & PAGE_WRITE) { 700 ret |= PPC4XX_TLBLO_WR; 701 } 702 return ret; 703 } 704 705 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, 706 target_ulong val) 707 { 708 CPUState *cs = env_cpu(env); 709 ppcemb_tlb_t *tlb; 710 target_ulong page, end; 711 712 qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n", 713 __func__, (int)entry, 714 val); 715 entry &= PPC4XX_TLB_ENTRY_MASK; 716 tlb = &env->tlb.tlbe[entry]; 717 /* Invalidate previous TLB (if it's valid) */ 718 if (tlb->prot & PAGE_VALID) { 719 end = tlb->EPN + tlb->size; 720 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " 721 TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, 722 (int)entry, tlb->EPN, end); 723 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { 724 tlb_flush_page(cs, page); 725 } 726 } 727 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT) 728 & PPC4XX_TLBHI_SIZE_MASK); 729 /* 730 * We cannot handle TLB size < TARGET_PAGE_SIZE. 731 * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY 732 */ 733 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) { 734 cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u " 735 "are not supported (%d)\n" 736 "Please implement TARGET_PAGE_BITS_VARY\n", 737 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); 738 } 739 tlb->EPN = val & ~(tlb->size - 1); 740 if (val & PPC4XX_TLBHI_V) { 741 tlb->prot |= PAGE_VALID; 742 if (val & PPC4XX_TLBHI_E) { 743 /* XXX: TO BE FIXED */ 744 cpu_abort(cs, 745 "Little-endian TLB entries are not supported by now\n"); 746 } 747 } else { 748 tlb->prot &= ~PAGE_VALID; 749 } 750 tlb->PID = env->spr[SPR_40x_PID]; /* PID */ 751 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx 752 " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx 753 " prot %c%c%c%c PID %d\n", __func__, 754 (int)entry, tlb->RPN, tlb->EPN, tlb->size, 755 tlb->prot & PAGE_READ ? 'r' : '-', 756 tlb->prot & PAGE_WRITE ? 'w' : '-', 757 tlb->prot & PAGE_EXEC ? 'x' : '-', 758 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); 759 /* Invalidate new TLB (if valid) */ 760 if (tlb->prot & PAGE_VALID) { 761 end = tlb->EPN + tlb->size; 762 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start " 763 TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, 764 (int)entry, tlb->EPN, end); 765 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { 766 tlb_flush_page(cs, page); 767 } 768 } 769 } 770 771 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, 772 target_ulong val) 773 { 774 ppcemb_tlb_t *tlb; 775 776 qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n", 777 __func__, (int)entry, val); 778 entry &= PPC4XX_TLB_ENTRY_MASK; 779 tlb = &env->tlb.tlbe[entry]; 780 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; 781 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK; 782 tlb->prot = PAGE_READ; 783 if (val & PPC4XX_TLBLO_EX) { 784 tlb->prot |= PAGE_EXEC; 785 } 786 if (val & PPC4XX_TLBLO_WR) { 787 tlb->prot |= PAGE_WRITE; 788 } 789 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx 790 " EPN " TARGET_FMT_lx 791 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, 792 (int)entry, tlb->RPN, tlb->EPN, tlb->size, 793 tlb->prot & PAGE_READ ? 'r' : '-', 794 tlb->prot & PAGE_WRITE ? 'w' : '-', 795 tlb->prot & PAGE_EXEC ? 'x' : '-', 796 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); 797 } 798 799 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address) 800 { 801 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); 802 } 803 804 /* PowerPC 440 TLB management */ 805 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry, 806 target_ulong value) 807 { 808 ppcemb_tlb_t *tlb; 809 target_ulong EPN, RPN, size; 810 int do_flush_tlbs; 811 812 qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n", 813 __func__, word, (int)entry, value); 814 do_flush_tlbs = 0; 815 entry &= 0x3F; 816 tlb = &env->tlb.tlbe[entry]; 817 switch (word) { 818 default: 819 /* Just here to please gcc */ 820 case 0: 821 EPN = value & 0xFFFFFC00; 822 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) { 823 do_flush_tlbs = 1; 824 } 825 tlb->EPN = EPN; 826 size = booke_tlb_to_page_size((value >> 4) & 0xF); 827 if ((tlb->prot & PAGE_VALID) && tlb->size < size) { 828 do_flush_tlbs = 1; 829 } 830 tlb->size = size; 831 tlb->attr &= ~0x1; 832 tlb->attr |= (value >> 8) & 1; 833 if (value & 0x200) { 834 tlb->prot |= PAGE_VALID; 835 } else { 836 if (tlb->prot & PAGE_VALID) { 837 tlb->prot &= ~PAGE_VALID; 838 do_flush_tlbs = 1; 839 } 840 } 841 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF; 842 if (do_flush_tlbs) { 843 tlb_flush(env_cpu(env)); 844 } 845 break; 846 case 1: 847 RPN = value & 0xFFFFFC0F; 848 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) { 849 tlb_flush(env_cpu(env)); 850 } 851 tlb->RPN = RPN; 852 break; 853 case 2: 854 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00); 855 tlb->prot = tlb->prot & PAGE_VALID; 856 if (value & 0x1) { 857 tlb->prot |= PAGE_READ << 4; 858 } 859 if (value & 0x2) { 860 tlb->prot |= PAGE_WRITE << 4; 861 } 862 if (value & 0x4) { 863 tlb->prot |= PAGE_EXEC << 4; 864 } 865 if (value & 0x8) { 866 tlb->prot |= PAGE_READ; 867 } 868 if (value & 0x10) { 869 tlb->prot |= PAGE_WRITE; 870 } 871 if (value & 0x20) { 872 tlb->prot |= PAGE_EXEC; 873 } 874 break; 875 } 876 } 877 878 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word, 879 target_ulong entry) 880 { 881 ppcemb_tlb_t *tlb; 882 target_ulong ret; 883 int size; 884 885 entry &= 0x3F; 886 tlb = &env->tlb.tlbe[entry]; 887 switch (word) { 888 default: 889 /* Just here to please gcc */ 890 case 0: 891 ret = tlb->EPN; 892 size = booke_page_size_to_tlb(tlb->size); 893 if (size < 0 || size > 0xF) { 894 size = 1; 895 } 896 ret |= size << 4; 897 if (tlb->attr & 0x1) { 898 ret |= 0x100; 899 } 900 if (tlb->prot & PAGE_VALID) { 901 ret |= 0x200; 902 } 903 env->spr[SPR_440_MMUCR] &= ~0x000000FF; 904 env->spr[SPR_440_MMUCR] |= tlb->PID; 905 break; 906 case 1: 907 ret = tlb->RPN; 908 break; 909 case 2: 910 ret = tlb->attr & ~0x1; 911 if (tlb->prot & (PAGE_READ << 4)) { 912 ret |= 0x1; 913 } 914 if (tlb->prot & (PAGE_WRITE << 4)) { 915 ret |= 0x2; 916 } 917 if (tlb->prot & (PAGE_EXEC << 4)) { 918 ret |= 0x4; 919 } 920 if (tlb->prot & PAGE_READ) { 921 ret |= 0x8; 922 } 923 if (tlb->prot & PAGE_WRITE) { 924 ret |= 0x10; 925 } 926 if (tlb->prot & PAGE_EXEC) { 927 ret |= 0x20; 928 } 929 break; 930 } 931 return ret; 932 } 933 934 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address) 935 { 936 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); 937 } 938 939 /* PowerPC BookE 2.06 TLB management */ 940 941 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env) 942 { 943 uint32_t tlbncfg = 0; 944 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT; 945 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK); 946 int tlb; 947 948 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; 949 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb]; 950 951 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) { 952 cpu_abort(env_cpu(env), "we don't support HES yet\n"); 953 } 954 955 return booke206_get_tlbm(env, tlb, ea, esel); 956 } 957 958 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid) 959 { 960 env->spr[pidn] = pid; 961 /* changing PIDs mean we're in a different address space now */ 962 tlb_flush(env_cpu(env)); 963 } 964 965 void helper_booke_set_eplc(CPUPPCState *env, target_ulong val) 966 { 967 env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK; 968 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD); 969 } 970 void helper_booke_set_epsc(CPUPPCState *env, target_ulong val) 971 { 972 env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK; 973 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE); 974 } 975 976 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb) 977 { 978 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) { 979 tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK); 980 } else { 981 tlb_flush(env_cpu(env)); 982 } 983 } 984 985 void helper_booke206_tlbwe(CPUPPCState *env) 986 { 987 uint32_t tlbncfg, tlbn; 988 ppcmas_tlb_t *tlb; 989 uint32_t size_tlb, size_ps; 990 target_ulong mask; 991 992 993 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) { 994 case MAS0_WQ_ALWAYS: 995 /* good to go, write that entry */ 996 break; 997 case MAS0_WQ_COND: 998 /* XXX check if reserved */ 999 if (0) { 1000 return; 1001 } 1002 break; 1003 case MAS0_WQ_CLR_RSRV: 1004 /* XXX clear entry */ 1005 return; 1006 default: 1007 /* no idea what to do */ 1008 return; 1009 } 1010 1011 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) && 1012 !msr_gs) { 1013 /* XXX we don't support direct LRAT setting yet */ 1014 fprintf(stderr, "cpu: don't support LRAT setting yet\n"); 1015 return; 1016 } 1017 1018 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; 1019 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn]; 1020 1021 tlb = booke206_cur_tlb(env); 1022 1023 if (!tlb) { 1024 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1025 POWERPC_EXCP_INVAL | 1026 POWERPC_EXCP_INVAL_INVAL, GETPC()); 1027 } 1028 1029 /* check that we support the targeted size */ 1030 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; 1031 size_ps = booke206_tlbnps(env, tlbn); 1032 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) && 1033 !(size_ps & (1 << size_tlb))) { 1034 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1035 POWERPC_EXCP_INVAL | 1036 POWERPC_EXCP_INVAL_INVAL, GETPC()); 1037 } 1038 1039 if (msr_gs) { 1040 cpu_abort(env_cpu(env), "missing HV implementation\n"); 1041 } 1042 1043 if (tlb->mas1 & MAS1_VALID) { 1044 /* 1045 * Invalidate the page in QEMU TLB if it was a valid entry. 1046 * 1047 * In "PowerPC e500 Core Family Reference Manual, Rev. 1", 1048 * Section "12.4.2 TLB Write Entry (tlbwe) Instruction": 1049 * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf) 1050 * 1051 * "Note that when an L2 TLB entry is written, it may be displacing an 1052 * already valid entry in the same L2 TLB location (a victim). If a 1053 * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1 1054 * TLB entry is automatically invalidated." 1055 */ 1056 flush_page(env, tlb); 1057 } 1058 1059 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) | 1060 env->spr[SPR_BOOKE_MAS3]; 1061 tlb->mas1 = env->spr[SPR_BOOKE_MAS1]; 1062 1063 if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { 1064 /* For TLB which has a fixed size TSIZE is ignored with MAV2 */ 1065 booke206_fixed_size_tlbn(env, tlbn, tlb); 1066 } else { 1067 if (!(tlbncfg & TLBnCFG_AVAIL)) { 1068 /* force !AVAIL TLB entries to correct page size */ 1069 tlb->mas1 &= ~MAS1_TSIZE_MASK; 1070 /* XXX can be configured in MMUCSR0 */ 1071 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12; 1072 } 1073 } 1074 1075 /* Make a mask from TLB size to discard invalid bits in EPN field */ 1076 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); 1077 /* Add a mask for page attributes */ 1078 mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E; 1079 1080 if (!msr_cm) { 1081 /* 1082 * Executing a tlbwe instruction in 32-bit mode will set bits 1083 * 0:31 of the TLB EPN field to zero. 1084 */ 1085 mask &= 0xffffffff; 1086 } 1087 1088 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask; 1089 1090 if (!(tlbncfg & TLBnCFG_IPROT)) { 1091 /* no IPROT supported by TLB */ 1092 tlb->mas1 &= ~MAS1_IPROT; 1093 } 1094 1095 flush_page(env, tlb); 1096 } 1097 1098 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb) 1099 { 1100 int tlbn = booke206_tlbm_to_tlbn(env, tlb); 1101 int way = booke206_tlbm_to_way(env, tlb); 1102 1103 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT; 1104 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT; 1105 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; 1106 1107 env->spr[SPR_BOOKE_MAS1] = tlb->mas1; 1108 env->spr[SPR_BOOKE_MAS2] = tlb->mas2; 1109 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3; 1110 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32; 1111 } 1112 1113 void helper_booke206_tlbre(CPUPPCState *env) 1114 { 1115 ppcmas_tlb_t *tlb = NULL; 1116 1117 tlb = booke206_cur_tlb(env); 1118 if (!tlb) { 1119 env->spr[SPR_BOOKE_MAS1] = 0; 1120 } else { 1121 booke206_tlb_to_mas(env, tlb); 1122 } 1123 } 1124 1125 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address) 1126 { 1127 ppcmas_tlb_t *tlb = NULL; 1128 int i, j; 1129 hwaddr raddr; 1130 uint32_t spid, sas; 1131 1132 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT; 1133 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS; 1134 1135 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1136 int ways = booke206_tlb_ways(env, i); 1137 1138 for (j = 0; j < ways; j++) { 1139 tlb = booke206_get_tlbm(env, i, address, j); 1140 1141 if (!tlb) { 1142 continue; 1143 } 1144 1145 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) { 1146 continue; 1147 } 1148 1149 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) { 1150 continue; 1151 } 1152 1153 booke206_tlb_to_mas(env, tlb); 1154 return; 1155 } 1156 } 1157 1158 /* no entry found, fill with defaults */ 1159 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK; 1160 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK; 1161 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK; 1162 env->spr[SPR_BOOKE_MAS3] = 0; 1163 env->spr[SPR_BOOKE_MAS7] = 0; 1164 1165 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) { 1166 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS; 1167 } 1168 1169 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16) 1170 << MAS1_TID_SHIFT; 1171 1172 /* next victim logic */ 1173 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT; 1174 env->last_way++; 1175 env->last_way &= booke206_tlb_ways(env, 0) - 1; 1176 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; 1177 } 1178 1179 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn, 1180 vaddr ea) 1181 { 1182 int i; 1183 int ways = booke206_tlb_ways(env, tlbn); 1184 target_ulong mask; 1185 1186 for (i = 0; i < ways; i++) { 1187 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i); 1188 if (!tlb) { 1189 continue; 1190 } 1191 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); 1192 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) && 1193 !(tlb->mas1 & MAS1_IPROT)) { 1194 tlb->mas1 &= ~MAS1_VALID; 1195 } 1196 } 1197 } 1198 1199 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address) 1200 { 1201 CPUState *cs; 1202 1203 if (address & 0x4) { 1204 /* flush all entries */ 1205 if (address & 0x8) { 1206 /* flush all of TLB1 */ 1207 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1); 1208 } else { 1209 /* flush all of TLB0 */ 1210 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0); 1211 } 1212 return; 1213 } 1214 1215 if (address & 0x8) { 1216 /* flush TLB1 entries */ 1217 booke206_invalidate_ea_tlb(env, 1, address); 1218 CPU_FOREACH(cs) { 1219 tlb_flush(cs); 1220 } 1221 } else { 1222 /* flush TLB0 entries */ 1223 booke206_invalidate_ea_tlb(env, 0, address); 1224 CPU_FOREACH(cs) { 1225 tlb_flush_page(cs, address & MAS2_EPN_MASK); 1226 } 1227 } 1228 } 1229 1230 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address) 1231 { 1232 /* XXX missing LPID handling */ 1233 booke206_flush_tlb(env, -1, 1); 1234 } 1235 1236 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address) 1237 { 1238 int i, j; 1239 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); 1240 ppcmas_tlb_t *tlb = env->tlb.tlbm; 1241 int tlb_size; 1242 1243 /* XXX missing LPID handling */ 1244 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1245 tlb_size = booke206_tlb_size(env, i); 1246 for (j = 0; j < tlb_size; j++) { 1247 if (!(tlb[j].mas1 & MAS1_IPROT) && 1248 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) { 1249 tlb[j].mas1 &= ~MAS1_VALID; 1250 } 1251 } 1252 tlb += booke206_tlb_size(env, i); 1253 } 1254 tlb_flush(env_cpu(env)); 1255 } 1256 1257 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address) 1258 { 1259 int i, j; 1260 ppcmas_tlb_t *tlb; 1261 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); 1262 int pid = tid >> MAS6_SPID_SHIFT; 1263 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS; 1264 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0; 1265 /* XXX check for unsupported isize and raise an invalid opcode then */ 1266 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK; 1267 /* XXX implement MAV2 handling */ 1268 bool mav2 = false; 1269 1270 /* XXX missing LPID handling */ 1271 /* flush by pid and ea */ 1272 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1273 int ways = booke206_tlb_ways(env, i); 1274 1275 for (j = 0; j < ways; j++) { 1276 tlb = booke206_get_tlbm(env, i, address, j); 1277 if (!tlb) { 1278 continue; 1279 } 1280 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) || 1281 (tlb->mas1 & MAS1_IPROT) || 1282 ((tlb->mas1 & MAS1_IND) != ind) || 1283 ((tlb->mas8 & MAS8_TGS) != sgs)) { 1284 continue; 1285 } 1286 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) { 1287 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */ 1288 continue; 1289 } 1290 /* XXX e500mc doesn't match SAS, but other cores might */ 1291 tlb->mas1 &= ~MAS1_VALID; 1292 } 1293 } 1294 tlb_flush(env_cpu(env)); 1295 } 1296 1297 void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type) 1298 { 1299 int flags = 0; 1300 1301 if (type & 2) { 1302 flags |= BOOKE206_FLUSH_TLB1; 1303 } 1304 1305 if (type & 4) { 1306 flags |= BOOKE206_FLUSH_TLB0; 1307 } 1308 1309 booke206_flush_tlb(env, flags, 1); 1310 } 1311 1312 1313 void helper_check_tlb_flush_local(CPUPPCState *env) 1314 { 1315 check_tlb_flush(env, false); 1316 } 1317 1318 void helper_check_tlb_flush_global(CPUPPCState *env) 1319 { 1320 check_tlb_flush(env, true); 1321 } 1322 1323 1324 bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, 1325 MMUAccessType access_type, int mmu_idx, 1326 bool probe, uintptr_t retaddr) 1327 { 1328 PowerPCCPU *cpu = POWERPC_CPU(cs); 1329 hwaddr raddr; 1330 int page_size, prot; 1331 1332 if (ppc_xlate(cpu, eaddr, access_type, &raddr, 1333 &page_size, &prot, mmu_idx, !probe)) { 1334 tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, 1335 prot, mmu_idx, 1UL << page_size); 1336 return true; 1337 } 1338 if (probe) { 1339 return false; 1340 } 1341 raise_exception_err_ra(&cpu->env, cs->exception_index, 1342 cpu->env.error_code, retaddr); 1343 } 1344