qemu/target/ppc/mmu_helper.c
<<
>>
Prefs
   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 */
  45static 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
  63static 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
  89static 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
  95static 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 */
 116static 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 */
 137static 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
 149static 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
 171static 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)
 183static 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
 208static 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
 216void 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
 243void 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
 249void 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
 276void 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/*****************************************************************************/
 283/* TLB management */
 284void ppc_tlb_invalidate_all(CPUPPCState *env)
 285{
 286#if defined(TARGET_PPC64)
 287    if (mmu_is_64bit(env->mmu_model)) {
 288        env->tlb_need_flush = 0;
 289        tlb_flush(env_cpu(env));
 290    } else
 291#endif /* defined(TARGET_PPC64) */
 292    switch (env->mmu_model) {
 293    case POWERPC_MMU_SOFT_6xx:
 294        ppc6xx_tlb_invalidate_all(env);
 295        break;
 296    case POWERPC_MMU_SOFT_4xx:
 297        ppc4xx_tlb_invalidate_all(env);
 298        break;
 299    case POWERPC_MMU_REAL:
 300        cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n");
 301        break;
 302    case POWERPC_MMU_MPC8xx:
 303        /* XXX: TODO */
 304        cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
 305        break;
 306    case POWERPC_MMU_BOOKE:
 307        tlb_flush(env_cpu(env));
 308        break;
 309    case POWERPC_MMU_BOOKE206:
 310        booke206_flush_tlb(env, -1, 0);
 311        break;
 312    case POWERPC_MMU_32B:
 313        env->tlb_need_flush = 0;
 314        tlb_flush(env_cpu(env));
 315        break;
 316    default:
 317        /* XXX: TODO */
 318        cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model);
 319        break;
 320    }
 321}
 322
 323void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
 324{
 325#if !defined(FLUSH_ALL_TLBS)
 326    addr &= TARGET_PAGE_MASK;
 327#if defined(TARGET_PPC64)
 328    if (mmu_is_64bit(env->mmu_model)) {
 329        /* tlbie invalidate TLBs for all segments */
 330        /*
 331         * XXX: given the fact that there are too many segments to invalidate,
 332         *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
 333         *      we just invalidate all TLBs
 334         */
 335        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 336    } else
 337#endif /* defined(TARGET_PPC64) */
 338    switch (env->mmu_model) {
 339    case POWERPC_MMU_SOFT_6xx:
 340        ppc6xx_tlb_invalidate_virt(env, addr, 0);
 341        if (env->id_tlbs == 1) {
 342            ppc6xx_tlb_invalidate_virt(env, addr, 1);
 343        }
 344        break;
 345    case POWERPC_MMU_32B:
 346        /*
 347         * Actual CPUs invalidate entire congruence classes based on
 348         * the geometry of their TLBs and some OSes take that into
 349         * account, we just mark the TLB to be flushed later (context
 350         * synchronizing event or sync instruction on 32-bit).
 351         */
 352        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 353        break;
 354    default:
 355        /* Should never reach here with other MMU models */
 356        assert(0);
 357    }
 358#else
 359    ppc_tlb_invalidate_all(env);
 360#endif
 361}
 362
 363/*****************************************************************************/
 364/* Special registers manipulation */
 365
 366/* Segment registers load and store */
 367target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
 368{
 369#if defined(TARGET_PPC64)
 370    if (mmu_is_64bit(env->mmu_model)) {
 371        /* XXX */
 372        return 0;
 373    }
 374#endif
 375    return env->sr[sr_num];
 376}
 377
 378void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
 379{
 380    qemu_log_mask(CPU_LOG_MMU,
 381            "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
 382            (int)srnum, value, env->sr[srnum]);
 383#if defined(TARGET_PPC64)
 384    if (mmu_is_64bit(env->mmu_model)) {
 385        PowerPCCPU *cpu = env_archcpu(env);
 386        uint64_t esid, vsid;
 387
 388        /* ESID = srnum */
 389        esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
 390
 391        /* VSID = VSID */
 392        vsid = (value & 0xfffffff) << 12;
 393        /* flags = flags */
 394        vsid |= ((value >> 27) & 0xf) << 8;
 395
 396        ppc_store_slb(cpu, srnum, esid, vsid);
 397    } else
 398#endif
 399    if (env->sr[srnum] != value) {
 400        env->sr[srnum] = value;
 401        /*
 402         * Invalidating 256MB of virtual memory in 4kB pages is way
 403         * longer than flushing the whole TLB.
 404         */
 405#if !defined(FLUSH_ALL_TLBS) && 0
 406        {
 407            target_ulong page, end;
 408            /* Invalidate 256 MB of virtual memory */
 409            page = (16 << 20) * srnum;
 410            end = page + (16 << 20);
 411            for (; page != end; page += TARGET_PAGE_SIZE) {
 412                tlb_flush_page(env_cpu(env), page);
 413            }
 414        }
 415#else
 416        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 417#endif
 418    }
 419}
 420
 421/* TLB management */
 422void helper_tlbia(CPUPPCState *env)
 423{
 424    ppc_tlb_invalidate_all(env);
 425}
 426
 427void helper_tlbie(CPUPPCState *env, target_ulong addr)
 428{
 429    ppc_tlb_invalidate_one(env, addr);
 430}
 431
 432#if defined(TARGET_PPC64)
 433
 434/* Invalidation Selector */
 435#define TLBIE_IS_VA         0
 436#define TLBIE_IS_PID        1
 437#define TLBIE_IS_LPID       2
 438#define TLBIE_IS_ALL        3
 439
 440/* Radix Invalidation Control */
 441#define TLBIE_RIC_TLB       0
 442#define TLBIE_RIC_PWC       1
 443#define TLBIE_RIC_ALL       2
 444#define TLBIE_RIC_GRP       3
 445
 446/* Radix Actual Page sizes */
 447#define TLBIE_R_AP_4K       0
 448#define TLBIE_R_AP_64K      5
 449#define TLBIE_R_AP_2M       1
 450#define TLBIE_R_AP_1G       2
 451
 452/* RB field masks */
 453#define TLBIE_RB_EPN_MASK   PPC_BITMASK(0, 51)
 454#define TLBIE_RB_IS_MASK    PPC_BITMASK(52, 53)
 455#define TLBIE_RB_AP_MASK    PPC_BITMASK(56, 58)
 456
 457void helper_tlbie_isa300(CPUPPCState *env, target_ulong rb, target_ulong rs,
 458                         uint32_t flags)
 459{
 460    unsigned ric = (flags & TLBIE_F_RIC_MASK) >> TLBIE_F_RIC_SHIFT;
 461    /*
 462     * With the exception of the checks for invalid instruction forms,
 463     * PRS is currently ignored, because we don't know if a given TLB entry
 464     * is process or partition scoped.
 465     */
 466    bool prs = flags & TLBIE_F_PRS;
 467    bool r = flags & TLBIE_F_R;
 468    bool local = flags & TLBIE_F_LOCAL;
 469    bool effR;
 470    unsigned is = extract64(rb, PPC_BIT_NR(53), 2);
 471    unsigned ap;        /* actual page size */
 472    target_ulong addr, pgoffs_mask;
 473
 474    qemu_log_mask(CPU_LOG_MMU,
 475        "%s: local=%d addr=" TARGET_FMT_lx " ric=%u prs=%d r=%d is=%u\n",
 476        __func__, local, rb & TARGET_PAGE_MASK, ric, prs, r, is);
 477
 478    effR = FIELD_EX64(env->msr, MSR, HV) ? r : env->spr[SPR_LPCR] & LPCR_HR;
 479
 480    /* Partial TLB invalidation is supported for Radix only for now. */
 481    if (!effR) {
 482        goto inval_all;
 483    }
 484
 485    /* Check for invalid instruction forms (effR=1). */
 486    if (unlikely(ric == TLBIE_RIC_GRP ||
 487                 ((ric == TLBIE_RIC_PWC || ric == TLBIE_RIC_ALL) &&
 488                                           is == TLBIE_IS_VA) ||
 489                 (!prs && is == TLBIE_IS_PID))) {
 490        qemu_log_mask(LOG_GUEST_ERROR,
 491            "%s: invalid instruction form: ric=%u prs=%d r=%d is=%u\n",
 492            __func__, ric, prs, r, is);
 493        goto invalid;
 494    }
 495
 496    /* We don't cache Page Walks. */
 497    if (ric == TLBIE_RIC_PWC) {
 498        if (local) {
 499            unsigned set = extract64(rb, PPC_BIT_NR(51), 12);
 500            if (set != 0) {
 501                qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid set: %d\n",
 502                              __func__, set);
 503                goto invalid;
 504            }
 505        }
 506        return;
 507    }
 508
 509    /*
 510     * Invalidation by LPID or PID is not supported, so fallback
 511     * to full TLB flush in these cases.
 512     */
 513    if (is != TLBIE_IS_VA) {
 514        goto inval_all;
 515    }
 516
 517    /*
 518     * The results of an attempt to invalidate a translation outside of
 519     * quadrant 0 for Radix Tree translation (effR=1, RIC=0, PRS=1, IS=0,
 520     * and EA 0:1 != 0b00) are boundedly undefined.
 521     */
 522    if (unlikely(ric == TLBIE_RIC_TLB && prs && is == TLBIE_IS_VA &&
 523                 (rb & R_EADDR_QUADRANT) != R_EADDR_QUADRANT0)) {
 524        qemu_log_mask(LOG_GUEST_ERROR,
 525            "%s: attempt to invalidate a translation outside of quadrant 0\n",
 526            __func__);
 527        goto inval_all;
 528    }
 529
 530    assert(is == TLBIE_IS_VA);
 531    assert(ric == TLBIE_RIC_TLB || ric == TLBIE_RIC_ALL);
 532
 533    ap = extract64(rb, PPC_BIT_NR(58), 3);
 534    switch (ap) {
 535    case TLBIE_R_AP_4K:
 536        pgoffs_mask = 0xfffull;
 537        break;
 538
 539    case TLBIE_R_AP_64K:
 540        pgoffs_mask = 0xffffull;
 541        break;
 542
 543    case TLBIE_R_AP_2M:
 544        pgoffs_mask = 0x1fffffull;
 545        break;
 546
 547    case TLBIE_R_AP_1G:
 548        pgoffs_mask = 0x3fffffffull;
 549        break;
 550
 551    default:
 552        /*
 553         * If the value specified in RS 0:31, RS 32:63, RB 54:55, RB 56:58,
 554         * RB 44:51, or RB 56:63, when it is needed to perform the specified
 555         * operation, is not supported by the implementation, the instruction
 556         * is treated as if the instruction form were invalid.
 557         */
 558        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid AP: %d\n", __func__, ap);
 559        goto invalid;
 560    }
 561
 562    addr = rb & TLBIE_RB_EPN_MASK & ~pgoffs_mask;
 563
 564    if (local) {
 565        tlb_flush_page(env_cpu(env), addr);
 566    } else {
 567        tlb_flush_page_all_cpus(env_cpu(env), addr);
 568    }
 569    return;
 570
 571inval_all:
 572    env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 573    if (!local) {
 574        env->tlb_need_flush |= TLB_NEED_GLOBAL_FLUSH;
 575    }
 576    return;
 577
 578invalid:
 579    raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
 580                           POWERPC_EXCP_INVAL |
 581                           POWERPC_EXCP_INVAL_INVAL, GETPC());
 582}
 583
 584#endif
 585
 586void helper_tlbiva(CPUPPCState *env, target_ulong addr)
 587{
 588    /* tlbiva instruction only exists on BookE */
 589    assert(env->mmu_model == POWERPC_MMU_BOOKE);
 590    /* XXX: TODO */
 591    cpu_abort(env_cpu(env), "BookE MMU model is not implemented\n");
 592}
 593
 594/* Software driven TLBs management */
 595/* PowerPC 602/603 software TLB load instructions helpers */
 596static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
 597{
 598    target_ulong RPN, CMP, EPN;
 599    int way;
 600
 601    RPN = env->spr[SPR_RPA];
 602    if (is_code) {
 603        CMP = env->spr[SPR_ICMP];
 604        EPN = env->spr[SPR_IMISS];
 605    } else {
 606        CMP = env->spr[SPR_DCMP];
 607        EPN = env->spr[SPR_DMISS];
 608    }
 609    way = (env->spr[SPR_SRR1] >> 17) & 1;
 610    (void)EPN; /* avoid a compiler warning */
 611    qemu_log_mask(CPU_LOG_MMU, "%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx
 612                  " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n",
 613                  __func__, new_EPN, EPN, CMP, RPN, way);
 614    /* Store this TLB */
 615    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
 616                     way, is_code, CMP, RPN);
 617}
 618
 619void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
 620{
 621    do_6xx_tlb(env, EPN, 0);
 622}
 623
 624void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
 625{
 626    do_6xx_tlb(env, EPN, 1);
 627}
 628
 629/*****************************************************************************/
 630/* PowerPC 601 specific instructions (POWER bridge) */
 631
 632target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
 633{
 634    mmu_ctx_t ctx;
 635    int nb_BATs;
 636    target_ulong ret = 0;
 637
 638    /*
 639     * We don't have to generate many instances of this instruction,
 640     * as rac is supervisor only.
 641     *
 642     * XXX: FIX THIS: Pretend we have no BAT
 643     */
 644    nb_BATs = env->nb_BATs;
 645    env->nb_BATs = 0;
 646    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
 647        ret = ctx.raddr;
 648    }
 649    env->nb_BATs = nb_BATs;
 650    return ret;
 651}
 652
 653static inline target_ulong booke_tlb_to_page_size(int size)
 654{
 655    return 1024 << (2 * size);
 656}
 657
 658static inline int booke_page_size_to_tlb(target_ulong page_size)
 659{
 660    int size;
 661
 662    switch (page_size) {
 663    case 0x00000400UL:
 664        size = 0x0;
 665        break;
 666    case 0x00001000UL:
 667        size = 0x1;
 668        break;
 669    case 0x00004000UL:
 670        size = 0x2;
 671        break;
 672    case 0x00010000UL:
 673        size = 0x3;
 674        break;
 675    case 0x00040000UL:
 676        size = 0x4;
 677        break;
 678    case 0x00100000UL:
 679        size = 0x5;
 680        break;
 681    case 0x00400000UL:
 682        size = 0x6;
 683        break;
 684    case 0x01000000UL:
 685        size = 0x7;
 686        break;
 687    case 0x04000000UL:
 688        size = 0x8;
 689        break;
 690    case 0x10000000UL:
 691        size = 0x9;
 692        break;
 693    case 0x40000000UL:
 694        size = 0xA;
 695        break;
 696#if defined(TARGET_PPC64)
 697    case 0x000100000000ULL:
 698        size = 0xB;
 699        break;
 700    case 0x000400000000ULL:
 701        size = 0xC;
 702        break;
 703    case 0x001000000000ULL:
 704        size = 0xD;
 705        break;
 706    case 0x004000000000ULL:
 707        size = 0xE;
 708        break;
 709    case 0x010000000000ULL:
 710        size = 0xF;
 711        break;
 712#endif
 713    default:
 714        size = -1;
 715        break;
 716    }
 717
 718    return size;
 719}
 720
 721/* Helpers for 4xx TLB management */
 722#define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
 723
 724#define PPC4XX_TLBHI_V              0x00000040
 725#define PPC4XX_TLBHI_E              0x00000020
 726#define PPC4XX_TLBHI_SIZE_MIN       0
 727#define PPC4XX_TLBHI_SIZE_MAX       7
 728#define PPC4XX_TLBHI_SIZE_DEFAULT   1
 729#define PPC4XX_TLBHI_SIZE_SHIFT     7
 730#define PPC4XX_TLBHI_SIZE_MASK      0x00000007
 731
 732#define PPC4XX_TLBLO_EX             0x00000200
 733#define PPC4XX_TLBLO_WR             0x00000100
 734#define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
 735#define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
 736
 737void helper_store_40x_pid(CPUPPCState *env, target_ulong val)
 738{
 739    if (env->spr[SPR_40x_PID] != val) {
 740        env->spr[SPR_40x_PID] = val;
 741        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 742    }
 743}
 744
 745target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
 746{
 747    ppcemb_tlb_t *tlb;
 748    target_ulong ret;
 749    int size;
 750
 751    entry &= PPC4XX_TLB_ENTRY_MASK;
 752    tlb = &env->tlb.tlbe[entry];
 753    ret = tlb->EPN;
 754    if (tlb->prot & PAGE_VALID) {
 755        ret |= PPC4XX_TLBHI_V;
 756    }
 757    size = booke_page_size_to_tlb(tlb->size);
 758    if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
 759        size = PPC4XX_TLBHI_SIZE_DEFAULT;
 760    }
 761    ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
 762    helper_store_40x_pid(env, tlb->PID);
 763    return ret;
 764}
 765
 766target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
 767{
 768    ppcemb_tlb_t *tlb;
 769    target_ulong ret;
 770
 771    entry &= PPC4XX_TLB_ENTRY_MASK;
 772    tlb = &env->tlb.tlbe[entry];
 773    ret = tlb->RPN;
 774    if (tlb->prot & PAGE_EXEC) {
 775        ret |= PPC4XX_TLBLO_EX;
 776    }
 777    if (tlb->prot & PAGE_WRITE) {
 778        ret |= PPC4XX_TLBLO_WR;
 779    }
 780    return ret;
 781}
 782
 783void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
 784                         target_ulong val)
 785{
 786    CPUState *cs = env_cpu(env);
 787    ppcemb_tlb_t *tlb;
 788    target_ulong page, end;
 789
 790    qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n",
 791                  __func__, (int)entry,
 792              val);
 793    entry &= PPC4XX_TLB_ENTRY_MASK;
 794    tlb = &env->tlb.tlbe[entry];
 795    /* Invalidate previous TLB (if it's valid) */
 796    if (tlb->prot & PAGE_VALID) {
 797        end = tlb->EPN + tlb->size;
 798        qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
 799                      TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
 800                      (int)entry, tlb->EPN, end);
 801        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
 802            tlb_flush_page(cs, page);
 803        }
 804    }
 805    tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
 806                                       & PPC4XX_TLBHI_SIZE_MASK);
 807    /*
 808     * We cannot handle TLB size < TARGET_PAGE_SIZE.
 809     * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
 810     */
 811    if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
 812        cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
 813                  "are not supported (%d)\n"
 814                  "Please implement TARGET_PAGE_BITS_VARY\n",
 815                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
 816    }
 817    tlb->EPN = val & ~(tlb->size - 1);
 818    if (val & PPC4XX_TLBHI_V) {
 819        tlb->prot |= PAGE_VALID;
 820        if (val & PPC4XX_TLBHI_E) {
 821            /* XXX: TO BE FIXED */
 822            cpu_abort(cs,
 823                      "Little-endian TLB entries are not supported by now\n");
 824        }
 825    } else {
 826        tlb->prot &= ~PAGE_VALID;
 827    }
 828    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
 829    qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx
 830                  " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx
 831                  " prot %c%c%c%c PID %d\n", __func__,
 832                  (int)entry, tlb->RPN, tlb->EPN, tlb->size,
 833                  tlb->prot & PAGE_READ ? 'r' : '-',
 834                  tlb->prot & PAGE_WRITE ? 'w' : '-',
 835                  tlb->prot & PAGE_EXEC ? 'x' : '-',
 836                  tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
 837    /* Invalidate new TLB (if valid) */
 838    if (tlb->prot & PAGE_VALID) {
 839        end = tlb->EPN + tlb->size;
 840        qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start "
 841                      TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
 842                      (int)entry, tlb->EPN, end);
 843        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
 844            tlb_flush_page(cs, page);
 845        }
 846    }
 847}
 848
 849void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
 850                         target_ulong val)
 851{
 852    ppcemb_tlb_t *tlb;
 853
 854    qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n",
 855                  __func__, (int)entry, val);
 856    entry &= PPC4XX_TLB_ENTRY_MASK;
 857    tlb = &env->tlb.tlbe[entry];
 858    tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
 859    tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
 860    tlb->prot = PAGE_READ;
 861    if (val & PPC4XX_TLBLO_EX) {
 862        tlb->prot |= PAGE_EXEC;
 863    }
 864    if (val & PPC4XX_TLBLO_WR) {
 865        tlb->prot |= PAGE_WRITE;
 866    }
 867    qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx
 868                  " EPN " TARGET_FMT_lx
 869                  " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
 870                  (int)entry, tlb->RPN, tlb->EPN, tlb->size,
 871                  tlb->prot & PAGE_READ ? 'r' : '-',
 872                  tlb->prot & PAGE_WRITE ? 'w' : '-',
 873                  tlb->prot & PAGE_EXEC ? 'x' : '-',
 874                  tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
 875
 876    env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
 877}
 878
 879target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
 880{
 881    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
 882}
 883
 884/* PowerPC 440 TLB management */
 885void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
 886                      target_ulong value)
 887{
 888    ppcemb_tlb_t *tlb;
 889    target_ulong EPN, RPN, size;
 890    int do_flush_tlbs;
 891
 892    qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n",
 893                  __func__, word, (int)entry, value);
 894    do_flush_tlbs = 0;
 895    entry &= 0x3F;
 896    tlb = &env->tlb.tlbe[entry];
 897    switch (word) {
 898    default:
 899        /* Just here to please gcc */
 900    case 0:
 901        EPN = value & 0xFFFFFC00;
 902        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
 903            do_flush_tlbs = 1;
 904        }
 905        tlb->EPN = EPN;
 906        size = booke_tlb_to_page_size((value >> 4) & 0xF);
 907        if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
 908            do_flush_tlbs = 1;
 909        }
 910        tlb->size = size;
 911        tlb->attr &= ~0x1;
 912        tlb->attr |= (value >> 8) & 1;
 913        if (value & 0x200) {
 914            tlb->prot |= PAGE_VALID;
 915        } else {
 916            if (tlb->prot & PAGE_VALID) {
 917                tlb->prot &= ~PAGE_VALID;
 918                do_flush_tlbs = 1;
 919            }
 920        }
 921        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
 922        if (do_flush_tlbs) {
 923            tlb_flush(env_cpu(env));
 924        }
 925        break;
 926    case 1:
 927        RPN = value & 0xFFFFFC0F;
 928        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
 929            tlb_flush(env_cpu(env));
 930        }
 931        tlb->RPN = RPN;
 932        break;
 933    case 2:
 934        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
 935        tlb->prot = tlb->prot & PAGE_VALID;
 936        if (value & 0x1) {
 937            tlb->prot |= PAGE_READ << 4;
 938        }
 939        if (value & 0x2) {
 940            tlb->prot |= PAGE_WRITE << 4;
 941        }
 942        if (value & 0x4) {
 943            tlb->prot |= PAGE_EXEC << 4;
 944        }
 945        if (value & 0x8) {
 946            tlb->prot |= PAGE_READ;
 947        }
 948        if (value & 0x10) {
 949            tlb->prot |= PAGE_WRITE;
 950        }
 951        if (value & 0x20) {
 952            tlb->prot |= PAGE_EXEC;
 953        }
 954        break;
 955    }
 956}
 957
 958target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
 959                              target_ulong entry)
 960{
 961    ppcemb_tlb_t *tlb;
 962    target_ulong ret;
 963    int size;
 964
 965    entry &= 0x3F;
 966    tlb = &env->tlb.tlbe[entry];
 967    switch (word) {
 968    default:
 969        /* Just here to please gcc */
 970    case 0:
 971        ret = tlb->EPN;
 972        size = booke_page_size_to_tlb(tlb->size);
 973        if (size < 0 || size > 0xF) {
 974            size = 1;
 975        }
 976        ret |= size << 4;
 977        if (tlb->attr & 0x1) {
 978            ret |= 0x100;
 979        }
 980        if (tlb->prot & PAGE_VALID) {
 981            ret |= 0x200;
 982        }
 983        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
 984        env->spr[SPR_440_MMUCR] |= tlb->PID;
 985        break;
 986    case 1:
 987        ret = tlb->RPN;
 988        break;
 989    case 2:
 990        ret = tlb->attr & ~0x1;
 991        if (tlb->prot & (PAGE_READ << 4)) {
 992            ret |= 0x1;
 993        }
 994        if (tlb->prot & (PAGE_WRITE << 4)) {
 995            ret |= 0x2;
 996        }
 997        if (tlb->prot & (PAGE_EXEC << 4)) {
 998            ret |= 0x4;
 999        }
1000        if (tlb->prot & PAGE_READ) {
1001            ret |= 0x8;
1002        }
1003        if (tlb->prot & PAGE_WRITE) {
1004            ret |= 0x10;
1005        }
1006        if (tlb->prot & PAGE_EXEC) {
1007            ret |= 0x20;
1008        }
1009        break;
1010    }
1011    return ret;
1012}
1013
1014target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
1015{
1016    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
1017}
1018
1019/* PowerPC BookE 2.06 TLB management */
1020
1021static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
1022{
1023    uint32_t tlbncfg = 0;
1024    int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
1025    int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
1026    int tlb;
1027
1028    tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
1029    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
1030
1031    if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
1032        cpu_abort(env_cpu(env), "we don't support HES yet\n");
1033    }
1034
1035    return booke206_get_tlbm(env, tlb, ea, esel);
1036}
1037
1038void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
1039{
1040    env->spr[pidn] = pid;
1041    /* changing PIDs mean we're in a different address space now */
1042    tlb_flush(env_cpu(env));
1043}
1044
1045void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
1046{
1047    env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
1048    tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD);
1049}
1050void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
1051{
1052    env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
1053    tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE);
1054}
1055
1056static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
1057{
1058    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
1059        tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK);
1060    } else {
1061        tlb_flush(env_cpu(env));
1062    }
1063}
1064
1065void helper_booke206_tlbwe(CPUPPCState *env)
1066{
1067    uint32_t tlbncfg, tlbn;
1068    ppcmas_tlb_t *tlb;
1069    uint32_t size_tlb, size_ps;
1070    target_ulong mask;
1071
1072
1073    switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
1074    case MAS0_WQ_ALWAYS:
1075        /* good to go, write that entry */
1076        break;
1077    case MAS0_WQ_COND:
1078        /* XXX check if reserved */
1079        if (0) {
1080            return;
1081        }
1082        break;
1083    case MAS0_WQ_CLR_RSRV:
1084        /* XXX clear entry */
1085        return;
1086    default:
1087        /* no idea what to do */
1088        return;
1089    }
1090
1091    if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
1092        !FIELD_EX64(env->msr, MSR, GS)) {
1093        /* XXX we don't support direct LRAT setting yet */
1094        fprintf(stderr, "cpu: don't support LRAT setting yet\n");
1095        return;
1096    }
1097
1098    tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
1099    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
1100
1101    tlb = booke206_cur_tlb(env);
1102
1103    if (!tlb) {
1104        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1105                               POWERPC_EXCP_INVAL |
1106                               POWERPC_EXCP_INVAL_INVAL, GETPC());
1107    }
1108
1109    /* check that we support the targeted size */
1110    size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1111    size_ps = booke206_tlbnps(env, tlbn);
1112    if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
1113        !(size_ps & (1 << size_tlb))) {
1114        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1115                               POWERPC_EXCP_INVAL |
1116                               POWERPC_EXCP_INVAL_INVAL, GETPC());
1117    }
1118
1119    if (FIELD_EX64(env->msr, MSR, GS)) {
1120        cpu_abort(env_cpu(env), "missing HV implementation\n");
1121    }
1122
1123    if (tlb->mas1 & MAS1_VALID) {
1124        /*
1125         * Invalidate the page in QEMU TLB if it was a valid entry.
1126         *
1127         * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
1128         * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
1129         * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
1130         *
1131         * "Note that when an L2 TLB entry is written, it may be displacing an
1132         * already valid entry in the same L2 TLB location (a victim). If a
1133         * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
1134         * TLB entry is automatically invalidated."
1135         */
1136        flush_page(env, tlb);
1137    }
1138
1139    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
1140        env->spr[SPR_BOOKE_MAS3];
1141    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
1142
1143    if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
1144        /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
1145        booke206_fixed_size_tlbn(env, tlbn, tlb);
1146    } else {
1147        if (!(tlbncfg & TLBnCFG_AVAIL)) {
1148            /* force !AVAIL TLB entries to correct page size */
1149            tlb->mas1 &= ~MAS1_TSIZE_MASK;
1150            /* XXX can be configured in MMUCSR0 */
1151            tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
1152        }
1153    }
1154
1155    /* Make a mask from TLB size to discard invalid bits in EPN field */
1156    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1157    /* Add a mask for page attributes */
1158    mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
1159
1160    if (!FIELD_EX64(env->msr, MSR, CM)) {
1161        /*
1162         * Executing a tlbwe instruction in 32-bit mode will set bits
1163         * 0:31 of the TLB EPN field to zero.
1164         */
1165        mask &= 0xffffffff;
1166    }
1167
1168    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
1169
1170    if (!(tlbncfg & TLBnCFG_IPROT)) {
1171        /* no IPROT supported by TLB */
1172        tlb->mas1 &= ~MAS1_IPROT;
1173    }
1174
1175    flush_page(env, tlb);
1176}
1177
1178static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
1179{
1180    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
1181    int way = booke206_tlbm_to_way(env, tlb);
1182
1183    env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
1184    env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
1185    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1186
1187    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
1188    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
1189    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
1190    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
1191}
1192
1193void helper_booke206_tlbre(CPUPPCState *env)
1194{
1195    ppcmas_tlb_t *tlb = NULL;
1196
1197    tlb = booke206_cur_tlb(env);
1198    if (!tlb) {
1199        env->spr[SPR_BOOKE_MAS1] = 0;
1200    } else {
1201        booke206_tlb_to_mas(env, tlb);
1202    }
1203}
1204
1205void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
1206{
1207    ppcmas_tlb_t *tlb = NULL;
1208    int i, j;
1209    hwaddr raddr;
1210    uint32_t spid, sas;
1211
1212    spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
1213    sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
1214
1215    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1216        int ways = booke206_tlb_ways(env, i);
1217
1218        for (j = 0; j < ways; j++) {
1219            tlb = booke206_get_tlbm(env, i, address, j);
1220
1221            if (!tlb) {
1222                continue;
1223            }
1224
1225            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
1226                continue;
1227            }
1228
1229            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1230                continue;
1231            }
1232
1233            booke206_tlb_to_mas(env, tlb);
1234            return;
1235        }
1236    }
1237
1238    /* no entry found, fill with defaults */
1239    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1240    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1241    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1242    env->spr[SPR_BOOKE_MAS3] = 0;
1243    env->spr[SPR_BOOKE_MAS7] = 0;
1244
1245    if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
1246        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1247    }
1248
1249    env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
1250        << MAS1_TID_SHIFT;
1251
1252    /* next victim logic */
1253    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1254    env->last_way++;
1255    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1256    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1257}
1258
1259static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
1260                                              vaddr ea)
1261{
1262    int i;
1263    int ways = booke206_tlb_ways(env, tlbn);
1264    target_ulong mask;
1265
1266    for (i = 0; i < ways; i++) {
1267        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
1268        if (!tlb) {
1269            continue;
1270        }
1271        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1272        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
1273            !(tlb->mas1 & MAS1_IPROT)) {
1274            tlb->mas1 &= ~MAS1_VALID;
1275        }
1276    }
1277}
1278
1279void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
1280{
1281    CPUState *cs;
1282
1283    if (address & 0x4) {
1284        /* flush all entries */
1285        if (address & 0x8) {
1286            /* flush all of TLB1 */
1287            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
1288        } else {
1289            /* flush all of TLB0 */
1290            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
1291        }
1292        return;
1293    }
1294
1295    if (address & 0x8) {
1296        /* flush TLB1 entries */
1297        booke206_invalidate_ea_tlb(env, 1, address);
1298        CPU_FOREACH(cs) {
1299            tlb_flush(cs);
1300        }
1301    } else {
1302        /* flush TLB0 entries */
1303        booke206_invalidate_ea_tlb(env, 0, address);
1304        CPU_FOREACH(cs) {
1305            tlb_flush_page(cs, address & MAS2_EPN_MASK);
1306        }
1307    }
1308}
1309
1310void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
1311{
1312    /* XXX missing LPID handling */
1313    booke206_flush_tlb(env, -1, 1);
1314}
1315
1316void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
1317{
1318    int i, j;
1319    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
1320    ppcmas_tlb_t *tlb = env->tlb.tlbm;
1321    int tlb_size;
1322
1323    /* XXX missing LPID handling */
1324    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1325        tlb_size = booke206_tlb_size(env, i);
1326        for (j = 0; j < tlb_size; j++) {
1327            if (!(tlb[j].mas1 & MAS1_IPROT) &&
1328                ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
1329                tlb[j].mas1 &= ~MAS1_VALID;
1330            }
1331        }
1332        tlb += booke206_tlb_size(env, i);
1333    }
1334    tlb_flush(env_cpu(env));
1335}
1336
1337void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
1338{
1339    int i, j;
1340    ppcmas_tlb_t *tlb;
1341    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
1342    int pid = tid >> MAS6_SPID_SHIFT;
1343    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
1344    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
1345    /* XXX check for unsupported isize and raise an invalid opcode then */
1346    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
1347    /* XXX implement MAV2 handling */
1348    bool mav2 = false;
1349
1350    /* XXX missing LPID handling */
1351    /* flush by pid and ea */
1352    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1353        int ways = booke206_tlb_ways(env, i);
1354
1355        for (j = 0; j < ways; j++) {
1356            tlb = booke206_get_tlbm(env, i, address, j);
1357            if (!tlb) {
1358                continue;
1359            }
1360            if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
1361                (tlb->mas1 & MAS1_IPROT) ||
1362                ((tlb->mas1 & MAS1_IND) != ind) ||
1363                ((tlb->mas8 & MAS8_TGS) != sgs)) {
1364                continue;
1365            }
1366            if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
1367                /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
1368                continue;
1369            }
1370            /* XXX e500mc doesn't match SAS, but other cores might */
1371            tlb->mas1 &= ~MAS1_VALID;
1372        }
1373    }
1374    tlb_flush(env_cpu(env));
1375}
1376
1377void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
1378{
1379    int flags = 0;
1380
1381    if (type & 2) {
1382        flags |= BOOKE206_FLUSH_TLB1;
1383    }
1384
1385    if (type & 4) {
1386        flags |= BOOKE206_FLUSH_TLB0;
1387    }
1388
1389    booke206_flush_tlb(env, flags, 1);
1390}
1391
1392
1393void helper_check_tlb_flush_local(CPUPPCState *env)
1394{
1395    check_tlb_flush(env, false);
1396}
1397
1398void helper_check_tlb_flush_global(CPUPPCState *env)
1399{
1400    check_tlb_flush(env, true);
1401}
1402
1403
1404bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size,
1405                      MMUAccessType access_type, int mmu_idx,
1406                      bool probe, uintptr_t retaddr)
1407{
1408    PowerPCCPU *cpu = POWERPC_CPU(cs);
1409    hwaddr raddr;
1410    int page_size, prot;
1411
1412    if (ppc_xlate(cpu, eaddr, access_type, &raddr,
1413                  &page_size, &prot, mmu_idx, !probe)) {
1414        tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
1415                     prot, mmu_idx, 1UL << page_size);
1416        return true;
1417    }
1418    if (probe) {
1419        return false;
1420    }
1421    raise_exception_err_ra(&cpu->env, cs->exception_index,
1422                           cpu->env.error_code, retaddr);
1423}
1424