qemu/target/ppc/mmu-radix64.c
<<
>>
Prefs
   1/*
   2 *  PowerPC Radix MMU mulation helpers for QEMU.
   3 *
   4 *  Copyright (c) 2016 Suraj Jitindar Singh, IBM Corporation
   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 "cpu.h"
  22#include "exec/page-protection.h"
  23#include "qemu/error-report.h"
  24#include "system/kvm.h"
  25#include "system/memory.h"
  26#include "kvm_ppc.h"
  27#include "exec/log.h"
  28#include "internal.h"
  29#include "mmu-radix64.h"
  30#include "mmu-book3s-v3.h"
  31#include "mmu-books.h"
  32
  33/* Radix Partition Table Entry Fields */
  34#define PATE1_R_PRTB           0x0FFFFFFFFFFFF000
  35#define PATE1_R_PRTS           0x000000000000001F
  36
  37/* Radix Process Table Entry Fields */
  38#define PRTBE_R_GET_RTS(rts) \
  39    ((((rts >> 58) & 0x18) | ((rts >> 5) & 0x7)) + 31)
  40#define PRTBE_R_RPDB            0x0FFFFFFFFFFFFF00
  41#define PRTBE_R_RPDS            0x000000000000001F
  42
  43/* Radix Page Directory/Table Entry Fields */
  44#define R_PTE_VALID             0x8000000000000000
  45#define R_PTE_LEAF              0x4000000000000000
  46#define R_PTE_SW0               0x2000000000000000
  47#define R_PTE_RPN               0x01FFFFFFFFFFF000
  48#define R_PTE_SW1               0x0000000000000E00
  49#define R_GET_SW(sw)            (((sw >> 58) & 0x8) | ((sw >> 9) & 0x7))
  50#define R_PTE_R                 0x0000000000000100
  51#define R_PTE_C                 0x0000000000000080
  52#define R_PTE_ATT               0x0000000000000030
  53#define R_PTE_ATT_NORMAL        0x0000000000000000
  54#define R_PTE_ATT_SAO           0x0000000000000010
  55#define R_PTE_ATT_NI_IO         0x0000000000000020
  56#define R_PTE_ATT_TOLERANT_IO   0x0000000000000030
  57#define R_PTE_EAA_PRIV          0x0000000000000008
  58#define R_PTE_EAA_R             0x0000000000000004
  59#define R_PTE_EAA_RW            0x0000000000000002
  60#define R_PTE_EAA_X             0x0000000000000001
  61#define R_PDE_NLB               PRTBE_R_RPDB
  62#define R_PDE_NLS               PRTBE_R_RPDS
  63
  64static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
  65                                                 vaddr eaddr,
  66                                                 uint64_t *lpid, uint64_t *pid)
  67{
  68    /* When EA(2:11) are nonzero, raise a segment interrupt */
  69    if (eaddr & ~R_EADDR_VALID_MASK) {
  70        return false;
  71    }
  72
  73    if (FIELD_EX64(env->msr, MSR, HV)) { /* MSR[HV] -> Hypervisor/bare metal */
  74        switch (eaddr & R_EADDR_QUADRANT) {
  75        case R_EADDR_QUADRANT0:
  76            *lpid = 0;
  77            *pid = env->spr[SPR_BOOKS_PID];
  78            break;
  79        case R_EADDR_QUADRANT1:
  80            *lpid = env->spr[SPR_LPIDR];
  81            *pid = env->spr[SPR_BOOKS_PID];
  82            break;
  83        case R_EADDR_QUADRANT2:
  84            *lpid = env->spr[SPR_LPIDR];
  85            *pid = 0;
  86            break;
  87        case R_EADDR_QUADRANT3:
  88            *lpid = 0;
  89            *pid = 0;
  90            break;
  91        default:
  92            g_assert_not_reached();
  93        }
  94    } else {  /* !MSR[HV] -> Guest */
  95        switch (eaddr & R_EADDR_QUADRANT) {
  96        case R_EADDR_QUADRANT0: /* Guest application */
  97            *lpid = env->spr[SPR_LPIDR];
  98            *pid = env->spr[SPR_BOOKS_PID];
  99            break;
 100        case R_EADDR_QUADRANT1: /* Illegal */
 101        case R_EADDR_QUADRANT2:
 102            return false;
 103        case R_EADDR_QUADRANT3: /* Guest OS */
 104            *lpid = env->spr[SPR_LPIDR];
 105            *pid = 0; /* pid set to 0 -> addresses guest operating system */
 106            break;
 107        default:
 108            g_assert_not_reached();
 109        }
 110    }
 111
 112    return true;
 113}
 114
 115static void ppc_radix64_raise_segi(PowerPCCPU *cpu, MMUAccessType access_type,
 116                                   vaddr eaddr)
 117{
 118    CPUState *cs = CPU(cpu);
 119    CPUPPCState *env = &cpu->env;
 120
 121    switch (access_type) {
 122    case MMU_INST_FETCH:
 123        /* Instruction Segment Interrupt */
 124        cs->exception_index = POWERPC_EXCP_ISEG;
 125        break;
 126    case MMU_DATA_STORE:
 127    case MMU_DATA_LOAD:
 128        /* Data Segment Interrupt */
 129        cs->exception_index = POWERPC_EXCP_DSEG;
 130        env->spr[SPR_DAR] = eaddr;
 131        break;
 132    default:
 133        g_assert_not_reached();
 134    }
 135    env->error_code = 0;
 136}
 137
 138static inline const char *access_str(MMUAccessType access_type)
 139{
 140    return access_type == MMU_DATA_LOAD ? "reading" :
 141        (access_type == MMU_DATA_STORE ? "writing" : "execute");
 142}
 143
 144static void ppc_radix64_raise_si(PowerPCCPU *cpu, MMUAccessType access_type,
 145                                 vaddr eaddr, uint32_t cause)
 146{
 147    CPUState *cs = CPU(cpu);
 148    CPUPPCState *env = &cpu->env;
 149
 150    qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" cause %08x\n",
 151                  __func__, access_str(access_type),
 152                  eaddr, cause);
 153
 154    switch (access_type) {
 155    case MMU_INST_FETCH:
 156        /* Instruction Storage Interrupt */
 157        cs->exception_index = POWERPC_EXCP_ISI;
 158        env->error_code = cause;
 159        break;
 160    case MMU_DATA_STORE:
 161        cause |= DSISR_ISSTORE;
 162        /* fall through */
 163    case MMU_DATA_LOAD:
 164        /* Data Storage Interrupt */
 165        cs->exception_index = POWERPC_EXCP_DSI;
 166        env->spr[SPR_DSISR] = cause;
 167        env->spr[SPR_DAR] = eaddr;
 168        env->error_code = 0;
 169        break;
 170    default:
 171        g_assert_not_reached();
 172    }
 173}
 174
 175static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type,
 176                                  vaddr eaddr, hwaddr g_raddr, uint32_t cause)
 177{
 178    CPUState *cs = CPU(cpu);
 179    CPUPPCState *env = &cpu->env;
 180
 181    env->error_code = 0;
 182    if (cause & DSISR_PRTABLE_FAULT) {
 183        /* HDSI PRTABLE_FAULT gets the originating access type in error_code */
 184        env->error_code = access_type;
 185        access_type = MMU_DATA_LOAD;
 186    }
 187
 188    qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" 0x%"
 189                  HWADDR_PRIx" cause %08x\n",
 190                  __func__, access_str(access_type),
 191                  eaddr, g_raddr, cause);
 192
 193    switch (access_type) {
 194    case MMU_INST_FETCH:
 195        /* H Instruction Storage Interrupt */
 196        cs->exception_index = POWERPC_EXCP_HISI;
 197        env->spr[SPR_ASDR] = g_raddr;
 198        env->error_code = cause;
 199        break;
 200    case MMU_DATA_STORE:
 201        cause |= DSISR_ISSTORE;
 202        /* fall through */
 203    case MMU_DATA_LOAD:
 204        /* H Data Storage Interrupt */
 205        cs->exception_index = POWERPC_EXCP_HDSI;
 206        env->spr[SPR_HDSISR] = cause;
 207        env->spr[SPR_HDAR] = eaddr;
 208        env->spr[SPR_ASDR] = g_raddr;
 209        break;
 210    default:
 211        g_assert_not_reached();
 212    }
 213}
 214
 215static int ppc_radix64_get_prot_eaa(uint64_t pte)
 216{
 217    return (pte & R_PTE_EAA_R ? PAGE_READ : 0) |
 218           (pte & R_PTE_EAA_RW ? PAGE_READ | PAGE_WRITE : 0) |
 219           (pte & R_PTE_EAA_X ? PAGE_EXEC : 0);
 220}
 221
 222static int ppc_radix64_get_prot_amr(const PowerPCCPU *cpu)
 223{
 224    const CPUPPCState *env = &cpu->env;
 225    int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */
 226    int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 */
 227
 228    return (amr & 0x2 ? 0 : PAGE_WRITE) | /* Access denied if bit is set */
 229           (amr & 0x1 ? 0 : PAGE_READ) |
 230           (iamr & 0x1 ? 0 : PAGE_EXEC);
 231}
 232
 233static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type,
 234                                   uint64_t pte, int *fault_cause, int *prot,
 235                                   int mmu_idx, bool partition_scoped)
 236{
 237    CPUPPCState *env = &cpu->env;
 238
 239    /* Check Page Attributes (pte58:59) */
 240    if ((pte & R_PTE_ATT) == R_PTE_ATT_NI_IO && access_type == MMU_INST_FETCH) {
 241        /*
 242         * Radix PTE entries with the non-idempotent I/O attribute are treated
 243         * as guarded storage
 244         */
 245        *fault_cause |= SRR1_NOEXEC_GUARD;
 246        return true;
 247    }
 248
 249    /* Determine permissions allowed by Encoded Access Authority */
 250    if (!partition_scoped && (pte & R_PTE_EAA_PRIV) &&
 251        FIELD_EX64(env->msr, MSR, PR)) {
 252        *prot = 0;
 253    } else if (mmuidx_pr(mmu_idx) || (pte & R_PTE_EAA_PRIV) ||
 254               partition_scoped) {
 255        *prot = ppc_radix64_get_prot_eaa(pte);
 256    } else { /* !MSR_PR && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */
 257        *prot = ppc_radix64_get_prot_eaa(pte);
 258        *prot &= ppc_radix64_get_prot_amr(cpu); /* Least combined permissions */
 259    }
 260
 261    /* Check if requested access type is allowed */
 262    if (!check_prot_access_type(*prot, access_type)) {
 263        /* Page Protected for that Access */
 264        *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :
 265                                                        DSISR_PROTFAULT;
 266        return true;
 267    }
 268
 269    return false;
 270}
 271
 272static int ppc_radix64_check_rc(MMUAccessType access_type, uint64_t pte)
 273{
 274    switch (access_type) {
 275    case MMU_DATA_STORE:
 276        if (!(pte & R_PTE_C)) {
 277            break;
 278        }
 279        /* fall through */
 280    case MMU_INST_FETCH:
 281    case MMU_DATA_LOAD:
 282        if (!(pte & R_PTE_R)) {
 283            break;
 284        }
 285
 286        /* R/C bits are already set appropriately for this access */
 287        return 0;
 288    }
 289
 290    return 1;
 291}
 292
 293static bool ppc_radix64_is_valid_level(int level, int psize, uint64_t nls)
 294{
 295    bool ret;
 296
 297    /*
 298     * Check if this is a valid level, according to POWER9 and POWER10
 299     * Processor User's Manuals, sections 4.10.4.1 and 5.10.6.1, respectively:
 300     * Supported Radix Tree Configurations and Resulting Page Sizes.
 301     *
 302     * Note: these checks are specific to POWER9 and POWER10 CPUs. Any future
 303     * CPUs that supports a different Radix MMU configuration will need their
 304     * own implementation.
 305     */
 306    switch (level) {
 307    case 0:     /* Root Page Dir */
 308        ret = psize == 52 && nls == 13;
 309        break;
 310    case 1:
 311    case 2:
 312        ret = nls == 9;
 313        break;
 314    case 3:
 315        ret = nls == 9 || nls == 5;
 316        break;
 317    default:
 318        ret = false;
 319    }
 320
 321    if (unlikely(!ret)) {
 322        qemu_log_mask(LOG_GUEST_ERROR, "invalid radix configuration: "
 323                      "level %d size %d nls %"PRIu64"\n",
 324                      level, psize, nls);
 325    }
 326    return ret;
 327}
 328
 329static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr,
 330                                  uint64_t *pte_addr, uint64_t *nls,
 331                                  int *psize, uint64_t *pte, int *fault_cause)
 332{
 333    uint64_t index, mask, nlb, pde;
 334
 335    /* Read page <directory/table> entry from guest address space */
 336    pde = ldq_phys(as, *pte_addr);
 337    if (!(pde & R_PTE_VALID)) {         /* Invalid Entry */
 338        *fault_cause |= DSISR_NOPTE;
 339        return 1;
 340    }
 341
 342    *pte = pde;
 343    *psize -= *nls;
 344    if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */
 345        *nls = pde & R_PDE_NLS;
 346        index = eaddr >> (*psize - *nls);       /* Shift */
 347        index &= ((1UL << *nls) - 1);           /* Mask */
 348        nlb = pde & R_PDE_NLB;
 349        mask = MAKE_64BIT_MASK(0, *nls + 3);
 350
 351        if (nlb & mask) {
 352            qemu_log_mask(LOG_GUEST_ERROR,
 353                "%s: misaligned page dir/table base: 0x%" PRIx64
 354                " page dir size: 0x%" PRIx64 "\n",
 355                __func__, nlb, mask + 1);
 356            nlb &= ~mask;
 357        }
 358        *pte_addr = nlb + index * sizeof(pde);
 359    }
 360    return 0;
 361}
 362
 363static int ppc_radix64_walk_tree(AddressSpace *as, vaddr eaddr,
 364                                 uint64_t base_addr, uint64_t nls,
 365                                 hwaddr *raddr, int *psize, uint64_t *pte,
 366                                 int *fault_cause, hwaddr *pte_addr)
 367{
 368    uint64_t index, pde, rpn, mask;
 369    int level = 0;
 370
 371    index = eaddr >> (*psize - nls);    /* Shift */
 372    index &= ((1UL << nls) - 1);        /* Mask */
 373    mask = MAKE_64BIT_MASK(0, nls + 3);
 374
 375    if (base_addr & mask) {
 376        qemu_log_mask(LOG_GUEST_ERROR,
 377            "%s: misaligned page dir base: 0x%" PRIx64
 378            " page dir size: 0x%" PRIx64 "\n",
 379            __func__, base_addr, mask + 1);
 380        base_addr &= ~mask;
 381    }
 382    *pte_addr = base_addr + index * sizeof(pde);
 383
 384    do {
 385        int ret;
 386
 387        if (!ppc_radix64_is_valid_level(level++, *psize, nls)) {
 388            *fault_cause |= DSISR_R_BADCONFIG;
 389            return 1;
 390        }
 391
 392        ret = ppc_radix64_next_level(as, eaddr, pte_addr, &nls, psize, &pde,
 393                                     fault_cause);
 394        if (ret) {
 395            return ret;
 396        }
 397    } while (!(pde & R_PTE_LEAF));
 398
 399    *pte = pde;
 400    rpn = pde & R_PTE_RPN;
 401    mask = (1UL << *psize) - 1;
 402
 403    /* Or high bits of rpn and low bits to ea to form whole real addr */
 404    *raddr = (rpn & ~mask) | (eaddr & mask);
 405    return 0;
 406}
 407
 408static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate)
 409{
 410    CPUPPCState *env = &cpu->env;
 411
 412    if (!(pate->dw0 & PATE0_HR)) {
 413        return false;
 414    }
 415    if (lpid == 0 && !FIELD_EX64(env->msr, MSR, HV)) {
 416        return false;
 417    }
 418    if ((pate->dw0 & PATE1_R_PRTS) < 5) {
 419        return false;
 420    }
 421    /* More checks ... */
 422    return true;
 423}
 424
 425static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
 426                                              MMUAccessType orig_access_type,
 427                                              vaddr eaddr, hwaddr g_raddr,
 428                                              ppc_v3_pate_t pate,
 429                                              hwaddr *h_raddr, int *h_prot,
 430                                              int *h_page_size, bool pde_addr,
 431                                              int mmu_idx, uint64_t lpid,
 432                                              bool guest_visible)
 433{
 434    MMUAccessType access_type = orig_access_type;
 435    int fault_cause = 0;
 436    hwaddr pte_addr;
 437    uint64_t pte;
 438
 439    if (pde_addr) {
 440        /*
 441         * Translation of process-scoped tables/directories is performed as
 442         * a read-access.
 443         */
 444        access_type = MMU_DATA_LOAD;
 445    }
 446
 447    qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
 448                  " mmu_idx %u 0x%"HWADDR_PRIx"\n",
 449                  __func__, access_str(access_type),
 450                  eaddr, mmu_idx, g_raddr);
 451
 452    *h_page_size = PRTBE_R_GET_RTS(pate.dw0);
 453    /* No valid pte or access denied due to protection */
 454    if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB,
 455                              pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size,
 456                              &pte, &fault_cause, &pte_addr) ||
 457        ppc_radix64_check_prot(cpu, access_type, pte,
 458                               &fault_cause, h_prot, mmu_idx, true)) {
 459        if (pde_addr) { /* address being translated was that of a guest pde */
 460            fault_cause |= DSISR_PRTABLE_FAULT;
 461        }
 462        if (guest_visible) {
 463            ppc_radix64_raise_hsi(cpu, orig_access_type,
 464                                  eaddr, g_raddr, fault_cause);
 465        }
 466        return 1;
 467    }
 468
 469    if (guest_visible) {
 470        if (ppc_radix64_check_rc(access_type, pte)) {
 471            /*
 472             * Per ISA 3.1 Book III, 7.5.3 and 7.5.5, failure to set R/C during
 473             * partition-scoped translation when effLPID = 0 results in normal
 474             * (non-Hypervisor) Data and Instruction Storage Interrupts
 475             * respectively.
 476             *
 477             * ISA 3.0 is ambiguous about this, but tests on POWER9 hardware
 478             * seem to exhibit the same behavior.
 479             */
 480            if (lpid > 0) {
 481                ppc_radix64_raise_hsi(cpu, access_type, eaddr, g_raddr,
 482                                      DSISR_ATOMIC_RC);
 483            } else {
 484                ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_ATOMIC_RC);
 485            }
 486            return 1;
 487        }
 488    }
 489
 490    return 0;
 491}
 492
 493/*
 494 * The spapr vhc has a flat partition scope provided by qemu memory when
 495 * not nested.
 496 *
 497 * When running a nested guest, the addressing is 2-level radix on top of the
 498 * vhc memory, so it works practically identically to the bare metal 2-level
 499 * radix. So that code is selected directly. A cleaner and more flexible nested
 500 * hypervisor implementation would allow the vhc to provide a ->nested_xlate()
 501 * function but that is not required for the moment.
 502 */
 503static bool vhyp_flat_addressing(PowerPCCPU *cpu)
 504{
 505    if (cpu->vhyp) {
 506        return !vhyp_cpu_in_nested(cpu);
 507    }
 508    return false;
 509}
 510
 511static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
 512                                            MMUAccessType access_type,
 513                                            vaddr eaddr, uint64_t pid,
 514                                            ppc_v3_pate_t pate, hwaddr *g_raddr,
 515                                            int *g_prot, int *g_page_size,
 516                                            int mmu_idx, uint64_t lpid,
 517                                            bool guest_visible)
 518{
 519    CPUState *cs = CPU(cpu);
 520    CPUPPCState *env = &cpu->env;
 521    uint64_t offset, size, prtb, prtbe_addr, prtbe0, base_addr, nls, index, pte;
 522    int fault_cause = 0, h_page_size, h_prot;
 523    hwaddr h_raddr, pte_addr;
 524    int ret;
 525
 526    qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
 527                  " mmu_idx %u pid %"PRIu64"\n",
 528                  __func__, access_str(access_type),
 529                  eaddr, mmu_idx, pid);
 530
 531    prtb = (pate.dw1 & PATE1_R_PRTB);
 532    size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
 533    if (prtb & (size - 1)) {
 534        /* Process Table not properly aligned */
 535        if (guest_visible) {
 536            ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFIG);
 537        }
 538        return 1;
 539    }
 540
 541    /* Index Process Table by PID to Find Corresponding Process Table Entry */
 542    offset = pid * sizeof(struct prtb_entry);
 543    if (offset >= size) {
 544        /* offset exceeds size of the process table */
 545        if (guest_visible) {
 546            ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_NOPTE);
 547        }
 548        return 1;
 549    }
 550    prtbe_addr = prtb + offset;
 551
 552    if (vhyp_flat_addressing(cpu)) {
 553        prtbe0 = ldq_phys(cs->as, prtbe_addr);
 554    } else {
 555        /*
 556         * Process table addresses are subject to partition-scoped
 557         * translation
 558         *
 559         * On a Radix host, the partition-scoped page table for LPID=0
 560         * is only used to translate the effective addresses of the
 561         * process table entries.
 562         */
 563        /* mmu_idx is 5 because we're translating from hypervisor scope */
 564        ret = ppc_radix64_partition_scoped_xlate(cpu, access_type, eaddr,
 565                                                 prtbe_addr, pate, &h_raddr,
 566                                                 &h_prot, &h_page_size, true,
 567                                                 5, lpid, guest_visible);
 568        if (ret) {
 569            return ret;
 570        }
 571        prtbe0 = ldq_phys(cs->as, h_raddr);
 572    }
 573
 574    /*
 575     * Some Linux uses a zero process table entry in PID!=0 for kernel context
 576     * without userspace in order to fault on NULL dereference, because using
 577     * PIDR=0 for the kernel causes the Q0 page table to be used to translate
 578     * Q3 as well. Check for that case here to avoid the invalid configuration
 579     * message.
 580     */
 581    if (unlikely(!prtbe0)) {
 582        if (guest_visible) {
 583            ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFIG);
 584        }
 585        return 1;
 586    }
 587
 588    /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
 589    *g_page_size = PRTBE_R_GET_RTS(prtbe0);
 590    base_addr = prtbe0 & PRTBE_R_RPDB;
 591    nls = prtbe0 & PRTBE_R_RPDS;
 592    if (FIELD_EX64(env->msr, MSR, HV) || vhyp_flat_addressing(cpu)) {
 593        /*
 594         * Can treat process table addresses as real addresses
 595         */
 596        ret = ppc_radix64_walk_tree(cs->as, eaddr & R_EADDR_MASK, base_addr,
 597                                    nls, g_raddr, g_page_size, &pte,
 598                                    &fault_cause, &pte_addr);
 599        if (ret) {
 600            /* No valid PTE */
 601            if (guest_visible) {
 602                ppc_radix64_raise_si(cpu, access_type, eaddr, fault_cause);
 603            }
 604            return ret;
 605        }
 606    } else {
 607        uint64_t rpn, mask;
 608        int level = 0;
 609
 610        index = (eaddr & R_EADDR_MASK) >> (*g_page_size - nls); /* Shift */
 611        index &= ((1UL << nls) - 1);                            /* Mask */
 612        pte_addr = base_addr + (index * sizeof(pte));
 613
 614        /*
 615         * Each process table address is subject to a partition-scoped
 616         * translation
 617         */
 618        do {
 619            /* mmu_idx is 5 because we're translating from hypervisor scope */
 620            ret = ppc_radix64_partition_scoped_xlate(cpu, access_type, eaddr,
 621                                                     pte_addr, pate, &h_raddr,
 622                                                     &h_prot, &h_page_size,
 623                                                     true, 5, lpid,
 624                                                     guest_visible);
 625            if (ret) {
 626                return ret;
 627            }
 628
 629            if (!ppc_radix64_is_valid_level(level++, *g_page_size, nls)) {
 630                fault_cause |= DSISR_R_BADCONFIG;
 631                ret = 1;
 632            } else {
 633                ret = ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK,
 634                                             &h_raddr, &nls, g_page_size,
 635                                             &pte, &fault_cause);
 636            }
 637
 638            if (ret) {
 639                /* No valid pte */
 640                if (guest_visible) {
 641                    ppc_radix64_raise_si(cpu, access_type, eaddr, fault_cause);
 642                }
 643                return ret;
 644            }
 645            pte_addr = h_raddr;
 646        } while (!(pte & R_PTE_LEAF));
 647
 648        rpn = pte & R_PTE_RPN;
 649        mask = (1UL << *g_page_size) - 1;
 650
 651        /* Or high bits of rpn and low bits to ea to form whole real addr */
 652        *g_raddr = (rpn & ~mask) | (eaddr & mask);
 653    }
 654
 655    if (ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause,
 656                               g_prot, mmu_idx, false)) {
 657        /* Access denied due to protection */
 658        if (guest_visible) {
 659            ppc_radix64_raise_si(cpu, access_type, eaddr, fault_cause);
 660        }
 661        return 1;
 662    }
 663
 664    if (guest_visible) {
 665        /* R/C bits not appropriately set for access */
 666        if (ppc_radix64_check_rc(access_type, pte)) {
 667            ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_ATOMIC_RC);
 668            return 1;
 669        }
 670    }
 671
 672    return 0;
 673}
 674
 675/*
 676 * Radix tree translation is a 2 steps translation process:
 677 *
 678 * 1. Process-scoped translation:   Guest Eff Addr  -> Guest Real Addr
 679 * 2. Partition-scoped translation: Guest Real Addr -> Host Real Addr
 680 *
 681 *                                  MSR[HV]
 682 *              +-------------+----------------+---------------+
 683 *              |             |     HV = 0     |     HV = 1    |
 684 *              +-------------+----------------+---------------+
 685 *              | Relocation  |    Partition   |      No       |
 686 *              | = Off       |     Scoped     |  Translation  |
 687 *  Relocation  +-------------+----------------+---------------+
 688 *              | Relocation  |   Partition &  |    Process    |
 689 *              | = On        | Process Scoped |    Scoped     |
 690 *              +-------------+----------------+---------------+
 691 */
 692static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vaddr eaddr,
 693                                   MMUAccessType access_type, hwaddr *raddr,
 694                                   int *psizep, int *protp, int mmu_idx,
 695                                   bool guest_visible)
 696{
 697    CPUPPCState *env = &cpu->env;
 698    uint64_t lpid, pid;
 699    ppc_v3_pate_t pate;
 700    int psize, prot;
 701    hwaddr g_raddr;
 702    bool relocation;
 703
 704    assert(!(mmuidx_hv(mmu_idx) && cpu->vhyp));
 705
 706    relocation = !mmuidx_real(mmu_idx);
 707
 708    /* HV or virtual hypervisor Real Mode Access */
 709    if (!relocation && (mmuidx_hv(mmu_idx) || vhyp_flat_addressing(cpu))) {
 710        /* In real mode top 4 effective addr bits (mostly) ignored */
 711        *raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
 712
 713        /* In HV mode, add HRMOR if top EA bit is clear */
 714        if (mmuidx_hv(mmu_idx) || !env->has_hv_mode) {
 715            if (!(eaddr >> 63)) {
 716                *raddr |= env->spr[SPR_HRMOR];
 717           }
 718        }
 719        *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 720        *psizep = TARGET_PAGE_BITS;
 721        return true;
 722    }
 723
 724    /*
 725     * Check UPRT (we avoid the check in real mode to deal with
 726     * transitional states during kexec.
 727     */
 728    if (guest_visible && !ppc64_use_proc_tbl(cpu)) {
 729        qemu_log_mask(LOG_GUEST_ERROR,
 730                      "LPCR:UPRT not set in radix mode ! LPCR="
 731                      TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
 732    }
 733
 734    /* Virtual Mode Access - get the fully qualified address */
 735    if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) {
 736        if (guest_visible) {
 737            ppc_radix64_raise_segi(cpu, access_type, eaddr);
 738        }
 739        return false;
 740    }
 741
 742    /* Get Partition Table */
 743    if (cpu->vhyp) {
 744        if (!cpu->vhyp_class->get_pate(cpu->vhyp, cpu, lpid, &pate)) {
 745            if (guest_visible) {
 746                ppc_radix64_raise_hsi(cpu, access_type, eaddr, eaddr,
 747                                      DSISR_R_BADCONFIG);
 748            }
 749            return false;
 750        }
 751    } else {
 752        if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
 753            if (guest_visible) {
 754                ppc_radix64_raise_hsi(cpu, access_type, eaddr, eaddr,
 755                                      DSISR_R_BADCONFIG);
 756            }
 757            return false;
 758        }
 759        if (!validate_pate(cpu, lpid, &pate)) {
 760            if (guest_visible) {
 761                ppc_radix64_raise_hsi(cpu, access_type, eaddr, eaddr,
 762                                      DSISR_R_BADCONFIG);
 763            }
 764            return false;
 765        }
 766    }
 767
 768    *psizep = INT_MAX;
 769    *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 770
 771    /*
 772     * Perform process-scoped translation if relocation enabled.
 773     *
 774     * - Translates an effective address to a host real address in
 775     *   quadrants 0 and 3 when HV=1.
 776     *
 777     * - Translates an effective address to a guest real address.
 778     */
 779    if (relocation) {
 780        int ret = ppc_radix64_process_scoped_xlate(cpu, access_type, eaddr, pid,
 781                                                   pate, &g_raddr, &prot,
 782                                                   &psize, mmu_idx, lpid,
 783                                                   guest_visible);
 784        if (ret) {
 785            return false;
 786        }
 787        *psizep = MIN(*psizep, psize);
 788        *protp &= prot;
 789    } else {
 790        g_raddr = eaddr & R_EADDR_MASK;
 791    }
 792
 793    if (vhyp_flat_addressing(cpu)) {
 794        *raddr = g_raddr;
 795    } else {
 796        /*
 797         * Perform partition-scoped translation if !HV or HV access to
 798         * quadrants 1 or 2. Translates a guest real address to a host
 799         * real address.
 800         */
 801        if (lpid || !mmuidx_hv(mmu_idx)) {
 802            int ret;
 803
 804            ret = ppc_radix64_partition_scoped_xlate(cpu, access_type, eaddr,
 805                                                     g_raddr, pate, raddr,
 806                                                     &prot, &psize, false,
 807                                                     mmu_idx, lpid,
 808                                                     guest_visible);
 809            if (ret) {
 810                return false;
 811            }
 812            *psizep = MIN(*psizep, psize);
 813            *protp &= prot;
 814        } else {
 815            *raddr = g_raddr;
 816        }
 817    }
 818
 819    return true;
 820}
 821
 822bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
 823                       hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
 824                       bool guest_visible)
 825{
 826    bool ret = ppc_radix64_xlate_impl(cpu, eaddr, access_type, raddrp,
 827                                      psizep, protp, mmu_idx, guest_visible);
 828
 829    qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
 830                  " mmu_idx %u (prot %c%c%c) -> 0x%"HWADDR_PRIx"\n",
 831                  __func__, access_str(access_type),
 832                  eaddr, mmu_idx,
 833                  *protp & PAGE_READ ? 'r' : '-',
 834                  *protp & PAGE_WRITE ? 'w' : '-',
 835                  *protp & PAGE_EXEC ? 'x' : '-',
 836                  *raddrp);
 837
 838    return ret;
 839}
 840