cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

xlnx-bbram.c (15251B)


      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
     41REG32(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)
     46REG32(BBRAM_CTRL, 0x4)
     47    FIELD(BBRAM_CTRL, ZEROIZE, 0, 1)
     48REG32(PGM_MODE, 0x8)
     49REG32(BBRAM_AES_CRC, 0xc)
     50REG32(BBRAM_0, 0x10)
     51REG32(BBRAM_1, 0x14)
     52REG32(BBRAM_2, 0x18)
     53REG32(BBRAM_3, 0x1c)
     54REG32(BBRAM_4, 0x20)
     55REG32(BBRAM_5, 0x24)
     56REG32(BBRAM_6, 0x28)
     57REG32(BBRAM_7, 0x2c)
     58REG32(BBRAM_8, 0x30)
     59REG32(BBRAM_SLVERR, 0x34)
     60    FIELD(BBRAM_SLVERR, ENABLE, 0, 1)
     61REG32(BBRAM_ISR, 0x38)
     62    FIELD(BBRAM_ISR, APB_SLVERR, 0, 1)
     63REG32(BBRAM_IMR, 0x3c)
     64    FIELD(BBRAM_IMR, APB_SLVERR, 0, 1)
     65REG32(BBRAM_IER, 0x40)
     66    FIELD(BBRAM_IER, APB_SLVERR, 0, 1)
     67REG32(BBRAM_IDR, 0x44)
     68    FIELD(BBRAM_IDR, APB_SLVERR, 0, 1)
     69REG32(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
     78QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs));
     79
     80static bool bbram_msw_locked(XlnxBBRam *s)
     81{
     82    return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0;
     83}
     84
     85static bool bbram_pgm_enabled(XlnxBBRam *s)
     86{
     87    return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0;
     88}
     89
     90static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail)
     91{
     92    Error *errp;
     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
    102static 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, ram, nr) < 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
    141static 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, &le32, 4, 0);
    163    if (rc < 0) {
    164        bbram_bdrv_error(s, rc, g_strdup_printf("write to offset %u", offset));
    165    }
    166}
    167
    168static 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
    189static 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
    197static 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
    204static 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
    216static 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
    229static 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
    255static 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
    270static 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
    277static uint64_t bbram_wo_postr(RegisterInfo *reg, uint64_t val)
    278{
    279    return 0;
    280}
    281
    282static 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
    289static bool bbram_r8_readonly(XlnxBBRam *s)
    290{
    291    return !bbram_pgm_enabled(s) || bbram_msw_locked(s);
    292}
    293
    294static 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
    305static 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
    314static 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
    328static 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
    335static 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
    345static 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
    355static 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
    419static 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
    433static 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
    443static 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
    454static 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
    472static 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
    485static 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
    491static void bbram_prop_release_drive(Object *obj, const char *name,
    492                                     void *opaque)
    493{
    494    qdev_prop_drive.release(obj, name, opaque);
    495}
    496
    497static 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
    506static 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
    516static 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
    522static 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
    532static 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
    540static void bbram_ctrl_register_types(void)
    541{
    542    type_register_static(&bbram_ctrl_info);
    543}
    544
    545type_init(bbram_ctrl_register_types)