qemu/hw/misc/xilinx-xppu.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the XPPU
   3 *
   4 * Copyright (c) 2014 - 2016 Xilinx Inc.
   5 *
   6 * Autogenerated by xregqemu.py 2016-02-14.
   7 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   8 *
   9 * Permission is hereby granted, free of charge, to any person obtaining a copy
  10 * of this software and associated documentation files (the "Software"), to deal
  11 * in the Software without restriction, including without limitation the rights
  12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13 * copies of the Software, and to permit persons to whom the Software is
  14 * furnished to do so, subject to the following conditions:
  15 *
  16 * The above copyright notice and this permission notice shall be included in
  17 * all copies or substantial portions of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25 * THE SOFTWARE.
  26 */
  27
  28#include "qemu/osdep.h"
  29#include "hw/sysbus.h"
  30#include "hw/register.h"
  31#include "qemu/bitops.h"
  32#include "sysemu/dma.h"
  33#include "qapi/error.h"
  34#include "qemu/log.h"
  35
  36#include "hw/fdt_generic_util.h"
  37
  38#ifndef XILINX_XPPU_ERR_DEBUG
  39#define XILINX_XPPU_ERR_DEBUG 0
  40#endif
  41
  42#define TYPE_XILINX_XPPU "xlnx.xppu"
  43
  44#define XILINX_XPPU(obj) \
  45     OBJECT_CHECK(XPPU, (obj), TYPE_XILINX_XPPU)
  46
  47REG32(CTRL, 0x0)
  48    FIELD(CTRL, APER_PARITY_EN, 1, 2)
  49    FIELD(CTRL, MID_PARITY_EN, 1, 1)
  50    FIELD(CTRL, ENABLE, 1, 0)
  51REG32(ERR_STATUS1, 0x4)
  52    FIELD(ERR_STATUS1, AXI_ADDR, 20, 0)
  53REG32(ERR_STATUS2, 0x8)
  54    FIELD(ERR_STATUS2, AXI_ID, 10, 0)
  55REG32(POISON, 0xc)
  56    FIELD(POISON, BASE, 20, 0)
  57REG32(ISR, 0x10)
  58    FIELD(ISR, APER_PARITY, 1, 7)
  59    FIELD(ISR, APER_TZ, 1, 6)
  60    FIELD(ISR, APER_PERM, 1, 5)
  61    FIELD(ISR, MID_PARITY, 1, 3)
  62    FIELD(ISR, MID_RO, 1, 2)
  63    FIELD(ISR, MID_MISS, 1, 1)
  64    FIELD(ISR, INV_APB, 1, 0)
  65REG32(IMR, 0x14)
  66    FIELD(IMR, APER_PARITY, 1, 7)
  67    FIELD(IMR, APER_TZ, 1, 6)
  68    FIELD(IMR, APER_PERM, 1, 5)
  69    FIELD(IMR, MID_PARITY, 1, 3)
  70    FIELD(IMR, MID_RO, 1, 2)
  71    FIELD(IMR, MID_MISS, 1, 1)
  72    FIELD(IMR, INV_APB, 1, 0)
  73REG32(IEN, 0x18)
  74    FIELD(IEN, APER_PARITY, 1, 7)
  75    FIELD(IEN, APER_TZ, 1, 6)
  76    FIELD(IEN, APER_PERM, 1, 5)
  77    FIELD(IEN, MID_PARITY, 1, 3)
  78    FIELD(IEN, MID_RO, 1, 2)
  79    FIELD(IEN, MID_MISS, 1, 1)
  80    FIELD(IEN, INV_APB, 1, 0)
  81REG32(IDS, 0x1c)
  82    FIELD(IDS, APER_PARITY, 1, 7)
  83    FIELD(IDS, APER_TZ, 1, 6)
  84    FIELD(IDS, APER_PERM, 1, 5)
  85    FIELD(IDS, MID_PARITY, 1, 3)
  86    FIELD(IDS, MID_RO, 1, 2)
  87    FIELD(IDS, MID_MISS, 1, 1)
  88    FIELD(IDS, INV_APB, 1, 0)
  89REG32(M_MASTER_IDS, 0x3c)
  90REG32(M_APERTURE_32B, 0x40)
  91REG32(M_APERTURE_64KB, 0x44)
  92REG32(M_APERTURE_1MB, 0x48)
  93REG32(M_APERTURE_512MB, 0x4c)
  94REG32(BASE_32B, 0x50)
  95REG32(BASE_64KB, 0x54)
  96REG32(BASE_1MB, 0x58)
  97REG32(BASE_512MB, 0x5c)
  98REG32(ECO, 0xfc)
  99REG32(MASTER_ID00, 0x100)
 100    FIELD(MASTER_ID00, MIDP, 1, 31)
 101    FIELD(MASTER_ID00, MIDR, 1, 30)
 102    FIELD(MASTER_ID00, MIDM, 10, 16)
 103    FIELD(MASTER_ID00, MID, 10, 0)
 104REG32(MASTER_ID01, 0x104)
 105    FIELD(MASTER_ID01, MIDP, 1, 31)
 106    FIELD(MASTER_ID01, MIDR, 1, 30)
 107    FIELD(MASTER_ID01, MIDM, 10, 16)
 108    FIELD(MASTER_ID01, MID, 10, 0)
 109REG32(MASTER_ID02, 0x108)
 110    FIELD(MASTER_ID02, MIDP, 1, 31)
 111    FIELD(MASTER_ID02, MIDR, 1, 30)
 112    FIELD(MASTER_ID02, MIDM, 10, 16)
 113    FIELD(MASTER_ID02, MID, 10, 0)
 114REG32(MASTER_ID03, 0x10c)
 115    FIELD(MASTER_ID03, MIDP, 1, 31)
 116    FIELD(MASTER_ID03, MIDR, 1, 30)
 117    FIELD(MASTER_ID03, MIDM, 10, 16)
 118    FIELD(MASTER_ID03, MID, 10, 0)
 119REG32(MASTER_ID04, 0x110)
 120    FIELD(MASTER_ID04, MIDP, 1, 31)
 121    FIELD(MASTER_ID04, MIDR, 1, 30)
 122    FIELD(MASTER_ID04, MIDM, 10, 16)
 123    FIELD(MASTER_ID04, MID, 10, 0)
 124REG32(MASTER_ID05, 0x114)
 125    FIELD(MASTER_ID05, MIDP, 1, 31)
 126    FIELD(MASTER_ID05, MIDR, 1, 30)
 127    FIELD(MASTER_ID05, MIDM, 10, 16)
 128    FIELD(MASTER_ID05, MID, 10, 0)
 129REG32(MASTER_ID06, 0x118)
 130    FIELD(MASTER_ID06, MIDP, 1, 31)
 131    FIELD(MASTER_ID06, MIDR, 1, 30)
 132    FIELD(MASTER_ID06, MIDM, 10, 16)
 133    FIELD(MASTER_ID06, MID, 10, 0)
 134REG32(MASTER_ID07, 0x11c)
 135    FIELD(MASTER_ID07, MIDP, 1, 31)
 136    FIELD(MASTER_ID07, MIDR, 1, 30)
 137    FIELD(MASTER_ID07, MIDM, 10, 16)
 138    FIELD(MASTER_ID07, MID, 10, 0)
 139REG32(MASTER_ID08, 0x120)
 140    FIELD(MASTER_ID08, MIDP, 1, 31)
 141    FIELD(MASTER_ID08, MIDR, 1, 30)
 142    FIELD(MASTER_ID08, MIDM, 10, 16)
 143    FIELD(MASTER_ID08, MID, 10, 0)
 144REG32(MASTER_ID09, 0x124)
 145    FIELD(MASTER_ID09, MIDP, 1, 31)
 146    FIELD(MASTER_ID09, MIDR, 1, 30)
 147    FIELD(MASTER_ID09, MIDM, 10, 16)
 148    FIELD(MASTER_ID09, MID, 10, 0)
 149REG32(MASTER_ID10, 0x128)
 150    FIELD(MASTER_ID10, MIDP, 1, 31)
 151    FIELD(MASTER_ID10, MIDR, 1, 30)
 152    FIELD(MASTER_ID10, MIDM, 10, 16)
 153    FIELD(MASTER_ID10, MID, 10, 0)
 154REG32(MASTER_ID11, 0x12c)
 155    FIELD(MASTER_ID11, MIDP, 1, 31)
 156    FIELD(MASTER_ID11, MIDR, 1, 30)
 157    FIELD(MASTER_ID11, MIDM, 10, 16)
 158    FIELD(MASTER_ID11, MID, 10, 0)
 159REG32(MASTER_ID12, 0x130)
 160    FIELD(MASTER_ID12, MIDP, 1, 31)
 161    FIELD(MASTER_ID12, MIDR, 1, 30)
 162    FIELD(MASTER_ID12, MIDM, 10, 16)
 163    FIELD(MASTER_ID12, MID, 10, 0)
 164REG32(MASTER_ID13, 0x134)
 165    FIELD(MASTER_ID13, MIDP, 1, 31)
 166    FIELD(MASTER_ID13, MIDR, 1, 30)
 167    FIELD(MASTER_ID13, MIDM, 10, 16)
 168    FIELD(MASTER_ID13, MID, 10, 0)
 169REG32(MASTER_ID14, 0x138)
 170    FIELD(MASTER_ID14, MIDP, 1, 31)
 171    FIELD(MASTER_ID14, MIDR, 1, 30)
 172    FIELD(MASTER_ID14, MIDM, 10, 16)
 173    FIELD(MASTER_ID14, MID, 10, 0)
 174REG32(MASTER_ID15, 0x13c)
 175    FIELD(MASTER_ID15, MIDP, 1, 31)
 176    FIELD(MASTER_ID15, MIDR, 1, 30)
 177    FIELD(MASTER_ID15, MIDM, 10, 16)
 178    FIELD(MASTER_ID15, MID, 10, 0)
 179REG32(MASTER_ID16, 0x140)
 180    FIELD(MASTER_ID16, MIDP, 1, 31)
 181    FIELD(MASTER_ID16, MIDR, 1, 30)
 182    FIELD(MASTER_ID16, MIDM, 10, 16)
 183    FIELD(MASTER_ID16, MID, 10, 0)
 184REG32(MASTER_ID17, 0x144)
 185    FIELD(MASTER_ID17, MIDP, 1, 31)
 186    FIELD(MASTER_ID17, MIDR, 1, 30)
 187    FIELD(MASTER_ID17, MIDM, 10, 16)
 188    FIELD(MASTER_ID17, MID, 10, 0)
 189REG32(MASTER_ID18, 0x148)
 190    FIELD(MASTER_ID18, MIDP, 1, 31)
 191    FIELD(MASTER_ID18, MIDR, 1, 30)
 192    FIELD(MASTER_ID18, MIDM, 10, 16)
 193    FIELD(MASTER_ID18, MID, 10, 0)
 194REG32(MASTER_ID19, 0x14c)
 195    FIELD(MASTER_ID19, MIDP, 1, 31)
 196    FIELD(MASTER_ID19, MIDR, 1, 30)
 197    FIELD(MASTER_ID19, MIDM, 10, 16)
 198    FIELD(MASTER_ID19, MID, 10, 0)
 199REG32(RAM_ADJ, 0x1fc)
 200    FIELD(RAM_ADJ, MESSAGE_EMAS, 1, 13)
 201    FIELD(RAM_ADJ, MESSAGE_EMAW, 2, 11)
 202    FIELD(RAM_ADJ, MESSAGE_EMA, 3, 8)
 203    FIELD(RAM_ADJ, PERMISSION_EMAS, 1, 5)
 204    FIELD(RAM_ADJ, PERMISSION_EMAW, 2, 3)
 205    FIELD(RAM_ADJ, PERMISSION_EMA, 3, 0)
 206
 207#define R_MAX (R_RAM_ADJ + 1)
 208
 209#define NR_MID_ENTRIES 20
 210
 211#define NR_32B_APL_ENTRIES 128
 212#define NR_64K_APL_ENTRIES 256
 213#define NR_1M_APL_ENTRIES 16
 214#define NR_512M_APL_ENTRIES 1
 215#define NR_APL_ENTRIES (NR_32B_APL_ENTRIES + NR_64K_APL_ENTRIES \
 216                        + NR_1M_APL_ENTRIES + NR_512M_APL_ENTRIES)
 217
 218typedef enum {
 219    GRANULE_32B,
 220    GRANULE_64K,
 221    GRANULE_1M,
 222    GRANULE_512M,
 223} XPPUGranule;
 224
 225typedef struct XPPU XPPU;
 226
 227typedef struct XPPUAperture {
 228    XPPU *parent;
 229    MemoryRegion iomem;
 230
 231    XPPUGranule granule;
 232    /* MR base so we can offset the forwarded access.  */
 233    uint64_t base;
 234    /* Mask used to extract parts of the incoming address.  */
 235    uint64_t extract_mask;
 236    uint64_t extract_shift;
 237    /* RAM base. Start of APL tables for this particular Aperture.  */
 238    uint32_t ram_base;
 239} XPPUAperture;
 240
 241struct XPPU {
 242    SysBusDevice parent_obj;
 243    MemoryRegion iomem;
 244    qemu_irq irq_isr;
 245
 246    MemoryRegion *mr;
 247    AddressSpace *as;
 248
 249    XPPUAperture ap[4];
 250
 251    uint32_t perm_ram[NR_APL_ENTRIES];
 252
 253    uint32_t regs[R_MAX];
 254    RegisterInfo regs_info[R_MAX];
 255};
 256
 257static bool parity32(uint32_t v)
 258{
 259    /* We compute the parity in parallel, folding
 260     * each result in half, all the way down to one last bit.
 261     */
 262    v = v ^ (v >> 16);
 263    v = v ^ (v >> 8);
 264    v = v ^ (v >> 4);
 265    v = v ^ (v >> 2);
 266    v = v ^ (v >> 1);
 267    return v & 1;
 268}
 269
 270static bool check_mid_parity(XPPU *s, uint32_t val32)
 271{
 272    static const uint32_t rsvd = 0x3c00fc00;
 273    bool p_written;
 274    bool p_computed;
 275
 276    if (!AF_EX32(s->regs, CTRL, MID_PARITY_EN)) {
 277        return true;
 278    }
 279
 280    /* Save the written parity.  */
 281    p_written = val32 & 0x80000000;
 282
 283    /* Mask off parity field.  */
 284    val32 &= ~0x80000000;
 285    /* Mask off rsvd fields.  */
 286    val32 &= ~rsvd;
 287    p_computed = parity32(val32);
 288
 289    return p_written == p_computed;
 290}
 291
 292static void check_mid_parities(XPPU *s)
 293{
 294    unsigned int i;
 295
 296    for (i = 0; i < NR_MID_ENTRIES; i++) {
 297        uint32_t val32;
 298
 299        val32 = s->regs[R_MASTER_ID00 + i];
 300
 301        /* Check MID parity.  */
 302        if (check_mid_parity(s, val32) == false) {
 303            AF_DP32(s->regs, ISR, MID_PARITY, true);
 304            continue;
 305        }
 306    }
 307}
 308
 309static bool check_apl_parity(XPPU *s, uint32_t val32)
 310{
 311    unsigned int i;
 312    /* Bit 31 - Parity of 27, 19:15.
 313     * Bit 30 - Parity of 14:10
 314     * Bit 29 - Parity of 9:5
 315     * Bit 28 - Parity of 4:0
 316     */
 317    static const uint32_t apl_parities[] = {
 318        0x1f,
 319        0x1f << 5,
 320        0x1f << 10,
 321        (0x1f << 15) | 1 << 27,
 322    };
 323    uint32_t p = 0, p_written;
 324    bool ok;
 325
 326    if (!AF_EX32(s->regs, CTRL, APER_PARITY_EN)) {
 327        return true;
 328    }
 329
 330    for (i = 0; i < ARRAY_SIZE(apl_parities); i++) {
 331        uint32_t v = val32;
 332        bool parity;
 333
 334        /* Extract the lanes for this pairity.  */
 335        v &= apl_parities[i];
 336        parity = parity32(v);
 337        p |= ((int) parity) << i;
 338    }
 339
 340    p_written = val32 >> 28;
 341    ok = p_written == p;
 342
 343    if (!ok) {
 344        qemu_log_mask(LOG_GUEST_ERROR, "Bad APL parity!\n");
 345        AF_DP32(s->regs, ISR, APER_PARITY, true);
 346    }
 347    return ok;
 348}
 349
 350static void isr_update_irq(XPPU *s)
 351{
 352    bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
 353    qemu_set_irq(s->irq_isr, pending);
 354}
 355
 356static void isr_postw(RegisterInfo *reg, uint64_t val64)
 357{
 358    XPPU *s = XILINX_XPPU(reg->opaque);
 359    isr_update_irq(s);
 360}
 361
 362static uint64_t ien_prew(RegisterInfo *reg, uint64_t val64)
 363{
 364    XPPU *s = XILINX_XPPU(reg->opaque);
 365    uint32_t val = val64;
 366
 367    s->regs[R_IMR] &= ~val;
 368    isr_update_irq(s);
 369    return 0;
 370}
 371
 372static uint64_t ids_prew(RegisterInfo *reg, uint64_t val64)
 373{
 374    XPPU *s = XILINX_XPPU(reg->opaque);
 375    uint32_t val = val64;
 376
 377    s->regs[R_IMR] |= val;
 378    isr_update_irq(s);
 379    return 0;
 380}
 381
 382static void update_mrs(XPPU *s)
 383{
 384    bool xppu_enabled = AF_EX32(s->regs, CTRL, ENABLE);
 385    unsigned int i;
 386
 387    for (i = 0; i < ARRAY_SIZE(s->ap); i++) {
 388        memory_region_set_enabled(&s->ap[i].iomem, xppu_enabled);
 389    }
 390}
 391
 392static void ctrl_postw(RegisterInfo *reg, uint64_t val64)
 393{
 394    XPPU *s = XILINX_XPPU(reg->opaque);
 395    update_mrs(s);
 396    check_mid_parities(s);
 397    isr_update_irq(s);
 398}
 399
 400static void mid_postw(RegisterInfo *reg, uint64_t val64)
 401{
 402    XPPU *s = XILINX_XPPU(reg->opaque);
 403    check_mid_parity(s, val64);
 404    isr_update_irq(s);
 405}
 406
 407static RegisterAccessInfo xppu_regs_info[] = {
 408    {   .name = "CTRL",  .decode.addr = A_CTRL,
 409        .rsvd = 0xfffffff8,
 410        .ro = 0xfffffff8,
 411        .post_write = ctrl_postw,
 412    },{ .name = "ERR_STATUS1",  .decode.addr = A_ERR_STATUS1,
 413        .rsvd = 0xfff00000,
 414        .ro = 0xffffffff,
 415    },{ .name = "ERR_STATUS2",  .decode.addr = A_ERR_STATUS2,
 416        .rsvd = 0xfffffc00,
 417        .ro = 0xffffffff,
 418    },{ .name = "POISON",  .decode.addr = A_POISON,
 419        .reset = 0xff9c0,
 420        .rsvd = 0xfff00000,
 421        .ro = 0xffffffff,
 422    },{ .name = "ISR",  .decode.addr = A_ISR,
 423        .rsvd = 0xffffff10,
 424        .ro = 0xffffff10,
 425        .w1c = 0xef,
 426        .post_write = isr_postw,
 427    },{ .name = "IMR",  .decode.addr = A_IMR,
 428        .reset = 0xef,
 429        .rsvd = 0xffffff10,
 430        .ro = 0xffffffff,
 431    },{ .name = "IEN",  .decode.addr = A_IEN,
 432        .rsvd = 0xffffff10,
 433        .ro = 0xffffff10,
 434        .pre_write = ien_prew,
 435    },{ .name = "IDS",  .decode.addr = A_IDS,
 436        .rsvd = 0xffffff10,
 437        .ro = 0xffffff10,
 438        .pre_write = ids_prew,
 439    },{ .name = "M_MASTER_IDS",  .decode.addr = A_M_MASTER_IDS,
 440        .reset = 0x14,
 441        .ro = 0xffffffff,
 442    },{ .name = "M_APERTURE_32B",  .decode.addr = A_M_APERTURE_32B,
 443        .reset = 0x80,
 444        .ro = 0xffffffff,
 445    },{ .name = "M_APERTURE_64KB",  .decode.addr = A_M_APERTURE_64KB,
 446        .reset = 0x100,
 447        .ro = 0xffffffff,
 448    },{ .name = "M_APERTURE_1MB",  .decode.addr = A_M_APERTURE_1MB,
 449        .reset = 0x10,
 450        .ro = 0xffffffff,
 451    },{ .name = "M_APERTURE_512MB",  .decode.addr = A_M_APERTURE_512MB,
 452        .reset = 0x1,
 453        .ro = 0xffffffff,
 454    },{ .name = "BASE_32B",  .decode.addr = A_BASE_32B,
 455        .reset = 0xff990000,
 456        .ro = 0xffffffff,
 457    },{ .name = "BASE_64KB",  .decode.addr = A_BASE_64KB,
 458        .reset = 0xff000000,
 459        .ro = 0xffffffff,
 460    },{ .name = "BASE_1MB",  .decode.addr = A_BASE_1MB,
 461        .reset = 0xfe000000,
 462        .ro = 0xffffffff,
 463    },{ .name = "BASE_512MB",  .decode.addr = A_BASE_512MB,
 464        .reset = 0xc0000000,
 465        .ro = 0xffffffff,
 466    },{ .name = "ECO",  .decode.addr = A_ECO,
 467    },{ .name = "MASTER_ID00",  .decode.addr = A_MASTER_ID00,
 468        .reset = 0x83ff0040,
 469        .rsvd = 0x3c00fc00,
 470        .ro = 0x3c00fc00,
 471        .post_write = mid_postw,
 472    },{ .name = "MASTER_ID01",  .decode.addr = A_MASTER_ID01,
 473        .reset = 0x3f00000,
 474        .rsvd = 0x3c00fc00,
 475        .ro = 0x3c00fc00,
 476        .post_write = mid_postw,
 477    },{ .name = "MASTER_ID02",  .decode.addr = A_MASTER_ID02,
 478        .reset = 0x83f00010,
 479        .rsvd = 0x3c00fc00,
 480        .ro = 0x3c00fc00,
 481        .post_write = mid_postw,
 482    },{ .name = "MASTER_ID03",  .decode.addr = A_MASTER_ID03,
 483        .reset = 0x83c00080,
 484        .rsvd = 0x3c00fc00,
 485        .ro = 0x3c00fc00,
 486        .post_write = mid_postw,
 487    },{ .name = "MASTER_ID04",  .decode.addr = A_MASTER_ID04,
 488        .reset = 0x83c30080,
 489        .rsvd = 0x3c00fc00,
 490        .ro = 0x3c00fc00,
 491    },{ .name = "MASTER_ID05",  .decode.addr = A_MASTER_ID05,
 492        .reset = 0x3c30081,
 493        .rsvd = 0x3c00fc00,
 494        .ro = 0x3c00fc00,
 495    },{ .name = "MASTER_ID06",  .decode.addr = A_MASTER_ID06,
 496        .reset = 0x3c30082,
 497        .rsvd = 0x3c00fc00,
 498        .ro = 0x3c00fc00,
 499    },{ .name = "MASTER_ID07",  .decode.addr = A_MASTER_ID07,
 500        .reset = 0x83c30083,
 501        .rsvd = 0x3c00fc00,
 502        .ro = 0x3c00fc00,
 503    },{ .name = "MASTER_ID08",  .decode.addr = A_MASTER_ID08,
 504        .rsvd = 0x3c00fc00,
 505        .ro = 0x3c00fc00,
 506    },{ .name = "MASTER_ID09",  .decode.addr = A_MASTER_ID09,
 507        .rsvd = 0x3c00fc00,
 508        .ro = 0x3c00fc00,
 509    },{ .name = "MASTER_ID10",  .decode.addr = A_MASTER_ID10,
 510        .rsvd = 0x3c00fc00,
 511        .ro = 0x3c00fc00,
 512    },{ .name = "MASTER_ID11",  .decode.addr = A_MASTER_ID11,
 513        .rsvd = 0x3c00fc00,
 514        .ro = 0x3c00fc00,
 515    },{ .name = "MASTER_ID12",  .decode.addr = A_MASTER_ID12,
 516        .rsvd = 0x3c00fc00,
 517        .ro = 0x3c00fc00,
 518    },{ .name = "MASTER_ID13",  .decode.addr = A_MASTER_ID13,
 519        .rsvd = 0x3c00fc00,
 520        .ro = 0x3c00fc00,
 521    },{ .name = "MASTER_ID14",  .decode.addr = A_MASTER_ID14,
 522        .rsvd = 0x3c00fc00,
 523        .ro = 0x3c00fc00,
 524    },{ .name = "MASTER_ID15",  .decode.addr = A_MASTER_ID15,
 525        .rsvd = 0x3c00fc00,
 526        .ro = 0x3c00fc00,
 527    },{ .name = "MASTER_ID16",  .decode.addr = A_MASTER_ID16,
 528        .rsvd = 0x3c00fc00,
 529        .ro = 0x3c00fc00,
 530    },{ .name = "MASTER_ID17",  .decode.addr = A_MASTER_ID17,
 531        .rsvd = 0x3c00fc00,
 532        .ro = 0x3c00fc00,
 533    },{ .name = "MASTER_ID18",  .decode.addr = A_MASTER_ID18,
 534        .rsvd = 0x3c00fc00,
 535        .ro = 0x3c00fc00,
 536    },{ .name = "MASTER_ID19",  .decode.addr = A_MASTER_ID19,
 537        .rsvd = 0x3c00fc00,
 538        .ro = 0x3c00fc00,
 539    },{ .name = "RAM_ADJ",  .decode.addr = A_RAM_ADJ,
 540        .reset = 0xb0b,
 541        .rsvd = 0xffffc0c0,
 542        .ro = 0xffffc0c0,
 543    }
 544};
 545
 546static void xppu_reset(DeviceState *dev)
 547{
 548    XPPU *s = XILINX_XPPU(dev);
 549    unsigned int i;
 550
 551    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 552        register_reset(&s->regs_info[i]);
 553    }
 554    update_mrs(s);
 555    isr_update_irq(s);
 556}
 557
 558static bool xppu_ap_check(XPPU *s, MemoryTransaction *tr, uint32_t apl)
 559{
 560    unsigned int i;
 561    bool mid_match = false;
 562    bool tz = extract32(apl, 27, 1);
 563    bool ok;
 564
 565    ok = check_apl_parity(s, apl);
 566    if (!ok) {
 567        return false;
 568    }
 569
 570    /* Check MIDs.  */
 571    for (i = 0; i < NR_MID_ENTRIES; i++) {
 572        uint32_t val32, mid, mask;
 573        bool readonly;
 574
 575        if (!extract32(apl, i, 1)) {
 576            continue;
 577        }
 578
 579        val32 = s->regs[R_MASTER_ID00 + i];
 580        mid = F_EX32(val32, MASTER_ID00, MID);
 581        readonly = F_EX32(val32, MASTER_ID00, MIDR);
 582        mask = F_EX32(val32, MASTER_ID00, MIDM);
 583
 584        if ((mid & mask) != (tr->attr.master_id & mask)) {
 585            continue;
 586        }
 587
 588        mid_match = true;
 589
 590        /* Check MID parity.  */
 591        if (check_mid_parity(s, val32) == false) {
 592            AF_DP32(s->regs, ISR, MID_PARITY, true);
 593            continue;
 594        }
 595
 596        if (readonly && tr->rw) {
 597            AF_DP32(s->regs, ISR, MID_RO, true);
 598            continue;
 599        }
 600
 601        if (!tr->attr.secure && !tz) {
 602            AF_DP32(s->regs, ISR, APER_TZ, true);
 603            continue;
 604        }
 605
 606        break;
 607    }
 608
 609    if (!mid_match) {
 610        /* Set if MID checks don't make it past masking and compare.  */
 611        AF_DP32(s->regs, ISR, MID_MISS, true);
 612    }
 613
 614    return i < NR_MID_ENTRIES;
 615}
 616
 617static void xppu_ap_access(MemoryTransaction *tr)
 618{
 619    XPPUAperture *ap = tr->opaque;
 620    XPPU *s = ap->parent;
 621    hwaddr addr = tr->addr;
 622    uint32_t ram_offset;
 623    uint32_t apl;
 624    bool valid;
 625    bool isr_free;
 626    bool xppu_enabled = AF_EX32(s->regs, CTRL, ENABLE);
 627
 628    assert(xppu_enabled);
 629
 630    addr += ap->base;
 631
 632    /* If any of bits ISR[7:1] are set, we cant store new faults.  */
 633    isr_free = (s->regs[R_ISR] & 0xf6) == 0;
 634
 635    ram_offset = addr & ap->extract_mask;
 636    ram_offset >>= ap->extract_shift;
 637
 638    ram_offset += ap->ram_base;
 639    apl = s->perm_ram[ram_offset];
 640    valid = xppu_ap_check(s, tr, apl);
 641
 642    if (!valid) {
 643        if (isr_free) {
 644            AF_DP32(s->regs, ISR, APER_PERM, true);
 645            AF_DP32(s->regs, ERR_STATUS1, AXI_ADDR, addr >> 12);
 646            AF_DP32(s->regs, ERR_STATUS2, AXI_ID, tr->attr.master_id);
 647        }
 648
 649        /* Poison the transaction.
 650         *
 651         * Bits 11:0  remain untouched.
 652         * Bits 31:12 are taken from the POISONBASE register
 653         * Bits 48:32 are zeroed.
 654         */
 655        addr &= (1 << 12) - 1;
 656        addr |= AF_EX32(s->regs, POISON, BASE) << 12;
 657        isr_update_irq(s);
 658    }
 659
 660    /* The access is accepted, let it through.  */
 661    tr->data.u64 = cpu_to_le64(tr->data.u64);
 662    address_space_rw(s->as, addr, tr->attr, (uint8_t *) &tr->data.u64,
 663                          tr->size, tr->rw);
 664    tr->data.u64 = le64_to_cpu(tr->data.u64);
 665}
 666
 667static const MemoryRegionOps xppu_ap_ops = {
 668    .access = xppu_ap_access,
 669    .endianness = DEVICE_LITTLE_ENDIAN,
 670    .valid = {
 671        .min_access_size = 4,
 672        .max_access_size = 4,
 673    },
 674};
 675
 676static uint64_t xppu_read(void *opaque, hwaddr addr, unsigned size,
 677                          MemTxAttrs attr)
 678{
 679    XPPU *s = XILINX_XPPU(opaque);
 680    RegisterInfo *r = &s->regs_info[addr / 4];
 681
 682    if (!attr.secure) {
 683        /* Non secure, return zero */
 684        return 0;
 685    }
 686
 687    if (addr >= 0x1000 && addr < 0x1644) {
 688        unsigned int i = (addr - 0x1000) / 4;
 689        assert(i < ARRAY_SIZE(s->perm_ram));
 690        return s->perm_ram[i];
 691    }
 692
 693    if (!r->data) {
 694        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 695                 object_get_canonical_path(OBJECT(s)),
 696                 addr);
 697        AF_DP32(s->regs, ISR, INV_APB, true);
 698        isr_update_irq(s);
 699        return 0;
 700    }
 701    return register_read(r);
 702}
 703
 704static void xppu_write(void *opaque, hwaddr addr, uint64_t value,
 705                       unsigned size, MemTxAttrs attr)
 706{
 707    XPPU *s = XILINX_XPPU(opaque);
 708    RegisterInfo *r = &s->regs_info[addr / 4];
 709
 710    if (!attr.secure) {
 711        return;
 712    }
 713
 714    if (addr >= 0x1000 && addr < 0x1644) {
 715        unsigned int i = (addr - 0x1000) / 4;
 716        assert(i < ARRAY_SIZE(s->perm_ram));
 717        s->perm_ram[i] = value;
 718        return;
 719    }
 720
 721    if (!r->data) {
 722        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 723                 object_get_canonical_path(OBJECT(s)),
 724                 addr, value);
 725        AF_DP32(s->regs, ISR, INV_APB, true);
 726        isr_update_irq(s);
 727        return;
 728    }
 729    register_write(r, value, ~0);
 730}
 731
 732static void xppu_access(MemoryTransaction *tr)
 733{
 734    MemTxAttrs attr = tr->attr;
 735    void *opaque = tr->opaque;
 736    hwaddr addr = tr->addr;
 737    unsigned size = tr->size;
 738    uint64_t value = tr->data.u64;;
 739    bool is_write = tr->rw;
 740
 741    if (is_write) {
 742        xppu_write(opaque, addr, value, size, attr);
 743    } else {
 744        tr->data.u64 = xppu_read(opaque, addr, size, attr);
 745    }
 746}
 747
 748static const MemoryRegionOps xppu_ops = {
 749    .access = xppu_access,
 750    .endianness = DEVICE_LITTLE_ENDIAN,
 751    .valid = {
 752        .min_access_size = 4,
 753        .max_access_size = 4,
 754    },
 755};
 756
 757static void xppu_realize(DeviceState *dev, Error **errp)
 758{
 759    XPPU *s = XILINX_XPPU(dev);
 760    const char *prefix = object_get_canonical_path(OBJECT(dev));
 761    unsigned int i;
 762
 763    for (i = 0; i < ARRAY_SIZE(xppu_regs_info); ++i) {
 764        RegisterInfo *r = &s->regs_info[xppu_regs_info[i].decode.addr/4];
 765
 766        *r = (RegisterInfo) {
 767            .data = (uint8_t *)&s->regs[
 768                    xppu_regs_info[i].decode.addr/4],
 769            .data_size = sizeof(uint32_t),
 770            .access = &xppu_regs_info[i],
 771            .debug = XILINX_XPPU_ERR_DEBUG,
 772            .prefix = prefix,
 773            .opaque = s,
 774        };
 775    }
 776
 777    s->as = s->mr ? address_space_init_shareable(s->mr, NULL)
 778                          : &address_space_memory;
 779}
 780
 781static void xppu_init(Object *obj)
 782{
 783    XPPU *s = XILINX_XPPU(obj);
 784    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 785
 786    sysbus_init_irq(sbd, &s->irq_isr);
 787
 788    object_property_add_link(obj, "mr", TYPE_MEMORY_REGION,
 789                             (Object **)&s->mr,
 790                             qdev_prop_allow_set_link_before_realize,
 791                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 792                             &error_abort);
 793}
 794
 795static bool xppu_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
 796                           Error **errp)
 797{
 798    XPPU *s = XILINX_XPPU(obj);
 799    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 800    ObjectClass *klass = object_class_by_name(TYPE_XILINX_XPPU);
 801    FDTGenericMMapClass *parent_fmc;
 802    unsigned int i;
 803
 804    parent_fmc = FDT_GENERIC_MMAP_CLASS(object_class_get_parent(klass));
 805    memory_region_init_io(&s->iomem, OBJECT(obj), &xppu_ops, s,
 806                          TYPE_XILINX_XPPU, 0x10000);
 807    sysbus_init_mmio(sbd, &s->iomem);
 808
 809    for (i = 0; i < (reg.n - 1) && i < ARRAY_SIZE(s->ap); i++) {
 810        static const XPPUGranule granules[] = {
 811            GRANULE_32B,
 812            GRANULE_64K,
 813            GRANULE_1M,
 814            GRANULE_512M
 815        };
 816        static const uint64_t bases[] = {
 817            0xff990000,
 818            0xff000000,
 819            0xfe000000,
 820            0xc0000000,
 821        };
 822        static const uint64_t masks[] = {
 823            0x7f << 5,  /* 32B, bits 11:05.  */
 824            0xff << 16, /* 64K, bits 23:16.  */
 825            0x0f << 20, /* 1MB, bits 23:20.  */
 826            0, /* No extraction.  */
 827        };
 828        static const unsigned int shifts[] = {
 829            5,  /* 32B, bits 11:05.  */
 830            16, /* 64K, bits 23:16.  */
 831            20, /* 1MB, bits 23:20.  */
 832            0, /* No extraction.  */
 833        };
 834        static const uint32_t ram_bases[] = {
 835            0x100,
 836            0x0,
 837            0x180,
 838            0x190,
 839        };
 840        char *name;
 841
 842        s->ap[i].parent = s;
 843        s->ap[i].granule = granules[i];
 844        s->ap[i].base = bases[i];
 845        s->ap[i].extract_mask = masks[i];
 846        s->ap[i].extract_shift = shifts[i];
 847        s->ap[i].ram_base = ram_bases[i];
 848
 849        name = g_strdup_printf("xppu-mr-%d\n", i);
 850        memory_region_init_io(&s->ap[i].iomem, OBJECT(obj),
 851                              &xppu_ap_ops, &s->ap[i],
 852                              name, reg.s[i + 1]);
 853        sysbus_init_mmio(sbd, &s->ap[i].iomem);
 854        g_free(name);
 855    }
 856    return parent_fmc ? parent_fmc->parse_reg(obj, reg, errp) : false;
 857}
 858
 859static const VMStateDescription vmstate_xppu = {
 860    .name = TYPE_XILINX_XPPU,
 861    .version_id = 1,
 862    .minimum_version_id = 1,
 863    .minimum_version_id_old = 1,
 864    .fields = (VMStateField[]) {
 865        VMSTATE_UINT32_ARRAY(regs, XPPU, R_MAX),
 866        VMSTATE_END_OF_LIST(),
 867    }
 868};
 869
 870static void xppu_class_init(ObjectClass *klass, void *data)
 871{
 872    DeviceClass *dc = DEVICE_CLASS(klass);
 873    FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
 874
 875    dc->reset = xppu_reset;
 876    dc->realize = xppu_realize;
 877    dc->vmsd = &vmstate_xppu;
 878    fmc->parse_reg = xppu_parse_reg;
 879}
 880
 881static const TypeInfo xppu_info = {
 882    .name          = TYPE_XILINX_XPPU,
 883    .parent        = TYPE_SYS_BUS_DEVICE,
 884    .instance_size = sizeof(XPPU),
 885    .class_init    = xppu_class_init,
 886    .instance_init = xppu_init,
 887    .interfaces    = (InterfaceInfo[]) {
 888        { TYPE_FDT_GENERIC_MMAP },
 889        { },
 890    },
 891
 892};
 893
 894static void xppu_register_types(void)
 895{
 896    type_register_static(&xppu_info);
 897}
 898
 899type_init(xppu_register_types)
 900