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

pnv_phb3_pbcq.c (11917B)


      1/*
      2 * QEMU PowerPC PowerNV (POWER8) PHB3 model
      3 *
      4 * Copyright (c) 2014-2020, IBM Corporation.
      5 *
      6 * This code is licensed under the GPL version 2 or later. See the
      7 * COPYING file in the top-level directory.
      8 */
      9#include "qemu/osdep.h"
     10#include "qapi/error.h"
     11#include "qemu-common.h"
     12#include "qemu/log.h"
     13#include "target/ppc/cpu.h"
     14#include "hw/ppc/fdt.h"
     15#include "hw/pci-host/pnv_phb3_regs.h"
     16#include "hw/pci-host/pnv_phb3.h"
     17#include "hw/ppc/pnv.h"
     18#include "hw/ppc/pnv_xscom.h"
     19#include "hw/pci/pci_bridge.h"
     20#include "hw/pci/pci_bus.h"
     21
     22#include <libfdt.h>
     23
     24#define phb3_pbcq_error(pbcq, fmt, ...)                                 \
     25    qemu_log_mask(LOG_GUEST_ERROR, "phb3_pbcq[%d:%d]: " fmt "\n",       \
     26                  (pbcq)->phb->chip_id, (pbcq)->phb->phb_id, ## __VA_ARGS__)
     27
     28static uint64_t pnv_pbcq_nest_xscom_read(void *opaque, hwaddr addr,
     29                                         unsigned size)
     30{
     31    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
     32    uint32_t offset = addr >> 3;
     33
     34    return pbcq->nest_regs[offset];
     35}
     36
     37static uint64_t pnv_pbcq_pci_xscom_read(void *opaque, hwaddr addr,
     38                                        unsigned size)
     39{
     40    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
     41    uint32_t offset = addr >> 3;
     42
     43    return pbcq->pci_regs[offset];
     44}
     45
     46static uint64_t pnv_pbcq_spci_xscom_read(void *opaque, hwaddr addr,
     47                                         unsigned size)
     48{
     49    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
     50    uint32_t offset = addr >> 3;
     51
     52    if (offset == PBCQ_SPCI_ASB_DATA) {
     53        return pnv_phb3_reg_read(pbcq->phb,
     54                                 pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR], 8);
     55    }
     56    return pbcq->spci_regs[offset];
     57}
     58
     59static void pnv_pbcq_update_map(PnvPBCQState *pbcq)
     60{
     61    uint64_t bar_en = pbcq->nest_regs[PBCQ_NEST_BAR_EN];
     62    uint64_t bar, mask, size;
     63
     64    /*
     65     * NOTE: This will really not work well if those are remapped
     66     * after the PHB has created its sub regions. We could do better
     67     * if we had a way to resize regions but we don't really care
     68     * that much in practice as the stuff below really only happens
     69     * once early during boot
     70     */
     71
     72    /* Handle unmaps */
     73    if (memory_region_is_mapped(&pbcq->mmbar0) &&
     74        !(bar_en & PBCQ_NEST_BAR_EN_MMIO0)) {
     75        memory_region_del_subregion(get_system_memory(), &pbcq->mmbar0);
     76    }
     77    if (memory_region_is_mapped(&pbcq->mmbar1) &&
     78        !(bar_en & PBCQ_NEST_BAR_EN_MMIO1)) {
     79        memory_region_del_subregion(get_system_memory(), &pbcq->mmbar1);
     80    }
     81    if (memory_region_is_mapped(&pbcq->phbbar) &&
     82        !(bar_en & PBCQ_NEST_BAR_EN_PHB)) {
     83        memory_region_del_subregion(get_system_memory(), &pbcq->phbbar);
     84    }
     85
     86    /* Update PHB */
     87    pnv_phb3_update_regions(pbcq->phb);
     88
     89    /* Handle maps */
     90    if (!memory_region_is_mapped(&pbcq->mmbar0) &&
     91        (bar_en & PBCQ_NEST_BAR_EN_MMIO0)) {
     92        bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] >> 14;
     93        mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0];
     94        size = ((~mask) >> 14) + 1;
     95        memory_region_init(&pbcq->mmbar0, OBJECT(pbcq), "pbcq-mmio0", size);
     96        memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar0);
     97        pbcq->mmio0_base = bar;
     98        pbcq->mmio0_size = size;
     99    }
    100    if (!memory_region_is_mapped(&pbcq->mmbar1) &&
    101        (bar_en & PBCQ_NEST_BAR_EN_MMIO1)) {
    102        bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] >> 14;
    103        mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1];
    104        size = ((~mask) >> 14) + 1;
    105        memory_region_init(&pbcq->mmbar1, OBJECT(pbcq), "pbcq-mmio1", size);
    106        memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar1);
    107        pbcq->mmio1_base = bar;
    108        pbcq->mmio1_size = size;
    109    }
    110    if (!memory_region_is_mapped(&pbcq->phbbar)
    111        && (bar_en & PBCQ_NEST_BAR_EN_PHB)) {
    112        bar = pbcq->nest_regs[PBCQ_NEST_PHB_BAR] >> 14;
    113        size = 0x1000;
    114        memory_region_init(&pbcq->phbbar, OBJECT(pbcq), "pbcq-phb", size);
    115        memory_region_add_subregion(get_system_memory(), bar, &pbcq->phbbar);
    116    }
    117
    118    /* Update PHB */
    119    pnv_phb3_update_regions(pbcq->phb);
    120}
    121
    122static void pnv_pbcq_nest_xscom_write(void *opaque, hwaddr addr,
    123                                uint64_t val, unsigned size)
    124{
    125    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
    126    uint32_t reg = addr >> 3;
    127
    128    switch (reg) {
    129    case PBCQ_NEST_MMIO_BAR0:
    130    case PBCQ_NEST_MMIO_BAR1:
    131    case PBCQ_NEST_MMIO_MASK0:
    132    case PBCQ_NEST_MMIO_MASK1:
    133        if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] &
    134            (PBCQ_NEST_BAR_EN_MMIO0 |
    135             PBCQ_NEST_BAR_EN_MMIO1)) {
    136            phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported");
    137        }
    138        pbcq->nest_regs[reg] = val & 0xffffffffc0000000ull;
    139        break;
    140    case PBCQ_NEST_PHB_BAR:
    141        if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] & PBCQ_NEST_BAR_EN_PHB) {
    142            phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported");
    143        }
    144        pbcq->nest_regs[reg] = val & 0xfffffffffc000000ull;
    145        break;
    146    case PBCQ_NEST_BAR_EN:
    147        pbcq->nest_regs[reg] = val & 0xf800000000000000ull;
    148        pnv_pbcq_update_map(pbcq);
    149        pnv_phb3_remap_irqs(pbcq->phb);
    150        break;
    151    case PBCQ_NEST_IRSN_COMPARE:
    152    case PBCQ_NEST_IRSN_MASK:
    153        pbcq->nest_regs[reg] = val & PBCQ_NEST_IRSN_COMP;
    154        pnv_phb3_remap_irqs(pbcq->phb);
    155        break;
    156    case PBCQ_NEST_LSI_SRC_ID:
    157        pbcq->nest_regs[reg] = val & PBCQ_NEST_LSI_SRC;
    158        pnv_phb3_remap_irqs(pbcq->phb);
    159        break;
    160    default:
    161        phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__,
    162                        addr, val);
    163    }
    164}
    165
    166static void pnv_pbcq_pci_xscom_write(void *opaque, hwaddr addr,
    167                                     uint64_t val, unsigned size)
    168{
    169    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
    170    uint32_t reg = addr >> 3;
    171
    172    switch (reg) {
    173    case PBCQ_PCI_BAR2:
    174        pbcq->pci_regs[reg] = val & 0xfffffffffc000000ull;
    175        pnv_pbcq_update_map(pbcq);
    176        break;
    177    default:
    178        phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__,
    179                        addr, val);
    180    }
    181}
    182
    183static void pnv_pbcq_spci_xscom_write(void *opaque, hwaddr addr,
    184                                uint64_t val, unsigned size)
    185{
    186    PnvPBCQState *pbcq = PNV_PBCQ(opaque);
    187    uint32_t reg = addr >> 3;
    188
    189    switch (reg) {
    190    case PBCQ_SPCI_ASB_ADDR:
    191        pbcq->spci_regs[reg] = val & 0xfff;
    192        break;
    193    case PBCQ_SPCI_ASB_STATUS:
    194        pbcq->spci_regs[reg] &= ~val;
    195        break;
    196    case PBCQ_SPCI_ASB_DATA:
    197        pnv_phb3_reg_write(pbcq->phb, pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR],
    198                           val, 8);
    199        break;
    200    case PBCQ_SPCI_AIB_CAPP_EN:
    201    case PBCQ_SPCI_CAPP_SEC_TMR:
    202        break;
    203    default:
    204        phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__,
    205                        addr, val);
    206    }
    207}
    208
    209static const MemoryRegionOps pnv_pbcq_nest_xscom_ops = {
    210    .read = pnv_pbcq_nest_xscom_read,
    211    .write = pnv_pbcq_nest_xscom_write,
    212    .valid.min_access_size = 8,
    213    .valid.max_access_size = 8,
    214    .impl.min_access_size = 8,
    215    .impl.max_access_size = 8,
    216    .endianness = DEVICE_BIG_ENDIAN,
    217};
    218
    219static const MemoryRegionOps pnv_pbcq_pci_xscom_ops = {
    220    .read = pnv_pbcq_pci_xscom_read,
    221    .write = pnv_pbcq_pci_xscom_write,
    222    .valid.min_access_size = 8,
    223    .valid.max_access_size = 8,
    224    .impl.min_access_size = 8,
    225    .impl.max_access_size = 8,
    226    .endianness = DEVICE_BIG_ENDIAN,
    227};
    228
    229static const MemoryRegionOps pnv_pbcq_spci_xscom_ops = {
    230    .read = pnv_pbcq_spci_xscom_read,
    231    .write = pnv_pbcq_spci_xscom_write,
    232    .valid.min_access_size = 8,
    233    .valid.max_access_size = 8,
    234    .impl.min_access_size = 8,
    235    .impl.max_access_size = 8,
    236    .endianness = DEVICE_BIG_ENDIAN,
    237};
    238
    239static void pnv_pbcq_default_bars(PnvPBCQState *pbcq)
    240{
    241    uint64_t mm0, mm1, reg;
    242    PnvPHB3 *phb = pbcq->phb;
    243
    244    mm0 = 0x3d00000000000ull + 0x4000000000ull * phb->chip_id +
    245            0x1000000000ull * phb->phb_id;
    246    mm1 = 0x3ff8000000000ull + 0x0200000000ull * phb->chip_id +
    247            0x0080000000ull * phb->phb_id;
    248    reg = 0x3fffe40000000ull + 0x0000400000ull * phb->chip_id +
    249            0x0000100000ull * phb->phb_id;
    250
    251    pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] = mm0 << 14;
    252    pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] = mm1 << 14;
    253    pbcq->nest_regs[PBCQ_NEST_PHB_BAR] = reg << 14;
    254    pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0] = 0x3fff000000000ull << 14;
    255    pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1] = 0x3ffff80000000ull << 14;
    256    pbcq->pci_regs[PBCQ_PCI_BAR2] = reg << 14;
    257}
    258
    259static void pnv_pbcq_realize(DeviceState *dev, Error **errp)
    260{
    261    PnvPBCQState *pbcq = PNV_PBCQ(dev);
    262    PnvPHB3 *phb;
    263    char name[32];
    264
    265    assert(pbcq->phb);
    266    phb = pbcq->phb;
    267
    268    /* TODO: Fix OPAL to do that: establish default BAR values */
    269    pnv_pbcq_default_bars(pbcq);
    270
    271    /* Initialize the XSCOM region for the PBCQ registers */
    272    snprintf(name, sizeof(name), "xscom-pbcq-nest-%d.%d",
    273             phb->chip_id, phb->phb_id);
    274    pnv_xscom_region_init(&pbcq->xscom_nest_regs, OBJECT(dev),
    275                          &pnv_pbcq_nest_xscom_ops, pbcq, name,
    276                          PNV_XSCOM_PBCQ_NEST_SIZE);
    277    snprintf(name, sizeof(name), "xscom-pbcq-pci-%d.%d",
    278             phb->chip_id, phb->phb_id);
    279    pnv_xscom_region_init(&pbcq->xscom_pci_regs, OBJECT(dev),
    280                          &pnv_pbcq_pci_xscom_ops, pbcq, name,
    281                          PNV_XSCOM_PBCQ_PCI_SIZE);
    282    snprintf(name, sizeof(name), "xscom-pbcq-spci-%d.%d",
    283             phb->chip_id, phb->phb_id);
    284    pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
    285                          &pnv_pbcq_spci_xscom_ops, pbcq, name,
    286                          PNV_XSCOM_PBCQ_SPCI_SIZE);
    287}
    288
    289static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt,
    290                             int xscom_offset)
    291{
    292    const char compat[] = "ibm,power8-pbcq";
    293    PnvPHB3 *phb = PNV_PBCQ(dev)->phb;
    294    char *name;
    295    int offset;
    296    uint32_t lpc_pcba = PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id;
    297    uint32_t reg[] = {
    298        cpu_to_be32(lpc_pcba),
    299        cpu_to_be32(PNV_XSCOM_PBCQ_NEST_SIZE),
    300        cpu_to_be32(PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id),
    301        cpu_to_be32(PNV_XSCOM_PBCQ_PCI_SIZE),
    302        cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id),
    303        cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_SIZE)
    304    };
    305
    306    name = g_strdup_printf("pbcq@%x", lpc_pcba);
    307    offset = fdt_add_subnode(fdt, xscom_offset, name);
    308    _FDT(offset);
    309    g_free(name);
    310
    311    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
    312
    313    _FDT((fdt_setprop_cell(fdt, offset, "ibm,phb-index", phb->phb_id)));
    314    _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", phb->chip_id)));
    315    _FDT((fdt_setprop(fdt, offset, "compatible", compat,
    316                      sizeof(compat))));
    317    return 0;
    318}
    319
    320static void phb3_pbcq_instance_init(Object *obj)
    321{
    322    PnvPBCQState *pbcq = PNV_PBCQ(obj);
    323
    324    object_property_add_link(obj, "phb", TYPE_PNV_PHB3,
    325                             (Object **)&pbcq->phb,
    326                             object_property_allow_set_link,
    327                             OBJ_PROP_LINK_STRONG);
    328}
    329
    330static void pnv_pbcq_class_init(ObjectClass *klass, void *data)
    331{
    332    DeviceClass *dc = DEVICE_CLASS(klass);
    333    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
    334
    335    xdc->dt_xscom = pnv_pbcq_dt_xscom;
    336
    337    dc->realize = pnv_pbcq_realize;
    338    dc->user_creatable = false;
    339}
    340
    341static const TypeInfo pnv_pbcq_type_info = {
    342    .name          = TYPE_PNV_PBCQ,
    343    .parent        = TYPE_DEVICE,
    344    .instance_size = sizeof(PnvPBCQState),
    345    .instance_init = phb3_pbcq_instance_init,
    346    .class_init    = pnv_pbcq_class_init,
    347    .interfaces    = (InterfaceInfo[]) {
    348        { TYPE_PNV_XSCOM_INTERFACE },
    349        { }
    350    }
    351};
    352
    353static void pnv_pbcq_register_types(void)
    354{
    355    type_register_static(&pnv_pbcq_type_info);
    356}
    357
    358type_init(pnv_pbcq_register_types)