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

zaurus.c (7654B)


      1/*
      2 * Copyright (c) 2006-2008 Openedhand Ltd.
      3 * Written by Andrzej Zaborowski <balrog@zabor.org>
      4 *
      5 * This program is free software; you can redistribute it and/or
      6 * modify it under the terms of the GNU General Public License as
      7 * published by the Free Software Foundation; either version 2 or
      8 * (at your option) version 3 of the License.
      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 along
     16 * with this program; if not, see <http://www.gnu.org/licenses/>.
     17 */
     18
     19#include "qemu/osdep.h"
     20#include "hw/irq.h"
     21#include "hw/arm/sharpsl.h"
     22#include "hw/sysbus.h"
     23#include "migration/vmstate.h"
     24#include "qemu/module.h"
     25#include "qemu/log.h"
     26#include "qom/object.h"
     27
     28/* SCOOP devices */
     29
     30#define TYPE_SCOOP "scoop"
     31OBJECT_DECLARE_SIMPLE_TYPE(ScoopInfo, SCOOP)
     32
     33struct ScoopInfo {
     34    SysBusDevice parent_obj;
     35
     36    qemu_irq handler[16];
     37    MemoryRegion iomem;
     38    uint16_t status;
     39    uint16_t power;
     40    uint32_t gpio_level;
     41    uint32_t gpio_dir;
     42    uint32_t prev_level;
     43
     44    uint16_t mcr;
     45    uint16_t cdr;
     46    uint16_t ccr;
     47    uint16_t irr;
     48    uint16_t imr;
     49    uint16_t isr;
     50};
     51
     52#define SCOOP_MCR	0x00
     53#define SCOOP_CDR	0x04
     54#define SCOOP_CSR	0x08
     55#define SCOOP_CPR	0x0c
     56#define SCOOP_CCR	0x10
     57#define SCOOP_IRR_IRM	0x14
     58#define SCOOP_IMR	0x18
     59#define SCOOP_ISR	0x1c
     60#define SCOOP_GPCR	0x20
     61#define SCOOP_GPWR	0x24
     62#define SCOOP_GPRR	0x28
     63
     64static inline void scoop_gpio_handler_update(ScoopInfo *s) {
     65    uint32_t level, diff;
     66    int bit;
     67    level = s->gpio_level & s->gpio_dir;
     68
     69    for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
     70        bit = ctz32(diff);
     71        qemu_set_irq(s->handler[bit], (level >> bit) & 1);
     72    }
     73
     74    s->prev_level = level;
     75}
     76
     77static uint64_t scoop_read(void *opaque, hwaddr addr,
     78                           unsigned size)
     79{
     80    ScoopInfo *s = (ScoopInfo *) opaque;
     81
     82    switch (addr & 0x3f) {
     83    case SCOOP_MCR:
     84        return s->mcr;
     85    case SCOOP_CDR:
     86        return s->cdr;
     87    case SCOOP_CSR:
     88        return s->status;
     89    case SCOOP_CPR:
     90        return s->power;
     91    case SCOOP_CCR:
     92        return s->ccr;
     93    case SCOOP_IRR_IRM:
     94        return s->irr;
     95    case SCOOP_IMR:
     96        return s->imr;
     97    case SCOOP_ISR:
     98        return s->isr;
     99    case SCOOP_GPCR:
    100        return s->gpio_dir;
    101    case SCOOP_GPWR:
    102    case SCOOP_GPRR:
    103        return s->gpio_level;
    104    default:
    105        qemu_log_mask(LOG_GUEST_ERROR,
    106                      "scoop_read: bad register offset 0x%02" HWADDR_PRIx "\n",
    107                      addr);
    108    }
    109
    110    return 0;
    111}
    112
    113static void scoop_write(void *opaque, hwaddr addr,
    114                        uint64_t value, unsigned size)
    115{
    116    ScoopInfo *s = (ScoopInfo *) opaque;
    117    value &= 0xffff;
    118
    119    switch (addr & 0x3f) {
    120    case SCOOP_MCR:
    121        s->mcr = value;
    122        break;
    123    case SCOOP_CDR:
    124        s->cdr = value;
    125        break;
    126    case SCOOP_CPR:
    127        s->power = value;
    128        if (value & 0x80)
    129            s->power |= 0x8040;
    130        break;
    131    case SCOOP_CCR:
    132        s->ccr = value;
    133        break;
    134    case SCOOP_IRR_IRM:
    135        s->irr = value;
    136        break;
    137    case SCOOP_IMR:
    138        s->imr = value;
    139        break;
    140    case SCOOP_ISR:
    141        s->isr = value;
    142        break;
    143    case SCOOP_GPCR:
    144        s->gpio_dir = value;
    145        scoop_gpio_handler_update(s);
    146        break;
    147    case SCOOP_GPWR:
    148    case SCOOP_GPRR:	/* GPRR is probably R/O in real HW */
    149        s->gpio_level = value & s->gpio_dir;
    150        scoop_gpio_handler_update(s);
    151        break;
    152    default:
    153        qemu_log_mask(LOG_GUEST_ERROR,
    154                      "scoop_write: bad register offset 0x%02" HWADDR_PRIx "\n",
    155                      addr);
    156    }
    157}
    158
    159static const MemoryRegionOps scoop_ops = {
    160    .read = scoop_read,
    161    .write = scoop_write,
    162    .endianness = DEVICE_NATIVE_ENDIAN,
    163};
    164
    165static void scoop_gpio_set(void *opaque, int line, int level)
    166{
    167    ScoopInfo *s = (ScoopInfo *) opaque;
    168
    169    if (level)
    170        s->gpio_level |= (1 << line);
    171    else
    172        s->gpio_level &= ~(1 << line);
    173}
    174
    175static void scoop_init(Object *obj)
    176{
    177    DeviceState *dev = DEVICE(obj);
    178    ScoopInfo *s = SCOOP(obj);
    179    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    180
    181    s->status = 0x02;
    182    qdev_init_gpio_out(dev, s->handler, 16);
    183    qdev_init_gpio_in(dev, scoop_gpio_set, 16);
    184    memory_region_init_io(&s->iomem, obj, &scoop_ops, s, "scoop", 0x1000);
    185
    186    sysbus_init_mmio(sbd, &s->iomem);
    187}
    188
    189static int scoop_post_load(void *opaque, int version_id)
    190{
    191    ScoopInfo *s = (ScoopInfo *) opaque;
    192    int i;
    193    uint32_t level;
    194
    195    level = s->gpio_level & s->gpio_dir;
    196
    197    for (i = 0; i < 16; i++) {
    198        qemu_set_irq(s->handler[i], (level >> i) & 1);
    199    }
    200
    201    s->prev_level = level;
    202
    203    return 0;
    204}
    205
    206static bool is_version_0 (void *opaque, int version_id)
    207{
    208    return version_id == 0;
    209}
    210
    211static bool vmstate_scoop_validate(void *opaque, int version_id)
    212{
    213    ScoopInfo *s = opaque;
    214
    215    return !(s->prev_level & 0xffff0000) &&
    216        !(s->gpio_level & 0xffff0000) &&
    217        !(s->gpio_dir & 0xffff0000);
    218}
    219
    220static const VMStateDescription vmstate_scoop_regs = {
    221    .name = "scoop",
    222    .version_id = 1,
    223    .minimum_version_id = 0,
    224    .post_load = scoop_post_load,
    225    .fields = (VMStateField[]) {
    226        VMSTATE_UINT16(status, ScoopInfo),
    227        VMSTATE_UINT16(power, ScoopInfo),
    228        VMSTATE_UINT32(gpio_level, ScoopInfo),
    229        VMSTATE_UINT32(gpio_dir, ScoopInfo),
    230        VMSTATE_UINT32(prev_level, ScoopInfo),
    231        VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
    232        VMSTATE_UINT16(mcr, ScoopInfo),
    233        VMSTATE_UINT16(cdr, ScoopInfo),
    234        VMSTATE_UINT16(ccr, ScoopInfo),
    235        VMSTATE_UINT16(irr, ScoopInfo),
    236        VMSTATE_UINT16(imr, ScoopInfo),
    237        VMSTATE_UINT16(isr, ScoopInfo),
    238        VMSTATE_UNUSED_TEST(is_version_0, 2),
    239        VMSTATE_END_OF_LIST(),
    240    },
    241};
    242
    243static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
    244{
    245    DeviceClass *dc = DEVICE_CLASS(klass);
    246
    247    dc->desc = "Scoop2 Sharp custom ASIC";
    248    dc->vmsd = &vmstate_scoop_regs;
    249}
    250
    251static const TypeInfo scoop_sysbus_info = {
    252    .name          = TYPE_SCOOP,
    253    .parent        = TYPE_SYS_BUS_DEVICE,
    254    .instance_size = sizeof(ScoopInfo),
    255    .instance_init = scoop_init,
    256    .class_init    = scoop_sysbus_class_init,
    257};
    258
    259static void scoop_register_types(void)
    260{
    261    type_register_static(&scoop_sysbus_info);
    262}
    263
    264type_init(scoop_register_types)
    265
    266/* Write the bootloader parameters memory area.  */
    267
    268#define MAGIC_CHG(a, b, c, d)	((d << 24) | (c << 16) | (b << 8) | a)
    269
    270static struct QEMU_PACKED sl_param_info {
    271    uint32_t comadj_keyword;
    272    int32_t comadj;
    273
    274    uint32_t uuid_keyword;
    275    char uuid[16];
    276
    277    uint32_t touch_keyword;
    278    int32_t touch_xp;
    279    int32_t touch_yp;
    280    int32_t touch_xd;
    281    int32_t touch_yd;
    282
    283    uint32_t adadj_keyword;
    284    int32_t adadj;
    285
    286    uint32_t phad_keyword;
    287    int32_t phadadj;
    288} zaurus_bootparam = {
    289    .comadj_keyword	= MAGIC_CHG('C', 'M', 'A', 'D'),
    290    .comadj		= 125,
    291    .uuid_keyword	= MAGIC_CHG('U', 'U', 'I', 'D'),
    292    .uuid		= { -1 },
    293    .touch_keyword	= MAGIC_CHG('T', 'U', 'C', 'H'),
    294    .touch_xp		= -1,
    295    .adadj_keyword	= MAGIC_CHG('B', 'V', 'A', 'D'),
    296    .adadj		= -1,
    297    .phad_keyword	= MAGIC_CHG('P', 'H', 'A', 'D'),
    298    .phadadj		= 0x01,
    299};
    300
    301void sl_bootparam_write(hwaddr ptr)
    302{
    303    cpu_physical_memory_write(ptr, &zaurus_bootparam,
    304                              sizeof(struct sl_param_info));
    305}