cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

mmu_common.c (53804B)


      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
     37/* #define DEBUG_MMU */
     38/* #define DEBUG_BATS */
     39/* #define DEBUG_SOFTWARE_TLB */
     40/* #define DUMP_PAGE_TABLES */
     41/* #define FLUSH_ALL_TLBS */
     42
     43#ifdef DEBUG_MMU
     44#  define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
     45#else
     46#  define LOG_MMU_STATE(cpu) do { } while (0)
     47#endif
     48
     49#ifdef DEBUG_SOFTWARE_TLB
     50#  define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
     51#else
     52#  define LOG_SWTLB(...) do { } while (0)
     53#endif
     54
     55#ifdef DEBUG_BATS
     56#  define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
     57#else
     58#  define LOG_BATS(...) do { } while (0)
     59#endif
     60
     61void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
     62{
     63    PowerPCCPU *cpu = env_archcpu(env);
     64    qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
     65    assert(!cpu->env.has_hv_mode || !cpu->vhyp);
     66#if defined(TARGET_PPC64)
     67    if (mmu_is_64bit(env->mmu_model)) {
     68        target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
     69        target_ulong htabsize = value & SDR_64_HTABSIZE;
     70
     71        if (value & ~sdr_mask) {
     72            qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
     73                     " set in SDR1", value & ~sdr_mask);
     74            value &= sdr_mask;
     75        }
     76        if (htabsize > 28) {
     77            qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
     78                     " stored in SDR1", htabsize);
     79            return;
     80        }
     81    }
     82#endif /* defined(TARGET_PPC64) */
     83    /* FIXME: Should check for valid HTABMASK values in 32-bit case */
     84    env->spr[SPR_SDR1] = value;
     85}
     86
     87/*****************************************************************************/
     88/* PowerPC MMU emulation */
     89
     90static int pp_check(int key, int pp, int nx)
     91{
     92    int access;
     93
     94    /* Compute access rights */
     95    access = 0;
     96    if (key == 0) {
     97        switch (pp) {
     98        case 0x0:
     99        case 0x1:
    100        case 0x2:
    101            access |= PAGE_WRITE;
    102            /* fall through */
    103        case 0x3:
    104            access |= PAGE_READ;
    105            break;
    106        }
    107    } else {
    108        switch (pp) {
    109        case 0x0:
    110            access = 0;
    111            break;
    112        case 0x1:
    113        case 0x3:
    114            access = PAGE_READ;
    115            break;
    116        case 0x2:
    117            access = PAGE_READ | PAGE_WRITE;
    118            break;
    119        }
    120    }
    121    if (nx == 0) {
    122        access |= PAGE_EXEC;
    123    }
    124
    125    return access;
    126}
    127
    128static int check_prot(int prot, MMUAccessType access_type)
    129{
    130    return prot & prot_for_access_type(access_type) ? 0 : -2;
    131}
    132
    133int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
    134                                    int way, int is_code)
    135{
    136    int nr;
    137
    138    /* Select TLB num in a way from address */
    139    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
    140    /* Select TLB way */
    141    nr += env->tlb_per_way * way;
    142    /* 6xx have separate TLBs for instructions and data */
    143    if (is_code && env->id_tlbs == 1) {
    144        nr += env->nb_tlb;
    145    }
    146
    147    return nr;
    148}
    149
    150static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
    151                                target_ulong pte1, int h,
    152                                MMUAccessType access_type)
    153{
    154    target_ulong ptem, mmask;
    155    int access, ret, pteh, ptev, pp;
    156
    157    ret = -1;
    158    /* Check validity and table match */
    159    ptev = pte_is_valid(pte0);
    160    pteh = (pte0 >> 6) & 1;
    161    if (ptev && h == pteh) {
    162        /* Check vsid & api */
    163        ptem = pte0 & PTE_PTEM_MASK;
    164        mmask = PTE_CHECK_MASK;
    165        pp = pte1 & 0x00000003;
    166        if (ptem == ctx->ptem) {
    167            if (ctx->raddr != (hwaddr)-1ULL) {
    168                /* all matches should have equal RPN, WIMG & PP */
    169                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
    170                    qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
    171                    return -3;
    172                }
    173            }
    174            /* Compute access rights */
    175            access = pp_check(ctx->key, pp, ctx->nx);
    176            /* Keep the matching PTE information */
    177            ctx->raddr = pte1;
    178            ctx->prot = access;
    179            ret = check_prot(ctx->prot, access_type);
    180            if (ret == 0) {
    181                /* Access granted */
    182                qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
    183            } else {
    184                /* Access right violation */
    185                qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
    186            }
    187        }
    188    }
    189
    190    return ret;
    191}
    192
    193static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
    194                            int ret, MMUAccessType access_type)
    195{
    196    int store = 0;
    197
    198    /* Update page flags */
    199    if (!(*pte1p & 0x00000100)) {
    200        /* Update accessed flag */
    201        *pte1p |= 0x00000100;
    202        store = 1;
    203    }
    204    if (!(*pte1p & 0x00000080)) {
    205        if (access_type == MMU_DATA_STORE && ret == 0) {
    206            /* Update changed flag */
    207            *pte1p |= 0x00000080;
    208            store = 1;
    209        } else {
    210            /* Force page fault for first write access */
    211            ctx->prot &= ~PAGE_WRITE;
    212        }
    213    }
    214
    215    return store;
    216}
    217
    218/* Software driven TLB helpers */
    219
    220static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
    221                            target_ulong eaddr, MMUAccessType access_type)
    222{
    223    ppc6xx_tlb_t *tlb;
    224    int nr, best, way;
    225    int ret;
    226
    227    best = -1;
    228    ret = -1; /* No TLB found */
    229    for (way = 0; way < env->nb_ways; way++) {
    230        nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
    231        tlb = &env->tlb.tlb6[nr];
    232        /* This test "emulates" the PTE index match for hardware TLBs */
    233        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
    234            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
    235                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
    236                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
    237                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
    238            continue;
    239        }
    240        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
    241                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
    242                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
    243                  tlb->EPN, eaddr, tlb->pte1,
    244                  access_type == MMU_DATA_STORE ? 'S' : 'L',
    245                  access_type == MMU_INST_FETCH ? 'I' : 'D');
    246        switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
    247                                     0, access_type)) {
    248        case -3:
    249            /* TLB inconsistency */
    250            return -1;
    251        case -2:
    252            /* Access violation */
    253            ret = -2;
    254            best = nr;
    255            break;
    256        case -1:
    257        default:
    258            /* No match */
    259            break;
    260        case 0:
    261            /* access granted */
    262            /*
    263             * XXX: we should go on looping to check all TLBs
    264             *      consistency but we can speed-up the whole thing as
    265             *      the result would be undefined if TLBs are not
    266             *      consistent.
    267             */
    268            ret = 0;
    269            best = nr;
    270            goto done;
    271        }
    272    }
    273    if (best != -1) {
    274    done:
    275        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
    276                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
    277        /* Update page flags */
    278        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type);
    279    }
    280
    281    return ret;
    282}
    283
    284/* Perform BAT hit & translation */
    285static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
    286                                 int *validp, int *protp, target_ulong *BATu,
    287                                 target_ulong *BATl)
    288{
    289    target_ulong bl;
    290    int pp, valid, prot;
    291
    292    bl = (*BATu & 0x00001FFC) << 15;
    293    valid = 0;
    294    prot = 0;
    295    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
    296        ((msr_pr != 0) && (*BATu & 0x00000001))) {
    297        valid = 1;
    298        pp = *BATl & 0x00000003;
    299        if (pp != 0) {
    300            prot = PAGE_READ | PAGE_EXEC;
    301            if (pp == 0x2) {
    302                prot |= PAGE_WRITE;
    303            }
    304        }
    305    }
    306    *blp = bl;
    307    *validp = valid;
    308    *protp = prot;
    309}
    310
    311static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
    312                           target_ulong virtual, MMUAccessType access_type)
    313{
    314    target_ulong *BATlt, *BATut, *BATu, *BATl;
    315    target_ulong BEPIl, BEPIu, bl;
    316    int i, valid, prot;
    317    int ret = -1;
    318    bool ifetch = access_type == MMU_INST_FETCH;
    319
    320    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
    321             ifetch ? 'I' : 'D', virtual);
    322    if (ifetch) {
    323        BATlt = env->IBAT[1];
    324        BATut = env->IBAT[0];
    325    } else {
    326        BATlt = env->DBAT[1];
    327        BATut = env->DBAT[0];
    328    }
    329    for (i = 0; i < env->nb_BATs; i++) {
    330        BATu = &BATut[i];
    331        BATl = &BATlt[i];
    332        BEPIu = *BATu & 0xF0000000;
    333        BEPIl = *BATu & 0x0FFE0000;
    334        bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
    335        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
    336                 " BATl " TARGET_FMT_lx "\n", __func__,
    337                 ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
    338        if ((virtual & 0xF0000000) == BEPIu &&
    339            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
    340            /* BAT matches */
    341            if (valid != 0) {
    342                /* Get physical address */
    343                ctx->raddr = (*BATl & 0xF0000000) |
    344                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
    345                    (virtual & 0x0001F000);
    346                /* Compute access rights */
    347                ctx->prot = prot;
    348                ret = check_prot(ctx->prot, access_type);
    349                if (ret == 0) {
    350                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
    351                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
    352                             ctx->prot & PAGE_WRITE ? 'W' : '-');
    353                }
    354                break;
    355            }
    356        }
    357    }
    358    if (ret < 0) {
    359#if defined(DEBUG_BATS)
    360        if (qemu_log_enabled()) {
    361            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
    362            for (i = 0; i < 4; i++) {
    363                BATu = &BATut[i];
    364                BATl = &BATlt[i];
    365                BEPIu = *BATu & 0xF0000000;
    366                BEPIl = *BATu & 0x0FFE0000;
    367                bl = (*BATu & 0x00001FFC) << 15;
    368                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
    369                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
    370                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
    371                         __func__, ifetch ? 'I' : 'D', i, virtual,
    372                         *BATu, *BATl, BEPIu, BEPIl, bl);
    373            }
    374        }
    375#endif
    376    }
    377    /* No hit */
    378    return ret;
    379}
    380
    381/* Perform segment based translation */
    382static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
    383                               target_ulong eaddr, MMUAccessType access_type,
    384                               int type)
    385{
    386    PowerPCCPU *cpu = env_archcpu(env);
    387    hwaddr hash;
    388    target_ulong vsid;
    389    int ds, pr, target_page_bits;
    390    int ret;
    391    target_ulong sr, pgidx;
    392
    393    pr = msr_pr;
    394    ctx->eaddr = eaddr;
    395
    396    sr = env->sr[eaddr >> 28];
    397    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
    398                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
    399    ds = sr & 0x80000000 ? 1 : 0;
    400    ctx->nx = sr & 0x10000000 ? 1 : 0;
    401    vsid = sr & 0x00FFFFFF;
    402    target_page_bits = TARGET_PAGE_BITS;
    403    qemu_log_mask(CPU_LOG_MMU,
    404            "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
    405            " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
    406            " ir=%d dr=%d pr=%d %d t=%d\n",
    407            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
    408            (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type);
    409    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
    410    hash = vsid ^ pgidx;
    411    ctx->ptem = (vsid << 7) | (pgidx >> 10);
    412
    413    qemu_log_mask(CPU_LOG_MMU,
    414            "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
    415            ctx->key, ds, ctx->nx, vsid);
    416    ret = -1;
    417    if (!ds) {
    418        /* Check if instruction fetch is allowed, if needed */
    419        if (type != ACCESS_CODE || ctx->nx == 0) {
    420            /* Page address translation */
    421            qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
    422                    " htab_mask " TARGET_FMT_plx
    423                    " hash " TARGET_FMT_plx "\n",
    424                    ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
    425            ctx->hash[0] = hash;
    426            ctx->hash[1] = ~hash;
    427
    428            /* Initialize real address with an invalid value */
    429            ctx->raddr = (hwaddr)-1ULL;
    430            /* Software TLB search */
    431            ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
    432#if defined(DUMP_PAGE_TABLES)
    433            if (qemu_loglevel_mask(CPU_LOG_MMU)) {
    434                CPUState *cs = env_cpu(env);
    435                hwaddr curaddr;
    436                uint32_t a0, a1, a2, a3;
    437
    438                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
    439                         "\n", ppc_hash32_hpt_base(cpu),
    440                         ppc_hash32_hpt_mask(cpu) + 0x80);
    441                for (curaddr = ppc_hash32_hpt_base(cpu);
    442                     curaddr < (ppc_hash32_hpt_base(cpu)
    443                                + ppc_hash32_hpt_mask(cpu) + 0x80);
    444                     curaddr += 16) {
    445                    a0 = ldl_phys(cs->as, curaddr);
    446                    a1 = ldl_phys(cs->as, curaddr + 4);
    447                    a2 = ldl_phys(cs->as, curaddr + 8);
    448                    a3 = ldl_phys(cs->as, curaddr + 12);
    449                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
    450                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
    451                                 curaddr, a0, a1, a2, a3);
    452                    }
    453                }
    454            }
    455#endif
    456        } else {
    457            qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
    458            ret = -3;
    459        }
    460    } else {
    461        target_ulong sr;
    462
    463        qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
    464        /* Direct-store segment : absolutely *BUGGY* for now */
    465
    466        /*
    467         * Direct-store implies a 32-bit MMU.
    468         * Check the Segment Register's bus unit ID (BUID).
    469         */
    470        sr = env->sr[eaddr >> 28];
    471        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
    472            /*
    473             * Memory-forced I/O controller interface access
    474             *
    475             * If T=1 and BUID=x'07F', the 601 performs a memory
    476             * access to SR[28-31] LA[4-31], bypassing all protection
    477             * mechanisms.
    478             */
    479            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
    480            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
    481            return 0;
    482        }
    483
    484        switch (type) {
    485        case ACCESS_INT:
    486            /* Integer load/store : only access allowed */
    487            break;
    488        case ACCESS_CODE:
    489            /* No code fetch is allowed in direct-store areas */
    490            return -4;
    491        case ACCESS_FLOAT:
    492            /* Floating point load/store */
    493            return -4;
    494        case ACCESS_RES:
    495            /* lwarx, ldarx or srwcx. */
    496            return -4;
    497        case ACCESS_CACHE:
    498            /*
    499             * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
    500             *
    501             * Should make the instruction do no-op.  As it already do
    502             * no-op, it's quite easy :-)
    503             */
    504            ctx->raddr = eaddr;
    505            return 0;
    506        case ACCESS_EXT:
    507            /* eciwx or ecowx */
    508            return -4;
    509        default:
    510            qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
    511                          "address translation\n");
    512            return -4;
    513        }
    514        if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
    515            (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
    516            ctx->raddr = eaddr;
    517            ret = 2;
    518        } else {
    519            ret = -2;
    520        }
    521    }
    522
    523    return ret;
    524}
    525
    526/* Generic TLB check function for embedded PowerPC implementations */
    527int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
    528                            hwaddr *raddrp,
    529                            target_ulong address, uint32_t pid, int ext,
    530                            int i)
    531{
    532    target_ulong mask;
    533
    534    /* Check valid flag */
    535    if (!(tlb->prot & PAGE_VALID)) {
    536        return -1;
    537    }
    538    mask = ~(tlb->size - 1);
    539    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
    540              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
    541              mask, (uint32_t)tlb->PID, tlb->prot);
    542    /* Check PID */
    543    if (tlb->PID != 0 && tlb->PID != pid) {
    544        return -1;
    545    }
    546    /* Check effective address */
    547    if ((address & mask) != tlb->EPN) {
    548        return -1;
    549    }
    550    *raddrp = (tlb->RPN & mask) | (address & ~mask);
    551    if (ext) {
    552        /* Extend the physical address to 36 bits */
    553        *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
    554    }
    555
    556    return 0;
    557}
    558
    559static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
    560                                       target_ulong address,
    561                                       MMUAccessType access_type)
    562{
    563    ppcemb_tlb_t *tlb;
    564    hwaddr raddr;
    565    int i, ret, zsel, zpr, pr;
    566
    567    ret = -1;
    568    raddr = (hwaddr)-1ULL;
    569    pr = msr_pr;
    570    for (i = 0; i < env->nb_tlb; i++) {
    571        tlb = &env->tlb.tlbe[i];
    572        if (ppcemb_tlb_check(env, tlb, &raddr, address,
    573                             env->spr[SPR_40x_PID], 0, i) < 0) {
    574            continue;
    575        }
    576        zsel = (tlb->attr >> 4) & 0xF;
    577        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
    578        LOG_SWTLB("%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
    579                    __func__, i, zsel, zpr, access_type, tlb->attr);
    580        /* Check execute enable bit */
    581        switch (zpr) {
    582        case 0x2:
    583            if (pr != 0) {
    584                goto check_perms;
    585            }
    586            /* fall through */
    587        case 0x3:
    588            /* All accesses granted */
    589            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
    590            ret = 0;
    591            break;
    592        case 0x0:
    593            if (pr != 0) {
    594                /* Raise Zone protection fault.  */
    595                env->spr[SPR_40x_ESR] = 1 << 22;
    596                ctx->prot = 0;
    597                ret = -2;
    598                break;
    599            }
    600            /* fall through */
    601        case 0x1:
    602        check_perms:
    603            /* Check from TLB entry */
    604            ctx->prot = tlb->prot;
    605            ret = check_prot(ctx->prot, access_type);
    606            if (ret == -2) {
    607                env->spr[SPR_40x_ESR] = 0;
    608            }
    609            break;
    610        }
    611        if (ret >= 0) {
    612            ctx->raddr = raddr;
    613            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
    614                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
    615                      ret);
    616            return 0;
    617        }
    618    }
    619    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
    620              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
    621
    622    return ret;
    623}
    624
    625static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
    626                              hwaddr *raddr, int *prot, target_ulong address,
    627                              MMUAccessType access_type, int i)
    628{
    629    int prot2;
    630
    631    if (ppcemb_tlb_check(env, tlb, raddr, address,
    632                         env->spr[SPR_BOOKE_PID],
    633                         !env->nb_pids, i) >= 0) {
    634        goto found_tlb;
    635    }
    636
    637    if (env->spr[SPR_BOOKE_PID1] &&
    638        ppcemb_tlb_check(env, tlb, raddr, address,
    639                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
    640        goto found_tlb;
    641    }
    642
    643    if (env->spr[SPR_BOOKE_PID2] &&
    644        ppcemb_tlb_check(env, tlb, raddr, address,
    645                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
    646        goto found_tlb;
    647    }
    648
    649    LOG_SWTLB("%s: TLB entry not found\n", __func__);
    650    return -1;
    651
    652found_tlb:
    653
    654    if (msr_pr != 0) {
    655        prot2 = tlb->prot & 0xF;
    656    } else {
    657        prot2 = (tlb->prot >> 4) & 0xF;
    658    }
    659
    660    /* Check the address space */
    661    if ((access_type == MMU_INST_FETCH ? msr_ir : msr_dr) != (tlb->attr & 1)) {
    662        LOG_SWTLB("%s: AS doesn't match\n", __func__);
    663        return -1;
    664    }
    665
    666    *prot = prot2;
    667    if (prot2 & prot_for_access_type(access_type)) {
    668        LOG_SWTLB("%s: good TLB!\n", __func__);
    669        return 0;
    670    }
    671
    672    LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2);
    673    return access_type == MMU_INST_FETCH ? -3 : -2;
    674}
    675
    676static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
    677                                         target_ulong address,
    678                                         MMUAccessType access_type)
    679{
    680    ppcemb_tlb_t *tlb;
    681    hwaddr raddr;
    682    int i, ret;
    683
    684    ret = -1;
    685    raddr = (hwaddr)-1ULL;
    686    for (i = 0; i < env->nb_tlb; i++) {
    687        tlb = &env->tlb.tlbe[i];
    688        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address,
    689                                 access_type, i);
    690        if (ret != -1) {
    691            break;
    692        }
    693    }
    694
    695    if (ret >= 0) {
    696        ctx->raddr = raddr;
    697        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
    698                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
    699                  ret);
    700    } else {
    701        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
    702                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
    703    }
    704
    705    return ret;
    706}
    707
    708hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
    709                                        ppcmas_tlb_t *tlb)
    710{
    711    int tlbm_size;
    712
    713    tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
    714
    715    return 1024ULL << tlbm_size;
    716}
    717
    718/* TLB check function for MAS based SoftTLBs */
    719int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
    720                            hwaddr *raddrp, target_ulong address,
    721                            uint32_t pid)
    722{
    723    hwaddr mask;
    724    uint32_t tlb_pid;
    725
    726    if (!msr_cm) {
    727        /* In 32bit mode we can only address 32bit EAs */
    728        address = (uint32_t)address;
    729    }
    730
    731    /* Check valid flag */
    732    if (!(tlb->mas1 & MAS1_VALID)) {
    733        return -1;
    734    }
    735
    736    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
    737    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
    738              PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
    739              PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
    740              tlb->mas7_3, tlb->mas8);
    741
    742    /* Check PID */
    743    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
    744    if (tlb_pid != 0 && tlb_pid != pid) {
    745        return -1;
    746    }
    747
    748    /* Check effective address */
    749    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
    750        return -1;
    751    }
    752
    753    if (raddrp) {
    754        *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
    755    }
    756
    757    return 0;
    758}
    759
    760static bool is_epid_mmu(int mmu_idx)
    761{
    762    return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
    763}
    764
    765static uint32_t mmubooke206_esr(int mmu_idx, MMUAccessType access_type)
    766{
    767    uint32_t esr = 0;
    768    if (access_type == MMU_DATA_STORE) {
    769        esr |= ESR_ST;
    770    }
    771    if (is_epid_mmu(mmu_idx)) {
    772        esr |= ESR_EPID;
    773    }
    774    return esr;
    775}
    776
    777/*
    778 * Get EPID register given the mmu_idx. If this is regular load,
    779 * construct the EPID access bits from current processor state
    780 *
    781 * Get the effective AS and PR bits and the PID. The PID is returned
    782 * only if EPID load is requested, otherwise the caller must detect
    783 * the correct EPID.  Return true if valid EPID is returned.
    784 */
    785static bool mmubooke206_get_as(CPUPPCState *env,
    786                               int mmu_idx, uint32_t *epid_out,
    787                               bool *as_out, bool *pr_out)
    788{
    789    if (is_epid_mmu(mmu_idx)) {
    790        uint32_t epidr;
    791        if (mmu_idx == PPC_TLB_EPID_STORE) {
    792            epidr = env->spr[SPR_BOOKE_EPSC];
    793        } else {
    794            epidr = env->spr[SPR_BOOKE_EPLC];
    795        }
    796        *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
    797        *as_out = !!(epidr & EPID_EAS);
    798        *pr_out = !!(epidr & EPID_EPR);
    799        return true;
    800    } else {
    801        *as_out = msr_ds;
    802        *pr_out = msr_pr;
    803        return false;
    804    }
    805}
    806
    807/* Check if the tlb found by hashing really matches */
    808static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
    809                                 hwaddr *raddr, int *prot,
    810                                 target_ulong address,
    811                                 MMUAccessType access_type, int mmu_idx)
    812{
    813    int prot2 = 0;
    814    uint32_t epid;
    815    bool as, pr;
    816    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
    817
    818    if (!use_epid) {
    819        if (ppcmas_tlb_check(env, tlb, raddr, address,
    820                             env->spr[SPR_BOOKE_PID]) >= 0) {
    821            goto found_tlb;
    822        }
    823
    824        if (env->spr[SPR_BOOKE_PID1] &&
    825            ppcmas_tlb_check(env, tlb, raddr, address,
    826                             env->spr[SPR_BOOKE_PID1]) >= 0) {
    827            goto found_tlb;
    828        }
    829
    830        if (env->spr[SPR_BOOKE_PID2] &&
    831            ppcmas_tlb_check(env, tlb, raddr, address,
    832                             env->spr[SPR_BOOKE_PID2]) >= 0) {
    833            goto found_tlb;
    834        }
    835    } else {
    836        if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
    837            goto found_tlb;
    838        }
    839    }
    840
    841    LOG_SWTLB("%s: TLB entry not found\n", __func__);
    842    return -1;
    843
    844found_tlb:
    845
    846    if (pr) {
    847        if (tlb->mas7_3 & MAS3_UR) {
    848            prot2 |= PAGE_READ;
    849        }
    850        if (tlb->mas7_3 & MAS3_UW) {
    851            prot2 |= PAGE_WRITE;
    852        }
    853        if (tlb->mas7_3 & MAS3_UX) {
    854            prot2 |= PAGE_EXEC;
    855        }
    856    } else {
    857        if (tlb->mas7_3 & MAS3_SR) {
    858            prot2 |= PAGE_READ;
    859        }
    860        if (tlb->mas7_3 & MAS3_SW) {
    861            prot2 |= PAGE_WRITE;
    862        }
    863        if (tlb->mas7_3 & MAS3_SX) {
    864            prot2 |= PAGE_EXEC;
    865        }
    866    }
    867
    868    /* Check the address space and permissions */
    869    if (access_type == MMU_INST_FETCH) {
    870        /* There is no way to fetch code using epid load */
    871        assert(!use_epid);
    872        as = msr_ir;
    873    }
    874
    875    if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
    876        LOG_SWTLB("%s: AS doesn't match\n", __func__);
    877        return -1;
    878    }
    879
    880    *prot = prot2;
    881    if (prot2 & prot_for_access_type(access_type)) {
    882        LOG_SWTLB("%s: good TLB!\n", __func__);
    883        return 0;
    884    }
    885
    886    LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2);
    887    return access_type == MMU_INST_FETCH ? -3 : -2;
    888}
    889
    890static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
    891                                            target_ulong address,
    892                                            MMUAccessType access_type,
    893                                            int mmu_idx)
    894{
    895    ppcmas_tlb_t *tlb;
    896    hwaddr raddr;
    897    int i, j, ret;
    898
    899    ret = -1;
    900    raddr = (hwaddr)-1ULL;
    901
    902    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
    903        int ways = booke206_tlb_ways(env, i);
    904
    905        for (j = 0; j < ways; j++) {
    906            tlb = booke206_get_tlbm(env, i, address, j);
    907            if (!tlb) {
    908                continue;
    909            }
    910            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
    911                                        access_type, mmu_idx);
    912            if (ret != -1) {
    913                goto found_tlb;
    914            }
    915        }
    916    }
    917
    918found_tlb:
    919
    920    if (ret >= 0) {
    921        ctx->raddr = raddr;
    922        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
    923                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
    924                  ret);
    925    } else {
    926        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
    927                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
    928    }
    929
    930    return ret;
    931}
    932
    933static const char *book3e_tsize_to_str[32] = {
    934    "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
    935    "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
    936    "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
    937    "1T", "2T"
    938};
    939
    940static void mmubooke_dump_mmu(CPUPPCState *env)
    941{
    942    ppcemb_tlb_t *entry;
    943    int i;
    944
    945    if (kvm_enabled() && !env->kvm_sw_tlb) {
    946        qemu_printf("Cannot access KVM TLB\n");
    947        return;
    948    }
    949
    950    qemu_printf("\nTLB:\n");
    951    qemu_printf("Effective          Physical           Size PID   Prot     "
    952                "Attr\n");
    953
    954    entry = &env->tlb.tlbe[0];
    955    for (i = 0; i < env->nb_tlb; i++, entry++) {
    956        hwaddr ea, pa;
    957        target_ulong mask;
    958        uint64_t size = (uint64_t)entry->size;
    959        char size_buf[20];
    960
    961        /* Check valid flag */
    962        if (!(entry->prot & PAGE_VALID)) {
    963            continue;
    964        }
    965
    966        mask = ~(entry->size - 1);
    967        ea = entry->EPN & mask;
    968        pa = entry->RPN & mask;
    969        /* Extend the physical address to 36 bits */
    970        pa |= (hwaddr)(entry->RPN & 0xF) << 32;
    971        if (size >= 1 * MiB) {
    972            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
    973        } else {
    974            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
    975        }
    976        qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
    977                    (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
    978                    entry->prot, entry->attr);
    979    }
    980
    981}
    982
    983static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
    984                                     int tlbsize)
    985{
    986    ppcmas_tlb_t *entry;
    987    int i;
    988
    989    qemu_printf("\nTLB%d:\n", tlbn);
    990    qemu_printf("Effective          Physical           Size TID   TS SRWX"
    991                " URWX WIMGE U0123\n");
    992
    993    entry = &env->tlb.tlbm[offset];
    994    for (i = 0; i < tlbsize; i++, entry++) {
    995        hwaddr ea, pa, size;
    996        int tsize;
    997
    998        if (!(entry->mas1 & MAS1_VALID)) {
    999            continue;
   1000        }
   1001
   1002        tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
   1003        size = 1024ULL << tsize;
   1004        ea = entry->mas2 & ~(size - 1);
   1005        pa = entry->mas7_3 & ~(size - 1);
   1006
   1007        qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
   1008                    "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
   1009                    (uint64_t)ea, (uint64_t)pa,
   1010                    book3e_tsize_to_str[tsize],
   1011                    (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
   1012                    (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
   1013                    entry->mas7_3 & MAS3_SR ? 'R' : '-',
   1014                    entry->mas7_3 & MAS3_SW ? 'W' : '-',
   1015                    entry->mas7_3 & MAS3_SX ? 'X' : '-',
   1016                    entry->mas7_3 & MAS3_UR ? 'R' : '-',
   1017                    entry->mas7_3 & MAS3_UW ? 'W' : '-',
   1018                    entry->mas7_3 & MAS3_UX ? 'X' : '-',
   1019                    entry->mas2 & MAS2_W ? 'W' : '-',
   1020                    entry->mas2 & MAS2_I ? 'I' : '-',
   1021                    entry->mas2 & MAS2_M ? 'M' : '-',
   1022                    entry->mas2 & MAS2_G ? 'G' : '-',
   1023                    entry->mas2 & MAS2_E ? 'E' : '-',
   1024                    entry->mas7_3 & MAS3_U0 ? '0' : '-',
   1025                    entry->mas7_3 & MAS3_U1 ? '1' : '-',
   1026                    entry->mas7_3 & MAS3_U2 ? '2' : '-',
   1027                    entry->mas7_3 & MAS3_U3 ? '3' : '-');
   1028    }
   1029}
   1030
   1031static void mmubooke206_dump_mmu(CPUPPCState *env)
   1032{
   1033    int offset = 0;
   1034    int i;
   1035
   1036    if (kvm_enabled() && !env->kvm_sw_tlb) {
   1037        qemu_printf("Cannot access KVM TLB\n");
   1038        return;
   1039    }
   1040
   1041    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
   1042        int size = booke206_tlb_size(env, i);
   1043
   1044        if (size == 0) {
   1045            continue;
   1046        }
   1047
   1048        mmubooke206_dump_one_tlb(env, i, offset, size);
   1049        offset += size;
   1050    }
   1051}
   1052
   1053static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
   1054{
   1055    target_ulong *BATlt, *BATut, *BATu, *BATl;
   1056    target_ulong BEPIl, BEPIu, bl;
   1057    int i;
   1058
   1059    switch (type) {
   1060    case ACCESS_CODE:
   1061        BATlt = env->IBAT[1];
   1062        BATut = env->IBAT[0];
   1063        break;
   1064    default:
   1065        BATlt = env->DBAT[1];
   1066        BATut = env->DBAT[0];
   1067        break;
   1068    }
   1069
   1070    for (i = 0; i < env->nb_BATs; i++) {
   1071        BATu = &BATut[i];
   1072        BATl = &BATlt[i];
   1073        BEPIu = *BATu & 0xF0000000;
   1074        BEPIl = *BATu & 0x0FFE0000;
   1075        bl = (*BATu & 0x00001FFC) << 15;
   1076        qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
   1077                    " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
   1078                    TARGET_FMT_lx " " TARGET_FMT_lx "\n",
   1079                    type == ACCESS_CODE ? "code" : "data", i,
   1080                    *BATu, *BATl, BEPIu, BEPIl, bl);
   1081    }
   1082}
   1083
   1084static void mmu6xx_dump_mmu(CPUPPCState *env)
   1085{
   1086    PowerPCCPU *cpu = env_archcpu(env);
   1087    ppc6xx_tlb_t *tlb;
   1088    target_ulong sr;
   1089    int type, way, entry, i;
   1090
   1091    qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
   1092    qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
   1093
   1094    qemu_printf("\nSegment registers:\n");
   1095    for (i = 0; i < 32; i++) {
   1096        sr = env->sr[i];
   1097        if (sr & 0x80000000) {
   1098            qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
   1099                        "CNTLR_SPEC=0x%05x\n", i,
   1100                        sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
   1101                        sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
   1102                        (uint32_t)(sr & 0xFFFFF));
   1103        } else {
   1104            qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
   1105                        sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
   1106                        sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
   1107                        (uint32_t)(sr & 0x00FFFFFF));
   1108        }
   1109    }
   1110
   1111    qemu_printf("\nBATs:\n");
   1112    mmu6xx_dump_BATs(env, ACCESS_INT);
   1113    mmu6xx_dump_BATs(env, ACCESS_CODE);
   1114
   1115    if (env->id_tlbs != 1) {
   1116        qemu_printf("ERROR: 6xx MMU should have separated TLB"
   1117                    " for code and data\n");
   1118    }
   1119
   1120    qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
   1121
   1122    for (type = 0; type < 2; type++) {
   1123        for (way = 0; way < env->nb_ways; way++) {
   1124            for (entry = env->nb_tlb * type + env->tlb_per_way * way;
   1125                 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
   1126                 entry++) {
   1127
   1128                tlb = &env->tlb.tlb6[entry];
   1129                qemu_printf("%s TLB %02d/%02d way:%d %s ["
   1130                            TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
   1131                            type ? "code" : "data", entry % env->nb_tlb,
   1132                            env->nb_tlb, way,
   1133                            pte_is_valid(tlb->pte0) ? "valid" : "inval",
   1134                            tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
   1135            }
   1136        }
   1137    }
   1138}
   1139
   1140void dump_mmu(CPUPPCState *env)
   1141{
   1142    switch (env->mmu_model) {
   1143    case POWERPC_MMU_BOOKE:
   1144        mmubooke_dump_mmu(env);
   1145        break;
   1146    case POWERPC_MMU_BOOKE206:
   1147        mmubooke206_dump_mmu(env);
   1148        break;
   1149    case POWERPC_MMU_SOFT_6xx:
   1150    case POWERPC_MMU_SOFT_74xx:
   1151        mmu6xx_dump_mmu(env);
   1152        break;
   1153#if defined(TARGET_PPC64)
   1154    case POWERPC_MMU_64B:
   1155    case POWERPC_MMU_2_03:
   1156    case POWERPC_MMU_2_06:
   1157    case POWERPC_MMU_2_07:
   1158        dump_slb(env_archcpu(env));
   1159        break;
   1160    case POWERPC_MMU_3_00:
   1161        if (ppc64_v3_radix(env_archcpu(env))) {
   1162            qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
   1163                          __func__);
   1164        } else {
   1165            dump_slb(env_archcpu(env));
   1166        }
   1167        break;
   1168#endif
   1169    default:
   1170        qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
   1171    }
   1172}
   1173
   1174static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
   1175                          MMUAccessType access_type)
   1176{
   1177    int in_plb, ret;
   1178
   1179    ctx->raddr = eaddr;
   1180    ctx->prot = PAGE_READ | PAGE_EXEC;
   1181    ret = 0;
   1182    switch (env->mmu_model) {
   1183    case POWERPC_MMU_SOFT_6xx:
   1184    case POWERPC_MMU_SOFT_74xx:
   1185    case POWERPC_MMU_SOFT_4xx:
   1186    case POWERPC_MMU_REAL:
   1187    case POWERPC_MMU_BOOKE:
   1188        ctx->prot |= PAGE_WRITE;
   1189        break;
   1190
   1191    case POWERPC_MMU_SOFT_4xx_Z:
   1192        if (unlikely(msr_pe != 0)) {
   1193            /*
   1194             * 403 family add some particular protections, using
   1195             * PBL/PBU registers for accesses with no translation.
   1196             */
   1197            in_plb =
   1198                /* Check PLB validity */
   1199                (env->pb[0] < env->pb[1] &&
   1200                 /* and address in plb area */
   1201                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
   1202                (env->pb[2] < env->pb[3] &&
   1203                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
   1204            if (in_plb ^ msr_px) {
   1205                /* Access in protected area */
   1206                if (access_type == MMU_DATA_STORE) {
   1207                    /* Access is not allowed */
   1208                    ret = -2;
   1209                }
   1210            } else {
   1211                /* Read-write access is allowed */
   1212                ctx->prot |= PAGE_WRITE;
   1213            }
   1214        }
   1215        break;
   1216
   1217    default:
   1218        /* Caller's checks mean we should never get here for other models */
   1219        abort();
   1220        return -1;
   1221    }
   1222
   1223    return ret;
   1224}
   1225
   1226int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
   1227                                     target_ulong eaddr,
   1228                                     MMUAccessType access_type, int type,
   1229                                     int mmu_idx)
   1230{
   1231    int ret = -1;
   1232    bool real_mode = (type == ACCESS_CODE && msr_ir == 0)
   1233        || (type != ACCESS_CODE && msr_dr == 0);
   1234
   1235    switch (env->mmu_model) {
   1236    case POWERPC_MMU_SOFT_6xx:
   1237    case POWERPC_MMU_SOFT_74xx:
   1238        if (real_mode) {
   1239            ret = check_physical(env, ctx, eaddr, access_type);
   1240        } else {
   1241            /* Try to find a BAT */
   1242            if (env->nb_BATs != 0) {
   1243                ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
   1244            }
   1245            if (ret < 0) {
   1246                /* We didn't match any BAT entry or don't have BATs */
   1247                ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
   1248            }
   1249        }
   1250        break;
   1251
   1252    case POWERPC_MMU_SOFT_4xx:
   1253    case POWERPC_MMU_SOFT_4xx_Z:
   1254        if (real_mode) {
   1255            ret = check_physical(env, ctx, eaddr, access_type);
   1256        } else {
   1257            ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
   1258        }
   1259        break;
   1260    case POWERPC_MMU_BOOKE:
   1261        ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
   1262        break;
   1263    case POWERPC_MMU_BOOKE206:
   1264        ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
   1265                                               mmu_idx);
   1266        break;
   1267    case POWERPC_MMU_MPC8xx:
   1268        /* XXX: TODO */
   1269        cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
   1270        break;
   1271    case POWERPC_MMU_REAL:
   1272        if (real_mode) {
   1273            ret = check_physical(env, ctx, eaddr, access_type);
   1274        } else {
   1275            cpu_abort(env_cpu(env),
   1276                      "PowerPC in real mode do not do any translation\n");
   1277        }
   1278        return -1;
   1279    default:
   1280        cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
   1281        return -1;
   1282    }
   1283
   1284    return ret;
   1285}
   1286
   1287static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
   1288                                         MMUAccessType access_type, int mmu_idx)
   1289{
   1290    uint32_t epid;
   1291    bool as, pr;
   1292    uint32_t missed_tid = 0;
   1293    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
   1294
   1295    if (access_type == MMU_INST_FETCH) {
   1296        as = msr_ir;
   1297    }
   1298    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
   1299    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
   1300    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
   1301    env->spr[SPR_BOOKE_MAS3] = 0;
   1302    env->spr[SPR_BOOKE_MAS6] = 0;
   1303    env->spr[SPR_BOOKE_MAS7] = 0;
   1304
   1305    /* AS */
   1306    if (as) {
   1307        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
   1308        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
   1309    }
   1310
   1311    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
   1312    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
   1313
   1314    if (!use_epid) {
   1315        switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
   1316        case MAS4_TIDSELD_PID0:
   1317            missed_tid = env->spr[SPR_BOOKE_PID];
   1318            break;
   1319        case MAS4_TIDSELD_PID1:
   1320            missed_tid = env->spr[SPR_BOOKE_PID1];
   1321            break;
   1322        case MAS4_TIDSELD_PID2:
   1323            missed_tid = env->spr[SPR_BOOKE_PID2];
   1324            break;
   1325        }
   1326        env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
   1327    } else {
   1328        missed_tid = epid;
   1329        env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
   1330    }
   1331    env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
   1332
   1333
   1334    /* next victim logic */
   1335    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
   1336    env->last_way++;
   1337    env->last_way &= booke206_tlb_ways(env, 0) - 1;
   1338    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
   1339}
   1340
   1341/* Perform address translation */
   1342/* TODO: Split this by mmu_model. */
   1343static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
   1344                            MMUAccessType access_type,
   1345                            hwaddr *raddrp, int *psizep, int *protp,
   1346                            int mmu_idx, bool guest_visible)
   1347{
   1348    CPUState *cs = CPU(cpu);
   1349    CPUPPCState *env = &cpu->env;
   1350    mmu_ctx_t ctx;
   1351    int type;
   1352    int ret;
   1353
   1354    if (access_type == MMU_INST_FETCH) {
   1355        /* code access */
   1356        type = ACCESS_CODE;
   1357    } else if (guest_visible) {
   1358        /* data access */
   1359        type = env->access_type;
   1360    } else {
   1361        type = ACCESS_INT;
   1362    }
   1363
   1364    ret = get_physical_address_wtlb(env, &ctx, eaddr, access_type,
   1365                                    type, mmu_idx);
   1366    if (ret == 0) {
   1367        *raddrp = ctx.raddr;
   1368        *protp = ctx.prot;
   1369        *psizep = TARGET_PAGE_BITS;
   1370        return true;
   1371    }
   1372
   1373    if (guest_visible) {
   1374        LOG_MMU_STATE(cs);
   1375        if (type == ACCESS_CODE) {
   1376            switch (ret) {
   1377            case -1:
   1378                /* No matches in page tables or TLB */
   1379                switch (env->mmu_model) {
   1380                case POWERPC_MMU_SOFT_6xx:
   1381                    cs->exception_index = POWERPC_EXCP_IFTLB;
   1382                    env->error_code = 1 << 18;
   1383                    env->spr[SPR_IMISS] = eaddr;
   1384                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
   1385                    goto tlb_miss;
   1386                case POWERPC_MMU_SOFT_74xx:
   1387                    cs->exception_index = POWERPC_EXCP_IFTLB;
   1388                    goto tlb_miss_74xx;
   1389                case POWERPC_MMU_SOFT_4xx:
   1390                case POWERPC_MMU_SOFT_4xx_Z:
   1391                    cs->exception_index = POWERPC_EXCP_ITLB;
   1392                    env->error_code = 0;
   1393                    env->spr[SPR_40x_DEAR] = eaddr;
   1394                    env->spr[SPR_40x_ESR] = 0x00000000;
   1395                    break;
   1396                case POWERPC_MMU_BOOKE206:
   1397                    booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
   1398                    /* fall through */
   1399                case POWERPC_MMU_BOOKE:
   1400                    cs->exception_index = POWERPC_EXCP_ITLB;
   1401                    env->error_code = 0;
   1402                    env->spr[SPR_BOOKE_DEAR] = eaddr;
   1403                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD);
   1404                    break;
   1405                case POWERPC_MMU_MPC8xx:
   1406                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
   1407                case POWERPC_MMU_REAL:
   1408                    cpu_abort(cs, "PowerPC in real mode should never raise "
   1409                              "any MMU exceptions\n");
   1410                default:
   1411                    cpu_abort(cs, "Unknown or invalid MMU model\n");
   1412                }
   1413                break;
   1414            case -2:
   1415                /* Access rights violation */
   1416                cs->exception_index = POWERPC_EXCP_ISI;
   1417                env->error_code = 0x08000000;
   1418                break;
   1419            case -3:
   1420                /* No execute protection violation */
   1421                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
   1422                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
   1423                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
   1424                }
   1425                cs->exception_index = POWERPC_EXCP_ISI;
   1426                env->error_code = 0x10000000;
   1427                break;
   1428            case -4:
   1429                /* Direct store exception */
   1430                /* No code fetch is allowed in direct-store areas */
   1431                cs->exception_index = POWERPC_EXCP_ISI;
   1432                env->error_code = 0x10000000;
   1433                break;
   1434            }
   1435        } else {
   1436            switch (ret) {
   1437            case -1:
   1438                /* No matches in page tables or TLB */
   1439                switch (env->mmu_model) {
   1440                case POWERPC_MMU_SOFT_6xx:
   1441                    if (access_type == MMU_DATA_STORE) {
   1442                        cs->exception_index = POWERPC_EXCP_DSTLB;
   1443                        env->error_code = 1 << 16;
   1444                    } else {
   1445                        cs->exception_index = POWERPC_EXCP_DLTLB;
   1446                        env->error_code = 0;
   1447                    }
   1448                    env->spr[SPR_DMISS] = eaddr;
   1449                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
   1450                tlb_miss:
   1451                    env->error_code |= ctx.key << 19;
   1452                    env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
   1453                        get_pteg_offset32(cpu, ctx.hash[0]);
   1454                    env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
   1455                        get_pteg_offset32(cpu, ctx.hash[1]);
   1456                    break;
   1457                case POWERPC_MMU_SOFT_74xx:
   1458                    if (access_type == MMU_DATA_STORE) {
   1459                        cs->exception_index = POWERPC_EXCP_DSTLB;
   1460                    } else {
   1461                        cs->exception_index = POWERPC_EXCP_DLTLB;
   1462                    }
   1463                tlb_miss_74xx:
   1464                    /* Implement LRU algorithm */
   1465                    env->error_code = ctx.key << 19;
   1466                    env->spr[SPR_TLBMISS] = (eaddr & ~((target_ulong)0x3)) |
   1467                        ((env->last_way + 1) & (env->nb_ways - 1));
   1468                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
   1469                    break;
   1470                case POWERPC_MMU_SOFT_4xx:
   1471                case POWERPC_MMU_SOFT_4xx_Z:
   1472                    cs->exception_index = POWERPC_EXCP_DTLB;
   1473                    env->error_code = 0;
   1474                    env->spr[SPR_40x_DEAR] = eaddr;
   1475                    if (access_type == MMU_DATA_STORE) {
   1476                        env->spr[SPR_40x_ESR] = 0x00800000;
   1477                    } else {
   1478                        env->spr[SPR_40x_ESR] = 0x00000000;
   1479                    }
   1480                    break;
   1481                case POWERPC_MMU_MPC8xx:
   1482                    /* XXX: TODO */
   1483                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
   1484                case POWERPC_MMU_BOOKE206:
   1485                    booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
   1486                    /* fall through */
   1487                case POWERPC_MMU_BOOKE:
   1488                    cs->exception_index = POWERPC_EXCP_DTLB;
   1489                    env->error_code = 0;
   1490                    env->spr[SPR_BOOKE_DEAR] = eaddr;
   1491                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
   1492                    break;
   1493                case POWERPC_MMU_REAL:
   1494                    cpu_abort(cs, "PowerPC in real mode should never raise "
   1495                              "any MMU exceptions\n");
   1496                default:
   1497                    cpu_abort(cs, "Unknown or invalid MMU model\n");
   1498                }
   1499                break;
   1500            case -2:
   1501                /* Access rights violation */
   1502                cs->exception_index = POWERPC_EXCP_DSI;
   1503                env->error_code = 0;
   1504                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
   1505                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
   1506                    env->spr[SPR_40x_DEAR] = eaddr;
   1507                    if (access_type == MMU_DATA_STORE) {
   1508                        env->spr[SPR_40x_ESR] |= 0x00800000;
   1509                    }
   1510                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
   1511                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
   1512                    env->spr[SPR_BOOKE_DEAR] = eaddr;
   1513                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
   1514                } else {
   1515                    env->spr[SPR_DAR] = eaddr;
   1516                    if (access_type == MMU_DATA_STORE) {
   1517                        env->spr[SPR_DSISR] = 0x0A000000;
   1518                    } else {
   1519                        env->spr[SPR_DSISR] = 0x08000000;
   1520                    }
   1521                }
   1522                break;
   1523            case -4:
   1524                /* Direct store exception */
   1525                switch (type) {
   1526                case ACCESS_FLOAT:
   1527                    /* Floating point load/store */
   1528                    cs->exception_index = POWERPC_EXCP_ALIGN;
   1529                    env->error_code = POWERPC_EXCP_ALIGN_FP;
   1530                    env->spr[SPR_DAR] = eaddr;
   1531                    break;
   1532                case ACCESS_RES:
   1533                    /* lwarx, ldarx or stwcx. */
   1534                    cs->exception_index = POWERPC_EXCP_DSI;
   1535                    env->error_code = 0;
   1536                    env->spr[SPR_DAR] = eaddr;
   1537                    if (access_type == MMU_DATA_STORE) {
   1538                        env->spr[SPR_DSISR] = 0x06000000;
   1539                    } else {
   1540                        env->spr[SPR_DSISR] = 0x04000000;
   1541                    }
   1542                    break;
   1543                case ACCESS_EXT:
   1544                    /* eciwx or ecowx */
   1545                    cs->exception_index = POWERPC_EXCP_DSI;
   1546                    env->error_code = 0;
   1547                    env->spr[SPR_DAR] = eaddr;
   1548                    if (access_type == MMU_DATA_STORE) {
   1549                        env->spr[SPR_DSISR] = 0x06100000;
   1550                    } else {
   1551                        env->spr[SPR_DSISR] = 0x04100000;
   1552                    }
   1553                    break;
   1554                default:
   1555                    printf("DSI: invalid exception (%d)\n", ret);
   1556                    cs->exception_index = POWERPC_EXCP_PROGRAM;
   1557                    env->error_code =
   1558                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
   1559                    env->spr[SPR_DAR] = eaddr;
   1560                    break;
   1561                }
   1562                break;
   1563            }
   1564        }
   1565    }
   1566    return false;
   1567}
   1568
   1569/*****************************************************************************/
   1570
   1571bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   1572                      hwaddr *raddrp, int *psizep, int *protp,
   1573                      int mmu_idx, bool guest_visible)
   1574{
   1575    switch (cpu->env.mmu_model) {
   1576#if defined(TARGET_PPC64)
   1577    case POWERPC_MMU_3_00:
   1578        if (ppc64_v3_radix(cpu)) {
   1579            return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
   1580                                     psizep, protp, mmu_idx, guest_visible);
   1581        }
   1582        /* fall through */
   1583    case POWERPC_MMU_64B:
   1584    case POWERPC_MMU_2_03:
   1585    case POWERPC_MMU_2_06:
   1586    case POWERPC_MMU_2_07:
   1587        return ppc_hash64_xlate(cpu, eaddr, access_type,
   1588                                raddrp, psizep, protp, mmu_idx, guest_visible);
   1589#endif
   1590
   1591    case POWERPC_MMU_32B:
   1592    case POWERPC_MMU_601:
   1593        return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
   1594                               psizep, protp, mmu_idx, guest_visible);
   1595
   1596    default:
   1597        return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
   1598                               psizep, protp, mmu_idx, guest_visible);
   1599    }
   1600}
   1601
   1602hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
   1603{
   1604    PowerPCCPU *cpu = POWERPC_CPU(cs);
   1605    hwaddr raddr;
   1606    int s, p;
   1607
   1608    /*
   1609     * Some MMUs have separate TLBs for code and data. If we only
   1610     * try an MMU_DATA_LOAD, we may not be able to read instructions
   1611     * mapped by code TLBs, so we also try a MMU_INST_FETCH.
   1612     */
   1613    if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
   1614                  cpu_mmu_index(&cpu->env, false), false) ||
   1615        ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
   1616                  cpu_mmu_index(&cpu->env, true), false)) {
   1617        return raddr & TARGET_PAGE_MASK;
   1618    }
   1619    return -1;
   1620}