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

hcd-ehci-sysbus.c (8765B)


      1/*
      2 * QEMU USB EHCI Emulation
      3 *
      4 * This library is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU Lesser General Public
      6 * License as published by the Free Software Foundation; either
      7 * version 2.1 of the License, or (at your option) any later version.
      8 *
      9 * This library is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12 * Lesser General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU Lesser General Public License
     15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "qemu/osdep.h"
     19#include "hw/qdev-properties.h"
     20#include "hw/usb/hcd-ehci.h"
     21#include "migration/vmstate.h"
     22#include "qemu/module.h"
     23
     24static const VMStateDescription vmstate_ehci_sysbus = {
     25    .name        = "ehci-sysbus",
     26    .version_id  = 2,
     27    .minimum_version_id  = 1,
     28    .fields = (VMStateField[]) {
     29        VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
     30        VMSTATE_END_OF_LIST()
     31    }
     32};
     33
     34static Property ehci_sysbus_properties[] = {
     35    DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
     36    DEFINE_PROP_BOOL("companion-enable", EHCISysBusState, ehci.companion_enable,
     37                     false),
     38    DEFINE_PROP_END_OF_LIST(),
     39};
     40
     41static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp)
     42{
     43    SysBusDevice *d = SYS_BUS_DEVICE(dev);
     44    EHCISysBusState *i = SYS_BUS_EHCI(dev);
     45    EHCIState *s = &i->ehci;
     46
     47    usb_ehci_realize(s, dev, errp);
     48    sysbus_init_irq(d, &s->irq);
     49}
     50
     51static void usb_ehci_sysbus_reset(DeviceState *dev)
     52{
     53    SysBusDevice *d = SYS_BUS_DEVICE(dev);
     54    EHCISysBusState *i = SYS_BUS_EHCI(d);
     55    EHCIState *s = &i->ehci;
     56
     57    ehci_reset(s);
     58}
     59
     60static void ehci_sysbus_init(Object *obj)
     61{
     62    SysBusDevice *d = SYS_BUS_DEVICE(obj);
     63    EHCISysBusState *i = SYS_BUS_EHCI(obj);
     64    SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj);
     65    EHCIState *s = &i->ehci;
     66
     67    s->capsbase = sec->capsbase;
     68    s->opregbase = sec->opregbase;
     69    s->portscbase = sec->portscbase;
     70    s->portnr = sec->portnr;
     71    s->as = &address_space_memory;
     72
     73    usb_ehci_init(s, DEVICE(obj));
     74    sysbus_init_mmio(d, &s->mem);
     75}
     76
     77static void ehci_sysbus_finalize(Object *obj)
     78{
     79    EHCISysBusState *i = SYS_BUS_EHCI(obj);
     80    EHCIState *s = &i->ehci;
     81
     82    usb_ehci_finalize(s);
     83}
     84
     85static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
     86{
     87    DeviceClass *dc = DEVICE_CLASS(klass);
     88    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
     89
     90    sec->portscbase = 0x44;
     91    sec->portnr = NB_PORTS;
     92
     93    dc->realize = usb_ehci_sysbus_realize;
     94    dc->vmsd = &vmstate_ehci_sysbus;
     95    device_class_set_props(dc, ehci_sysbus_properties);
     96    dc->reset = usb_ehci_sysbus_reset;
     97    set_bit(DEVICE_CATEGORY_USB, dc->categories);
     98}
     99
    100static const TypeInfo ehci_type_info = {
    101    .name          = TYPE_SYS_BUS_EHCI,
    102    .parent        = TYPE_SYS_BUS_DEVICE,
    103    .instance_size = sizeof(EHCISysBusState),
    104    .instance_init = ehci_sysbus_init,
    105    .instance_finalize = ehci_sysbus_finalize,
    106    .abstract      = true,
    107    .class_init    = ehci_sysbus_class_init,
    108    .class_size    = sizeof(SysBusEHCIClass),
    109};
    110
    111static void ehci_platform_class_init(ObjectClass *oc, void *data)
    112{
    113    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    114    DeviceClass *dc = DEVICE_CLASS(oc);
    115
    116    sec->capsbase = 0x0;
    117    sec->opregbase = 0x20;
    118    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    119}
    120
    121static const TypeInfo ehci_platform_type_info = {
    122    .name          = TYPE_PLATFORM_EHCI,
    123    .parent        = TYPE_SYS_BUS_EHCI,
    124    .class_init    = ehci_platform_class_init,
    125};
    126
    127static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
    128{
    129    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    130    DeviceClass *dc = DEVICE_CLASS(oc);
    131
    132    sec->capsbase = 0x0;
    133    sec->opregbase = 0x10;
    134    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    135}
    136
    137static const TypeInfo ehci_exynos4210_type_info = {
    138    .name          = TYPE_EXYNOS4210_EHCI,
    139    .parent        = TYPE_SYS_BUS_EHCI,
    140    .class_init    = ehci_exynos4210_class_init,
    141};
    142
    143static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
    144{
    145    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    146    DeviceClass *dc = DEVICE_CLASS(oc);
    147
    148    sec->capsbase = 0x0;
    149    sec->opregbase = 0x10;
    150    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    151}
    152
    153static const TypeInfo ehci_aw_h3_type_info = {
    154    .name          = TYPE_AW_H3_EHCI,
    155    .parent        = TYPE_SYS_BUS_EHCI,
    156    .class_init    = ehci_aw_h3_class_init,
    157};
    158
    159static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
    160{
    161    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    162    DeviceClass *dc = DEVICE_CLASS(oc);
    163
    164    sec->capsbase = 0x0;
    165    sec->opregbase = 0x10;
    166    sec->portscbase = 0x44;
    167    sec->portnr = 1;
    168    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    169}
    170
    171static const TypeInfo ehci_npcm7xx_type_info = {
    172    .name          = TYPE_NPCM7XX_EHCI,
    173    .parent        = TYPE_SYS_BUS_EHCI,
    174    .class_init    = ehci_npcm7xx_class_init,
    175};
    176
    177static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
    178{
    179    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    180    DeviceClass *dc = DEVICE_CLASS(oc);
    181
    182    sec->capsbase = 0x100;
    183    sec->opregbase = 0x140;
    184    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    185}
    186
    187static const TypeInfo ehci_tegra2_type_info = {
    188    .name          = TYPE_TEGRA2_EHCI,
    189    .parent        = TYPE_SYS_BUS_EHCI,
    190    .class_init    = ehci_tegra2_class_init,
    191};
    192
    193static void ehci_ppc4xx_init(Object *o)
    194{
    195    EHCISysBusState *s = SYS_BUS_EHCI(o);
    196
    197    s->ehci.companion_enable = true;
    198}
    199
    200static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
    201{
    202    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    203    DeviceClass *dc = DEVICE_CLASS(oc);
    204
    205    sec->capsbase = 0x0;
    206    sec->opregbase = 0x10;
    207    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    208}
    209
    210static const TypeInfo ehci_ppc4xx_type_info = {
    211    .name          = TYPE_PPC4xx_EHCI,
    212    .parent        = TYPE_SYS_BUS_EHCI,
    213    .class_init    = ehci_ppc4xx_class_init,
    214    .instance_init = ehci_ppc4xx_init,
    215};
    216
    217/*
    218 * Faraday FUSBH200 USB 2.0 EHCI
    219 */
    220
    221/**
    222 * FUSBH200EHCIRegs:
    223 * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
    224 * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
    225 */
    226enum FUSBH200EHCIRegs {
    227    FUSBH200_REG_EOF_ASTR = 0x34,
    228    FUSBH200_REG_BMCSR    = 0x40,
    229};
    230
    231static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
    232{
    233    EHCIState *s = opaque;
    234    hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
    235
    236    switch (off) {
    237    case FUSBH200_REG_EOF_ASTR:
    238        return 0x00000041;
    239    case FUSBH200_REG_BMCSR:
    240        /* High-Speed, VBUS valid, interrupt level-high active */
    241        return (2 << 9) | (1 << 8) | (1 << 3);
    242    }
    243
    244    return 0;
    245}
    246
    247static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
    248                                unsigned size)
    249{
    250}
    251
    252static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
    253    .read = fusbh200_ehci_read,
    254    .write = fusbh200_ehci_write,
    255    .valid.min_access_size = 4,
    256    .valid.max_access_size = 4,
    257    .endianness = DEVICE_LITTLE_ENDIAN,
    258};
    259
    260static void fusbh200_ehci_init(Object *obj)
    261{
    262    EHCISysBusState *i = SYS_BUS_EHCI(obj);
    263    FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
    264    EHCIState *s = &i->ehci;
    265
    266    memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
    267                          "fusbh200", 0x4c);
    268    memory_region_add_subregion(&s->mem,
    269                                s->opregbase + s->portscbase + 4 * s->portnr,
    270                                &f->mem_vendor);
    271}
    272
    273static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
    274{
    275    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
    276    DeviceClass *dc = DEVICE_CLASS(oc);
    277
    278    sec->capsbase = 0x0;
    279    sec->opregbase = 0x10;
    280    sec->portscbase = 0x20;
    281    sec->portnr = 1;
    282    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    283}
    284
    285static const TypeInfo ehci_fusbh200_type_info = {
    286    .name          = TYPE_FUSBH200_EHCI,
    287    .parent        = TYPE_SYS_BUS_EHCI,
    288    .instance_size = sizeof(FUSBH200EHCIState),
    289    .instance_init = fusbh200_ehci_init,
    290    .class_init    = fusbh200_ehci_class_init,
    291};
    292
    293static void ehci_sysbus_register_types(void)
    294{
    295    type_register_static(&ehci_type_info);
    296    type_register_static(&ehci_platform_type_info);
    297    type_register_static(&ehci_exynos4210_type_info);
    298    type_register_static(&ehci_aw_h3_type_info);
    299    type_register_static(&ehci_npcm7xx_type_info);
    300    type_register_static(&ehci_tegra2_type_info);
    301    type_register_static(&ehci_ppc4xx_type_info);
    302    type_register_static(&ehci_fusbh200_type_info);
    303}
    304
    305type_init(ehci_sysbus_register_types)