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

slavio_misc.c (13620B)


      1/*
      2 * QEMU Sparc SLAVIO aux io port emulation
      3 *
      4 * Copyright (c) 2005 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "hw/irq.h"
     27#include "hw/sysbus.h"
     28#include "migration/vmstate.h"
     29#include "qemu/module.h"
     30#include "sysemu/runstate.h"
     31#include "trace.h"
     32#include "qom/object.h"
     33
     34/*
     35 * This is the auxio port, chip control and system control part of
     36 * chip STP2001 (Slave I/O), also produced as NCR89C105. See
     37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
     38 *
     39 * This also includes the PMC CPU idle controller.
     40 */
     41
     42#define TYPE_SLAVIO_MISC "slavio_misc"
     43OBJECT_DECLARE_SIMPLE_TYPE(MiscState, SLAVIO_MISC)
     44
     45struct MiscState {
     46    SysBusDevice parent_obj;
     47
     48    MemoryRegion cfg_iomem;
     49    MemoryRegion diag_iomem;
     50    MemoryRegion mdm_iomem;
     51    MemoryRegion led_iomem;
     52    MemoryRegion sysctrl_iomem;
     53    MemoryRegion aux1_iomem;
     54    MemoryRegion aux2_iomem;
     55    qemu_irq irq;
     56    qemu_irq fdc_tc;
     57    uint32_t dummy;
     58    uint8_t config;
     59    uint8_t aux1, aux2;
     60    uint8_t diag, mctrl;
     61    uint8_t sysctrl;
     62    uint16_t leds;
     63};
     64
     65#define TYPE_APC "apc"
     66typedef struct APCState APCState;
     67DECLARE_INSTANCE_CHECKER(APCState, APC,
     68                         TYPE_APC)
     69
     70struct APCState {
     71    SysBusDevice parent_obj;
     72
     73    MemoryRegion iomem;
     74    qemu_irq cpu_halt;
     75};
     76
     77#define MISC_SIZE 1
     78#define LED_SIZE 2
     79#define SYSCTRL_SIZE 4
     80
     81#define AUX1_TC        0x02
     82
     83#define AUX2_PWROFF    0x01
     84#define AUX2_PWRINTCLR 0x02
     85#define AUX2_PWRFAIL   0x20
     86
     87#define CFG_PWRINTEN   0x08
     88
     89#define SYS_RESET      0x01
     90#define SYS_RESETSTAT  0x02
     91
     92static void slavio_misc_update_irq(void *opaque)
     93{
     94    MiscState *s = opaque;
     95
     96    if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
     97        trace_slavio_misc_update_irq_raise();
     98        qemu_irq_raise(s->irq);
     99    } else {
    100        trace_slavio_misc_update_irq_lower();
    101        qemu_irq_lower(s->irq);
    102    }
    103}
    104
    105static void slavio_misc_reset(DeviceState *d)
    106{
    107    MiscState *s = SLAVIO_MISC(d);
    108
    109    // Diagnostic and system control registers not cleared in reset
    110    s->config = s->aux1 = s->aux2 = s->mctrl = 0;
    111}
    112
    113static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
    114{
    115    MiscState *s = opaque;
    116
    117    trace_slavio_set_power_fail(power_failing, s->config);
    118    if (power_failing && (s->config & CFG_PWRINTEN)) {
    119        s->aux2 |= AUX2_PWRFAIL;
    120    } else {
    121        s->aux2 &= ~AUX2_PWRFAIL;
    122    }
    123    slavio_misc_update_irq(s);
    124}
    125
    126static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
    127                                  uint64_t val, unsigned size)
    128{
    129    MiscState *s = opaque;
    130
    131    trace_slavio_cfg_mem_writeb(val & 0xff);
    132    s->config = val & 0xff;
    133    slavio_misc_update_irq(s);
    134}
    135
    136static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
    137                                     unsigned size)
    138{
    139    MiscState *s = opaque;
    140    uint32_t ret = 0;
    141
    142    ret = s->config;
    143    trace_slavio_cfg_mem_readb(ret);
    144    return ret;
    145}
    146
    147static const MemoryRegionOps slavio_cfg_mem_ops = {
    148    .read = slavio_cfg_mem_readb,
    149    .write = slavio_cfg_mem_writeb,
    150    .endianness = DEVICE_NATIVE_ENDIAN,
    151    .valid = {
    152        .min_access_size = 1,
    153        .max_access_size = 1,
    154    },
    155};
    156
    157static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
    158                                   uint64_t val, unsigned size)
    159{
    160    MiscState *s = opaque;
    161
    162    trace_slavio_diag_mem_writeb(val & 0xff);
    163    s->diag = val & 0xff;
    164}
    165
    166static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
    167                                      unsigned size)
    168{
    169    MiscState *s = opaque;
    170    uint32_t ret = 0;
    171
    172    ret = s->diag;
    173    trace_slavio_diag_mem_readb(ret);
    174    return ret;
    175}
    176
    177static const MemoryRegionOps slavio_diag_mem_ops = {
    178    .read = slavio_diag_mem_readb,
    179    .write = slavio_diag_mem_writeb,
    180    .endianness = DEVICE_NATIVE_ENDIAN,
    181    .valid = {
    182        .min_access_size = 1,
    183        .max_access_size = 1,
    184    },
    185};
    186
    187static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
    188                                  uint64_t val, unsigned size)
    189{
    190    MiscState *s = opaque;
    191
    192    trace_slavio_mdm_mem_writeb(val & 0xff);
    193    s->mctrl = val & 0xff;
    194}
    195
    196static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
    197                                     unsigned size)
    198{
    199    MiscState *s = opaque;
    200    uint32_t ret = 0;
    201
    202    ret = s->mctrl;
    203    trace_slavio_mdm_mem_readb(ret);
    204    return ret;
    205}
    206
    207static const MemoryRegionOps slavio_mdm_mem_ops = {
    208    .read = slavio_mdm_mem_readb,
    209    .write = slavio_mdm_mem_writeb,
    210    .endianness = DEVICE_NATIVE_ENDIAN,
    211    .valid = {
    212        .min_access_size = 1,
    213        .max_access_size = 1,
    214    },
    215};
    216
    217static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
    218                                   uint64_t val, unsigned size)
    219{
    220    MiscState *s = opaque;
    221
    222    trace_slavio_aux1_mem_writeb(val & 0xff);
    223    if (val & AUX1_TC) {
    224        // Send a pulse to floppy terminal count line
    225        if (s->fdc_tc) {
    226            qemu_irq_raise(s->fdc_tc);
    227            qemu_irq_lower(s->fdc_tc);
    228        }
    229        val &= ~AUX1_TC;
    230    }
    231    s->aux1 = val & 0xff;
    232}
    233
    234static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
    235                                      unsigned size)
    236{
    237    MiscState *s = opaque;
    238    uint32_t ret = 0;
    239
    240    ret = s->aux1;
    241    trace_slavio_aux1_mem_readb(ret);
    242    return ret;
    243}
    244
    245static const MemoryRegionOps slavio_aux1_mem_ops = {
    246    .read = slavio_aux1_mem_readb,
    247    .write = slavio_aux1_mem_writeb,
    248    .endianness = DEVICE_NATIVE_ENDIAN,
    249    .valid = {
    250        .min_access_size = 1,
    251        .max_access_size = 1,
    252    },
    253};
    254
    255static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
    256                                   uint64_t val, unsigned size)
    257{
    258    MiscState *s = opaque;
    259
    260    val &= AUX2_PWRINTCLR | AUX2_PWROFF;
    261    trace_slavio_aux2_mem_writeb(val & 0xff);
    262    val |= s->aux2 & AUX2_PWRFAIL;
    263    if (val & AUX2_PWRINTCLR) // Clear Power Fail int
    264        val &= AUX2_PWROFF;
    265    s->aux2 = val;
    266    if (val & AUX2_PWROFF)
    267        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
    268    slavio_misc_update_irq(s);
    269}
    270
    271static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
    272                                      unsigned size)
    273{
    274    MiscState *s = opaque;
    275    uint32_t ret = 0;
    276
    277    ret = s->aux2;
    278    trace_slavio_aux2_mem_readb(ret);
    279    return ret;
    280}
    281
    282static const MemoryRegionOps slavio_aux2_mem_ops = {
    283    .read = slavio_aux2_mem_readb,
    284    .write = slavio_aux2_mem_writeb,
    285    .endianness = DEVICE_NATIVE_ENDIAN,
    286    .valid = {
    287        .min_access_size = 1,
    288        .max_access_size = 1,
    289    },
    290};
    291
    292static void apc_mem_writeb(void *opaque, hwaddr addr,
    293                           uint64_t val, unsigned size)
    294{
    295    APCState *s = opaque;
    296
    297    trace_apc_mem_writeb(val & 0xff);
    298    qemu_irq_raise(s->cpu_halt);
    299}
    300
    301static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
    302                              unsigned size)
    303{
    304    uint32_t ret = 0;
    305
    306    trace_apc_mem_readb(ret);
    307    return ret;
    308}
    309
    310static const MemoryRegionOps apc_mem_ops = {
    311    .read = apc_mem_readb,
    312    .write = apc_mem_writeb,
    313    .endianness = DEVICE_NATIVE_ENDIAN,
    314    .valid = {
    315        .min_access_size = 1,
    316        .max_access_size = 1,
    317    }
    318};
    319
    320static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
    321                                         unsigned size)
    322{
    323    MiscState *s = opaque;
    324    uint32_t ret = 0;
    325
    326    switch (addr) {
    327    case 0:
    328        ret = s->sysctrl;
    329        break;
    330    default:
    331        break;
    332    }
    333    trace_slavio_sysctrl_mem_readl(ret);
    334    return ret;
    335}
    336
    337static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
    338                                      uint64_t val, unsigned size)
    339{
    340    MiscState *s = opaque;
    341
    342    trace_slavio_sysctrl_mem_writel(val);
    343    switch (addr) {
    344    case 0:
    345        if (val & SYS_RESET) {
    346            s->sysctrl = SYS_RESETSTAT;
    347            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
    348        }
    349        break;
    350    default:
    351        break;
    352    }
    353}
    354
    355static const MemoryRegionOps slavio_sysctrl_mem_ops = {
    356    .read = slavio_sysctrl_mem_readl,
    357    .write = slavio_sysctrl_mem_writel,
    358    .endianness = DEVICE_NATIVE_ENDIAN,
    359    .valid = {
    360        .min_access_size = 4,
    361        .max_access_size = 4,
    362    },
    363};
    364
    365static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
    366                                     unsigned size)
    367{
    368    MiscState *s = opaque;
    369    uint32_t ret = 0;
    370
    371    switch (addr) {
    372    case 0:
    373        ret = s->leds;
    374        break;
    375    default:
    376        break;
    377    }
    378    trace_slavio_led_mem_readw(ret);
    379    return ret;
    380}
    381
    382static void slavio_led_mem_writew(void *opaque, hwaddr addr,
    383                                  uint64_t val, unsigned size)
    384{
    385    MiscState *s = opaque;
    386
    387    trace_slavio_led_mem_writew(val & 0xffff);
    388    switch (addr) {
    389    case 0:
    390        s->leds = val;
    391        break;
    392    default:
    393        break;
    394    }
    395}
    396
    397static const MemoryRegionOps slavio_led_mem_ops = {
    398    .read = slavio_led_mem_readw,
    399    .write = slavio_led_mem_writew,
    400    .endianness = DEVICE_NATIVE_ENDIAN,
    401    .valid = {
    402        .min_access_size = 2,
    403        .max_access_size = 2,
    404    },
    405};
    406
    407static const VMStateDescription vmstate_misc = {
    408    .name ="slavio_misc",
    409    .version_id = 1,
    410    .minimum_version_id = 1,
    411    .fields = (VMStateField[]) {
    412        VMSTATE_UINT32(dummy, MiscState),
    413        VMSTATE_UINT8(config, MiscState),
    414        VMSTATE_UINT8(aux1, MiscState),
    415        VMSTATE_UINT8(aux2, MiscState),
    416        VMSTATE_UINT8(diag, MiscState),
    417        VMSTATE_UINT8(mctrl, MiscState),
    418        VMSTATE_UINT8(sysctrl, MiscState),
    419        VMSTATE_END_OF_LIST()
    420    }
    421};
    422
    423static void apc_init(Object *obj)
    424{
    425    APCState *s = APC(obj);
    426    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    427
    428    sysbus_init_irq(dev, &s->cpu_halt);
    429
    430    /* Power management (APC) XXX: not a Slavio device */
    431    memory_region_init_io(&s->iomem, obj, &apc_mem_ops, s,
    432                          "apc", MISC_SIZE);
    433    sysbus_init_mmio(dev, &s->iomem);
    434}
    435
    436static void slavio_misc_init(Object *obj)
    437{
    438    DeviceState *dev = DEVICE(obj);
    439    MiscState *s = SLAVIO_MISC(obj);
    440    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    441
    442    sysbus_init_irq(sbd, &s->irq);
    443    sysbus_init_irq(sbd, &s->fdc_tc);
    444
    445    /* 8 bit registers */
    446    /* Slavio control */
    447    memory_region_init_io(&s->cfg_iomem, obj, &slavio_cfg_mem_ops, s,
    448                          "configuration", MISC_SIZE);
    449    sysbus_init_mmio(sbd, &s->cfg_iomem);
    450
    451    /* Diagnostics */
    452    memory_region_init_io(&s->diag_iomem, obj, &slavio_diag_mem_ops, s,
    453                          "diagnostic", MISC_SIZE);
    454    sysbus_init_mmio(sbd, &s->diag_iomem);
    455
    456    /* Modem control */
    457    memory_region_init_io(&s->mdm_iomem, obj, &slavio_mdm_mem_ops, s,
    458                          "modem", MISC_SIZE);
    459    sysbus_init_mmio(sbd, &s->mdm_iomem);
    460
    461    /* 16 bit registers */
    462    /* ss600mp diag LEDs */
    463    memory_region_init_io(&s->led_iomem, obj, &slavio_led_mem_ops, s,
    464                          "leds", LED_SIZE);
    465    sysbus_init_mmio(sbd, &s->led_iomem);
    466
    467    /* 32 bit registers */
    468    /* System control */
    469    memory_region_init_io(&s->sysctrl_iomem, obj, &slavio_sysctrl_mem_ops, s,
    470                          "system-control", SYSCTRL_SIZE);
    471    sysbus_init_mmio(sbd, &s->sysctrl_iomem);
    472
    473    /* AUX 1 (Misc System Functions) */
    474    memory_region_init_io(&s->aux1_iomem, obj, &slavio_aux1_mem_ops, s,
    475                          "misc-system-functions", MISC_SIZE);
    476    sysbus_init_mmio(sbd, &s->aux1_iomem);
    477
    478    /* AUX 2 (Software Powerdown Control) */
    479    memory_region_init_io(&s->aux2_iomem, obj, &slavio_aux2_mem_ops, s,
    480                          "software-powerdown-control", MISC_SIZE);
    481    sysbus_init_mmio(sbd, &s->aux2_iomem);
    482
    483    qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
    484}
    485
    486static void slavio_misc_class_init(ObjectClass *klass, void *data)
    487{
    488    DeviceClass *dc = DEVICE_CLASS(klass);
    489
    490    dc->reset = slavio_misc_reset;
    491    dc->vmsd = &vmstate_misc;
    492}
    493
    494static const TypeInfo slavio_misc_info = {
    495    .name          = TYPE_SLAVIO_MISC,
    496    .parent        = TYPE_SYS_BUS_DEVICE,
    497    .instance_size = sizeof(MiscState),
    498    .instance_init = slavio_misc_init,
    499    .class_init    = slavio_misc_class_init,
    500};
    501
    502static const TypeInfo apc_info = {
    503    .name          = TYPE_APC,
    504    .parent        = TYPE_SYS_BUS_DEVICE,
    505    .instance_size = sizeof(MiscState),
    506    .instance_init = apc_init,
    507};
    508
    509static void slavio_misc_register_types(void)
    510{
    511    type_register_static(&slavio_misc_info);
    512    type_register_static(&apc_info);
    513}
    514
    515type_init(slavio_misc_register_types)