qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xlnx-bbram.c (15261B)


      1 /*
      2  * QEMU model of the Xilinx BBRAM Battery Backed RAM
      3  *
      4  * Copyright (c) 2014-2021 Xilinx Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "hw/nvram/xlnx-bbram.h"
     27 
     28 #include "qemu/error-report.h"
     29 #include "qemu/log.h"
     30 #include "qapi/error.h"
     31 #include "sysemu/blockdev.h"
     32 #include "migration/vmstate.h"
     33 #include "hw/qdev-properties.h"
     34 #include "hw/qdev-properties-system.h"
     35 #include "hw/nvram/xlnx-efuse.h"
     36 
     37 #ifndef XLNX_BBRAM_ERR_DEBUG
     38 #define XLNX_BBRAM_ERR_DEBUG 0
     39 #endif
     40 
     41 REG32(BBRAM_STATUS, 0x0)
     42     FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1)
     43     FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1)
     44     FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1)
     45     FIELD(BBRAM_STATUS, PGM_MODE, 0, 1)
     46 REG32(BBRAM_CTRL, 0x4)
     47     FIELD(BBRAM_CTRL, ZEROIZE, 0, 1)
     48 REG32(PGM_MODE, 0x8)
     49 REG32(BBRAM_AES_CRC, 0xc)
     50 REG32(BBRAM_0, 0x10)
     51 REG32(BBRAM_1, 0x14)
     52 REG32(BBRAM_2, 0x18)
     53 REG32(BBRAM_3, 0x1c)
     54 REG32(BBRAM_4, 0x20)
     55 REG32(BBRAM_5, 0x24)
     56 REG32(BBRAM_6, 0x28)
     57 REG32(BBRAM_7, 0x2c)
     58 REG32(BBRAM_8, 0x30)
     59 REG32(BBRAM_SLVERR, 0x34)
     60     FIELD(BBRAM_SLVERR, ENABLE, 0, 1)
     61 REG32(BBRAM_ISR, 0x38)
     62     FIELD(BBRAM_ISR, APB_SLVERR, 0, 1)
     63 REG32(BBRAM_IMR, 0x3c)
     64     FIELD(BBRAM_IMR, APB_SLVERR, 0, 1)
     65 REG32(BBRAM_IER, 0x40)
     66     FIELD(BBRAM_IER, APB_SLVERR, 0, 1)
     67 REG32(BBRAM_IDR, 0x44)
     68     FIELD(BBRAM_IDR, APB_SLVERR, 0, 1)
     69 REG32(BBRAM_MSW_LOCK, 0x4c)
     70     FIELD(BBRAM_MSW_LOCK, VAL, 0, 1)
     71 
     72 #define R_MAX (R_BBRAM_MSW_LOCK + 1)
     73 
     74 #define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0)
     75 
     76 #define BBRAM_PGM_MAGIC 0x757bdf0d
     77 
     78 QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs));
     79 
     80 static bool bbram_msw_locked(XlnxBBRam *s)
     81 {
     82     return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0;
     83 }
     84 
     85 static bool bbram_pgm_enabled(XlnxBBRam *s)
     86 {
     87     return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0;
     88 }
     89 
     90 static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail)
     91 {
     92     Error *errp = NULL;
     93 
     94     error_setg_errno(&errp, -rc, "%s: BBRAM backstore %s failed.",
     95                      blk_name(s->blk), detail);
     96     error_report("%s", error_get_pretty(errp));
     97     error_free(errp);
     98 
     99     g_free(detail);
    100 }
    101 
    102 static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
    103 {
    104     uint32_t *ram = &s->regs[R_BBRAM_0];
    105     int nr = RAM_MAX;
    106 
    107     if (!s->blk) {
    108         return;
    109     }
    110 
    111     s->blk_ro = !blk_supports_write_perm(s->blk);
    112     if (!s->blk_ro) {
    113         int rc;
    114 
    115         rc = blk_set_perm(s->blk,
    116                           (BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE),
    117                           BLK_PERM_ALL, NULL);
    118         if (rc) {
    119             s->blk_ro = true;
    120         }
    121     }
    122     if (s->blk_ro) {
    123         warn_report("%s: Skip saving updates to read-only BBRAM backstore.",
    124                     blk_name(s->blk));
    125     }
    126 
    127     if (blk_pread(s->blk, 0, nr, ram, 0) < 0) {
    128         error_setg(errp,
    129                    "%s: Failed to read %u bytes from BBRAM backstore.",
    130                    blk_name(s->blk), nr);
    131         return;
    132     }
    133 
    134     /* Convert from little-endian backstore for each 32-bit word */
    135     nr /= 4;
    136     while (nr--) {
    137         ram[nr] = le32_to_cpu(ram[nr]);
    138     }
    139 }
    140 
    141 static void bbram_bdrv_sync(XlnxBBRam *s, uint64_t hwaddr)
    142 {
    143     uint32_t le32;
    144     unsigned offset;
    145     int rc;
    146 
    147     assert(A_BBRAM_0 <= hwaddr && hwaddr <= A_BBRAM_8);
    148 
    149     /* Backstore is always in little-endian */
    150     le32 = cpu_to_le32(s->regs[hwaddr / 4]);
    151 
    152     /* Update zeroized flag */
    153     if (le32 && (hwaddr != A_BBRAM_8 || s->bbram8_wo)) {
    154         ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 0);
    155     }
    156 
    157     if (!s->blk || s->blk_ro) {
    158         return;
    159     }
    160 
    161     offset = hwaddr - A_BBRAM_0;
    162     rc = blk_pwrite(s->blk, offset, 4, &le32, 0);
    163     if (rc < 0) {
    164         bbram_bdrv_error(s, rc, g_strdup_printf("write to offset %u", offset));
    165     }
    166 }
    167 
    168 static void bbram_bdrv_zero(XlnxBBRam *s)
    169 {
    170     int rc;
    171 
    172     ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 1);
    173 
    174     if (!s->blk || s->blk_ro) {
    175         return;
    176     }
    177 
    178     rc = blk_make_zero(s->blk, 0);
    179     if (rc < 0) {
    180         bbram_bdrv_error(s, rc, g_strdup("zeroizing"));
    181     }
    182 
    183     /* Restore bbram8 if it is non-zero */
    184     if (s->regs[R_BBRAM_8]) {
    185         bbram_bdrv_sync(s, A_BBRAM_8);
    186     }
    187 }
    188 
    189 static void bbram_zeroize(XlnxBBRam *s)
    190 {
    191     int nr = RAM_MAX - (s->bbram8_wo ? 0 : 4); /* only wo bbram8 is cleared */
    192 
    193     memset(&s->regs[R_BBRAM_0], 0, nr);
    194     bbram_bdrv_zero(s);
    195 }
    196 
    197 static void bbram_update_irq(XlnxBBRam *s)
    198 {
    199     bool pending = s->regs[R_BBRAM_ISR] & ~s->regs[R_BBRAM_IMR];
    200 
    201     qemu_set_irq(s->irq_bbram, pending);
    202 }
    203 
    204 static void bbram_ctrl_postw(RegisterInfo *reg, uint64_t val64)
    205 {
    206     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    207     uint32_t val = val64;
    208 
    209     if (val & R_BBRAM_CTRL_ZEROIZE_MASK) {
    210         bbram_zeroize(s);
    211         /* The bit is self clearing */
    212         s->regs[R_BBRAM_CTRL] &= ~R_BBRAM_CTRL_ZEROIZE_MASK;
    213     }
    214 }
    215 
    216 static void bbram_pgm_mode_postw(RegisterInfo *reg, uint64_t val64)
    217 {
    218     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    219     uint32_t val = val64;
    220 
    221     if (val == BBRAM_PGM_MAGIC) {
    222         bbram_zeroize(s);
    223 
    224         /* The status bit is cleared only by POR */
    225         ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, PGM_MODE, 1);
    226     }
    227 }
    228 
    229 static void bbram_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
    230 {
    231     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    232     uint32_t calc_crc;
    233 
    234     if (!bbram_pgm_enabled(s)) {
    235         /* We are not in programming mode, don't do anything */
    236         return;
    237     }
    238 
    239     /* Perform the AES integrity check */
    240     s->regs[R_BBRAM_STATUS] |= R_BBRAM_STATUS_AES_CRC_DONE_MASK;
    241 
    242     /*
    243      * Set check status.
    244      *
    245      * ZynqMP BBRAM check has a zero-u32 prepended; see:
    246      *  https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_bbramps_zynqmp.c#L311
    247      */
    248     calc_crc = xlnx_efuse_calc_crc(&s->regs[R_BBRAM_0],
    249                                    (R_BBRAM_8 - R_BBRAM_0), s->crc_zpads);
    250 
    251     ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, AES_CRC_PASS,
    252                      (s->regs[R_BBRAM_AES_CRC] == calc_crc));
    253 }
    254 
    255 static uint64_t bbram_key_prew(RegisterInfo *reg, uint64_t val64)
    256 {
    257     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    258     uint32_t original_data = *(uint32_t *) reg->data;
    259 
    260     if (bbram_pgm_enabled(s)) {
    261         return val64;
    262     } else {
    263         /* We are not in programming mode, don't do anything */
    264         qemu_log_mask(LOG_GUEST_ERROR,
    265                       "Not in programming mode, dropping the write\n");
    266         return original_data;
    267     }
    268 }
    269 
    270 static void bbram_key_postw(RegisterInfo *reg, uint64_t val64)
    271 {
    272     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    273 
    274     bbram_bdrv_sync(s, reg->access->addr);
    275 }
    276 
    277 static uint64_t bbram_wo_postr(RegisterInfo *reg, uint64_t val)
    278 {
    279     return 0;
    280 }
    281 
    282 static uint64_t bbram_r8_postr(RegisterInfo *reg, uint64_t val)
    283 {
    284     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    285 
    286     return s->bbram8_wo ? bbram_wo_postr(reg, val) : val;
    287 }
    288 
    289 static bool bbram_r8_readonly(XlnxBBRam *s)
    290 {
    291     return !bbram_pgm_enabled(s) || bbram_msw_locked(s);
    292 }
    293 
    294 static uint64_t bbram_r8_prew(RegisterInfo *reg, uint64_t val64)
    295 {
    296     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    297 
    298     if (bbram_r8_readonly(s)) {
    299         val64 = *(uint32_t *)reg->data;
    300     }
    301 
    302     return val64;
    303 }
    304 
    305 static void bbram_r8_postw(RegisterInfo *reg, uint64_t val64)
    306 {
    307     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    308 
    309     if (!bbram_r8_readonly(s)) {
    310         bbram_bdrv_sync(s, A_BBRAM_8);
    311     }
    312 }
    313 
    314 static uint64_t bbram_msw_lock_prew(RegisterInfo *reg, uint64_t val64)
    315 {
    316     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    317 
    318     /* Never lock if bbram8 is wo; and, only POR can clear the lock */
    319     if (s->bbram8_wo) {
    320         val64 = 0;
    321     } else {
    322         val64 |= s->regs[R_BBRAM_MSW_LOCK];
    323     }
    324 
    325     return val64;
    326 }
    327 
    328 static void bbram_isr_postw(RegisterInfo *reg, uint64_t val64)
    329 {
    330     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    331 
    332     bbram_update_irq(s);
    333 }
    334 
    335 static uint64_t bbram_ier_prew(RegisterInfo *reg, uint64_t val64)
    336 {
    337     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    338     uint32_t val = val64;
    339 
    340     s->regs[R_BBRAM_IMR] &= ~val;
    341     bbram_update_irq(s);
    342     return 0;
    343 }
    344 
    345 static uint64_t bbram_idr_prew(RegisterInfo *reg, uint64_t val64)
    346 {
    347     XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
    348     uint32_t val = val64;
    349 
    350     s->regs[R_BBRAM_IMR] |= val;
    351     bbram_update_irq(s);
    352     return 0;
    353 }
    354 
    355 static RegisterAccessInfo bbram_ctrl_regs_info[] = {
    356     {   .name = "BBRAM_STATUS",  .addr = A_BBRAM_STATUS,
    357         .rsvd = 0xee,
    358         .ro = 0x3ff,
    359     },{ .name = "BBRAM_CTRL",  .addr = A_BBRAM_CTRL,
    360         .post_write = bbram_ctrl_postw,
    361     },{ .name = "PGM_MODE",  .addr = A_PGM_MODE,
    362         .post_write = bbram_pgm_mode_postw,
    363     },{ .name = "BBRAM_AES_CRC",  .addr = A_BBRAM_AES_CRC,
    364         .post_write = bbram_aes_crc_postw,
    365         .post_read = bbram_wo_postr,
    366     },{ .name = "BBRAM_0",  .addr = A_BBRAM_0,
    367         .pre_write = bbram_key_prew,
    368         .post_write = bbram_key_postw,
    369         .post_read = bbram_wo_postr,
    370     },{ .name = "BBRAM_1",  .addr = A_BBRAM_1,
    371         .pre_write = bbram_key_prew,
    372         .post_write = bbram_key_postw,
    373         .post_read = bbram_wo_postr,
    374     },{ .name = "BBRAM_2",  .addr = A_BBRAM_2,
    375         .pre_write = bbram_key_prew,
    376         .post_write = bbram_key_postw,
    377         .post_read = bbram_wo_postr,
    378     },{ .name = "BBRAM_3",  .addr = A_BBRAM_3,
    379         .pre_write = bbram_key_prew,
    380         .post_write = bbram_key_postw,
    381         .post_read = bbram_wo_postr,
    382     },{ .name = "BBRAM_4",  .addr = A_BBRAM_4,
    383         .pre_write = bbram_key_prew,
    384         .post_write = bbram_key_postw,
    385         .post_read = bbram_wo_postr,
    386     },{ .name = "BBRAM_5",  .addr = A_BBRAM_5,
    387         .pre_write = bbram_key_prew,
    388         .post_write = bbram_key_postw,
    389         .post_read = bbram_wo_postr,
    390     },{ .name = "BBRAM_6",  .addr = A_BBRAM_6,
    391         .pre_write = bbram_key_prew,
    392         .post_write = bbram_key_postw,
    393         .post_read = bbram_wo_postr,
    394     },{ .name = "BBRAM_7",  .addr = A_BBRAM_7,
    395         .pre_write = bbram_key_prew,
    396         .post_write = bbram_key_postw,
    397         .post_read = bbram_wo_postr,
    398     },{ .name = "BBRAM_8",  .addr = A_BBRAM_8,
    399         .pre_write = bbram_r8_prew,
    400         .post_write = bbram_r8_postw,
    401         .post_read = bbram_r8_postr,
    402     },{ .name = "BBRAM_SLVERR",  .addr = A_BBRAM_SLVERR,
    403         .rsvd = ~1,
    404     },{ .name = "BBRAM_ISR",  .addr = A_BBRAM_ISR,
    405         .w1c = 0x1,
    406         .post_write = bbram_isr_postw,
    407     },{ .name = "BBRAM_IMR",  .addr = A_BBRAM_IMR,
    408         .ro = 0x1,
    409     },{ .name = "BBRAM_IER",  .addr = A_BBRAM_IER,
    410         .pre_write = bbram_ier_prew,
    411     },{ .name = "BBRAM_IDR",  .addr = A_BBRAM_IDR,
    412         .pre_write = bbram_idr_prew,
    413     },{ .name = "BBRAM_MSW_LOCK",  .addr = A_BBRAM_MSW_LOCK,
    414         .pre_write = bbram_msw_lock_prew,
    415         .ro = ~R_BBRAM_MSW_LOCK_VAL_MASK,
    416     }
    417 };
    418 
    419 static void bbram_ctrl_reset(DeviceState *dev)
    420 {
    421     XlnxBBRam *s = XLNX_BBRAM(dev);
    422     unsigned int i;
    423 
    424     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
    425         if (i < R_BBRAM_0 || i > R_BBRAM_8) {
    426             register_reset(&s->regs_info[i]);
    427         }
    428     }
    429 
    430     bbram_update_irq(s);
    431 }
    432 
    433 static const MemoryRegionOps bbram_ctrl_ops = {
    434     .read = register_read_memory,
    435     .write = register_write_memory,
    436     .endianness = DEVICE_LITTLE_ENDIAN,
    437     .valid = {
    438         .min_access_size = 4,
    439         .max_access_size = 4,
    440     },
    441 };
    442 
    443 static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
    444 {
    445     XlnxBBRam *s = XLNX_BBRAM(dev);
    446 
    447     if (s->crc_zpads) {
    448         s->bbram8_wo = true;
    449     }
    450 
    451     bbram_bdrv_read(s, errp);
    452 }
    453 
    454 static void bbram_ctrl_init(Object *obj)
    455 {
    456     XlnxBBRam *s = XLNX_BBRAM(obj);
    457     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    458     RegisterInfoArray *reg_array;
    459 
    460     reg_array =
    461         register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
    462                               ARRAY_SIZE(bbram_ctrl_regs_info),
    463                               s->regs_info, s->regs,
    464                               &bbram_ctrl_ops,
    465                               XLNX_BBRAM_ERR_DEBUG,
    466                               R_MAX * 4);
    467 
    468     sysbus_init_mmio(sbd, &reg_array->mem);
    469     sysbus_init_irq(sbd, &s->irq_bbram);
    470 }
    471 
    472 static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
    473                                  void *opaque, Error **errp)
    474 {
    475     DeviceState *dev = DEVICE(obj);
    476 
    477     qdev_prop_drive.set(obj, v, name, opaque, errp);
    478 
    479     /* Fill initial data if backend is attached after realized */
    480     if (dev->realized) {
    481         bbram_bdrv_read(XLNX_BBRAM(obj), errp);
    482     }
    483 }
    484 
    485 static void bbram_prop_get_drive(Object *obj, Visitor *v, const char *name,
    486                                  void *opaque, Error **errp)
    487 {
    488     qdev_prop_drive.get(obj, v, name, opaque, errp);
    489 }
    490 
    491 static void bbram_prop_release_drive(Object *obj, const char *name,
    492                                      void *opaque)
    493 {
    494     qdev_prop_drive.release(obj, name, opaque);
    495 }
    496 
    497 static const PropertyInfo bbram_prop_drive = {
    498     .name  = "str",
    499     .description = "Node name or ID of a block device to use as BBRAM backend",
    500     .realized_set_allowed = true,
    501     .get = bbram_prop_get_drive,
    502     .set = bbram_prop_set_drive,
    503     .release = bbram_prop_release_drive,
    504 };
    505 
    506 static const VMStateDescription vmstate_bbram_ctrl = {
    507     .name = TYPE_XLNX_BBRAM,
    508     .version_id = 1,
    509     .minimum_version_id = 1,
    510     .fields = (VMStateField[]) {
    511         VMSTATE_UINT32_ARRAY(regs, XlnxBBRam, R_MAX),
    512         VMSTATE_END_OF_LIST(),
    513     }
    514 };
    515 
    516 static Property bbram_ctrl_props[] = {
    517     DEFINE_PROP("drive", XlnxBBRam, blk, bbram_prop_drive, BlockBackend *),
    518     DEFINE_PROP_UINT32("crc-zpads", XlnxBBRam, crc_zpads, 1),
    519     DEFINE_PROP_END_OF_LIST(),
    520 };
    521 
    522 static void bbram_ctrl_class_init(ObjectClass *klass, void *data)
    523 {
    524     DeviceClass *dc = DEVICE_CLASS(klass);
    525 
    526     dc->reset = bbram_ctrl_reset;
    527     dc->realize = bbram_ctrl_realize;
    528     dc->vmsd = &vmstate_bbram_ctrl;
    529     device_class_set_props(dc, bbram_ctrl_props);
    530 }
    531 
    532 static const TypeInfo bbram_ctrl_info = {
    533     .name          = TYPE_XLNX_BBRAM,
    534     .parent        = TYPE_SYS_BUS_DEVICE,
    535     .instance_size = sizeof(XlnxBBRam),
    536     .class_init    = bbram_ctrl_class_init,
    537     .instance_init = bbram_ctrl_init,
    538 };
    539 
    540 static void bbram_ctrl_register_types(void)
    541 {
    542     type_register_static(&bbram_ctrl_info);
    543 }
    544 
    545 type_init(bbram_ctrl_register_types)