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

mchp_pfsoc_mmuart.c (5161B)


      1/*
      2 * Microchip PolarFire SoC MMUART emulation
      3 *
      4 * Copyright (c) 2020 Wind River Systems, Inc.
      5 *
      6 * Author:
      7 *   Bin Meng <bin.meng@windriver.com>
      8 *
      9 * This program is free software; you can redistribute it and/or
     10 * modify it under the terms of the GNU General Public License as
     11 * published by the Free Software Foundation; either version 2 or
     12 * (at your option) version 3 of the License.
     13 *
     14 * This program is distributed in the hope that it will be useful,
     15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 * GNU General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU General Public License along
     20 * with this program; if not, see <http://www.gnu.org/licenses/>.
     21 */
     22
     23#include "qemu/osdep.h"
     24#include "qemu/log.h"
     25#include "qapi/error.h"
     26#include "migration/vmstate.h"
     27#include "hw/char/mchp_pfsoc_mmuart.h"
     28#include "hw/qdev-properties.h"
     29
     30#define REGS_OFFSET 0x20
     31
     32static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size)
     33{
     34    MchpPfSoCMMUartState *s = opaque;
     35
     36    addr >>= 2;
     37    if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
     38        qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
     39                      __func__, addr << 2);
     40        return 0;
     41    }
     42
     43    return s->reg[addr];
     44}
     45
     46static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr,
     47                                    uint64_t value, unsigned size)
     48{
     49    MchpPfSoCMMUartState *s = opaque;
     50    uint32_t val32 = (uint32_t)value;
     51
     52    addr >>= 2;
     53    if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
     54        qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
     55                      " v=0x%x\n", __func__, addr << 2, val32);
     56        return;
     57    }
     58
     59    s->reg[addr] = val32;
     60}
     61
     62static const MemoryRegionOps mchp_pfsoc_mmuart_ops = {
     63    .read = mchp_pfsoc_mmuart_read,
     64    .write = mchp_pfsoc_mmuart_write,
     65    .endianness = DEVICE_LITTLE_ENDIAN,
     66    .impl = {
     67        .min_access_size = 4,
     68        .max_access_size = 4,
     69    },
     70};
     71
     72static void mchp_pfsoc_mmuart_reset(DeviceState *dev)
     73{
     74    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);
     75
     76    memset(s->reg, 0, sizeof(s->reg));
     77    device_cold_reset(DEVICE(&s->serial_mm));
     78}
     79
     80static void mchp_pfsoc_mmuart_init(Object *obj)
     81{
     82    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(obj);
     83
     84    object_initialize_child(obj, "serial-mm", &s->serial_mm, TYPE_SERIAL_MM);
     85    object_property_add_alias(obj, "chardev", OBJECT(&s->serial_mm), "chardev");
     86}
     87
     88static void mchp_pfsoc_mmuart_realize(DeviceState *dev, Error **errp)
     89{
     90    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);
     91
     92    qdev_prop_set_uint8(DEVICE(&s->serial_mm), "regshift", 2);
     93    qdev_prop_set_uint32(DEVICE(&s->serial_mm), "baudbase", 399193);
     94    qdev_prop_set_uint8(DEVICE(&s->serial_mm), "endianness",
     95                        DEVICE_LITTLE_ENDIAN);
     96    if (!sysbus_realize(SYS_BUS_DEVICE(&s->serial_mm), errp)) {
     97        return;
     98    }
     99
    100    sysbus_pass_irq(SYS_BUS_DEVICE(dev), SYS_BUS_DEVICE(&s->serial_mm));
    101
    102    memory_region_init(&s->container, OBJECT(s), "mchp.pfsoc.mmuart", 0x1000);
    103    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
    104
    105    memory_region_add_subregion(&s->container, 0,
    106                    sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial_mm), 0));
    107
    108    memory_region_init_io(&s->iomem, OBJECT(s), &mchp_pfsoc_mmuart_ops, s,
    109                          "mchp.pfsoc.mmuart.regs", 0x1000 - REGS_OFFSET);
    110    memory_region_add_subregion(&s->container, REGS_OFFSET, &s->iomem);
    111}
    112
    113static const VMStateDescription mchp_pfsoc_mmuart_vmstate = {
    114    .name = "mchp.pfsoc.uart",
    115    .version_id = 0,
    116    .minimum_version_id = 0,
    117    .fields = (VMStateField[]) {
    118        VMSTATE_UINT32_ARRAY(reg, MchpPfSoCMMUartState,
    119                             MCHP_PFSOC_MMUART_REG_COUNT),
    120        VMSTATE_END_OF_LIST()
    121    }
    122};
    123
    124static void mchp_pfsoc_mmuart_class_init(ObjectClass *oc, void *data)
    125{
    126    DeviceClass *dc = DEVICE_CLASS(oc);
    127
    128    dc->realize = mchp_pfsoc_mmuart_realize;
    129    dc->reset = mchp_pfsoc_mmuart_reset;
    130    dc->vmsd = &mchp_pfsoc_mmuart_vmstate;
    131    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
    132}
    133
    134static const TypeInfo mchp_pfsoc_mmuart_info = {
    135    .name          = TYPE_MCHP_PFSOC_UART,
    136    .parent        = TYPE_SYS_BUS_DEVICE,
    137    .instance_size = sizeof(MchpPfSoCMMUartState),
    138    .instance_init = mchp_pfsoc_mmuart_init,
    139    .class_init    = mchp_pfsoc_mmuart_class_init,
    140};
    141
    142static void mchp_pfsoc_mmuart_register_types(void)
    143{
    144    type_register_static(&mchp_pfsoc_mmuart_info);
    145}
    146
    147type_init(mchp_pfsoc_mmuart_register_types)
    148
    149MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
    150                                               hwaddr base,
    151                                               qemu_irq irq, Chardev *chr)
    152{
    153    DeviceState *dev = qdev_new(TYPE_MCHP_PFSOC_UART);
    154    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    155
    156    qdev_prop_set_chr(dev, "chardev", chr);
    157    sysbus_realize(sbd, &error_fatal);
    158
    159    memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(sbd, 0));
    160    sysbus_connect_irq(sbd, 0, irq);
    161
    162    return MCHP_PFSOC_UART(dev);
    163}