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_homer.c (12039B)


      1/*
      2 * QEMU PowerPC PowerNV Emulation of a few HOMER related registers
      3 *
      4 * Copyright (c) 2019, IBM Corporation.
      5 *
      6 * This program is free software; you can redistribute it and/or modify
      7 * it under the terms of the GNU General Public License, version 2, as
      8 * published by the Free Software Foundation.
      9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
     17 */
     18
     19#include "qemu/osdep.h"
     20#include "qemu/log.h"
     21#include "qapi/error.h"
     22#include "exec/hwaddr.h"
     23#include "exec/memory.h"
     24#include "sysemu/cpus.h"
     25#include "hw/qdev-core.h"
     26#include "hw/qdev-properties.h"
     27#include "hw/ppc/pnv.h"
     28#include "hw/ppc/pnv_homer.h"
     29#include "hw/ppc/pnv_xscom.h"
     30
     31
     32static bool core_max_array(PnvHomer *homer, hwaddr addr)
     33{
     34    int i;
     35    PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
     36
     37    for (i = 0; i <= homer->chip->nr_cores; i++) {
     38        if (addr == (hmrc->core_max_base + i)) {
     39            return true;
     40       }
     41    }
     42    return false;
     43}
     44
     45/* P8 Pstate table */
     46
     47#define PNV8_OCC_PSTATE_VERSION          0x1f8001
     48#define PNV8_OCC_PSTATE_MIN              0x1f8003
     49#define PNV8_OCC_PSTATE_VALID            0x1f8000
     50#define PNV8_OCC_PSTATE_THROTTLE         0x1f8002
     51#define PNV8_OCC_PSTATE_NOM              0x1f8004
     52#define PNV8_OCC_PSTATE_TURBO            0x1f8005
     53#define PNV8_OCC_PSTATE_ULTRA_TURBO      0x1f8006
     54#define PNV8_OCC_PSTATE_DATA             0x1f8008
     55#define PNV8_OCC_PSTATE_ID_ZERO          0x1f8010
     56#define PNV8_OCC_PSTATE_ID_ONE           0x1f8018
     57#define PNV8_OCC_PSTATE_ID_TWO           0x1f8020
     58#define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER  0x1f8012
     59#define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER  0x1f8013
     60#define PNV8_OCC_PSTATE_ZERO_FREQUENCY   0x1f8014
     61#define PNV8_OCC_PSTATE_ONE_FREQUENCY    0x1f801c
     62#define PNV8_OCC_PSTATE_TWO_FREQUENCY    0x1f8024
     63#define PNV8_CORE_MAX_BASE               0x1f8810
     64
     65
     66static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
     67                                      unsigned size)
     68{
     69    PnvHomer *homer = PNV_HOMER(opaque);
     70
     71    switch (addr) {
     72    case PNV8_OCC_PSTATE_VERSION:
     73    case PNV8_OCC_PSTATE_MIN:
     74    case PNV8_OCC_PSTATE_ID_ZERO:
     75        return 0;
     76    case PNV8_OCC_PSTATE_VALID:
     77    case PNV8_OCC_PSTATE_THROTTLE:
     78    case PNV8_OCC_PSTATE_NOM:
     79    case PNV8_OCC_PSTATE_TURBO:
     80    case PNV8_OCC_PSTATE_ID_ONE:
     81    case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER:
     82    case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER:
     83        return 1;
     84    case PNV8_OCC_PSTATE_ULTRA_TURBO:
     85    case PNV8_OCC_PSTATE_ID_TWO:
     86        return 2;
     87    case PNV8_OCC_PSTATE_DATA:
     88        return 0x1000000000000000;
     89    /* P8 frequency for 0, 1, and 2 pstates */
     90    case PNV8_OCC_PSTATE_ZERO_FREQUENCY:
     91    case PNV8_OCC_PSTATE_ONE_FREQUENCY:
     92    case PNV8_OCC_PSTATE_TWO_FREQUENCY:
     93        return 3000;
     94    }
     95    /* pstate table core max array */
     96    if (core_max_array(homer, addr)) {
     97        return 1;
     98    }
     99    return 0;
    100}
    101
    102static void pnv_power8_homer_write(void *opaque, hwaddr addr,
    103                                   uint64_t val, unsigned size)
    104{
    105    /* callback function defined to homer write */
    106    return;
    107}
    108
    109static const MemoryRegionOps pnv_power8_homer_ops = {
    110    .read = pnv_power8_homer_read,
    111    .write = pnv_power8_homer_write,
    112    .valid.min_access_size = 1,
    113    .valid.max_access_size = 8,
    114    .impl.min_access_size = 1,
    115    .impl.max_access_size = 8,
    116    .endianness = DEVICE_BIG_ENDIAN,
    117};
    118
    119/* P8 PBA BARs */
    120#define PBA_BAR0                     0x00
    121#define PBA_BAR1                     0x01
    122#define PBA_BAR2                     0x02
    123#define PBA_BAR3                     0x03
    124#define PBA_BARMASK0                 0x04
    125#define PBA_BARMASK1                 0x05
    126#define PBA_BARMASK2                 0x06
    127#define PBA_BARMASK3                 0x07
    128
    129static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr,
    130                                          unsigned size)
    131{
    132    PnvHomer *homer = PNV_HOMER(opaque);
    133    PnvChip *chip = homer->chip;
    134    uint32_t reg = addr >> 3;
    135    uint64_t val = 0;
    136
    137    switch (reg) {
    138    case PBA_BAR0:
    139        val = PNV_HOMER_BASE(chip);
    140        break;
    141    case PBA_BARMASK0: /* P8 homer region mask */
    142        val = (PNV_HOMER_SIZE - 1) & 0x300000;
    143        break;
    144    case PBA_BAR3: /* P8 occ common area */
    145        val = PNV_OCC_COMMON_AREA_BASE;
    146        break;
    147    case PBA_BARMASK3: /* P8 occ common area mask */
    148        val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
    149        break;
    150    default:
    151        qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
    152                      HWADDR_PRIx "\n", addr >> 3);
    153    }
    154    return val;
    155}
    156
    157static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr,
    158                                         uint64_t val, unsigned size)
    159{
    160    qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
    161                  HWADDR_PRIx "\n", addr >> 3);
    162}
    163
    164static const MemoryRegionOps pnv_homer_power8_pba_ops = {
    165    .read = pnv_homer_power8_pba_read,
    166    .write = pnv_homer_power8_pba_write,
    167    .valid.min_access_size = 8,
    168    .valid.max_access_size = 8,
    169    .impl.min_access_size = 8,
    170    .impl.max_access_size = 8,
    171    .endianness = DEVICE_BIG_ENDIAN,
    172};
    173
    174static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
    175{
    176    PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
    177
    178    homer->pba_size = PNV_XSCOM_PBA_SIZE;
    179    homer->pba_ops = &pnv_homer_power8_pba_ops;
    180    homer->homer_size = PNV_HOMER_SIZE;
    181    homer->homer_ops = &pnv_power8_homer_ops;
    182    homer->core_max_base = PNV8_CORE_MAX_BASE;
    183}
    184
    185static const TypeInfo pnv_homer_power8_type_info = {
    186    .name          = TYPE_PNV8_HOMER,
    187    .parent        = TYPE_PNV_HOMER,
    188    .instance_size = sizeof(PnvHomer),
    189    .class_init    = pnv_homer_power8_class_init,
    190};
    191
    192/* P9 Pstate table */
    193
    194#define PNV9_OCC_PSTATE_ID_ZERO          0xe2018
    195#define PNV9_OCC_PSTATE_ID_ONE           0xe2020
    196#define PNV9_OCC_PSTATE_ID_TWO           0xe2028
    197#define PNV9_OCC_PSTATE_DATA             0xe2000
    198#define PNV9_OCC_PSTATE_DATA_AREA        0xe2008
    199#define PNV9_OCC_PSTATE_MIN              0xe2003
    200#define PNV9_OCC_PSTATE_NOM              0xe2004
    201#define PNV9_OCC_PSTATE_TURBO            0xe2005
    202#define PNV9_OCC_PSTATE_ULTRA_TURBO      0xe2818
    203#define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO  0xe2006
    204#define PNV9_OCC_PSTATE_MAJOR_VERSION    0xe2001
    205#define PNV9_OCC_OPAL_RUNTIME_DATA       0xe2b85
    206#define PNV9_CHIP_HOMER_IMAGE_POINTER    0x200008
    207#define PNV9_CHIP_HOMER_BASE             0x0
    208#define PNV9_OCC_PSTATE_ZERO_FREQUENCY   0xe201c
    209#define PNV9_OCC_PSTATE_ONE_FREQUENCY    0xe2024
    210#define PNV9_OCC_PSTATE_TWO_FREQUENCY    0xe202c
    211#define PNV9_OCC_ROLE_MASTER_OR_SLAVE    0xe2002
    212#define PNV9_CORE_MAX_BASE               0xe2819
    213
    214
    215static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
    216                                      unsigned size)
    217{
    218    PnvHomer *homer = PNV_HOMER(opaque);
    219
    220    switch (addr) {
    221    case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
    222    case PNV9_OCC_PSTATE_ID_ZERO:
    223        return 0;
    224    case PNV9_OCC_PSTATE_DATA:
    225    case PNV9_OCC_ROLE_MASTER_OR_SLAVE:
    226    case PNV9_OCC_PSTATE_NOM:
    227    case PNV9_OCC_PSTATE_TURBO:
    228    case PNV9_OCC_PSTATE_ID_ONE:
    229    case PNV9_OCC_PSTATE_ULTRA_TURBO:
    230    case PNV9_OCC_OPAL_RUNTIME_DATA:
    231        return 1;
    232    case PNV9_OCC_PSTATE_MIN:
    233    case PNV9_OCC_PSTATE_ID_TWO:
    234        return 2;
    235
    236    /* 3000 khz frequency for 0, 1, and 2 pstates */
    237    case PNV9_OCC_PSTATE_ZERO_FREQUENCY:
    238    case PNV9_OCC_PSTATE_ONE_FREQUENCY:
    239    case PNV9_OCC_PSTATE_TWO_FREQUENCY:
    240        return 3000;
    241    case PNV9_OCC_PSTATE_MAJOR_VERSION:
    242        return 0x90;
    243    case PNV9_CHIP_HOMER_BASE:
    244    case PNV9_OCC_PSTATE_DATA_AREA:
    245    case PNV9_CHIP_HOMER_IMAGE_POINTER:
    246        return 0x1000000000000000;
    247    }
    248    /* pstate table core max array */
    249    if (core_max_array(homer, addr)) {
    250        return 1;
    251    }
    252    return 0;
    253}
    254
    255static void pnv_power9_homer_write(void *opaque, hwaddr addr,
    256                                   uint64_t val, unsigned size)
    257{
    258    /* callback function defined to homer write */
    259    return;
    260}
    261
    262static const MemoryRegionOps pnv_power9_homer_ops = {
    263    .read = pnv_power9_homer_read,
    264    .write = pnv_power9_homer_write,
    265    .valid.min_access_size = 1,
    266    .valid.max_access_size = 8,
    267    .impl.min_access_size = 1,
    268    .impl.max_access_size = 8,
    269    .endianness = DEVICE_BIG_ENDIAN,
    270};
    271
    272static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr,
    273                                          unsigned size)
    274{
    275    PnvHomer *homer = PNV_HOMER(opaque);
    276    PnvChip *chip = homer->chip;
    277    uint32_t reg = addr >> 3;
    278    uint64_t val = 0;
    279
    280    switch (reg) {
    281    case PBA_BAR0:
    282        val = PNV9_HOMER_BASE(chip);
    283        break;
    284    case PBA_BARMASK0: /* P9 homer region mask */
    285        val = (PNV9_HOMER_SIZE - 1) & 0x300000;
    286        break;
    287    case PBA_BAR2: /* P9 occ common area */
    288        val = PNV9_OCC_COMMON_AREA_BASE;
    289        break;
    290    case PBA_BARMASK2: /* P9 occ common area size */
    291        val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
    292        break;
    293    default:
    294        qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
    295                      HWADDR_PRIx "\n", addr >> 3);
    296    }
    297    return val;
    298}
    299
    300static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr,
    301                                         uint64_t val, unsigned size)
    302{
    303    qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
    304                  HWADDR_PRIx "\n", addr >> 3);
    305}
    306
    307static const MemoryRegionOps pnv_homer_power9_pba_ops = {
    308    .read = pnv_homer_power9_pba_read,
    309    .write = pnv_homer_power9_pba_write,
    310    .valid.min_access_size = 8,
    311    .valid.max_access_size = 8,
    312    .impl.min_access_size = 8,
    313    .impl.max_access_size = 8,
    314    .endianness = DEVICE_BIG_ENDIAN,
    315};
    316
    317static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
    318{
    319    PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
    320
    321    homer->pba_size = PNV9_XSCOM_PBA_SIZE;
    322    homer->pba_ops = &pnv_homer_power9_pba_ops;
    323    homer->homer_size = PNV9_HOMER_SIZE;
    324    homer->homer_ops = &pnv_power9_homer_ops;
    325    homer->core_max_base = PNV9_CORE_MAX_BASE;
    326}
    327
    328static const TypeInfo pnv_homer_power9_type_info = {
    329    .name          = TYPE_PNV9_HOMER,
    330    .parent        = TYPE_PNV_HOMER,
    331    .instance_size = sizeof(PnvHomer),
    332    .class_init    = pnv_homer_power9_class_init,
    333};
    334
    335static void pnv_homer_realize(DeviceState *dev, Error **errp)
    336{
    337    PnvHomer *homer = PNV_HOMER(dev);
    338    PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
    339
    340    assert(homer->chip);
    341
    342    pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops,
    343                          homer, "xscom-pba", hmrc->pba_size);
    344
    345    /* homer region */
    346    memory_region_init_io(&homer->regs, OBJECT(dev),
    347                          hmrc->homer_ops, homer, "homer-main-memory",
    348                          hmrc->homer_size);
    349}
    350
    351static Property pnv_homer_properties[] = {
    352    DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
    353    DEFINE_PROP_END_OF_LIST(),
    354};
    355
    356static void pnv_homer_class_init(ObjectClass *klass, void *data)
    357{
    358    DeviceClass *dc = DEVICE_CLASS(klass);
    359
    360    dc->realize = pnv_homer_realize;
    361    dc->desc = "PowerNV HOMER Memory";
    362    device_class_set_props(dc, pnv_homer_properties);
    363    dc->user_creatable = false;
    364}
    365
    366static const TypeInfo pnv_homer_type_info = {
    367    .name          = TYPE_PNV_HOMER,
    368    .parent        = TYPE_DEVICE,
    369    .instance_size = sizeof(PnvHomer),
    370    .class_init    = pnv_homer_class_init,
    371    .class_size    = sizeof(PnvHomerClass),
    372    .abstract      = true,
    373};
    374
    375static void pnv_homer_register_types(void)
    376{
    377    type_register_static(&pnv_homer_type_info);
    378    type_register_static(&pnv_homer_power8_type_info);
    379    type_register_static(&pnv_homer_power9_type_info);
    380}
    381
    382type_init(pnv_homer_register_types);