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 void helper_store_40x_pid(CPUPPCState *env, target_ulong val) 668 { 669 if (env->spr[SPR_40x_PID] != val) { 670 env->spr[SPR_40x_PID] = val; 671 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; 672 } 673 } 674 675 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry) 676 { 677 ppcemb_tlb_t *tlb; 678 target_ulong ret; 679 int size; 680 681 entry &= PPC4XX_TLB_ENTRY_MASK; 682 tlb = &env->tlb.tlbe[entry]; 683 ret = tlb->EPN; 684 if (tlb->prot & PAGE_VALID) { 685 ret |= PPC4XX_TLBHI_V; 686 } 687 size = booke_page_size_to_tlb(tlb->size); 688 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) { 689 size = PPC4XX_TLBHI_SIZE_DEFAULT; 690 } 691 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; 692 helper_store_40x_pid(env, tlb->PID); 693 return ret; 694 } 695 696 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry) 697 { 698 ppcemb_tlb_t *tlb; 699 target_ulong ret; 700 701 entry &= PPC4XX_TLB_ENTRY_MASK; 702 tlb = &env->tlb.tlbe[entry]; 703 ret = tlb->RPN; 704 if (tlb->prot & PAGE_EXEC) { 705 ret |= PPC4XX_TLBLO_EX; 706 } 707 if (tlb->prot & PAGE_WRITE) { 708 ret |= PPC4XX_TLBLO_WR; 709 } 710 return ret; 711 } 712 713 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, 714 target_ulong val) 715 { 716 CPUState *cs = env_cpu(env); 717 ppcemb_tlb_t *tlb; 718 target_ulong page, end; 719 720 qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n", 721 __func__, (int)entry, 722 val); 723 entry &= PPC4XX_TLB_ENTRY_MASK; 724 tlb = &env->tlb.tlbe[entry]; 725 /* Invalidate previous TLB (if it's valid) */ 726 if (tlb->prot & PAGE_VALID) { 727 end = tlb->EPN + tlb->size; 728 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " 729 TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, 730 (int)entry, tlb->EPN, end); 731 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { 732 tlb_flush_page(cs, page); 733 } 734 } 735 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT) 736 & PPC4XX_TLBHI_SIZE_MASK); 737 /* 738 * We cannot handle TLB size < TARGET_PAGE_SIZE. 739 * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY 740 */ 741 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) { 742 cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u " 743 "are not supported (%d)\n" 744 "Please implement TARGET_PAGE_BITS_VARY\n", 745 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); 746 } 747 tlb->EPN = val & ~(tlb->size - 1); 748 if (val & PPC4XX_TLBHI_V) { 749 tlb->prot |= PAGE_VALID; 750 if (val & PPC4XX_TLBHI_E) { 751 /* XXX: TO BE FIXED */ 752 cpu_abort(cs, 753 "Little-endian TLB entries are not supported by now\n"); 754 } 755 } else { 756 tlb->prot &= ~PAGE_VALID; 757 } 758 tlb->PID = env->spr[SPR_40x_PID]; /* PID */ 759 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx 760 " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx 761 " prot %c%c%c%c PID %d\n", __func__, 762 (int)entry, tlb->RPN, tlb->EPN, tlb->size, 763 tlb->prot & PAGE_READ ? 'r' : '-', 764 tlb->prot & PAGE_WRITE ? 'w' : '-', 765 tlb->prot & PAGE_EXEC ? 'x' : '-', 766 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); 767 /* Invalidate new TLB (if valid) */ 768 if (tlb->prot & PAGE_VALID) { 769 end = tlb->EPN + tlb->size; 770 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start " 771 TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, 772 (int)entry, tlb->EPN, end); 773 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { 774 tlb_flush_page(cs, page); 775 } 776 } 777 } 778 779 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, 780 target_ulong val) 781 { 782 ppcemb_tlb_t *tlb; 783 784 qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n", 785 __func__, (int)entry, val); 786 entry &= PPC4XX_TLB_ENTRY_MASK; 787 tlb = &env->tlb.tlbe[entry]; 788 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; 789 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK; 790 tlb->prot = PAGE_READ; 791 if (val & PPC4XX_TLBLO_EX) { 792 tlb->prot |= PAGE_EXEC; 793 } 794 if (val & PPC4XX_TLBLO_WR) { 795 tlb->prot |= PAGE_WRITE; 796 } 797 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx 798 " EPN " TARGET_FMT_lx 799 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, 800 (int)entry, tlb->RPN, tlb->EPN, tlb->size, 801 tlb->prot & PAGE_READ ? 'r' : '-', 802 tlb->prot & PAGE_WRITE ? 'w' : '-', 803 tlb->prot & PAGE_EXEC ? 'x' : '-', 804 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); 805 806 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; 807 } 808 809 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address) 810 { 811 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); 812 } 813 814 /* PowerPC 440 TLB management */ 815 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry, 816 target_ulong value) 817 { 818 ppcemb_tlb_t *tlb; 819 target_ulong EPN, RPN, size; 820 int do_flush_tlbs; 821 822 qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n", 823 __func__, word, (int)entry, value); 824 do_flush_tlbs = 0; 825 entry &= 0x3F; 826 tlb = &env->tlb.tlbe[entry]; 827 switch (word) { 828 default: 829 /* Just here to please gcc */ 830 case 0: 831 EPN = value & 0xFFFFFC00; 832 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) { 833 do_flush_tlbs = 1; 834 } 835 tlb->EPN = EPN; 836 size = booke_tlb_to_page_size((value >> 4) & 0xF); 837 if ((tlb->prot & PAGE_VALID) && tlb->size < size) { 838 do_flush_tlbs = 1; 839 } 840 tlb->size = size; 841 tlb->attr &= ~0x1; 842 tlb->attr |= (value >> 8) & 1; 843 if (value & 0x200) { 844 tlb->prot |= PAGE_VALID; 845 } else { 846 if (tlb->prot & PAGE_VALID) { 847 tlb->prot &= ~PAGE_VALID; 848 do_flush_tlbs = 1; 849 } 850 } 851 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF; 852 if (do_flush_tlbs) { 853 tlb_flush(env_cpu(env)); 854 } 855 break; 856 case 1: 857 RPN = value & 0xFFFFFC0F; 858 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) { 859 tlb_flush(env_cpu(env)); 860 } 861 tlb->RPN = RPN; 862 break; 863 case 2: 864 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00); 865 tlb->prot = tlb->prot & PAGE_VALID; 866 if (value & 0x1) { 867 tlb->prot |= PAGE_READ << 4; 868 } 869 if (value & 0x2) { 870 tlb->prot |= PAGE_WRITE << 4; 871 } 872 if (value & 0x4) { 873 tlb->prot |= PAGE_EXEC << 4; 874 } 875 if (value & 0x8) { 876 tlb->prot |= PAGE_READ; 877 } 878 if (value & 0x10) { 879 tlb->prot |= PAGE_WRITE; 880 } 881 if (value & 0x20) { 882 tlb->prot |= PAGE_EXEC; 883 } 884 break; 885 } 886 } 887 888 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word, 889 target_ulong entry) 890 { 891 ppcemb_tlb_t *tlb; 892 target_ulong ret; 893 int size; 894 895 entry &= 0x3F; 896 tlb = &env->tlb.tlbe[entry]; 897 switch (word) { 898 default: 899 /* Just here to please gcc */ 900 case 0: 901 ret = tlb->EPN; 902 size = booke_page_size_to_tlb(tlb->size); 903 if (size < 0 || size > 0xF) { 904 size = 1; 905 } 906 ret |= size << 4; 907 if (tlb->attr & 0x1) { 908 ret |= 0x100; 909 } 910 if (tlb->prot & PAGE_VALID) { 911 ret |= 0x200; 912 } 913 env->spr[SPR_440_MMUCR] &= ~0x000000FF; 914 env->spr[SPR_440_MMUCR] |= tlb->PID; 915 break; 916 case 1: 917 ret = tlb->RPN; 918 break; 919 case 2: 920 ret = tlb->attr & ~0x1; 921 if (tlb->prot & (PAGE_READ << 4)) { 922 ret |= 0x1; 923 } 924 if (tlb->prot & (PAGE_WRITE << 4)) { 925 ret |= 0x2; 926 } 927 if (tlb->prot & (PAGE_EXEC << 4)) { 928 ret |= 0x4; 929 } 930 if (tlb->prot & PAGE_READ) { 931 ret |= 0x8; 932 } 933 if (tlb->prot & PAGE_WRITE) { 934 ret |= 0x10; 935 } 936 if (tlb->prot & PAGE_EXEC) { 937 ret |= 0x20; 938 } 939 break; 940 } 941 return ret; 942 } 943 944 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address) 945 { 946 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); 947 } 948 949 /* PowerPC BookE 2.06 TLB management */ 950 951 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env) 952 { 953 uint32_t tlbncfg = 0; 954 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT; 955 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK); 956 int tlb; 957 958 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; 959 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb]; 960 961 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) { 962 cpu_abort(env_cpu(env), "we don't support HES yet\n"); 963 } 964 965 return booke206_get_tlbm(env, tlb, ea, esel); 966 } 967 968 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid) 969 { 970 env->spr[pidn] = pid; 971 /* changing PIDs mean we're in a different address space now */ 972 tlb_flush(env_cpu(env)); 973 } 974 975 void helper_booke_set_eplc(CPUPPCState *env, target_ulong val) 976 { 977 env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK; 978 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD); 979 } 980 void helper_booke_set_epsc(CPUPPCState *env, target_ulong val) 981 { 982 env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK; 983 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE); 984 } 985 986 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb) 987 { 988 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) { 989 tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK); 990 } else { 991 tlb_flush(env_cpu(env)); 992 } 993 } 994 995 void helper_booke206_tlbwe(CPUPPCState *env) 996 { 997 uint32_t tlbncfg, tlbn; 998 ppcmas_tlb_t *tlb; 999 uint32_t size_tlb, size_ps; 1000 target_ulong mask; 1001 1002 1003 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) { 1004 case MAS0_WQ_ALWAYS: 1005 /* good to go, write that entry */ 1006 break; 1007 case MAS0_WQ_COND: 1008 /* XXX check if reserved */ 1009 if (0) { 1010 return; 1011 } 1012 break; 1013 case MAS0_WQ_CLR_RSRV: 1014 /* XXX clear entry */ 1015 return; 1016 default: 1017 /* no idea what to do */ 1018 return; 1019 } 1020 1021 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) && 1022 !msr_gs) { 1023 /* XXX we don't support direct LRAT setting yet */ 1024 fprintf(stderr, "cpu: don't support LRAT setting yet\n"); 1025 return; 1026 } 1027 1028 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; 1029 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn]; 1030 1031 tlb = booke206_cur_tlb(env); 1032 1033 if (!tlb) { 1034 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1035 POWERPC_EXCP_INVAL | 1036 POWERPC_EXCP_INVAL_INVAL, GETPC()); 1037 } 1038 1039 /* check that we support the targeted size */ 1040 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; 1041 size_ps = booke206_tlbnps(env, tlbn); 1042 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) && 1043 !(size_ps & (1 << size_tlb))) { 1044 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 1045 POWERPC_EXCP_INVAL | 1046 POWERPC_EXCP_INVAL_INVAL, GETPC()); 1047 } 1048 1049 if (msr_gs) { 1050 cpu_abort(env_cpu(env), "missing HV implementation\n"); 1051 } 1052 1053 if (tlb->mas1 & MAS1_VALID) { 1054 /* 1055 * Invalidate the page in QEMU TLB if it was a valid entry. 1056 * 1057 * In "PowerPC e500 Core Family Reference Manual, Rev. 1", 1058 * Section "12.4.2 TLB Write Entry (tlbwe) Instruction": 1059 * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf) 1060 * 1061 * "Note that when an L2 TLB entry is written, it may be displacing an 1062 * already valid entry in the same L2 TLB location (a victim). If a 1063 * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1 1064 * TLB entry is automatically invalidated." 1065 */ 1066 flush_page(env, tlb); 1067 } 1068 1069 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) | 1070 env->spr[SPR_BOOKE_MAS3]; 1071 tlb->mas1 = env->spr[SPR_BOOKE_MAS1]; 1072 1073 if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { 1074 /* For TLB which has a fixed size TSIZE is ignored with MAV2 */ 1075 booke206_fixed_size_tlbn(env, tlbn, tlb); 1076 } else { 1077 if (!(tlbncfg & TLBnCFG_AVAIL)) { 1078 /* force !AVAIL TLB entries to correct page size */ 1079 tlb->mas1 &= ~MAS1_TSIZE_MASK; 1080 /* XXX can be configured in MMUCSR0 */ 1081 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12; 1082 } 1083 } 1084 1085 /* Make a mask from TLB size to discard invalid bits in EPN field */ 1086 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); 1087 /* Add a mask for page attributes */ 1088 mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E; 1089 1090 if (!msr_cm) { 1091 /* 1092 * Executing a tlbwe instruction in 32-bit mode will set bits 1093 * 0:31 of the TLB EPN field to zero. 1094 */ 1095 mask &= 0xffffffff; 1096 } 1097 1098 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask; 1099 1100 if (!(tlbncfg & TLBnCFG_IPROT)) { 1101 /* no IPROT supported by TLB */ 1102 tlb->mas1 &= ~MAS1_IPROT; 1103 } 1104 1105 flush_page(env, tlb); 1106 } 1107 1108 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb) 1109 { 1110 int tlbn = booke206_tlbm_to_tlbn(env, tlb); 1111 int way = booke206_tlbm_to_way(env, tlb); 1112 1113 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT; 1114 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT; 1115 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; 1116 1117 env->spr[SPR_BOOKE_MAS1] = tlb->mas1; 1118 env->spr[SPR_BOOKE_MAS2] = tlb->mas2; 1119 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3; 1120 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32; 1121 } 1122 1123 void helper_booke206_tlbre(CPUPPCState *env) 1124 { 1125 ppcmas_tlb_t *tlb = NULL; 1126 1127 tlb = booke206_cur_tlb(env); 1128 if (!tlb) { 1129 env->spr[SPR_BOOKE_MAS1] = 0; 1130 } else { 1131 booke206_tlb_to_mas(env, tlb); 1132 } 1133 } 1134 1135 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address) 1136 { 1137 ppcmas_tlb_t *tlb = NULL; 1138 int i, j; 1139 hwaddr raddr; 1140 uint32_t spid, sas; 1141 1142 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT; 1143 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS; 1144 1145 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1146 int ways = booke206_tlb_ways(env, i); 1147 1148 for (j = 0; j < ways; j++) { 1149 tlb = booke206_get_tlbm(env, i, address, j); 1150 1151 if (!tlb) { 1152 continue; 1153 } 1154 1155 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) { 1156 continue; 1157 } 1158 1159 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) { 1160 continue; 1161 } 1162 1163 booke206_tlb_to_mas(env, tlb); 1164 return; 1165 } 1166 } 1167 1168 /* no entry found, fill with defaults */ 1169 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK; 1170 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK; 1171 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK; 1172 env->spr[SPR_BOOKE_MAS3] = 0; 1173 env->spr[SPR_BOOKE_MAS7] = 0; 1174 1175 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) { 1176 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS; 1177 } 1178 1179 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16) 1180 << MAS1_TID_SHIFT; 1181 1182 /* next victim logic */ 1183 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT; 1184 env->last_way++; 1185 env->last_way &= booke206_tlb_ways(env, 0) - 1; 1186 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; 1187 } 1188 1189 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn, 1190 vaddr ea) 1191 { 1192 int i; 1193 int ways = booke206_tlb_ways(env, tlbn); 1194 target_ulong mask; 1195 1196 for (i = 0; i < ways; i++) { 1197 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i); 1198 if (!tlb) { 1199 continue; 1200 } 1201 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); 1202 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) && 1203 !(tlb->mas1 & MAS1_IPROT)) { 1204 tlb->mas1 &= ~MAS1_VALID; 1205 } 1206 } 1207 } 1208 1209 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address) 1210 { 1211 CPUState *cs; 1212 1213 if (address & 0x4) { 1214 /* flush all entries */ 1215 if (address & 0x8) { 1216 /* flush all of TLB1 */ 1217 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1); 1218 } else { 1219 /* flush all of TLB0 */ 1220 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0); 1221 } 1222 return; 1223 } 1224 1225 if (address & 0x8) { 1226 /* flush TLB1 entries */ 1227 booke206_invalidate_ea_tlb(env, 1, address); 1228 CPU_FOREACH(cs) { 1229 tlb_flush(cs); 1230 } 1231 } else { 1232 /* flush TLB0 entries */ 1233 booke206_invalidate_ea_tlb(env, 0, address); 1234 CPU_FOREACH(cs) { 1235 tlb_flush_page(cs, address & MAS2_EPN_MASK); 1236 } 1237 } 1238 } 1239 1240 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address) 1241 { 1242 /* XXX missing LPID handling */ 1243 booke206_flush_tlb(env, -1, 1); 1244 } 1245 1246 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address) 1247 { 1248 int i, j; 1249 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); 1250 ppcmas_tlb_t *tlb = env->tlb.tlbm; 1251 int tlb_size; 1252 1253 /* XXX missing LPID handling */ 1254 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1255 tlb_size = booke206_tlb_size(env, i); 1256 for (j = 0; j < tlb_size; j++) { 1257 if (!(tlb[j].mas1 & MAS1_IPROT) && 1258 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) { 1259 tlb[j].mas1 &= ~MAS1_VALID; 1260 } 1261 } 1262 tlb += booke206_tlb_size(env, i); 1263 } 1264 tlb_flush(env_cpu(env)); 1265 } 1266 1267 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address) 1268 { 1269 int i, j; 1270 ppcmas_tlb_t *tlb; 1271 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); 1272 int pid = tid >> MAS6_SPID_SHIFT; 1273 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS; 1274 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0; 1275 /* XXX check for unsupported isize and raise an invalid opcode then */ 1276 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK; 1277 /* XXX implement MAV2 handling */ 1278 bool mav2 = false; 1279 1280 /* XXX missing LPID handling */ 1281 /* flush by pid and ea */ 1282 for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 1283 int ways = booke206_tlb_ways(env, i); 1284 1285 for (j = 0; j < ways; j++) { 1286 tlb = booke206_get_tlbm(env, i, address, j); 1287 if (!tlb) { 1288 continue; 1289 } 1290 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) || 1291 (tlb->mas1 & MAS1_IPROT) || 1292 ((tlb->mas1 & MAS1_IND) != ind) || 1293 ((tlb->mas8 & MAS8_TGS) != sgs)) { 1294 continue; 1295 } 1296 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) { 1297 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */ 1298 continue; 1299 } 1300 /* XXX e500mc doesn't match SAS, but other cores might */ 1301 tlb->mas1 &= ~MAS1_VALID; 1302 } 1303 } 1304 tlb_flush(env_cpu(env)); 1305 } 1306 1307 void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type) 1308 { 1309 int flags = 0; 1310 1311 if (type & 2) { 1312 flags |= BOOKE206_FLUSH_TLB1; 1313 } 1314 1315 if (type & 4) { 1316 flags |= BOOKE206_FLUSH_TLB0; 1317 } 1318 1319 booke206_flush_tlb(env, flags, 1); 1320 } 1321 1322 1323 void helper_check_tlb_flush_local(CPUPPCState *env) 1324 { 1325 check_tlb_flush(env, false); 1326 } 1327 1328 void helper_check_tlb_flush_global(CPUPPCState *env) 1329 { 1330 check_tlb_flush(env, true); 1331 } 1332 1333 1334 bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, 1335 MMUAccessType access_type, int mmu_idx, 1336 bool probe, uintptr_t retaddr) 1337 { 1338 PowerPCCPU *cpu = POWERPC_CPU(cs); 1339 hwaddr raddr; 1340 int page_size, prot; 1341 1342 if (ppc_xlate(cpu, eaddr, access_type, &raddr, 1343 &page_size, &prot, mmu_idx, !probe)) { 1344 tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, 1345 prot, mmu_idx, 1UL << page_size); 1346 return true; 1347 } 1348 if (probe) { 1349 return false; 1350 } 1351 raise_exception_err_ra(&cpu->env, cs->exception_index, 1352 cpu->env.error_code, retaddr); 1353 } 1354