qemu/target-sparc/mmu_helper.c
<<
>>
Prefs
   1/*
   2 *  Sparc MMU helpers
   3 *
   4 *  Copyright (c) 2003-2005 Fabrice Bellard
   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 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 "trace.h"
  23#include "exec/address-spaces.h"
  24
  25/* Sparc MMU emulation */
  26
  27#if defined(CONFIG_USER_ONLY)
  28
  29int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
  30                               int mmu_idx)
  31{
  32    if (rw & 2) {
  33        cs->exception_index = TT_TFAULT;
  34    } else {
  35        cs->exception_index = TT_DFAULT;
  36    }
  37    return 1;
  38}
  39
  40#else
  41
  42#ifndef TARGET_SPARC64
  43/*
  44 * Sparc V8 Reference MMU (SRMMU)
  45 */
  46static const int access_table[8][8] = {
  47    { 0, 0, 0, 0, 8, 0, 12, 12 },
  48    { 0, 0, 0, 0, 8, 0, 0, 0 },
  49    { 8, 8, 0, 0, 0, 8, 12, 12 },
  50    { 8, 8, 0, 0, 0, 8, 0, 0 },
  51    { 8, 0, 8, 0, 8, 8, 12, 12 },
  52    { 8, 0, 8, 0, 8, 0, 8, 0 },
  53    { 8, 8, 8, 0, 8, 8, 12, 12 },
  54    { 8, 8, 8, 0, 8, 8, 8, 0 }
  55};
  56
  57static const int perm_table[2][8] = {
  58    {
  59        PAGE_READ,
  60        PAGE_READ | PAGE_WRITE,
  61        PAGE_READ | PAGE_EXEC,
  62        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
  63        PAGE_EXEC,
  64        PAGE_READ | PAGE_WRITE,
  65        PAGE_READ | PAGE_EXEC,
  66        PAGE_READ | PAGE_WRITE | PAGE_EXEC
  67    },
  68    {
  69        PAGE_READ,
  70        PAGE_READ | PAGE_WRITE,
  71        PAGE_READ | PAGE_EXEC,
  72        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
  73        PAGE_EXEC,
  74        PAGE_READ,
  75        0,
  76        0,
  77    }
  78};
  79
  80static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
  81                                int *prot, int *access_index,
  82                                target_ulong address, int rw, int mmu_idx,
  83                                target_ulong *page_size)
  84{
  85    int access_perms = 0;
  86    hwaddr pde_ptr;
  87    uint32_t pde;
  88    int error_code = 0, is_dirty, is_user;
  89    unsigned long page_offset;
  90    CPUState *cs = CPU(sparc_env_get_cpu(env));
  91
  92    is_user = mmu_idx == MMU_USER_IDX;
  93
  94    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
  95        *page_size = TARGET_PAGE_SIZE;
  96        /* Boot mode: instruction fetches are taken from PROM */
  97        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
  98            *physical = env->prom_addr | (address & 0x7ffffULL);
  99            *prot = PAGE_READ | PAGE_EXEC;
 100            return 0;
 101        }
 102        *physical = address;
 103        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 104        return 0;
 105    }
 106
 107    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user ? 0 : 1);
 108    *physical = 0xffffffffffff0000ULL;
 109
 110    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
 111    /* Context base + context number */
 112    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
 113    pde = ldl_phys(cs->as, pde_ptr);
 114
 115    /* Ctx pde */
 116    switch (pde & PTE_ENTRYTYPE_MASK) {
 117    default:
 118    case 0: /* Invalid */
 119        return 1 << 2;
 120    case 2: /* L0 PTE, maybe should not happen? */
 121    case 3: /* Reserved */
 122        return 4 << 2;
 123    case 1: /* L0 PDE */
 124        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
 125        pde = ldl_phys(cs->as, pde_ptr);
 126
 127        switch (pde & PTE_ENTRYTYPE_MASK) {
 128        default:
 129        case 0: /* Invalid */
 130            return (1 << 8) | (1 << 2);
 131        case 3: /* Reserved */
 132            return (1 << 8) | (4 << 2);
 133        case 1: /* L1 PDE */
 134            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
 135            pde = ldl_phys(cs->as, pde_ptr);
 136
 137            switch (pde & PTE_ENTRYTYPE_MASK) {
 138            default:
 139            case 0: /* Invalid */
 140                return (2 << 8) | (1 << 2);
 141            case 3: /* Reserved */
 142                return (2 << 8) | (4 << 2);
 143            case 1: /* L2 PDE */
 144                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
 145                pde = ldl_phys(cs->as, pde_ptr);
 146
 147                switch (pde & PTE_ENTRYTYPE_MASK) {
 148                default:
 149                case 0: /* Invalid */
 150                    return (3 << 8) | (1 << 2);
 151                case 1: /* PDE, should not happen */
 152                case 3: /* Reserved */
 153                    return (3 << 8) | (4 << 2);
 154                case 2: /* L3 PTE */
 155                    page_offset = 0;
 156                }
 157                *page_size = TARGET_PAGE_SIZE;
 158                break;
 159            case 2: /* L2 PTE */
 160                page_offset = address & 0x3f000;
 161                *page_size = 0x40000;
 162            }
 163            break;
 164        case 2: /* L1 PTE */
 165            page_offset = address & 0xfff000;
 166            *page_size = 0x1000000;
 167        }
 168    }
 169
 170    /* check access */
 171    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
 172    error_code = access_table[*access_index][access_perms];
 173    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user)) {
 174        return error_code;
 175    }
 176
 177    /* update page modified and dirty bits */
 178    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
 179    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
 180        pde |= PG_ACCESSED_MASK;
 181        if (is_dirty) {
 182            pde |= PG_MODIFIED_MASK;
 183        }
 184        stl_phys_notdirty(cs->as, pde_ptr, pde);
 185    }
 186
 187    /* the page can be put in the TLB */
 188    *prot = perm_table[is_user][access_perms];
 189    if (!(pde & PG_MODIFIED_MASK)) {
 190        /* only set write access if already dirty... otherwise wait
 191           for dirty access */
 192        *prot &= ~PAGE_WRITE;
 193    }
 194
 195    /* Even if large ptes, we map only one 4KB page in the cache to
 196       avoid filling it too fast */
 197    *physical = ((hwaddr)(pde & PTE_ADDR_MASK) << 4) + page_offset;
 198    return error_code;
 199}
 200
 201/* Perform address translation */
 202int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 203                               int mmu_idx)
 204{
 205    SPARCCPU *cpu = SPARC_CPU(cs);
 206    CPUSPARCState *env = &cpu->env;
 207    hwaddr paddr;
 208    target_ulong vaddr;
 209    target_ulong page_size;
 210    int error_code = 0, prot, access_index;
 211
 212    address &= TARGET_PAGE_MASK;
 213    error_code = get_physical_address(env, &paddr, &prot, &access_index,
 214                                      address, rw, mmu_idx, &page_size);
 215    vaddr = address;
 216    if (error_code == 0) {
 217        qemu_log_mask(CPU_LOG_MMU,
 218                "Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr "
 219                TARGET_FMT_lx "\n", address, paddr, vaddr);
 220        tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
 221        return 0;
 222    }
 223
 224    if (env->mmuregs[3]) { /* Fault status register */
 225        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
 226    }
 227    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
 228    env->mmuregs[4] = address; /* Fault address register */
 229
 230    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
 231        /* No fault mode: if a mapping is available, just override
 232           permissions. If no mapping is available, redirect accesses to
 233           neverland. Fake/overridden mappings will be flushed when
 234           switching to normal mode. */
 235        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 236        tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
 237        return 0;
 238    } else {
 239        if (rw & 2) {
 240            cs->exception_index = TT_TFAULT;
 241        } else {
 242            cs->exception_index = TT_DFAULT;
 243        }
 244        return 1;
 245    }
 246}
 247
 248target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
 249{
 250    CPUState *cs = CPU(sparc_env_get_cpu(env));
 251    hwaddr pde_ptr;
 252    uint32_t pde;
 253
 254    /* Context base + context number */
 255    pde_ptr = (hwaddr)(env->mmuregs[1] << 4) +
 256        (env->mmuregs[2] << 2);
 257    pde = ldl_phys(cs->as, pde_ptr);
 258
 259    switch (pde & PTE_ENTRYTYPE_MASK) {
 260    default:
 261    case 0: /* Invalid */
 262    case 2: /* PTE, maybe should not happen? */
 263    case 3: /* Reserved */
 264        return 0;
 265    case 1: /* L1 PDE */
 266        if (mmulev == 3) {
 267            return pde;
 268        }
 269        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
 270        pde = ldl_phys(cs->as, pde_ptr);
 271
 272        switch (pde & PTE_ENTRYTYPE_MASK) {
 273        default:
 274        case 0: /* Invalid */
 275        case 3: /* Reserved */
 276            return 0;
 277        case 2: /* L1 PTE */
 278            return pde;
 279        case 1: /* L2 PDE */
 280            if (mmulev == 2) {
 281                return pde;
 282            }
 283            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
 284            pde = ldl_phys(cs->as, pde_ptr);
 285
 286            switch (pde & PTE_ENTRYTYPE_MASK) {
 287            default:
 288            case 0: /* Invalid */
 289            case 3: /* Reserved */
 290                return 0;
 291            case 2: /* L2 PTE */
 292                return pde;
 293            case 1: /* L3 PDE */
 294                if (mmulev == 1) {
 295                    return pde;
 296                }
 297                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
 298                pde = ldl_phys(cs->as, pde_ptr);
 299
 300                switch (pde & PTE_ENTRYTYPE_MASK) {
 301                default:
 302                case 0: /* Invalid */
 303                case 1: /* PDE, should not happen */
 304                case 3: /* Reserved */
 305                    return 0;
 306                case 2: /* L3 PTE */
 307                    return pde;
 308                }
 309            }
 310        }
 311    }
 312    return 0;
 313}
 314
 315void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
 316{
 317    CPUState *cs = CPU(sparc_env_get_cpu(env));
 318    target_ulong va, va1, va2;
 319    unsigned int n, m, o;
 320    hwaddr pde_ptr, pa;
 321    uint32_t pde;
 322
 323    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
 324    pde = ldl_phys(cs->as, pde_ptr);
 325    (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
 326                   (hwaddr)env->mmuregs[1] << 4, env->mmuregs[2]);
 327    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
 328        pde = mmu_probe(env, va, 2);
 329        if (pde) {
 330            pa = cpu_get_phys_page_debug(cs, va);
 331            (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
 332                           " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
 333            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
 334                pde = mmu_probe(env, va1, 1);
 335                if (pde) {
 336                    pa = cpu_get_phys_page_debug(cs, va1);
 337                    (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
 338                                   TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
 339                                   va1, pa, pde);
 340                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
 341                        pde = mmu_probe(env, va2, 0);
 342                        if (pde) {
 343                            pa = cpu_get_phys_page_debug(cs, va2);
 344                            (*cpu_fprintf)(f, "  VA: " TARGET_FMT_lx ", PA: "
 345                                           TARGET_FMT_plx " PTE: "
 346                                           TARGET_FMT_lx "\n",
 347                                           va2, pa, pde);
 348                        }
 349                    }
 350                }
 351            }
 352        }
 353    }
 354}
 355
 356/* Gdb expects all registers windows to be flushed in ram. This function handles
 357 * reads (and only reads) in stack frames as if windows were flushed. We assume
 358 * that the sparc ABI is followed.
 359 */
 360int sparc_cpu_memory_rw_debug(CPUState *cs, vaddr address,
 361                              uint8_t *buf, int len, bool is_write)
 362{
 363    SPARCCPU *cpu = SPARC_CPU(cs);
 364    CPUSPARCState *env = &cpu->env;
 365    target_ulong addr = address;
 366    int i;
 367    int len1;
 368    int cwp = env->cwp;
 369
 370    if (!is_write) {
 371        for (i = 0; i < env->nwindows; i++) {
 372            int off;
 373            target_ulong fp = env->regbase[cwp * 16 + 22];
 374
 375            /* Assume fp == 0 means end of frame.  */
 376            if (fp == 0) {
 377                break;
 378            }
 379
 380            cwp = cpu_cwp_inc(env, cwp + 1);
 381
 382            /* Invalid window ? */
 383            if (env->wim & (1 << cwp)) {
 384                break;
 385            }
 386
 387            /* According to the ABI, the stack is growing downward.  */
 388            if (addr + len < fp) {
 389                break;
 390            }
 391
 392            /* Not in this frame.  */
 393            if (addr > fp + 64) {
 394                continue;
 395            }
 396
 397            /* Handle access before this window.  */
 398            if (addr < fp) {
 399                len1 = fp - addr;
 400                if (cpu_memory_rw_debug(cs, addr, buf, len1, is_write) != 0) {
 401                    return -1;
 402                }
 403                addr += len1;
 404                len -= len1;
 405                buf += len1;
 406            }
 407
 408            /* Access byte per byte to registers. Not very efficient but speed
 409             * is not critical.
 410             */
 411            off = addr - fp;
 412            len1 = 64 - off;
 413
 414            if (len1 > len) {
 415                len1 = len;
 416            }
 417
 418            for (; len1; len1--) {
 419                int reg = cwp * 16 + 8 + (off >> 2);
 420                union {
 421                    uint32_t v;
 422                    uint8_t c[4];
 423                } u;
 424                u.v = cpu_to_be32(env->regbase[reg]);
 425                *buf++ = u.c[off & 3];
 426                addr++;
 427                len--;
 428                off++;
 429            }
 430
 431            if (len == 0) {
 432                return 0;
 433            }
 434        }
 435    }
 436    return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
 437}
 438
 439#else /* !TARGET_SPARC64 */
 440
 441/* 41 bit physical address space */
 442static inline hwaddr ultrasparc_truncate_physical(uint64_t x)
 443{
 444    return x & 0x1ffffffffffULL;
 445}
 446
 447/*
 448 * UltraSparc IIi I/DMMUs
 449 */
 450
 451/* Returns true if TTE tag is valid and matches virtual address value
 452   in context requires virtual address mask value calculated from TTE
 453   entry size */
 454static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
 455                                       uint64_t address, uint64_t context,
 456                                       hwaddr *physical)
 457{
 458    uint64_t mask;
 459
 460    switch (TTE_PGSIZE(tlb->tte)) {
 461    default:
 462    case 0x0: /* 8k */
 463        mask = 0xffffffffffffe000ULL;
 464        break;
 465    case 0x1: /* 64k */
 466        mask = 0xffffffffffff0000ULL;
 467        break;
 468    case 0x2: /* 512k */
 469        mask = 0xfffffffffff80000ULL;
 470        break;
 471    case 0x3: /* 4M */
 472        mask = 0xffffffffffc00000ULL;
 473        break;
 474    }
 475
 476    /* valid, context match, virtual address match? */
 477    if (TTE_IS_VALID(tlb->tte) &&
 478        (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
 479        && compare_masked(address, tlb->tag, mask)) {
 480        /* decode physical address */
 481        *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
 482        return 1;
 483    }
 484
 485    return 0;
 486}
 487
 488static int get_physical_address_data(CPUSPARCState *env,
 489                                     hwaddr *physical, int *prot,
 490                                     target_ulong address, int rw, int mmu_idx)
 491{
 492    CPUState *cs = CPU(sparc_env_get_cpu(env));
 493    unsigned int i;
 494    uint64_t context;
 495    uint64_t sfsr = 0;
 496
 497    int is_user = (mmu_idx == MMU_USER_IDX ||
 498                   mmu_idx == MMU_USER_SECONDARY_IDX);
 499
 500    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
 501        *physical = ultrasparc_truncate_physical(address);
 502        *prot = PAGE_READ | PAGE_WRITE;
 503        return 0;
 504    }
 505
 506    switch (mmu_idx) {
 507    case MMU_USER_IDX:
 508    case MMU_KERNEL_IDX:
 509        context = env->dmmu.mmu_primary_context & 0x1fff;
 510        sfsr |= SFSR_CT_PRIMARY;
 511        break;
 512    case MMU_USER_SECONDARY_IDX:
 513    case MMU_KERNEL_SECONDARY_IDX:
 514        context = env->dmmu.mmu_secondary_context & 0x1fff;
 515        sfsr |= SFSR_CT_SECONDARY;
 516        break;
 517    case MMU_NUCLEUS_IDX:
 518        sfsr |= SFSR_CT_NUCLEUS;
 519        /* FALLTHRU */
 520    default:
 521        context = 0;
 522        break;
 523    }
 524
 525    if (rw == 1) {
 526        sfsr |= SFSR_WRITE_BIT;
 527    } else if (rw == 4) {
 528        sfsr |= SFSR_NF_BIT;
 529    }
 530
 531    for (i = 0; i < 64; i++) {
 532        /* ctx match, vaddr match, valid? */
 533        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
 534            int do_fault = 0;
 535
 536            /* access ok? */
 537            /* multiple bits in SFSR.FT may be set on TT_DFAULT */
 538            if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
 539                do_fault = 1;
 540                sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
 541                trace_mmu_helper_dfault(address, context, mmu_idx, env->tl);
 542            }
 543            if (rw == 4) {
 544                if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
 545                    do_fault = 1;
 546                    sfsr |= SFSR_FT_NF_E_BIT;
 547                }
 548            } else {
 549                if (TTE_IS_NFO(env->dtlb[i].tte)) {
 550                    do_fault = 1;
 551                    sfsr |= SFSR_FT_NFO_BIT;
 552                }
 553            }
 554
 555            if (do_fault) {
 556                /* faults above are reported with TT_DFAULT. */
 557                cs->exception_index = TT_DFAULT;
 558            } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
 559                do_fault = 1;
 560                cs->exception_index = TT_DPROT;
 561
 562                trace_mmu_helper_dprot(address, context, mmu_idx, env->tl);
 563            }
 564
 565            if (!do_fault) {
 566                *prot = PAGE_READ;
 567                if (TTE_IS_W_OK(env->dtlb[i].tte)) {
 568                    *prot |= PAGE_WRITE;
 569                }
 570
 571                TTE_SET_USED(env->dtlb[i].tte);
 572
 573                return 0;
 574            }
 575
 576            if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
 577                sfsr |= SFSR_OW_BIT; /* overflow (not read before
 578                                        another fault) */
 579            }
 580
 581            if (env->pstate & PS_PRIV) {
 582                sfsr |= SFSR_PR_BIT;
 583            }
 584
 585            /* FIXME: ASI field in SFSR must be set */
 586            env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
 587
 588            env->dmmu.sfar = address; /* Fault address register */
 589
 590            env->dmmu.tag_access = (address & ~0x1fffULL) | context;
 591
 592            return 1;
 593        }
 594    }
 595
 596    trace_mmu_helper_dmiss(address, context);
 597
 598    /*
 599     * On MMU misses:
 600     * - UltraSPARC IIi: SFSR and SFAR unmodified
 601     * - JPS1: SFAR updated and some fields of SFSR updated
 602     */
 603    env->dmmu.tag_access = (address & ~0x1fffULL) | context;
 604    cs->exception_index = TT_DMISS;
 605    return 1;
 606}
 607
 608static int get_physical_address_code(CPUSPARCState *env,
 609                                     hwaddr *physical, int *prot,
 610                                     target_ulong address, int mmu_idx)
 611{
 612    CPUState *cs = CPU(sparc_env_get_cpu(env));
 613    unsigned int i;
 614    uint64_t context;
 615
 616    int is_user = (mmu_idx == MMU_USER_IDX ||
 617                   mmu_idx == MMU_USER_SECONDARY_IDX);
 618
 619    if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
 620        /* IMMU disabled */
 621        *physical = ultrasparc_truncate_physical(address);
 622        *prot = PAGE_EXEC;
 623        return 0;
 624    }
 625
 626    if (env->tl == 0) {
 627        /* PRIMARY context */
 628        context = env->dmmu.mmu_primary_context & 0x1fff;
 629    } else {
 630        /* NUCLEUS context */
 631        context = 0;
 632    }
 633
 634    for (i = 0; i < 64; i++) {
 635        /* ctx match, vaddr match, valid? */
 636        if (ultrasparc_tag_match(&env->itlb[i],
 637                                 address, context, physical)) {
 638            /* access ok? */
 639            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
 640                /* Fault status register */
 641                if (env->immu.sfsr & SFSR_VALID_BIT) {
 642                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
 643                                                     another fault) */
 644                } else {
 645                    env->immu.sfsr = 0;
 646                }
 647                if (env->pstate & PS_PRIV) {
 648                    env->immu.sfsr |= SFSR_PR_BIT;
 649                }
 650                if (env->tl > 0) {
 651                    env->immu.sfsr |= SFSR_CT_NUCLEUS;
 652                }
 653
 654                /* FIXME: ASI field in SFSR must be set */
 655                env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
 656                cs->exception_index = TT_TFAULT;
 657
 658                env->immu.tag_access = (address & ~0x1fffULL) | context;
 659
 660                trace_mmu_helper_tfault(address, context);
 661
 662                return 1;
 663            }
 664            *prot = PAGE_EXEC;
 665            TTE_SET_USED(env->itlb[i].tte);
 666            return 0;
 667        }
 668    }
 669
 670    trace_mmu_helper_tmiss(address, context);
 671
 672    /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
 673    env->immu.tag_access = (address & ~0x1fffULL) | context;
 674    cs->exception_index = TT_TMISS;
 675    return 1;
 676}
 677
 678static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
 679                                int *prot, int *access_index,
 680                                target_ulong address, int rw, int mmu_idx,
 681                                target_ulong *page_size)
 682{
 683    /* ??? We treat everything as a small page, then explicitly flush
 684       everything when an entry is evicted.  */
 685    *page_size = TARGET_PAGE_SIZE;
 686
 687    /* safety net to catch wrong softmmu index use from dynamic code */
 688    if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
 689        if (rw == 2) {
 690            trace_mmu_helper_get_phys_addr_code(env->tl, mmu_idx,
 691                                                env->dmmu.mmu_primary_context,
 692                                                env->dmmu.mmu_secondary_context,
 693                                                address);
 694        } else {
 695            trace_mmu_helper_get_phys_addr_data(env->tl, mmu_idx,
 696                                                env->dmmu.mmu_primary_context,
 697                                                env->dmmu.mmu_secondary_context,
 698                                                address);
 699        }
 700    }
 701
 702    if (rw == 2) {
 703        return get_physical_address_code(env, physical, prot, address,
 704                                         mmu_idx);
 705    } else {
 706        return get_physical_address_data(env, physical, prot, address, rw,
 707                                         mmu_idx);
 708    }
 709}
 710
 711/* Perform address translation */
 712int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 713                               int mmu_idx)
 714{
 715    SPARCCPU *cpu = SPARC_CPU(cs);
 716    CPUSPARCState *env = &cpu->env;
 717    target_ulong vaddr;
 718    hwaddr paddr;
 719    target_ulong page_size;
 720    int error_code = 0, prot, access_index;
 721
 722    address &= TARGET_PAGE_MASK;
 723    error_code = get_physical_address(env, &paddr, &prot, &access_index,
 724                                      address, rw, mmu_idx, &page_size);
 725    if (error_code == 0) {
 726        vaddr = address;
 727
 728        trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
 729                                   env->dmmu.mmu_primary_context,
 730                                   env->dmmu.mmu_secondary_context);
 731
 732        tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
 733        return 0;
 734    }
 735    /* XXX */
 736    return 1;
 737}
 738
 739void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
 740{
 741    unsigned int i;
 742    const char *mask;
 743
 744    (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
 745                   PRId64 "\n",
 746                   env->dmmu.mmu_primary_context,
 747                   env->dmmu.mmu_secondary_context);
 748    if ((env->lsu & DMMU_E) == 0) {
 749        (*cpu_fprintf)(f, "DMMU disabled\n");
 750    } else {
 751        (*cpu_fprintf)(f, "DMMU dump\n");
 752        for (i = 0; i < 64; i++) {
 753            switch (TTE_PGSIZE(env->dtlb[i].tte)) {
 754            default:
 755            case 0x0:
 756                mask = "  8k";
 757                break;
 758            case 0x1:
 759                mask = " 64k";
 760                break;
 761            case 0x2:
 762                mask = "512k";
 763                break;
 764            case 0x3:
 765                mask = "  4M";
 766                break;
 767            }
 768            if (TTE_IS_VALID(env->dtlb[i].tte)) {
 769                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
 770                               ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
 771                               i,
 772                               env->dtlb[i].tag & (uint64_t)~0x1fffULL,
 773                               TTE_PA(env->dtlb[i].tte),
 774                               mask,
 775                               TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
 776                               TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
 777                               TTE_IS_LOCKED(env->dtlb[i].tte) ?
 778                               "locked" : "unlocked",
 779                               env->dtlb[i].tag & (uint64_t)0x1fffULL,
 780                               TTE_IS_GLOBAL(env->dtlb[i].tte) ?
 781                               "global" : "local");
 782            }
 783        }
 784    }
 785    if ((env->lsu & IMMU_E) == 0) {
 786        (*cpu_fprintf)(f, "IMMU disabled\n");
 787    } else {
 788        (*cpu_fprintf)(f, "IMMU dump\n");
 789        for (i = 0; i < 64; i++) {
 790            switch (TTE_PGSIZE(env->itlb[i].tte)) {
 791            default:
 792            case 0x0:
 793                mask = "  8k";
 794                break;
 795            case 0x1:
 796                mask = " 64k";
 797                break;
 798            case 0x2:
 799                mask = "512k";
 800                break;
 801            case 0x3:
 802                mask = "  4M";
 803                break;
 804            }
 805            if (TTE_IS_VALID(env->itlb[i].tte)) {
 806                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
 807                               ", %s, %s, %s, ctx %" PRId64 " %s\n",
 808                               i,
 809                               env->itlb[i].tag & (uint64_t)~0x1fffULL,
 810                               TTE_PA(env->itlb[i].tte),
 811                               mask,
 812                               TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
 813                               TTE_IS_LOCKED(env->itlb[i].tte) ?
 814                               "locked" : "unlocked",
 815                               env->itlb[i].tag & (uint64_t)0x1fffULL,
 816                               TTE_IS_GLOBAL(env->itlb[i].tte) ?
 817                               "global" : "local");
 818            }
 819        }
 820    }
 821}
 822
 823#endif /* TARGET_SPARC64 */
 824
 825static int cpu_sparc_get_phys_page(CPUSPARCState *env, hwaddr *phys,
 826                                   target_ulong addr, int rw, int mmu_idx)
 827{
 828    target_ulong page_size;
 829    int prot, access_index;
 830
 831    return get_physical_address(env, phys, &prot, &access_index, addr, rw,
 832                                mmu_idx, &page_size);
 833}
 834
 835#if defined(TARGET_SPARC64)
 836hwaddr cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
 837                                           int mmu_idx)
 838{
 839    hwaddr phys_addr;
 840
 841    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
 842        return -1;
 843    }
 844    return phys_addr;
 845}
 846#endif
 847
 848hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 849{
 850    SPARCCPU *cpu = SPARC_CPU(cs);
 851    CPUSPARCState *env = &cpu->env;
 852    hwaddr phys_addr;
 853    int mmu_idx = cpu_mmu_index(env, false);
 854    MemoryRegionSection section;
 855
 856    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
 857        if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
 858            return -1;
 859        }
 860    }
 861    section = memory_region_find(get_system_memory(), phys_addr, 1);
 862    memory_region_unref(section.mr);
 863    if (!int128_nz(section.size)) {
 864        return -1;
 865    }
 866    return phys_addr;
 867}
 868#endif
 869