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

chipidea.c (5023B)


      1/*
      2 * Copyright (c) 2018, Impinj, Inc.
      3 *
      4 * Chipidea USB block emulation code
      5 *
      6 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
      7 *
      8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      9 * See the COPYING file in the top-level directory.
     10 */
     11
     12#include "qemu/osdep.h"
     13#include "hw/usb/hcd-ehci.h"
     14#include "hw/usb/chipidea.h"
     15#include "qemu/module.h"
     16
     17enum {
     18    CHIPIDEA_USBx_DCIVERSION   = 0x000,
     19    CHIPIDEA_USBx_DCCPARAMS    = 0x004,
     20    CHIPIDEA_USBx_DCCPARAMS_HC = BIT(8),
     21};
     22
     23static uint64_t chipidea_read(void *opaque, hwaddr offset,
     24                               unsigned size)
     25{
     26    return 0;
     27}
     28
     29static void chipidea_write(void *opaque, hwaddr offset,
     30                            uint64_t value, unsigned size)
     31{
     32}
     33
     34static const struct MemoryRegionOps chipidea_ops = {
     35    .read = chipidea_read,
     36    .write = chipidea_write,
     37    .endianness = DEVICE_NATIVE_ENDIAN,
     38    .impl = {
     39        /*
     40         * Our device would not work correctly if the guest was doing
     41         * unaligned access. This might not be a limitation on the
     42         * real device but in practice there is no reason for a guest
     43         * to access this device unaligned.
     44         */
     45        .min_access_size = 4,
     46        .max_access_size = 4,
     47        .unaligned = false,
     48    },
     49};
     50
     51static uint64_t chipidea_dc_read(void *opaque, hwaddr offset,
     52                                 unsigned size)
     53{
     54    switch (offset) {
     55    case CHIPIDEA_USBx_DCIVERSION:
     56        return 0x1;
     57    case CHIPIDEA_USBx_DCCPARAMS:
     58        /*
     59         * Real hardware (at least i.MX7) will also report the
     60         * controller as "Device Capable" (and 8 supported endpoints),
     61         * but there doesn't seem to be much point in doing so, since
     62         * we don't emulate that part.
     63         */
     64        return CHIPIDEA_USBx_DCCPARAMS_HC;
     65    }
     66
     67    return 0;
     68}
     69
     70static void chipidea_dc_write(void *opaque, hwaddr offset,
     71                              uint64_t value, unsigned size)
     72{
     73}
     74
     75static const struct MemoryRegionOps chipidea_dc_ops = {
     76    .read = chipidea_dc_read,
     77    .write = chipidea_dc_write,
     78    .endianness = DEVICE_NATIVE_ENDIAN,
     79    .impl = {
     80        /*
     81         * Our device would not work correctly if the guest was doing
     82         * unaligned access. This might not be a limitation on the real
     83         * device but in practice there is no reason for a guest to access
     84         * this device unaligned.
     85         */
     86        .min_access_size = 4,
     87        .max_access_size = 4,
     88        .unaligned = false,
     89    },
     90};
     91
     92static void chipidea_init(Object *obj)
     93{
     94    EHCIState *ehci = &SYS_BUS_EHCI(obj)->ehci;
     95    ChipideaState *ci = CHIPIDEA(obj);
     96    int i;
     97
     98    for (i = 0; i < ARRAY_SIZE(ci->iomem); i++) {
     99        const struct {
    100            const char *name;
    101            hwaddr offset;
    102            uint64_t size;
    103            const struct MemoryRegionOps *ops;
    104        } regions[ARRAY_SIZE(ci->iomem)] = {
    105            /*
    106             * Registers located between offsets 0x000 and 0xFC
    107             */
    108            {
    109                .name   = TYPE_CHIPIDEA ".misc",
    110                .offset = 0x000,
    111                .size   = 0x100,
    112                .ops    = &chipidea_ops,
    113            },
    114            /*
    115             * Registers located between offsets 0x1A4 and 0x1DC
    116             */
    117            {
    118                .name   = TYPE_CHIPIDEA ".endpoints",
    119                .offset = 0x1A4,
    120                .size   = 0x1DC - 0x1A4 + 4,
    121                .ops    = &chipidea_ops,
    122            },
    123            /*
    124             * USB_x_DCIVERSION and USB_x_DCCPARAMS
    125             */
    126            {
    127                .name   = TYPE_CHIPIDEA ".dc",
    128                .offset = 0x120,
    129                .size   = 8,
    130                .ops    = &chipidea_dc_ops,
    131            },
    132        };
    133
    134        memory_region_init_io(&ci->iomem[i],
    135                              obj,
    136                              regions[i].ops,
    137                              ci,
    138                              regions[i].name,
    139                              regions[i].size);
    140
    141        memory_region_add_subregion(&ehci->mem,
    142                                    regions[i].offset,
    143                                    &ci->iomem[i]);
    144    }
    145}
    146
    147static void chipidea_class_init(ObjectClass *klass, void *data)
    148{
    149    DeviceClass *dc = DEVICE_CLASS(klass);
    150    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
    151
    152    /*
    153     * Offsets used were taken from i.MX7Dual Applications Processor
    154     * Reference Manual, Rev 0.1, p. 3177, Table 11-59
    155     */
    156    sec->capsbase   = 0x100;
    157    sec->opregbase  = 0x140;
    158    sec->portnr     = 1;
    159
    160    set_bit(DEVICE_CATEGORY_USB, dc->categories);
    161    dc->desc = "Chipidea USB Module";
    162}
    163
    164static const TypeInfo chipidea_info = {
    165    .name          = TYPE_CHIPIDEA,
    166    .parent        = TYPE_SYS_BUS_EHCI,
    167    .instance_size = sizeof(ChipideaState),
    168    .instance_init = chipidea_init,
    169    .class_init    = chipidea_class_init,
    170};
    171
    172static void chipidea_register_type(void)
    173{
    174    type_register_static(&chipidea_info);
    175}
    176type_init(chipidea_register_type)