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

sifive_u_prci.c (5553B)


      1/*
      2 * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt)
      3 *
      4 * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com>
      5 *
      6 * Simple model of the PRCI to emulate register reads made by the SDK BSP
      7 *
      8 * This program is free software; you can redistribute it and/or modify it
      9 * under the terms and conditions of the GNU General Public License,
     10 * version 2 or later, as published by the Free Software Foundation.
     11 *
     12 * This program is distributed in the hope it will be useful, but WITHOUT
     13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     15 * more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along with
     18 * this program.  If not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "hw/sysbus.h"
     23#include "qemu/log.h"
     24#include "qemu/module.h"
     25#include "hw/misc/sifive_u_prci.h"
     26
     27static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size)
     28{
     29    SiFiveUPRCIState *s = opaque;
     30
     31    switch (addr) {
     32    case SIFIVE_U_PRCI_HFXOSCCFG:
     33        return s->hfxosccfg;
     34    case SIFIVE_U_PRCI_COREPLLCFG0:
     35        return s->corepllcfg0;
     36    case SIFIVE_U_PRCI_DDRPLLCFG0:
     37        return s->ddrpllcfg0;
     38    case SIFIVE_U_PRCI_DDRPLLCFG1:
     39        return s->ddrpllcfg1;
     40    case SIFIVE_U_PRCI_GEMGXLPLLCFG0:
     41        return s->gemgxlpllcfg0;
     42    case SIFIVE_U_PRCI_GEMGXLPLLCFG1:
     43        return s->gemgxlpllcfg1;
     44    case SIFIVE_U_PRCI_CORECLKSEL:
     45        return s->coreclksel;
     46    case SIFIVE_U_PRCI_DEVICESRESET:
     47        return s->devicesreset;
     48    case SIFIVE_U_PRCI_CLKMUXSTATUS:
     49        return s->clkmuxstatus;
     50    }
     51
     52    qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
     53                  __func__, addr);
     54
     55    return 0;
     56}
     57
     58static void sifive_u_prci_write(void *opaque, hwaddr addr,
     59                                uint64_t val64, unsigned int size)
     60{
     61    SiFiveUPRCIState *s = opaque;
     62    uint32_t val32 = (uint32_t)val64;
     63
     64    switch (addr) {
     65    case SIFIVE_U_PRCI_HFXOSCCFG:
     66        s->hfxosccfg = val32;
     67        /* OSC stays ready */
     68        s->hfxosccfg |= SIFIVE_U_PRCI_HFXOSCCFG_RDY;
     69        break;
     70    case SIFIVE_U_PRCI_COREPLLCFG0:
     71        s->corepllcfg0 = val32;
     72        /* internal feedback */
     73        s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
     74        /* PLL stays locked */
     75        s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
     76        break;
     77    case SIFIVE_U_PRCI_DDRPLLCFG0:
     78        s->ddrpllcfg0 = val32;
     79        /* internal feedback */
     80        s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
     81        /* PLL stays locked */
     82        s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
     83        break;
     84    case SIFIVE_U_PRCI_DDRPLLCFG1:
     85        s->ddrpllcfg1 = val32;
     86        break;
     87    case SIFIVE_U_PRCI_GEMGXLPLLCFG0:
     88        s->gemgxlpllcfg0 = val32;
     89        /* internal feedback */
     90        s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
     91        /* PLL stays locked */
     92        s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
     93        break;
     94    case SIFIVE_U_PRCI_GEMGXLPLLCFG1:
     95        s->gemgxlpllcfg1 = val32;
     96        break;
     97    case SIFIVE_U_PRCI_CORECLKSEL:
     98        s->coreclksel = val32;
     99        break;
    100    case SIFIVE_U_PRCI_DEVICESRESET:
    101        s->devicesreset = val32;
    102        break;
    103    case SIFIVE_U_PRCI_CLKMUXSTATUS:
    104        s->clkmuxstatus = val32;
    105        break;
    106    default:
    107        qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
    108                      " v=0x%x\n", __func__, addr, val32);
    109    }
    110}
    111
    112static const MemoryRegionOps sifive_u_prci_ops = {
    113    .read = sifive_u_prci_read,
    114    .write = sifive_u_prci_write,
    115    .endianness = DEVICE_NATIVE_ENDIAN,
    116    .valid = {
    117        .min_access_size = 4,
    118        .max_access_size = 4
    119    }
    120};
    121
    122static void sifive_u_prci_realize(DeviceState *dev, Error **errp)
    123{
    124    SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev);
    125
    126    memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_prci_ops, s,
    127                          TYPE_SIFIVE_U_PRCI, SIFIVE_U_PRCI_REG_SIZE);
    128    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
    129}
    130
    131static void sifive_u_prci_reset(DeviceState *dev)
    132{
    133    SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev);
    134
    135    /* Initialize register to power-on-reset values */
    136    s->hfxosccfg = SIFIVE_U_PRCI_HFXOSCCFG_RDY | SIFIVE_U_PRCI_HFXOSCCFG_EN;
    137    s->corepllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
    138                     SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
    139                     SIFIVE_U_PRCI_PLLCFG0_LOCK;
    140    s->ddrpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
    141                    SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
    142                    SIFIVE_U_PRCI_PLLCFG0_LOCK;
    143    s->gemgxlpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
    144                       SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
    145                       SIFIVE_U_PRCI_PLLCFG0_LOCK;
    146    s->coreclksel = SIFIVE_U_PRCI_CORECLKSEL_HFCLK;
    147}
    148
    149static void sifive_u_prci_class_init(ObjectClass *klass, void *data)
    150{
    151    DeviceClass *dc = DEVICE_CLASS(klass);
    152
    153    dc->realize = sifive_u_prci_realize;
    154    dc->reset = sifive_u_prci_reset;
    155}
    156
    157static const TypeInfo sifive_u_prci_info = {
    158    .name          = TYPE_SIFIVE_U_PRCI,
    159    .parent        = TYPE_SYS_BUS_DEVICE,
    160    .instance_size = sizeof(SiFiveUPRCIState),
    161    .class_init    = sifive_u_prci_class_init,
    162};
    163
    164static void sifive_u_prci_register_types(void)
    165{
    166    type_register_static(&sifive_u_prci_info);
    167}
    168
    169type_init(sifive_u_prci_register_types)