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

sysbus.c (10308B)


      1/*
      2 *  System (CPU) Bus device support code
      3 *
      4 *  Copyright (c) 2009 CodeSourcery
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "qapi/error.h"
     22#include "qemu/module.h"
     23#include "hw/sysbus.h"
     24#include "monitor/monitor.h"
     25#include "exec/address-spaces.h"
     26
     27static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
     28static char *sysbus_get_fw_dev_path(DeviceState *dev);
     29
     30typedef struct SysBusFind {
     31    void *opaque;
     32    FindSysbusDeviceFunc *func;
     33} SysBusFind;
     34
     35/* Run func() for every sysbus device, traverse the tree for everything else */
     36static int find_sysbus_device(Object *obj, void *opaque)
     37{
     38    SysBusFind *find = opaque;
     39    Object *dev;
     40    SysBusDevice *sbdev;
     41
     42    dev = object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE);
     43    sbdev = (SysBusDevice *)dev;
     44
     45    if (!sbdev) {
     46        /* Container, traverse it for children */
     47        return object_child_foreach(obj, find_sysbus_device, opaque);
     48    }
     49
     50    find->func(sbdev, find->opaque);
     51
     52    return 0;
     53}
     54
     55/*
     56 * Loop through all dynamically created sysbus devices and call
     57 * func() for each instance.
     58 */
     59void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque)
     60{
     61    Object *container;
     62    SysBusFind find = {
     63        .func = func,
     64        .opaque = opaque,
     65    };
     66
     67    /* Loop through all sysbus devices that were spawned outside the machine */
     68    container = container_get(qdev_get_machine(), "/peripheral");
     69    find_sysbus_device(container, &find);
     70    container = container_get(qdev_get_machine(), "/peripheral-anon");
     71    find_sysbus_device(container, &find);
     72}
     73
     74
     75static void system_bus_class_init(ObjectClass *klass, void *data)
     76{
     77    BusClass *k = BUS_CLASS(klass);
     78
     79    k->print_dev = sysbus_dev_print;
     80    k->get_fw_dev_path = sysbus_get_fw_dev_path;
     81}
     82
     83static const TypeInfo system_bus_info = {
     84    .name = TYPE_SYSTEM_BUS,
     85    .parent = TYPE_BUS,
     86    .instance_size = sizeof(BusState),
     87    .class_init = system_bus_class_init,
     88};
     89
     90/* Check whether an IRQ source exists */
     91bool sysbus_has_irq(SysBusDevice *dev, int n)
     92{
     93    char *prop = g_strdup_printf("%s[%d]", SYSBUS_DEVICE_GPIO_IRQ, n);
     94    ObjectProperty *r;
     95
     96    r = object_property_find(OBJECT(dev), prop);
     97    g_free(prop);
     98
     99    return (r != NULL);
    100}
    101
    102bool sysbus_is_irq_connected(SysBusDevice *dev, int n)
    103{
    104    return !!sysbus_get_connected_irq(dev, n);
    105}
    106
    107qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n)
    108{
    109    DeviceState *d = DEVICE(dev);
    110    return qdev_get_gpio_out_connector(d, SYSBUS_DEVICE_GPIO_IRQ, n);
    111}
    112
    113void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
    114{
    115    SysBusDeviceClass *sbd = SYS_BUS_DEVICE_GET_CLASS(dev);
    116
    117    qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq);
    118
    119    if (sbd->connect_irq_notifier) {
    120        sbd->connect_irq_notifier(dev, irq);
    121    }
    122}
    123
    124/* Check whether an MMIO region exists */
    125bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n)
    126{
    127    return (n < dev->num_mmio);
    128}
    129
    130static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
    131                                   bool may_overlap, int priority)
    132{
    133    assert(n >= 0 && n < dev->num_mmio);
    134
    135    if (dev->mmio[n].addr == addr) {
    136        /* ??? region already mapped here.  */
    137        return;
    138    }
    139    if (dev->mmio[n].addr != (hwaddr)-1) {
    140        /* Unregister previous mapping.  */
    141        memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
    142    }
    143    dev->mmio[n].addr = addr;
    144    if (may_overlap) {
    145        memory_region_add_subregion_overlap(get_system_memory(),
    146                                            addr,
    147                                            dev->mmio[n].memory,
    148                                            priority);
    149    }
    150    else {
    151        memory_region_add_subregion(get_system_memory(),
    152                                    addr,
    153                                    dev->mmio[n].memory);
    154    }
    155}
    156
    157void sysbus_mmio_unmap(SysBusDevice *dev, int n)
    158{
    159    assert(n >= 0 && n < dev->num_mmio);
    160
    161    if (dev->mmio[n].addr != (hwaddr)-1) {
    162        memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
    163        dev->mmio[n].addr = (hwaddr)-1;
    164    }
    165}
    166
    167void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
    168{
    169    sysbus_mmio_map_common(dev, n, addr, false, 0);
    170}
    171
    172void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
    173                             int priority)
    174{
    175    sysbus_mmio_map_common(dev, n, addr, true, priority);
    176}
    177
    178/* Request an IRQ source.  The actual IRQ object may be populated later.  */
    179void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
    180{
    181    qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1);
    182}
    183
    184/* Pass IRQs from a target device.  */
    185void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
    186{
    187    qdev_pass_gpios(DEVICE(target), DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ);
    188}
    189
    190void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
    191{
    192    int n;
    193
    194    assert(dev->num_mmio < QDEV_MAX_MMIO);
    195    n = dev->num_mmio++;
    196    dev->mmio[n].addr = -1;
    197    dev->mmio[n].memory = memory;
    198}
    199
    200MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n)
    201{
    202    assert(n >= 0 && n < QDEV_MAX_MMIO);
    203    return dev->mmio[n].memory;
    204}
    205
    206void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size)
    207{
    208    uint32_t i;
    209
    210    for (i = 0; i < size; i++) {
    211        assert(dev->num_pio < QDEV_MAX_PIO);
    212        dev->pio[dev->num_pio++] = ioport++;
    213    }
    214}
    215
    216/* The purpose of preserving this empty realize function
    217 * is to prevent the parent_realize field of some subclasses
    218 * from being set to NULL to break the normal init/realize
    219 * of some devices.
    220 */
    221static void sysbus_device_realize(DeviceState *dev, Error **errp)
    222{
    223}
    224
    225DeviceState *sysbus_create_varargs(const char *name,
    226                                   hwaddr addr, ...)
    227{
    228    DeviceState *dev;
    229    SysBusDevice *s;
    230    va_list va;
    231    qemu_irq irq;
    232    int n;
    233
    234    dev = qdev_new(name);
    235    s = SYS_BUS_DEVICE(dev);
    236    sysbus_realize_and_unref(s, &error_fatal);
    237    if (addr != (hwaddr)-1) {
    238        sysbus_mmio_map(s, 0, addr);
    239    }
    240    va_start(va, addr);
    241    n = 0;
    242    while (1) {
    243        irq = va_arg(va, qemu_irq);
    244        if (!irq) {
    245            break;
    246        }
    247        sysbus_connect_irq(s, n, irq);
    248        n++;
    249    }
    250    va_end(va);
    251    return dev;
    252}
    253
    254bool sysbus_realize(SysBusDevice *dev, Error **errp)
    255{
    256    return qdev_realize(DEVICE(dev), sysbus_get_default(), errp);
    257}
    258
    259bool sysbus_realize_and_unref(SysBusDevice *dev, Error **errp)
    260{
    261    return qdev_realize_and_unref(DEVICE(dev), sysbus_get_default(), errp);
    262}
    263
    264static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
    265{
    266    SysBusDevice *s = SYS_BUS_DEVICE(dev);
    267    hwaddr size;
    268    int i;
    269
    270    for (i = 0; i < s->num_mmio; i++) {
    271        size = memory_region_size(s->mmio[i].memory);
    272        monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
    273                       indent, "", s->mmio[i].addr, size);
    274    }
    275}
    276
    277static char *sysbus_get_fw_dev_path(DeviceState *dev)
    278{
    279    SysBusDevice *s = SYS_BUS_DEVICE(dev);
    280    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(s);
    281    char *addr, *fw_dev_path;
    282
    283    if (sbc->explicit_ofw_unit_address) {
    284        addr = sbc->explicit_ofw_unit_address(s);
    285        if (addr) {
    286            fw_dev_path = g_strdup_printf("%s@%s", qdev_fw_name(dev), addr);
    287            g_free(addr);
    288            return fw_dev_path;
    289        }
    290    }
    291    if (s->num_mmio) {
    292        return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
    293                               s->mmio[0].addr);
    294    }
    295    if (s->num_pio) {
    296        return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
    297    }
    298    return g_strdup(qdev_fw_name(dev));
    299}
    300
    301void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
    302                       MemoryRegion *mem)
    303{
    304    memory_region_add_subregion(get_system_io(), addr, mem);
    305}
    306
    307MemoryRegion *sysbus_address_space(SysBusDevice *dev)
    308{
    309    return get_system_memory();
    310}
    311
    312static void sysbus_device_class_init(ObjectClass *klass, void *data)
    313{
    314    DeviceClass *k = DEVICE_CLASS(klass);
    315    k->realize = sysbus_device_realize;
    316    k->bus_type = TYPE_SYSTEM_BUS;
    317    /*
    318     * device_add plugs devices into a suitable bus.  For "real" buses,
    319     * that actually connects the device.  For sysbus, the connections
    320     * need to be made separately, and device_add can't do that.  The
    321     * device would be left unconnected, and will probably not work
    322     *
    323     * However, a few machines can handle device_add/-device with
    324     * a few specific sysbus devices. In those cases, the device
    325     * subclass needs to override it and set user_creatable=true.
    326     */
    327    k->user_creatable = false;
    328}
    329
    330static const TypeInfo sysbus_device_type_info = {
    331    .name = TYPE_SYS_BUS_DEVICE,
    332    .parent = TYPE_DEVICE,
    333    .instance_size = sizeof(SysBusDevice),
    334    .abstract = true,
    335    .class_size = sizeof(SysBusDeviceClass),
    336    .class_init = sysbus_device_class_init,
    337};
    338
    339static BusState *main_system_bus;
    340
    341static void main_system_bus_create(void)
    342{
    343    /*
    344     * assign main_system_bus before qbus_init()
    345     * in order to make "if (bus != sysbus_get_default())" work
    346     */
    347    main_system_bus = g_malloc0(system_bus_info.instance_size);
    348    qbus_init(main_system_bus, system_bus_info.instance_size,
    349              TYPE_SYSTEM_BUS, NULL, "main-system-bus");
    350    OBJECT(main_system_bus)->free = g_free;
    351}
    352
    353BusState *sysbus_get_default(void)
    354{
    355    if (!main_system_bus) {
    356        main_system_bus_create();
    357    }
    358    return main_system_bus;
    359}
    360
    361static void sysbus_register_types(void)
    362{
    363    type_register_static(&system_bus_info);
    364    type_register_static(&sysbus_device_type_info);
    365}
    366
    367type_init(sysbus_register_types)