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_l2x0.c (5097B)


      1/*
      2 * ARM dummy L210, L220, PL310 cache controller.
      3 *
      4 * Copyright (c) 2010-2012 Calxeda
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms and conditions of the GNU General Public License,
      8 * version 2 or any later version, as published by the Free Software
      9 * Foundation.
     10 *
     11 * This program is distributed in the hope it will be useful, but WITHOUT
     12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     14 * more details.
     15 *
     16 * You should have received a copy of the GNU General Public License along with
     17 * this program.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "hw/qdev-properties.h"
     23#include "hw/sysbus.h"
     24#include "migration/vmstate.h"
     25#include "qemu/log.h"
     26#include "qemu/module.h"
     27#include "qom/object.h"
     28
     29/* L2C-310 r3p2 */
     30#define CACHE_ID 0x410000c8
     31
     32#define TYPE_ARM_L2X0 "l2x0"
     33OBJECT_DECLARE_SIMPLE_TYPE(L2x0State, ARM_L2X0)
     34
     35struct L2x0State {
     36    SysBusDevice parent_obj;
     37
     38    MemoryRegion iomem;
     39    uint32_t cache_type;
     40    uint32_t ctrl;
     41    uint32_t aux_ctrl;
     42    uint32_t data_ctrl;
     43    uint32_t tag_ctrl;
     44    uint32_t filter_start;
     45    uint32_t filter_end;
     46};
     47
     48static const VMStateDescription vmstate_l2x0 = {
     49    .name = "l2x0",
     50    .version_id = 1,
     51    .minimum_version_id = 1,
     52    .fields = (VMStateField[]) {
     53        VMSTATE_UINT32(ctrl, L2x0State),
     54        VMSTATE_UINT32(aux_ctrl, L2x0State),
     55        VMSTATE_UINT32(data_ctrl, L2x0State),
     56        VMSTATE_UINT32(tag_ctrl, L2x0State),
     57        VMSTATE_UINT32(filter_start, L2x0State),
     58        VMSTATE_UINT32(filter_end, L2x0State),
     59        VMSTATE_END_OF_LIST()
     60    }
     61};
     62
     63
     64static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
     65                               unsigned size)
     66{
     67    uint32_t cache_data;
     68    L2x0State *s = (L2x0State *)opaque;
     69    offset &= 0xfff;
     70    if (offset >= 0x730 && offset < 0x800) {
     71        return 0; /* cache ops complete */
     72    }
     73    switch (offset) {
     74    case 0:
     75        return CACHE_ID;
     76    case 0x4:
     77        /* aux_ctrl values affect cache_type values */
     78        cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
     79        cache_data |= (s->aux_ctrl & (1 << 16)) >> 16;
     80        return s->cache_type |= (cache_data << 18) | (cache_data << 6);
     81    case 0x100:
     82        return s->ctrl;
     83    case 0x104:
     84        return s->aux_ctrl;
     85    case 0x108:
     86        return s->tag_ctrl;
     87    case 0x10C:
     88        return s->data_ctrl;
     89    case 0xC00:
     90        return s->filter_start;
     91    case 0xC04:
     92        return s->filter_end;
     93    case 0xF40:
     94        return 0;
     95    case 0xF60:
     96        return 0;
     97    case 0xF80:
     98        return 0;
     99    default:
    100        qemu_log_mask(LOG_GUEST_ERROR,
    101                      "l2x0_priv_read: Bad offset %x\n", (int)offset);
    102        break;
    103    }
    104    return 0;
    105}
    106
    107static void l2x0_priv_write(void *opaque, hwaddr offset,
    108                            uint64_t value, unsigned size)
    109{
    110    L2x0State *s = (L2x0State *)opaque;
    111    offset &= 0xfff;
    112    if (offset >= 0x730 && offset < 0x800) {
    113        /* ignore */
    114        return;
    115    }
    116    switch (offset) {
    117    case 0x100:
    118        s->ctrl = value & 1;
    119        break;
    120    case 0x104:
    121        s->aux_ctrl = value;
    122        break;
    123    case 0x108:
    124        s->tag_ctrl = value;
    125        break;
    126    case 0x10C:
    127        s->data_ctrl = value;
    128        break;
    129    case 0xC00:
    130        s->filter_start = value;
    131        break;
    132    case 0xC04:
    133        s->filter_end = value;
    134        break;
    135    case 0xF40:
    136        return;
    137    case 0xF60:
    138        return;
    139    case 0xF80:
    140        return;
    141    default:
    142        qemu_log_mask(LOG_GUEST_ERROR,
    143                      "l2x0_priv_write: Bad offset %x\n", (int)offset);
    144        break;
    145    }
    146}
    147
    148static void l2x0_priv_reset(DeviceState *dev)
    149{
    150    L2x0State *s = ARM_L2X0(dev);
    151
    152    s->ctrl = 0;
    153    s->aux_ctrl = 0x02020000;
    154    s->tag_ctrl = 0;
    155    s->data_ctrl = 0;
    156    s->filter_start = 0;
    157    s->filter_end = 0;
    158}
    159
    160static const MemoryRegionOps l2x0_mem_ops = {
    161    .read = l2x0_priv_read,
    162    .write = l2x0_priv_write,
    163    .endianness = DEVICE_NATIVE_ENDIAN,
    164 };
    165
    166static void l2x0_priv_init(Object *obj)
    167{
    168    L2x0State *s = ARM_L2X0(obj);
    169    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    170
    171    memory_region_init_io(&s->iomem, obj, &l2x0_mem_ops, s,
    172                          "l2x0_cc", 0x1000);
    173    sysbus_init_mmio(dev, &s->iomem);
    174}
    175
    176static Property l2x0_properties[] = {
    177    DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100),
    178    DEFINE_PROP_END_OF_LIST(),
    179};
    180
    181static void l2x0_class_init(ObjectClass *klass, void *data)
    182{
    183    DeviceClass *dc = DEVICE_CLASS(klass);
    184
    185    dc->vmsd = &vmstate_l2x0;
    186    device_class_set_props(dc, l2x0_properties);
    187    dc->reset = l2x0_priv_reset;
    188}
    189
    190static const TypeInfo l2x0_info = {
    191    .name = TYPE_ARM_L2X0,
    192    .parent = TYPE_SYS_BUS_DEVICE,
    193    .instance_size = sizeof(L2x0State),
    194    .instance_init = l2x0_priv_init,
    195    .class_init = l2x0_class_init,
    196};
    197
    198static void l2x0_register_types(void)
    199{
    200    type_register_static(&l2x0_info);
    201}
    202
    203type_init(l2x0_register_types)