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