qemu/hw/misc/xilinx-xmpu.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the XMPU xmpu
   3 *
   4 * Copyright (c) 2014 Xilinx Inc.
   5 *
   6 * Partially autogenerated by xregqemu.py 2014-08-07.
   7 * Written by Edgar E. Iglesias <edgari@xilinx.com>
   8 *            Alistair Francis <alistai@xilinx.com>
   9 *
  10 * Permission is hereby granted, free of charge, to any person obtaining a copy
  11 * of this software and associated documentation files (the "Software"), to deal
  12 * in the Software without restriction, including without limitation the rights
  13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14 * copies of the Software, and to permit persons to whom the Software is
  15 * furnished to do so, subject to the following conditions:
  16 *
  17 * The above copyright notice and this permission notice shall be included in
  18 * all copies or substantial portions of the Software.
  19 *
  20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  26 * THE SOFTWARE.
  27 */
  28
  29#include "qemu/osdep.h"
  30#include "hw/sysbus.h"
  31#include "hw/register.h"
  32#include "qemu/bitops.h"
  33#include "qapi/error.h"
  34#include "qemu/log.h"
  35
  36#include "sysemu/dma.h"
  37#include "exec/address-spaces.h"
  38
  39#include "hw/fdt_generic_util.h"
  40
  41#ifndef XILINX_XMPU_ERR_DEBUG
  42#define XILINX_XMPU_ERR_DEBUG 0
  43#endif
  44
  45#define TYPE_XILINX_XMPU "xlnx.xmpu"
  46
  47#define XILINX_XMPU(obj) \
  48     OBJECT_CHECK(XMPU, (obj), TYPE_XILINX_XMPU)
  49
  50REG32(CTRL, 0x0)
  51    FIELD(CTRL, ALIGNCFG, 1, 3)
  52    FIELD(CTRL, POISONCFG, 1, 2)
  53    FIELD(CTRL, DEFWRALLOWED, 1, 1)
  54    FIELD(CTRL, DEFRDALLOWED, 1, 0)
  55REG32(ERR_STATUS1, 0x4)
  56    FIELD(ERR_STATUS1, AXI_ADDR, 20, 0)
  57REG32(ERR_STATUS2, 0x8)
  58    FIELD(ERR_STATUS2, AXI_ID, 10, 0)
  59REG32(POISON, 0xc)
  60    FIELD(POISON, ATTRIB, 1, 20)
  61    FIELD(POISON, BASE, 20, 0)
  62REG32(ISR, 0x10)
  63    FIELD(ISR, SECURITYVIO, 1, 3)
  64    FIELD(ISR, WRPERMVIO, 1, 2)
  65    FIELD(ISR, RDPERMVIO, 1, 1)
  66    FIELD(ISR, INV_APB, 1, 0)
  67REG32(IMR, 0x14)
  68    FIELD(IMR, SECURITYVIO, 1, 3)
  69    FIELD(IMR, WRPERMVIO, 1, 2)
  70    FIELD(IMR, RDPERMVIO, 1, 1)
  71    FIELD(IMR, INV_APB, 1, 0)
  72REG32(IEN, 0x18)
  73    FIELD(IEN, SECURITYVIO, 1, 3)
  74    FIELD(IEN, WRPERMVIO, 1, 2)
  75    FIELD(IEN, RDPERMVIO, 1, 1)
  76    FIELD(IEN, INV_APB, 1, 0)
  77REG32(IDS, 0x1c)
  78    FIELD(IDS, SECURITYVIO, 1, 3)
  79    FIELD(IDS, WRPERMVIO, 1, 2)
  80    FIELD(IDS, RDPERMVIO, 1, 1)
  81    FIELD(IDS, INV_APB, 1, 0)
  82REG32(LOCK, 0x20)
  83    FIELD(LOCK, REGWRDIS, 1, 0)
  84REG32(ECO, 0xfc)
  85REG32(R00_START, 0x100)
  86    FIELD(R00_START, ADDR, 20, 0)
  87REG32(R00_END, 0x104)
  88    FIELD(R00_END, ADDR, 20, 0)
  89REG32(R00_MASTER, 0x108)
  90    FIELD(R00_MASTER, MASK, 10, 16)
  91    FIELD(R00_MASTER, ID, 10, 0)
  92REG32(R00_CONFIG, 0x10c)
  93    FIELD(R00_CONFIG, NSCHECKTYPE, 1, 4)
  94    FIELD(R00_CONFIG, REGIONNS, 1, 3)
  95    FIELD(R00_CONFIG, WRALLOWED, 1, 2)
  96    FIELD(R00_CONFIG, RDALLOWED, 1, 1)
  97    FIELD(R00_CONFIG, ENABLE, 1, 0)
  98REG32(R01_START, 0x110)
  99    FIELD(R01_START, ADDR, 20, 0)
 100REG32(R01_END, 0x114)
 101    FIELD(R01_END, ADDR, 20, 0)
 102REG32(R01_MASTER, 0x118)
 103    FIELD(R01_MASTER, MASK, 10, 16)
 104    FIELD(R01_MASTER, ID, 10, 0)
 105REG32(R01_CONFIG, 0x11c)
 106    FIELD(R01_CONFIG, NSCHECKTYPE, 1, 4)
 107    FIELD(R01_CONFIG, REGIONNS, 1, 3)
 108    FIELD(R01_CONFIG, WRALLOWED, 1, 2)
 109    FIELD(R01_CONFIG, RDALLOWED, 1, 1)
 110    FIELD(R01_CONFIG, ENABLE, 1, 0)
 111REG32(R02_START, 0x120)
 112    FIELD(R02_START, ADDR, 20, 0)
 113REG32(R02_END, 0x124)
 114    FIELD(R02_END, ADDR, 20, 0)
 115REG32(R02_MASTER, 0x128)
 116    FIELD(R02_MASTER, MASK, 10, 16)
 117    FIELD(R02_MASTER, ID, 10, 0)
 118REG32(R02_CONFIG, 0x12c)
 119    FIELD(R02_CONFIG, NSCHECKTYPE, 1, 4)
 120    FIELD(R02_CONFIG, REGIONNS, 1, 3)
 121    FIELD(R02_CONFIG, WRALLOWED, 1, 2)
 122    FIELD(R02_CONFIG, RDALLOWED, 1, 1)
 123    FIELD(R02_CONFIG, ENABLE, 1, 0)
 124REG32(R03_START, 0x130)
 125    FIELD(R03_START, ADDR, 20, 0)
 126REG32(R03_END, 0x134)
 127    FIELD(R03_END, ADDR, 20, 0)
 128REG32(R03_MASTER, 0x138)
 129    FIELD(R03_MASTER, MASK, 10, 16)
 130    FIELD(R03_MASTER, ID, 10, 0)
 131REG32(R03_CONFIG, 0x13c)
 132    FIELD(R03_CONFIG, NSCHECKTYPE, 1, 4)
 133    FIELD(R03_CONFIG, REGIONNS, 1, 3)
 134    FIELD(R03_CONFIG, WRALLOWED, 1, 2)
 135    FIELD(R03_CONFIG, RDALLOWED, 1, 1)
 136    FIELD(R03_CONFIG, ENABLE, 1, 0)
 137REG32(R04_START, 0x140)
 138    FIELD(R04_START, ADDR, 20, 0)
 139REG32(R04_END, 0x144)
 140    FIELD(R04_END, ADDR, 20, 0)
 141REG32(R04_MASTER, 0x148)
 142    FIELD(R04_MASTER, MASK, 10, 16)
 143    FIELD(R04_MASTER, ID, 10, 0)
 144REG32(R04_CONFIG, 0x14c)
 145    FIELD(R04_CONFIG, NSCHECKTYPE, 1, 4)
 146    FIELD(R04_CONFIG, REGIONNS, 1, 3)
 147    FIELD(R04_CONFIG, WRALLOWED, 1, 2)
 148    FIELD(R04_CONFIG, RDALLOWED, 1, 1)
 149    FIELD(R04_CONFIG, ENABLE, 1, 0)
 150REG32(R05_START, 0x150)
 151    FIELD(R05_START, ADDR, 20, 0)
 152REG32(R05_END, 0x154)
 153    FIELD(R05_END, ADDR, 20, 0)
 154REG32(R05_MASTER, 0x158)
 155    FIELD(R05_MASTER, MASK, 10, 16)
 156    FIELD(R05_MASTER, ID, 10, 0)
 157REG32(R05_CONFIG, 0x15c)
 158    FIELD(R05_CONFIG, NSCHECKTYPE, 1, 4)
 159    FIELD(R05_CONFIG, REGIONNS, 1, 3)
 160    FIELD(R05_CONFIG, WRALLOWED, 1, 2)
 161    FIELD(R05_CONFIG, RDALLOWED, 1, 1)
 162    FIELD(R05_CONFIG, ENABLE, 1, 0)
 163REG32(R06_START, 0x160)
 164    FIELD(R06_START, ADDR, 20, 0)
 165REG32(R06_END, 0x164)
 166    FIELD(R06_END, ADDR, 20, 0)
 167REG32(R06_MASTER, 0x168)
 168    FIELD(R06_MASTER, MASK, 10, 16)
 169    FIELD(R06_MASTER, ID, 10, 0)
 170REG32(R06_CONFIG, 0x16c)
 171    FIELD(R06_CONFIG, NSCHECKTYPE, 1, 4)
 172    FIELD(R06_CONFIG, REGIONNS, 1, 3)
 173    FIELD(R06_CONFIG, WRALLOWED, 1, 2)
 174    FIELD(R06_CONFIG, RDALLOWED, 1, 1)
 175    FIELD(R06_CONFIG, ENABLE, 1, 0)
 176REG32(R07_START, 0x170)
 177    FIELD(R07_START, ADDR, 20, 0)
 178REG32(R07_END, 0x174)
 179    FIELD(R07_END, ADDR, 20, 0)
 180REG32(R07_MASTER, 0x178)
 181    FIELD(R07_MASTER, MASK, 10, 16)
 182    FIELD(R07_MASTER, ID, 10, 0)
 183REG32(R07_CONFIG, 0x17c)
 184    FIELD(R07_CONFIG, NSCHECKTYPE, 1, 4)
 185    FIELD(R07_CONFIG, REGIONNS, 1, 3)
 186    FIELD(R07_CONFIG, WRALLOWED, 1, 2)
 187    FIELD(R07_CONFIG, RDALLOWED, 1, 1)
 188    FIELD(R07_CONFIG, ENABLE, 1, 0)
 189REG32(R08_START, 0x180)
 190    FIELD(R08_START, ADDR, 20, 0)
 191REG32(R08_END, 0x184)
 192    FIELD(R08_END, ADDR, 20, 0)
 193REG32(R08_MASTER, 0x188)
 194    FIELD(R08_MASTER, MASK, 10, 16)
 195    FIELD(R08_MASTER, ID, 10, 0)
 196REG32(R08_CONFIG, 0x18c)
 197    FIELD(R08_CONFIG, NSCHECKTYPE, 1, 4)
 198    FIELD(R08_CONFIG, REGIONNS, 1, 3)
 199    FIELD(R08_CONFIG, WRALLOWED, 1, 2)
 200    FIELD(R08_CONFIG, RDALLOWED, 1, 1)
 201    FIELD(R08_CONFIG, ENABLE, 1, 0)
 202REG32(R09_START, 0x190)
 203    FIELD(R09_START, ADDR, 20, 0)
 204REG32(R09_END, 0x194)
 205    FIELD(R09_END, ADDR, 20, 0)
 206REG32(R09_MASTER, 0x198)
 207    FIELD(R09_MASTER, MASK, 10, 16)
 208    FIELD(R09_MASTER, ID, 10, 0)
 209REG32(R09_CONFIG, 0x19c)
 210    FIELD(R09_CONFIG, NSCHECKTYPE, 1, 4)
 211    FIELD(R09_CONFIG, REGIONNS, 1, 3)
 212    FIELD(R09_CONFIG, WRALLOWED, 1, 2)
 213    FIELD(R09_CONFIG, RDALLOWED, 1, 1)
 214    FIELD(R09_CONFIG, ENABLE, 1, 0)
 215REG32(R10_START, 0x1a0)
 216    FIELD(R10_START, ADDR, 20, 0)
 217REG32(R10_END, 0x1a4)
 218    FIELD(R10_END, ADDR, 20, 0)
 219REG32(R10_MASTER, 0x1a8)
 220    FIELD(R10_MASTER, MASK, 10, 16)
 221    FIELD(R10_MASTER, ID, 10, 0)
 222REG32(R10_CONFIG, 0x1ac)
 223    FIELD(R10_CONFIG, NSCHECKTYPE, 1, 4)
 224    FIELD(R10_CONFIG, REGIONNS, 1, 3)
 225    FIELD(R10_CONFIG, WRALLOWED, 1, 2)
 226    FIELD(R10_CONFIG, RDALLOWED, 1, 1)
 227    FIELD(R10_CONFIG, ENABLE, 1, 0)
 228REG32(R11_START, 0x1b0)
 229    FIELD(R11_START, ADDR, 20, 0)
 230REG32(R11_END, 0x1b4)
 231    FIELD(R11_END, ADDR, 20, 0)
 232REG32(R11_MASTER, 0x1b8)
 233    FIELD(R11_MASTER, MASK, 10, 16)
 234    FIELD(R11_MASTER, ID, 10, 0)
 235REG32(R11_CONFIG, 0x1bc)
 236    FIELD(R11_CONFIG, NSCHECKTYPE, 1, 4)
 237    FIELD(R11_CONFIG, REGIONNS, 1, 3)
 238    FIELD(R11_CONFIG, WRALLOWED, 1, 2)
 239    FIELD(R11_CONFIG, RDALLOWED, 1, 1)
 240    FIELD(R11_CONFIG, ENABLE, 1, 0)
 241REG32(R12_START, 0x1c0)
 242    FIELD(R12_START, ADDR, 20, 0)
 243REG32(R12_END, 0x1c4)
 244    FIELD(R12_END, ADDR, 20, 0)
 245REG32(R12_MASTER, 0x1c8)
 246    FIELD(R12_MASTER, MASK, 10, 16)
 247    FIELD(R12_MASTER, ID, 10, 0)
 248REG32(R12_CONFIG, 0x1cc)
 249    FIELD(R12_CONFIG, NSCHECKTYPE, 1, 4)
 250    FIELD(R12_CONFIG, REGIONNS, 1, 3)
 251    FIELD(R12_CONFIG, WRALLOWED, 1, 2)
 252    FIELD(R12_CONFIG, RDALLOWED, 1, 1)
 253    FIELD(R12_CONFIG, ENABLE, 1, 0)
 254REG32(R13_START, 0x1d0)
 255    FIELD(R13_START, ADDR, 20, 0)
 256REG32(R13_END, 0x1d4)
 257    FIELD(R13_END, ADDR, 20, 0)
 258REG32(R13_MASTER, 0x1d8)
 259    FIELD(R13_MASTER, MASK, 10, 16)
 260    FIELD(R13_MASTER, ID, 10, 0)
 261REG32(R13_CONFIG, 0x1dc)
 262    FIELD(R13_CONFIG, NSCHECKTYPE, 1, 4)
 263    FIELD(R13_CONFIG, REGIONNS, 1, 3)
 264    FIELD(R13_CONFIG, WRALLOWED, 1, 2)
 265    FIELD(R13_CONFIG, RDALLOWED, 1, 1)
 266    FIELD(R13_CONFIG, ENABLE, 1, 0)
 267REG32(R14_START, 0x1e0)
 268    FIELD(R14_START, ADDR, 20, 0)
 269REG32(R14_END, 0x1e4)
 270    FIELD(R14_END, ADDR, 20, 0)
 271REG32(R14_MASTER, 0x1e8)
 272    FIELD(R14_MASTER, MASK, 10, 16)
 273    FIELD(R14_MASTER, ID, 10, 0)
 274REG32(R14_CONFIG, 0x1ec)
 275    FIELD(R14_CONFIG, NSCHECKTYPE, 1, 4)
 276    FIELD(R14_CONFIG, REGIONNS, 1, 3)
 277    FIELD(R14_CONFIG, WRALLOWED, 1, 2)
 278    FIELD(R14_CONFIG, RDALLOWED, 1, 1)
 279    FIELD(R14_CONFIG, ENABLE, 1, 0)
 280REG32(R15_START, 0x1f0)
 281    FIELD(R15_START, ADDR, 20, 0)
 282REG32(R15_END, 0x1f4)
 283    FIELD(R15_END, ADDR, 20, 0)
 284REG32(R15_MASTER, 0x1f8)
 285    FIELD(R15_MASTER, MASK, 10, 16)
 286    FIELD(R15_MASTER, ID, 10, 0)
 287REG32(R15_CONFIG, 0x1fc)
 288    FIELD(R15_CONFIG, NSCHECKTYPE, 1, 4)
 289    FIELD(R15_CONFIG, REGIONNS, 1, 3)
 290    FIELD(R15_CONFIG, WRALLOWED, 1, 2)
 291    FIELD(R15_CONFIG, RDALLOWED, 1, 1)
 292    FIELD(R15_CONFIG, ENABLE, 1, 0)
 293
 294#define R_MAX (R_R15_CONFIG + 1)
 295
 296#define NR_XMPU_REGIONS 16
 297#define MAX_NR_MASTERS  8
 298
 299typedef struct XMPU XMPU;
 300
 301typedef struct XMPUMaster {
 302    XMPU *parent;
 303
 304    AddressSpace *parent_as;
 305    MemoryRegion *parent_mr;
 306    uint64_t size;
 307
 308    MemoryRegion mr;
 309    MemoryRegion iommu;
 310
 311    struct {
 312        struct {
 313            AddressSpace as;
 314            MemoryRegion mr;
 315        } rw, ro, none;
 316    } down;
 317
 318    struct {
 319        MemoryRegion mr[NR_XMPU_REGIONS];
 320    } err;
 321} XMPUMaster;
 322
 323struct XMPU {
 324    SysBusDevice parent_obj;
 325    MemoryRegion iomem;
 326
 327    MemoryRegion *protected_mr;
 328
 329    /* Dynamically size this one based on attached masters.  */
 330    XMPUMaster masters[MAX_NR_MASTERS];
 331    qemu_irq irq_isr;
 332
 333    uint64_t addr_mask;
 334    uint32_t addr_shift;
 335
 336    struct {
 337        uint32_t nr_masters;
 338        /* Will go away with proper MRs.  */
 339        uint64_t base;
 340
 341        bool align;
 342        bool poison;
 343    } cfg;
 344
 345    uint32_t regs[R_MAX];
 346    RegisterInfo regs_info[R_MAX];
 347    const char *prefix;
 348    bool enabled;
 349    qemu_irq enabled_signal;
 350};
 351
 352typedef struct XMPURegion {
 353    uint64_t start;
 354    uint64_t end;
 355    uint64_t size;
 356    union {
 357        uint32_t u32;
 358        struct {
 359            uint16_t mask;
 360            uint16_t id;
 361        };
 362    } master;
 363    struct {
 364        bool nschecktype;
 365        bool regionns;
 366        bool wrallowed;
 367        bool rdallowed;
 368        bool enable;
 369    } config;
 370} XMPURegion;
 371
 372static void xmpu_decode_region(XMPU *s, XMPURegion *xr, unsigned int region)
 373{
 374    assert(region < NR_XMPU_REGIONS);
 375    uint32_t config;
 376    unsigned int offset = region * (R_R01_START - R_R00_START);
 377
 378    xr->start = s->regs[offset + R_R00_START];
 379    xr->end = s->regs[offset + R_R00_END];
 380    xr->start <<= 12;
 381    xr->end <<= 12;
 382
 383    xr->size = xr->end - xr->start;
 384    xr->master.u32 = s->regs[offset + R_R00_MASTER];
 385
 386    config = s->regs[offset + R_R00_CONFIG];
 387    xr->config.enable = F_EX32(config, R00_CONFIG, ENABLE);
 388    xr->config.rdallowed = F_EX32(config, R00_CONFIG, RDALLOWED);
 389    xr->config.wrallowed = F_EX32(config, R00_CONFIG, WRALLOWED);
 390    xr->config.regionns = F_EX32(config, R00_CONFIG, REGIONNS);
 391    xr->config.nschecktype = F_EX32(config, R00_CONFIG, NSCHECKTYPE);
 392}
 393
 394static void isr_update_irq(XMPU *s)
 395{
 396    bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
 397    qemu_set_irq(s->irq_isr, pending);
 398}
 399
 400static void isr_postw(RegisterInfo *reg, uint64_t val64)
 401{
 402    XMPU *s = XILINX_XMPU(reg->opaque);
 403    isr_update_irq(s);
 404}
 405
 406static uint64_t ien_prew(RegisterInfo *reg, uint64_t val64)
 407{
 408    XMPU *s = XILINX_XMPU(reg->opaque);
 409    uint32_t val = val64;
 410
 411    s->regs[R_IMR] &= ~val;
 412    isr_update_irq(s);
 413    return 0;
 414}
 415
 416static uint64_t ids_prew(RegisterInfo *reg, uint64_t val64)
 417{
 418    XMPU *s = XILINX_XMPU(reg->opaque);
 419    uint32_t val = val64;
 420
 421    s->regs[R_IMR] |= val;
 422    isr_update_irq(s);
 423    return 0;
 424}
 425
 426static void xmpu_update_enabled(XMPU *s)
 427{
 428    bool regions_enabled = false;
 429    bool default_wr = AF_EX32(s->regs, CTRL, DEFWRALLOWED);
 430    bool default_rd = AF_EX32(s->regs, CTRL, DEFRDALLOWED);
 431    int i;
 432
 433    /* Lookup if this address fits a region.  */
 434    for (i = NR_XMPU_REGIONS - 1; i >= 0; i--) {
 435        XMPURegion xr;
 436        xmpu_decode_region(s, &xr, i);
 437        if (!xr.config.enable) {
 438            continue;
 439        }
 440        regions_enabled = true;
 441        break;
 442    }
 443
 444    s->enabled = true;
 445    if (!regions_enabled && default_wr && default_rd) {
 446        s->enabled = false;
 447    }
 448}
 449
 450static void xmpu_flush(XMPU *s)
 451{
 452    unsigned int i;
 453
 454    xmpu_update_enabled(s);
 455    qemu_set_irq(s->enabled_signal, s->enabled);
 456
 457    for (i = 0; i < s->cfg.nr_masters; i++) {
 458        IOMMUTLBEntry entry = {
 459            .target_as = s->masters[i].parent_as,
 460            .iova = 0,
 461            .translated_addr = 0,
 462            .addr_mask = ~0,
 463            .perm = IOMMU_NONE,
 464        };
 465        memory_region_notify_iommu(&s->masters[i].iommu, entry);
 466        /* Temporary hack.  */
 467        memory_region_transaction_begin();
 468        memory_region_set_readonly(&s->masters[i].iommu, false);
 469        memory_region_set_readonly(&s->masters[i].iommu, true);
 470        memory_region_set_enabled(&s->masters[i].iommu, s->enabled);
 471        memory_region_transaction_commit();
 472    }
 473}
 474
 475static void xmpu_setup_postw(RegisterInfo *reg, uint64_t val64)
 476{
 477    XMPU *s = XILINX_XMPU(reg->opaque);
 478    xmpu_flush(s);
 479}
 480
 481static RegisterAccessInfo xmpu_regs_info[] = {
 482    {   .name = "CTRL",  .decode.addr = A_CTRL,
 483        .reset = 0x3,
 484        .rsvd = 0xfffffff0,
 485        .ro = 0xfffffff8,
 486        .post_write = xmpu_setup_postw,
 487    },{ .name = "ERR_STATUS1",  .decode.addr = A_ERR_STATUS1,
 488        .rsvd = 0xfff00000,
 489        .ro = 0xffffffff,
 490    },{ .name = "ERR_STATUS2",  .decode.addr = A_ERR_STATUS2,
 491        .rsvd = 0xfffffc00,
 492        .ro = 0xffffffff,
 493    },{ .name = "POISON",  .decode.addr = A_POISON,
 494        .rsvd = 0xffe00000,
 495        .ro = 0xffefffff,
 496        .post_write = xmpu_setup_postw,
 497    },{ .name = "ISR",  .decode.addr = A_ISR,
 498        .rsvd = 0xfffffff0,
 499        .ro = 0xfffffff0,
 500        .w1c = 0xf,
 501        .post_write = isr_postw,
 502    },{ .name = "IMR",  .decode.addr = A_IMR,
 503        .reset = 0xf,
 504        .rsvd = 0xfffffff0,
 505        .ro = 0xffffffff,
 506    },{ .name = "IEN",  .decode.addr = A_IEN,
 507        .rsvd = 0xfffffff0,
 508        .ro = 0xfffffff0,
 509        .pre_write = ien_prew,
 510    },{ .name = "IDS",  .decode.addr = A_IDS,
 511        .rsvd = 0xfffffff0,
 512        .ro = 0xfffffff0,
 513        .pre_write = ids_prew,
 514    },{ .name = "LOCK",  .decode.addr = A_LOCK,
 515    },{ .name = "ECO",  .decode.addr = A_ECO,
 516    },{ .name = "R00_START",  .decode.addr = A_R00_START,
 517        .rsvd = 0xfff00000,
 518        .ro = 0xfff00000,
 519    },{ .name = "R00_END",  .decode.addr = A_R00_END,
 520        .rsvd = 0xfff00000,
 521        .ro = 0xfff00000,
 522    },{ .name = "R00_MASTER",  .decode.addr = A_R00_MASTER,
 523        .rsvd = 0xfc00fc00,
 524        .ro = 0xfc00fc00,
 525    },{ .name = "R00_CONFIG",  .decode.addr = A_R00_CONFIG,
 526        .reset = 0x8,
 527        .rsvd = 0xffffffe0,
 528        .ro = 0xffffffe0,
 529    },{ .name = "R01_START",  .decode.addr = A_R01_START,
 530        .rsvd = 0xfff00000,
 531        .ro = 0xfff00000,
 532    },{ .name = "R01_END",  .decode.addr = A_R01_END,
 533        .rsvd = 0xfff00000,
 534        .ro = 0xfff00000,
 535    },{ .name = "R01_MASTER",  .decode.addr = A_R01_MASTER,
 536        .rsvd = 0xfc00fc00,
 537        .ro = 0xfc00fc00,
 538    },{ .name = "R01_CONFIG",  .decode.addr = A_R01_CONFIG,
 539        .reset = 0x8,
 540        .rsvd = 0xffffffe0,
 541        .ro = 0xffffffe0,
 542    },{ .name = "R02_START",  .decode.addr = A_R02_START,
 543        .rsvd = 0xfff00000,
 544        .ro = 0xfff00000,
 545    },{ .name = "R02_END",  .decode.addr = A_R02_END,
 546        .rsvd = 0xfff00000,
 547        .ro = 0xfff00000,
 548    },{ .name = "R02_MASTER",  .decode.addr = A_R02_MASTER,
 549        .rsvd = 0xfc00fc00,
 550        .ro = 0xfc00fc00,
 551    },{ .name = "R02_CONFIG",  .decode.addr = A_R02_CONFIG,
 552        .reset = 0x8,
 553        .rsvd = 0xffffffe0,
 554        .ro = 0xffffffe0,
 555    },{ .name = "R03_START",  .decode.addr = A_R03_START,
 556        .rsvd = 0xfff00000,
 557        .ro = 0xfff00000,
 558    },{ .name = "R03_END",  .decode.addr = A_R03_END,
 559        .rsvd = 0xfff00000,
 560        .ro = 0xfff00000,
 561    },{ .name = "R03_MASTER",  .decode.addr = A_R03_MASTER,
 562        .rsvd = 0xfc00fc00,
 563        .ro = 0xfc00fc00,
 564    },{ .name = "R03_CONFIG",  .decode.addr = A_R03_CONFIG,
 565        .reset = 0x8,
 566        .rsvd = 0xffffffe0,
 567        .ro = 0xffffffe0,
 568    },{ .name = "R04_START",  .decode.addr = A_R04_START,
 569        .rsvd = 0xfff00000,
 570        .ro = 0xfff00000,
 571    },{ .name = "R04_END",  .decode.addr = A_R04_END,
 572        .rsvd = 0xfff00000,
 573        .ro = 0xfff00000,
 574    },{ .name = "R04_MASTER",  .decode.addr = A_R04_MASTER,
 575        .rsvd = 0xfc00fc00,
 576        .ro = 0xfc00fc00,
 577    },{ .name = "R04_CONFIG",  .decode.addr = A_R04_CONFIG,
 578        .reset = 0x8,
 579        .rsvd = 0xffffffe0,
 580        .ro = 0xffffffe0,
 581    },{ .name = "R05_START",  .decode.addr = A_R05_START,
 582        .rsvd = 0xfff00000,
 583        .ro = 0xfff00000,
 584    },{ .name = "R05_END",  .decode.addr = A_R05_END,
 585        .rsvd = 0xfff00000,
 586        .ro = 0xfff00000,
 587    },{ .name = "R05_MASTER",  .decode.addr = A_R05_MASTER,
 588        .rsvd = 0xfc00fc00,
 589        .ro = 0xfc00fc00,
 590    },{ .name = "R05_CONFIG",  .decode.addr = A_R05_CONFIG,
 591        .reset = 0x8,
 592        .rsvd = 0xffffffe0,
 593        .ro = 0xffffffe0,
 594    },{ .name = "R06_START",  .decode.addr = A_R06_START,
 595        .rsvd = 0xfff00000,
 596        .ro = 0xfff00000,
 597    },{ .name = "R06_END",  .decode.addr = A_R06_END,
 598        .rsvd = 0xfff00000,
 599        .ro = 0xfff00000,
 600    },{ .name = "R06_MASTER",  .decode.addr = A_R06_MASTER,
 601        .rsvd = 0xfc00fc00,
 602        .ro = 0xfc00fc00,
 603    },{ .name = "R06_CONFIG",  .decode.addr = A_R06_CONFIG,
 604        .reset = 0x8,
 605        .rsvd = 0xffffffe0,
 606        .ro = 0xffffffe0,
 607    },{ .name = "R07_START",  .decode.addr = A_R07_START,
 608        .rsvd = 0xfff00000,
 609        .ro = 0xfff00000,
 610    },{ .name = "R07_END",  .decode.addr = A_R07_END,
 611        .rsvd = 0xfff00000,
 612        .ro = 0xfff00000,
 613    },{ .name = "R07_MASTER",  .decode.addr = A_R07_MASTER,
 614        .rsvd = 0xfc00fc00,
 615        .ro = 0xfc00fc00,
 616    },{ .name = "R07_CONFIG",  .decode.addr = A_R07_CONFIG,
 617        .reset = 0x8,
 618        .rsvd = 0xffffffe0,
 619        .ro = 0xffffffe0,
 620    },{ .name = "R08_START",  .decode.addr = A_R08_START,
 621        .rsvd = 0xfff00000,
 622        .ro = 0xfff00000,
 623    },{ .name = "R08_END",  .decode.addr = A_R08_END,
 624        .rsvd = 0xfff00000,
 625        .ro = 0xfff00000,
 626    },{ .name = "R08_MASTER",  .decode.addr = A_R08_MASTER,
 627        .rsvd = 0xfc00fc00,
 628        .ro = 0xfc00fc00,
 629    },{ .name = "R08_CONFIG",  .decode.addr = A_R08_CONFIG,
 630        .reset = 0x8,
 631        .rsvd = 0xffffffe0,
 632        .ro = 0xffffffe0,
 633    },{ .name = "R09_START",  .decode.addr = A_R09_START,
 634        .rsvd = 0xfff00000,
 635        .ro = 0xfff00000,
 636    },{ .name = "R09_END",  .decode.addr = A_R09_END,
 637        .rsvd = 0xfff00000,
 638        .ro = 0xfff00000,
 639    },{ .name = "R09_MASTER",  .decode.addr = A_R09_MASTER,
 640        .rsvd = 0xfc00fc00,
 641        .ro = 0xfc00fc00,
 642    },{ .name = "R09_CONFIG",  .decode.addr = A_R09_CONFIG,
 643        .reset = 0x8,
 644        .rsvd = 0xffffffe0,
 645        .ro = 0xffffffe0,
 646    },{ .name = "R10_START",  .decode.addr = A_R10_START,
 647        .rsvd = 0xfff00000,
 648        .ro = 0xfff00000,
 649    },{ .name = "R10_END",  .decode.addr = A_R10_END,
 650        .rsvd = 0xfff00000,
 651        .ro = 0xfff00000,
 652    },{ .name = "R10_MASTER",  .decode.addr = A_R10_MASTER,
 653        .rsvd = 0xfc00fc00,
 654        .ro = 0xfc00fc00,
 655    },{ .name = "R10_CONFIG",  .decode.addr = A_R10_CONFIG,
 656        .reset = 0x8,
 657        .rsvd = 0xffffffe0,
 658        .ro = 0xffffffe0,
 659    },{ .name = "R11_START",  .decode.addr = A_R11_START,
 660        .rsvd = 0xfff00000,
 661        .ro = 0xfff00000,
 662    },{ .name = "R11_END",  .decode.addr = A_R11_END,
 663        .rsvd = 0xfff00000,
 664        .ro = 0xfff00000,
 665    },{ .name = "R11_MASTER",  .decode.addr = A_R11_MASTER,
 666        .rsvd = 0xfc00fc00,
 667        .ro = 0xfc00fc00,
 668    },{ .name = "R11_CONFIG",  .decode.addr = A_R11_CONFIG,
 669        .reset = 0x8,
 670        .rsvd = 0xffffffe0,
 671        .ro = 0xffffffe0,
 672    },{ .name = "R12_START",  .decode.addr = A_R12_START,
 673        .rsvd = 0xfff00000,
 674        .ro = 0xfff00000,
 675    },{ .name = "R12_END",  .decode.addr = A_R12_END,
 676        .rsvd = 0xfff00000,
 677        .ro = 0xfff00000,
 678    },{ .name = "R12_MASTER",  .decode.addr = A_R12_MASTER,
 679        .rsvd = 0xfc00fc00,
 680        .ro = 0xfc00fc00,
 681    },{ .name = "R12_CONFIG",  .decode.addr = A_R12_CONFIG,
 682        .reset = 0x8,
 683        .rsvd = 0xffffffe0,
 684        .ro = 0xffffffe0,
 685    },{ .name = "R13_START",  .decode.addr = A_R13_START,
 686        .rsvd = 0xfff00000,
 687        .ro = 0xfff00000,
 688    },{ .name = "R13_END",  .decode.addr = A_R13_END,
 689        .rsvd = 0xfff00000,
 690        .ro = 0xfff00000,
 691    },{ .name = "R13_MASTER",  .decode.addr = A_R13_MASTER,
 692        .rsvd = 0xfc00fc00,
 693        .ro = 0xfc00fc00,
 694    },{ .name = "R13_CONFIG",  .decode.addr = A_R13_CONFIG,
 695        .reset = 0x8,
 696        .rsvd = 0xffffffe0,
 697        .ro = 0xffffffe0,
 698    },{ .name = "R14_START",  .decode.addr = A_R14_START,
 699        .rsvd = 0xfff00000,
 700        .ro = 0xfff00000,
 701    },{ .name = "R14_END",  .decode.addr = A_R14_END,
 702        .rsvd = 0xfff00000,
 703        .ro = 0xfff00000,
 704    },{ .name = "R14_MASTER",  .decode.addr = A_R14_MASTER,
 705        .rsvd = 0xfc00fc00,
 706        .ro = 0xfc00fc00,
 707    },{ .name = "R14_CONFIG",  .decode.addr = A_R14_CONFIG,
 708        .reset = 0x8,
 709        .rsvd = 0xffffffe0,
 710        .ro = 0xffffffe0,
 711    },{ .name = "R15_START",  .decode.addr = A_R15_START,
 712        .rsvd = 0xfff00000,
 713        .ro = 0xfff00000,
 714    },{ .name = "R15_END",  .decode.addr = A_R15_END,
 715        .rsvd = 0xfff00000,
 716        .ro = 0xfff00000,
 717    },{ .name = "R15_MASTER",  .decode.addr = A_R15_MASTER,
 718        .rsvd = 0xfc00fc00,
 719        .ro = 0xfc00fc00,
 720    },{ .name = "R15_CONFIG",  .decode.addr = A_R15_CONFIG,
 721        .reset = 0x8,
 722        .rsvd = 0xffffffe0,
 723        .ro = 0xffffffe0,
 724    }
 725};
 726
 727static void xmpu_reset(DeviceState *dev)
 728{
 729    XMPU *s = XILINX_XMPU(dev);
 730    unsigned int i;
 731
 732    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 733        register_reset(&s->regs_info[i]);
 734    }
 735
 736    AF_DP32(s->regs, CTRL, ALIGNCFG, s->cfg.align);
 737    isr_update_irq(s);
 738    xmpu_flush(s);
 739}
 740
 741static uint64_t xmpu_read(void *opaque, hwaddr addr, unsigned size,
 742                          MemTxAttrs attr)
 743{
 744    XMPU *s = XILINX_XMPU(opaque);
 745    RegisterInfo *r = &s->regs_info[addr / 4];
 746
 747    if (!attr.secure) {
 748        /* Non secure, return zero */
 749        return 0;
 750    }
 751
 752    if (!r->data) {
 753        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 754                 object_get_canonical_path(OBJECT(s)),
 755                 addr);
 756        AF_DP32(s->regs, ISR, INV_APB, true);
 757        return 0;
 758    }
 759    return register_read(r);
 760}
 761
 762static void xmpu_write(void *opaque, hwaddr addr, uint64_t value,
 763                      unsigned size, MemTxAttrs attr)
 764{
 765    XMPU *s = XILINX_XMPU(opaque);
 766    RegisterInfo *r = &s->regs_info[addr / 4];
 767
 768    if (!attr.secure) {
 769        return;
 770    }
 771
 772    if (!r->data) {
 773        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 774                 object_get_canonical_path(OBJECT(s)),
 775                 addr, value);
 776        AF_DP32(s->regs, ISR, INV_APB, true);
 777        return;
 778    }
 779    register_write(r, value, ~0);
 780
 781    if (addr > R_R00_MASTER) {
 782        xmpu_flush(s);
 783    }
 784}
 785
 786static void xmpu_access(MemoryTransaction *tr)
 787{
 788    MemTxAttrs attr = tr->attr;
 789    void *opaque = tr->opaque;
 790    XMPU *s = XILINX_XMPU(opaque);
 791    hwaddr addr = tr->addr;
 792    unsigned size = tr->size;
 793    uint64_t value = tr->data.u64;;
 794    bool is_write = tr->rw;
 795    bool locked;
 796
 797    locked = AF_EX32(s->regs, LOCK, REGWRDIS);
 798    if (locked && (addr < A_ISR || addr >= A_LOCK)) {
 799        /* Locked access.  */
 800        qemu_log_mask(LOG_GUEST_ERROR, "%s: accessing locked register %lx\n",
 801                      object_get_canonical_path(OBJECT(s)), addr);
 802        tr->data.u64 = 0;
 803        return;
 804    }
 805
 806    if (is_write) {
 807        xmpu_write(opaque, addr, value, size, attr);
 808    } else {
 809        tr->data.u64 = xmpu_read(opaque, addr, size, attr);
 810    }
 811}
 812
 813static const MemoryRegionOps xmpu_ops = {
 814    .access = xmpu_access,
 815    .endianness = DEVICE_LITTLE_ENDIAN,
 816    .valid = {
 817        .min_access_size = 1,
 818        .max_access_size = 8,
 819    },
 820};
 821
 822static IOMMUTLBEntry xmpu_master_translate(XMPUMaster *xm, hwaddr addr,
 823                                           MemTxAttrs *attr,
 824                                           bool *sec_vio)
 825{
 826    XMPU *s = xm->parent;
 827    XMPURegion xr;
 828    IOMMUTLBEntry ret = {
 829        .iova = addr,
 830        .translated_addr = addr,
 831        .addr_mask = s->addr_mask,
 832        .perm = IOMMU_NONE,
 833    };
 834    AddressSpace *as_map[] = {
 835        [IOMMU_NONE] = &xm->down.none.as,
 836        [IOMMU_RO] = &xm->down.ro.as,
 837        [IOMMU_WO] = &xm->down.none.as,
 838        [IOMMU_RW] = &xm->down.rw.as,
 839    };
 840    bool default_wr = AF_EX32(s->regs, CTRL, DEFWRALLOWED);
 841    bool default_rd = AF_EX32(s->regs, CTRL, DEFRDALLOWED);
 842    bool sec = attr->secure;
 843    bool sec_access_check;
 844    unsigned int nr_matched = 0;
 845    int i;
 846
 847    /* No security violation by default.  */
 848    *sec_vio = false;
 849
 850    if (!s->enabled) {
 851        ret.target_as = &xm->down.rw.as;
 852        ret.perm = IOMMU_RW;
 853        return ret;
 854    }
 855
 856    /* Convert to an absolute address to simplify the compare logic.  */
 857    addr += s->cfg.base;
 858
 859    /* Lookup if this address fits a region.  */
 860    for (i = NR_XMPU_REGIONS - 1; i >= 0; i--) {
 861        bool id_match;
 862        bool match;
 863
 864        xmpu_decode_region(s, &xr, i);
 865        if (!xr.config.enable) {
 866            continue;
 867        }
 868
 869        if (xr.start & s->addr_mask) {
 870            qemu_log_mask(LOG_GUEST_ERROR,
 871                          "%s: Bad region start address %" PRIx64 "\n",
 872                          s->prefix, xr.start);
 873        }
 874
 875        if (xr.end & s->addr_mask) {
 876            qemu_log_mask(LOG_GUEST_ERROR,
 877                          "%s: Bad region end address %" PRIx64 "\n",
 878                           s->prefix, xr.end);
 879        }
 880
 881        if (xr.start < s->cfg.base) {
 882            qemu_log_mask(LOG_GUEST_ERROR,
 883                          "%s: Too low region start address %" PRIx64 "\n",
 884                           s->prefix, xr.end);
 885        }
 886
 887        xr.start &= ~s->addr_mask;
 888        xr.end &= ~s->addr_mask;
 889
 890        id_match = (xr.master.mask & xr.master.id) ==
 891                       (xr.master.mask & attr->master_id);
 892        match = id_match && (addr >= xr.start && addr < xr.end);
 893        if (match) {
 894            nr_matched++;
 895            /* Determine if this region is accessible by the transactions
 896             * security domain.
 897             */
 898            if (xr.config.nschecktype) {
 899                /* In strict mode, secure accesses are not allowed to
 900                 * non-secure regions (and vice-versa).
 901                 */
 902                sec_access_check = (sec != xr.config.regionns);
 903            } else {
 904                /* In relaxed mode secure accesses can access any region
 905                 * while non-secure can only access non-secure areas.
 906                 */
 907                sec_access_check = (sec || xr.config.regionns);
 908            }
 909
 910            if (sec_access_check) {
 911                if (xr.config.rdallowed) {
 912                    ret.perm |= IOMMU_RO;
 913                }
 914                if (xr.config.wrallowed) {
 915                    ret.perm |= IOMMU_WO;
 916                }
 917            } else {
 918                *sec_vio = true;
 919            }
 920            break;
 921        }
 922    }
 923
 924    if (nr_matched == 0) {
 925        if (default_rd) {
 926            ret.perm |= IOMMU_RO;
 927        }
 928        if (default_wr) {
 929            ret.perm |= IOMMU_WO;
 930        }
 931    }
 932
 933    ret.target_as = as_map[ret.perm];
 934    if (ret.perm == IOMMU_RO) {
 935        ret.target_as = &xm->down.none.as;
 936    }
 937#if 0
 938    qemu_log("%s: nr_matched=%d AS=%p addr=%lx - > %lx (%lx) perm=%x\n",
 939           __func__, nr_matched, ret.target_as, ret.iova,
 940          ret.translated_addr, (addr | ret.addr_mask) - addr + 1, ret.perm);
 941#endif
 942    return ret;
 943}
 944
 945static uint64_t zero_read(void *opaque, hwaddr addr, unsigned size,
 946                          MemTxAttrs attr)
 947{
 948    XMPUMaster *xm = opaque;
 949    XMPU *s = xm->parent;
 950    bool poisoncfg = AF_EX32(s->regs, CTRL, POISONCFG);
 951    uint64_t value = 0;
 952    bool sec_vio;
 953    IOMMUTLBEntry ret = xmpu_master_translate(xm, addr, &attr, &sec_vio);
 954
 955    if (ret.perm & IOMMU_RO) {
 956        dma_memory_read(&xm->down.rw.as, addr, &value, size);
 957    } else {
 958        if (!(s->regs[R_ISR] & (7 << 1))) {
 959            s->regs[R_ERR_STATUS1] = (addr + s->cfg.base) >> 12;
 960        }
 961        if (poisoncfg) {
 962            AddressSpace *as = xm->parent_as;
 963            addr = (AF_EX32(s->regs, POISON, BASE) << 12) | (addr & 0xfff);
 964            dma_memory_read(as, addr, &value, size);
 965        }
 966        AF_DP32(s->regs, ERR_STATUS2, AXI_ID, attr.master_id);
 967        if (sec_vio) {
 968            AF_DP32(s->regs, ISR, SECURITYVIO, true);
 969        } else {
 970            AF_DP32(s->regs, ISR, RDPERMVIO, true);
 971        }
 972        isr_update_irq(s);
 973    }
 974    return value;
 975}
 976
 977static void zero_write(void *opaque, hwaddr addr, uint64_t value,
 978                       unsigned size, MemTxAttrs attr)
 979{
 980    XMPUMaster *xm = opaque;
 981    XMPU *s = xm->parent;
 982    bool poisoncfg = AF_EX32(s->regs, CTRL, POISONCFG);
 983    bool sec_vio;
 984    IOMMUTLBEntry ret = xmpu_master_translate(xm, addr, &attr, &sec_vio);
 985
 986    if (ret.perm & IOMMU_WO) {
 987        dma_memory_write(&xm->down.rw.as, addr, &value, size);
 988    } else {
 989        if (!(s->regs[R_ISR] & (7 << 1))) {
 990            s->regs[R_ERR_STATUS1] = (addr + s->cfg.base) >> 12;
 991        }
 992        if (poisoncfg) {
 993            AddressSpace *as = xm->parent_as;
 994            addr = (AF_EX32(s->regs, POISON, BASE) << 12) | (addr & 0xfff);
 995            dma_memory_write(as, addr, &value, size);
 996        }
 997        AF_DP32(s->regs, ERR_STATUS2, AXI_ID, attr.master_id);
 998        if (sec_vio) {
 999            AF_DP32(s->regs, ISR, SECURITYVIO, true);
1000        } else {
1001            AF_DP32(s->regs, ISR, WRPERMVIO, true);
1002        }
1003        isr_update_irq(s);
1004    }
1005}
1006
1007static void zero_access(MemoryTransaction *tr)
1008{
1009    MemTxAttrs attr = tr->attr;
1010    void *opaque = tr->opaque;
1011    hwaddr addr = tr->addr;
1012    unsigned size = tr->size;
1013    uint64_t value = tr->data.u64;;
1014    bool is_write = tr->rw;
1015
1016    if (is_write) {
1017        zero_write(opaque, addr, value, size, attr);
1018    } else {
1019        tr->data.u64 = zero_read(opaque, addr, size, attr);
1020    }
1021}
1022
1023static const MemoryRegionOps zero_ops = {
1024    .access = zero_access,
1025    .endianness = DEVICE_LITTLE_ENDIAN,
1026    .valid = {
1027        .min_access_size = 4,
1028        .max_access_size = 4,
1029    },
1030};
1031
1032static IOMMUTLBEntry xmpu_translate(MemoryRegion *mr, hwaddr addr,
1033                                    bool is_write, MemTxAttrs *attr)
1034{
1035    XMPUMaster *xm;
1036    IOMMUTLBEntry ret;
1037    bool sec_vio;
1038
1039    xm = container_of(mr, XMPUMaster, iommu);
1040    ret = xmpu_master_translate(xm, addr, attr, &sec_vio);
1041#if 0
1042    qemu_log("%s: nr_matched=%d addr=%lx - > %lx (%lx) perm=%x\n",
1043           __func__, nr_matched, ret.iova,
1044          ret.translated_addr, (addr | ret.addr_mask) - addr + 1, ret.perm);
1045#endif
1046    ret.perm = IOMMU_RW;
1047    return ret;
1048}
1049
1050static MemoryRegionIOMMUOps xmpu_iommu_ops = {
1051    .translate_attr = xmpu_translate,
1052};
1053
1054#define MASK_4K  (0xfff)
1055#define MASK_1M  (0xfffff)
1056static void xmpu_realize(DeviceState *dev, Error **errp)
1057{
1058    XMPU *s = XILINX_XMPU(dev);
1059    unsigned int i;
1060
1061    s->prefix = object_get_canonical_path(OBJECT(dev));
1062
1063    for (i = 0; i < ARRAY_SIZE(xmpu_regs_info); ++i) {
1064        RegisterInfo *r = &s->regs_info[xmpu_regs_info[i].decode.addr/4];
1065
1066        *r = (RegisterInfo) {
1067            .data = (uint8_t *)&s->regs[
1068                    xmpu_regs_info[i].decode.addr/4],
1069            .data_size = sizeof(uint32_t),
1070            .access = &xmpu_regs_info[i],
1071            .debug = XILINX_XMPU_ERR_DEBUG,
1072            .prefix = s->prefix,
1073            .opaque = s,
1074        };
1075    }
1076
1077    s->addr_shift = s->cfg.align ? 20 : 12;
1078    s->addr_mask = (1ULL << s->addr_shift) - 1;
1079
1080    s->masters[0].parent = s;
1081}
1082
1083static void xmpu_init(Object *obj)
1084{
1085    XMPU *s = XILINX_XMPU(obj);
1086    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1087
1088    sysbus_init_irq(sbd, &s->irq_isr);
1089
1090    object_property_add_link(obj, "protected-mr", TYPE_MEMORY_REGION,
1091                             (Object **)&s->protected_mr,
1092                             qdev_prop_allow_set_link_before_realize,
1093                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
1094                             &error_abort);
1095    object_property_add_link(obj, "mr-0", TYPE_MEMORY_REGION,
1096                             (Object **)&s->masters[0].parent_mr,
1097                             qdev_prop_allow_set_link_before_realize,
1098                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
1099                             &error_abort);
1100
1101    qdev_init_gpio_out(DEVICE(sbd), &s->enabled_signal, 1);
1102}
1103
1104static bool xmpu_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
1105                           Error **errp)
1106{
1107    XMPU *s = XILINX_XMPU(obj);
1108    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1109    ObjectClass *klass = object_class_by_name(TYPE_XILINX_XMPU);
1110    FDTGenericMMapClass *parent_fmc;
1111    char *name;
1112    unsigned int i, mid;
1113
1114    parent_fmc = FDT_GENERIC_MMAP_CLASS(object_class_get_parent(klass));
1115    memory_region_init_io(&s->iomem, OBJECT(obj), &xmpu_ops, s,
1116                          TYPE_XILINX_XMPU, R_MAX * 4);
1117    sysbus_init_mmio(sbd, &s->iomem);
1118
1119    for (i = 0; i < (reg.n - 1); i++) {
1120        mid = i;
1121
1122        /* Create the read/write address space */
1123        name = g_strdup_printf("xmpu-down-rw-master%d", mid);
1124        memory_region_init_alias(&s->masters[mid].down.rw.mr, OBJECT(s),
1125                                 name, s->protected_mr,
1126                                 0, UINT64_MAX);
1127        address_space_init(&s->masters[mid].down.rw.as,
1128                           &s->masters[mid].down.rw.mr, name);
1129        g_free(name);
1130
1131        /* Create the read only address space  */
1132        name = g_strdup_printf("xmpu-down-ro-master%d", mid);
1133        memory_region_init_alias(&s->masters[mid].down.ro.mr, OBJECT(s),
1134                                 name, s->protected_mr,
1135                                 0, UINT64_MAX);
1136        memory_region_set_readonly(&s->masters[mid].down.ro.mr, true);
1137        address_space_init(&s->masters[mid].down.ro.as,
1138                           &s->masters[mid].down.ro.mr, name);
1139        g_free(name);
1140
1141        /* Create the no access address space */
1142        name = g_strdup_printf("xmpu-down-none-master\n");
1143        memory_region_init_io(&s->masters[mid].down.none.mr, OBJECT(s),
1144                              &zero_ops, &s->masters[mid],
1145                              name, UINT64_MAX);
1146        address_space_init(&s->masters[mid].down.none.as,
1147                           &s->masters[mid].down.none.mr, name);
1148        g_free(name);
1149
1150        name = g_strdup_printf("xmpu-master-%d\n", mid);
1151        s->masters[mid].parent_as = address_space_init_shareable(
1152                                            s->masters[mid].parent_mr,
1153                                            NULL);
1154
1155        memory_region_init_iommu(&s->masters[mid].iommu,
1156                                 OBJECT(s), &xmpu_iommu_ops,
1157                                 name, reg.s[i + 1]);
1158        g_free(name);
1159
1160        name = g_strdup_printf("xmpu-mr-%d\n", mid);
1161        memory_region_init(&s->masters[mid].mr, OBJECT(s), name, UINT64_MAX);
1162
1163        memory_region_add_subregion_overlap(&s->masters[mid].mr,
1164                                            0, &s->masters[mid].down.rw.mr, 0);
1165        memory_region_add_subregion_overlap(&s->masters[mid].mr,
1166                                            0, &s->masters[mid].iommu, 1);
1167        memory_region_set_enabled(&s->masters[mid].iommu, false);
1168        sysbus_init_mmio(sbd, &s->masters[mid].mr);
1169        g_free(name);
1170    }
1171    s->cfg.nr_masters = (i / 2) + 1;
1172
1173    return parent_fmc ? parent_fmc->parse_reg(obj, reg, errp) : false;
1174}
1175
1176static Property xmpu_properties[] = {
1177    DEFINE_PROP_BOOL("align", XMPU, cfg.align, 0),
1178    DEFINE_PROP_BOOL("poison", XMPU, cfg.poison, 0),
1179    DEFINE_PROP_UINT64("protected-base", XMPU, cfg.base, 0),
1180    DEFINE_PROP_END_OF_LIST(),
1181};
1182
1183static const VMStateDescription vmstate_xmpu = {
1184    .name = TYPE_XILINX_XMPU,
1185    .version_id = 1,
1186    .minimum_version_id = 1,
1187    .minimum_version_id_old = 1,
1188    .fields = (VMStateField[]) {
1189        VMSTATE_UINT32_ARRAY(regs, XMPU, R_MAX),
1190        VMSTATE_END_OF_LIST(),
1191    }
1192};
1193
1194static void xmpu_class_init(ObjectClass *klass, void *data)
1195{
1196    DeviceClass *dc = DEVICE_CLASS(klass);
1197    FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
1198
1199    dc->reset = xmpu_reset;
1200    dc->realize = xmpu_realize;
1201    dc->vmsd = &vmstate_xmpu;
1202    dc->props = xmpu_properties;
1203    fmc->parse_reg = xmpu_parse_reg;
1204}
1205
1206static const TypeInfo xmpu_info = {
1207    .name          = TYPE_XILINX_XMPU,
1208    .parent        = TYPE_SYS_BUS_DEVICE,
1209    .instance_size = sizeof(XMPU),
1210    .class_init    = xmpu_class_init,
1211    .instance_init = xmpu_init,
1212    .interfaces    = (InterfaceInfo[]) {
1213        { TYPE_FDT_GENERIC_MMAP },
1214        { },
1215    },
1216};
1217
1218static void xmpu_register_types(void)
1219{
1220    type_register_static(&xmpu_info);
1221}
1222
1223type_init(xmpu_register_types)
1224