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

arm_gicv3_its_common.c (5145B)


      1/*
      2 * ITS base class for a GICv3-based system
      3 *
      4 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
      5 * Written by Pavel Fedin
      6 *
      7 * This program is free software; you can redistribute it and/or modify
      8 * it under the terms of the GNU General Public License as published by
      9 * the Free Software Foundation, either version 2 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along
     18 * with this program; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "hw/pci/msi.h"
     23#include "migration/vmstate.h"
     24#include "hw/intc/arm_gicv3_its_common.h"
     25#include "qemu/log.h"
     26#include "qemu/module.h"
     27
     28static int gicv3_its_pre_save(void *opaque)
     29{
     30    GICv3ITSState *s = (GICv3ITSState *)opaque;
     31    GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
     32
     33    if (c->pre_save) {
     34        c->pre_save(s);
     35    }
     36
     37    return 0;
     38}
     39
     40static int gicv3_its_post_load(void *opaque, int version_id)
     41{
     42    GICv3ITSState *s = (GICv3ITSState *)opaque;
     43    GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
     44
     45    if (c->post_load) {
     46        c->post_load(s);
     47    }
     48    return 0;
     49}
     50
     51static const VMStateDescription vmstate_its = {
     52    .name = "arm_gicv3_its",
     53    .version_id = 1,
     54    .minimum_version_id = 1,
     55    .pre_save = gicv3_its_pre_save,
     56    .post_load = gicv3_its_post_load,
     57    .priority = MIG_PRI_GICV3_ITS,
     58    .fields = (VMStateField[]) {
     59        VMSTATE_UINT32(ctlr, GICv3ITSState),
     60        VMSTATE_UINT32(iidr, GICv3ITSState),
     61        VMSTATE_UINT64(cbaser, GICv3ITSState),
     62        VMSTATE_UINT64(cwriter, GICv3ITSState),
     63        VMSTATE_UINT64(creadr, GICv3ITSState),
     64        VMSTATE_UINT64_ARRAY(baser, GICv3ITSState, 8),
     65        VMSTATE_END_OF_LIST()
     66    },
     67};
     68
     69static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
     70                                        uint64_t *data, unsigned size,
     71                                        MemTxAttrs attrs)
     72{
     73    qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
     74    *data = 0;
     75    return MEMTX_OK;
     76}
     77
     78static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
     79                                         uint64_t value, unsigned size,
     80                                         MemTxAttrs attrs)
     81{
     82    if (offset == 0x0040 && ((size == 2) || (size == 4))) {
     83        GICv3ITSState *s = ARM_GICV3_ITS_COMMON(opaque);
     84        GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
     85        int ret = c->send_msi(s, le64_to_cpu(value), attrs.requester_id);
     86
     87        if (ret <= 0) {
     88            qemu_log_mask(LOG_GUEST_ERROR,
     89                          "ITS: Error sending MSI: %s\n", strerror(-ret));
     90        }
     91    } else {
     92        qemu_log_mask(LOG_GUEST_ERROR,
     93                      "ITS write at bad offset 0x%"PRIx64"\n", offset);
     94    }
     95    return MEMTX_OK;
     96}
     97
     98static const MemoryRegionOps gicv3_its_trans_ops = {
     99    .read_with_attrs = gicv3_its_trans_read,
    100    .write_with_attrs = gicv3_its_trans_write,
    101    .endianness = DEVICE_NATIVE_ENDIAN,
    102};
    103
    104void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
    105                         const MemoryRegionOps *tops)
    106{
    107    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
    108
    109    memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s,
    110                          "control", ITS_CONTROL_SIZE);
    111    memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
    112                          tops ? tops : &gicv3_its_trans_ops, s,
    113                          "translation", ITS_TRANS_SIZE);
    114
    115    /* Our two regions are always adjacent, therefore we now combine them
    116     * into a single one in order to make our users' life easier.
    117     */
    118    memory_region_init(&s->iomem_main, OBJECT(s), "gicv3_its", ITS_SIZE);
    119    memory_region_add_subregion(&s->iomem_main, 0, &s->iomem_its_cntrl);
    120    memory_region_add_subregion(&s->iomem_main, ITS_CONTROL_SIZE,
    121                                &s->iomem_its_translation);
    122    sysbus_init_mmio(sbd, &s->iomem_main);
    123
    124    msi_nonbroken = true;
    125}
    126
    127static void gicv3_its_common_reset(DeviceState *dev)
    128{
    129    GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
    130
    131    s->ctlr = 0;
    132    s->cbaser = 0;
    133    s->cwriter = 0;
    134    s->creadr = 0;
    135    s->iidr = 0;
    136    memset(&s->baser, 0, sizeof(s->baser));
    137}
    138
    139static void gicv3_its_common_class_init(ObjectClass *klass, void *data)
    140{
    141    DeviceClass *dc = DEVICE_CLASS(klass);
    142
    143    dc->reset = gicv3_its_common_reset;
    144    dc->vmsd = &vmstate_its;
    145}
    146
    147static const TypeInfo gicv3_its_common_info = {
    148    .name = TYPE_ARM_GICV3_ITS_COMMON,
    149    .parent = TYPE_SYS_BUS_DEVICE,
    150    .instance_size = sizeof(GICv3ITSState),
    151    .class_size = sizeof(GICv3ITSCommonClass),
    152    .class_init = gicv3_its_common_class_init,
    153    .abstract = true,
    154};
    155
    156static void gicv3_its_common_register_types(void)
    157{
    158    type_register_static(&gicv3_its_common_info);
    159}
    160
    161type_init(gicv3_its_common_register_types)