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

can_kvaser_pci.c (9629B)


      1/*
      2 * Kvaser PCI CAN device (SJA1000 based) emulation
      3 *
      4 * Copyright (c) 2013-2014 Jin Yang
      5 * Copyright (c) 2014-2018 Pavel Pisa
      6 *
      7 * Partially based on educational PCIexpress APOHW hardware
      8 * emulator used fro class A0B36APO at CTU FEE course by
      9 *    Rostislav Lisovy and Pavel Pisa
     10 *
     11 * Initial development supported by Google GSoC 2013 from RTEMS project slot
     12 *
     13 * Permission is hereby granted, free of charge, to any person obtaining a copy
     14 * of this software and associated documentation files (the "Software"), to deal
     15 * in the Software without restriction, including without limitation the rights
     16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17 * copies of the Software, and to permit persons to whom the Software is
     18 * furnished to do so, subject to the following conditions:
     19 *
     20 * The above copyright notice and this permission notice shall be included in
     21 * all copies or substantial portions of the Software.
     22 *
     23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     29 * THE SOFTWARE.
     30 */
     31
     32#include "qemu/osdep.h"
     33#include "qemu/event_notifier.h"
     34#include "qemu/module.h"
     35#include "qemu/thread.h"
     36#include "qemu/sockets.h"
     37#include "qapi/error.h"
     38#include "chardev/char.h"
     39#include "hw/irq.h"
     40#include "hw/pci/pci.h"
     41#include "hw/qdev-properties.h"
     42#include "migration/vmstate.h"
     43#include "net/can_emu.h"
     44
     45#include "can_sja1000.h"
     46#include "qom/object.h"
     47
     48#define TYPE_CAN_PCI_DEV "kvaser_pci"
     49
     50typedef struct KvaserPCIState KvaserPCIState;
     51DECLARE_INSTANCE_CHECKER(KvaserPCIState, KVASER_PCI_DEV,
     52                         TYPE_CAN_PCI_DEV)
     53
     54#ifndef KVASER_PCI_VENDOR_ID1
     55#define KVASER_PCI_VENDOR_ID1     0x10e8    /* the PCI device and vendor IDs */
     56#endif
     57
     58#ifndef KVASER_PCI_DEVICE_ID1
     59#define KVASER_PCI_DEVICE_ID1     0x8406
     60#endif
     61
     62#define KVASER_PCI_S5920_RANGE    0x80
     63#define KVASER_PCI_SJA_RANGE      0x80
     64#define KVASER_PCI_XILINX_RANGE   0x8
     65
     66#define KVASER_PCI_BYTES_PER_SJA  0x20
     67
     68#define S5920_OMB                 0x0C
     69#define S5920_IMB                 0x1C
     70#define S5920_MBEF                0x34
     71#define S5920_INTCSR              0x38
     72#define S5920_RCR                 0x3C
     73#define S5920_PTCR                0x60
     74
     75#define S5920_INTCSR_ADDON_INTENABLE_M        0x2000
     76#define S5920_INTCSR_INTERRUPT_ASSERTED_M     0x800000
     77
     78#define KVASER_PCI_XILINX_VERINT  7   /* Lower nibble simulate interrupts,
     79                                         high nibble version number. */
     80
     81#define KVASER_PCI_XILINX_VERSION_NUMBER 13
     82
     83struct KvaserPCIState {
     84    /*< private >*/
     85    PCIDevice       dev;
     86    /*< public >*/
     87    MemoryRegion    s5920_io;
     88    MemoryRegion    sja_io;
     89    MemoryRegion    xilinx_io;
     90
     91    CanSJA1000State sja_state;
     92    qemu_irq        irq;
     93
     94    uint32_t        s5920_intcsr;
     95    uint32_t        s5920_irqstate;
     96
     97    CanBusState     *canbus;
     98};
     99
    100static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level)
    101{
    102    KvaserPCIState *d = (KvaserPCIState *)opaque;
    103
    104    d->s5920_irqstate = level;
    105    if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M) {
    106        pci_set_irq(&d->dev, level);
    107    }
    108}
    109
    110static void kvaser_pci_reset(DeviceState *dev)
    111{
    112    KvaserPCIState *d = KVASER_PCI_DEV(dev);
    113    CanSJA1000State *s = &d->sja_state;
    114
    115    can_sja_hardware_reset(s);
    116}
    117
    118static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr,
    119                                         unsigned size)
    120{
    121    KvaserPCIState *d = opaque;
    122    uint64_t val;
    123
    124    switch (addr) {
    125    case S5920_INTCSR:
    126        val = d->s5920_intcsr;
    127        val &= ~S5920_INTCSR_INTERRUPT_ASSERTED_M;
    128        if (d->s5920_irqstate) {
    129            val |= S5920_INTCSR_INTERRUPT_ASSERTED_M;
    130        }
    131        return val;
    132    }
    133    return 0;
    134}
    135
    136static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t data,
    137                                      unsigned size)
    138{
    139    KvaserPCIState *d = opaque;
    140
    141    switch (addr) {
    142    case S5920_INTCSR:
    143        if (d->s5920_irqstate &&
    144            ((d->s5920_intcsr ^ data) & S5920_INTCSR_ADDON_INTENABLE_M)) {
    145            pci_set_irq(&d->dev, !!(data & S5920_INTCSR_ADDON_INTENABLE_M));
    146        }
    147        d->s5920_intcsr = data;
    148        break;
    149    }
    150}
    151
    152static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned size)
    153{
    154    KvaserPCIState *d = opaque;
    155    CanSJA1000State *s = &d->sja_state;
    156
    157    if (addr >= KVASER_PCI_BYTES_PER_SJA) {
    158        return 0;
    159    }
    160
    161    return can_sja_mem_read(s, addr, size);
    162}
    163
    164static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t data,
    165                                    unsigned size)
    166{
    167    KvaserPCIState *d = opaque;
    168    CanSJA1000State *s = &d->sja_state;
    169
    170    if (addr >= KVASER_PCI_BYTES_PER_SJA) {
    171        return;
    172    }
    173
    174    can_sja_mem_write(s, addr, data, size);
    175}
    176
    177static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr,
    178                                          unsigned size)
    179{
    180    switch (addr) {
    181    case KVASER_PCI_XILINX_VERINT:
    182        return (KVASER_PCI_XILINX_VERSION_NUMBER << 4) | 0;
    183    }
    184
    185    return 0;
    186}
    187
    188static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t data,
    189                             unsigned size)
    190{
    191
    192}
    193
    194static const MemoryRegionOps kvaser_pci_s5920_io_ops = {
    195    .read = kvaser_pci_s5920_io_read,
    196    .write = kvaser_pci_s5920_io_write,
    197    .endianness = DEVICE_LITTLE_ENDIAN,
    198    .impl = {
    199        .min_access_size = 4,
    200        .max_access_size = 4,
    201    },
    202};
    203
    204static const MemoryRegionOps kvaser_pci_sja_io_ops = {
    205    .read = kvaser_pci_sja_io_read,
    206    .write = kvaser_pci_sja_io_write,
    207    .endianness = DEVICE_LITTLE_ENDIAN,
    208    .impl = {
    209        .max_access_size = 1,
    210    },
    211};
    212
    213static const MemoryRegionOps kvaser_pci_xilinx_io_ops = {
    214    .read = kvaser_pci_xilinx_io_read,
    215    .write = kvaser_pci_xilinx_io_write,
    216    .endianness = DEVICE_LITTLE_ENDIAN,
    217    .impl = {
    218        .max_access_size = 1,
    219    },
    220};
    221
    222static void kvaser_pci_realize(PCIDevice *pci_dev, Error **errp)
    223{
    224    KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
    225    CanSJA1000State *s = &d->sja_state;
    226    uint8_t *pci_conf;
    227
    228    pci_conf = pci_dev->config;
    229    pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
    230
    231    d->irq = qemu_allocate_irq(kvaser_pci_irq_handler, d, 0);
    232
    233    can_sja_init(s, d->irq);
    234
    235    if (can_sja_connect_to_bus(s, d->canbus) < 0) {
    236        error_setg(errp, "can_sja_connect_to_bus failed");
    237        return;
    238    }
    239
    240    memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_ops,
    241                          d, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE);
    242    memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops,
    243                          d, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE);
    244    memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_ops,
    245                          d, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE);
    246
    247    pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO,
    248                                            &d->s5920_io);
    249    pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO,
    250                                            &d->sja_io);
    251    pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO,
    252                                            &d->xilinx_io);
    253}
    254
    255static void kvaser_pci_exit(PCIDevice *pci_dev)
    256{
    257    KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
    258    CanSJA1000State *s = &d->sja_state;
    259
    260    can_sja_disconnect(s);
    261
    262    qemu_free_irq(d->irq);
    263}
    264
    265static const VMStateDescription vmstate_kvaser_pci = {
    266    .name = "kvaser_pci",
    267    .version_id = 1,
    268    .minimum_version_id = 1,
    269    .minimum_version_id_old = 1,
    270    .fields = (VMStateField[]) {
    271        VMSTATE_PCI_DEVICE(dev, KvaserPCIState),
    272        /* Load this before sja_state.  */
    273        VMSTATE_UINT32(s5920_intcsr, KvaserPCIState),
    274        VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja,
    275                       CanSJA1000State),
    276        VMSTATE_END_OF_LIST()
    277    }
    278};
    279
    280static void kvaser_pci_instance_init(Object *obj)
    281{
    282    KvaserPCIState *d = KVASER_PCI_DEV(obj);
    283
    284    object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
    285                             (Object **)&d->canbus,
    286                             qdev_prop_allow_set_link_before_realize,
    287                             0);
    288}
    289
    290static void kvaser_pci_class_init(ObjectClass *klass, void *data)
    291{
    292    DeviceClass *dc = DEVICE_CLASS(klass);
    293    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    294
    295    k->realize = kvaser_pci_realize;
    296    k->exit = kvaser_pci_exit;
    297    k->vendor_id = KVASER_PCI_VENDOR_ID1;
    298    k->device_id = KVASER_PCI_DEVICE_ID1;
    299    k->revision = 0x00;
    300    k->class_id = 0x00ff00;
    301    dc->desc = "Kvaser PCICANx";
    302    dc->vmsd = &vmstate_kvaser_pci;
    303    dc->reset = kvaser_pci_reset;
    304    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    305}
    306
    307static const TypeInfo kvaser_pci_info = {
    308    .name          = TYPE_CAN_PCI_DEV,
    309    .parent        = TYPE_PCI_DEVICE,
    310    .instance_size = sizeof(KvaserPCIState),
    311    .class_init    = kvaser_pci_class_init,
    312    .instance_init = kvaser_pci_instance_init,
    313    .interfaces = (InterfaceInfo[]) {
    314        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
    315        { },
    316    },
    317};
    318
    319static void kvaser_pci_register_types(void)
    320{
    321    type_register_static(&kvaser_pci_info);
    322}
    323
    324type_init(kvaser_pci_register_types)