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

pci-pc.c (5343B)


      1/*
      2 * libqos PCI bindings for PC
      3 *
      4 * Copyright IBM, Corp. 2012-2013
      5 *
      6 * Authors:
      7 *  Anthony Liguori   <aliguori@us.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "libqtest.h"
     15#include "pci-pc.h"
     16#include "qapi/qmp/qdict.h"
     17#include "hw/pci/pci_regs.h"
     18
     19#include "qemu/module.h"
     20
     21#define ACPI_PCIHP_ADDR         0xae00
     22#define PCI_EJ_BASE             0x0008
     23
     24static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
     25{
     26    return qtest_inb(bus->qts, addr);
     27}
     28
     29static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
     30{
     31    qtest_outb(bus->qts, addr, val);
     32}
     33
     34static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
     35{
     36    return qtest_inw(bus->qts, addr);
     37}
     38
     39static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
     40{
     41    qtest_outw(bus->qts, addr, val);
     42}
     43
     44static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
     45{
     46    return qtest_inl(bus->qts, addr);
     47}
     48
     49static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
     50{
     51    qtest_outl(bus->qts, addr, val);
     52}
     53
     54static uint64_t qpci_pc_pio_readq(QPCIBus *bus, uint32_t addr)
     55{
     56    return (uint64_t)qtest_inl(bus->qts, addr) +
     57        ((uint64_t)qtest_inl(bus->qts, addr + 4) << 32);
     58}
     59
     60static void qpci_pc_pio_writeq(QPCIBus *bus, uint32_t addr, uint64_t val)
     61{
     62    qtest_outl(bus->qts, addr, val & 0xffffffff);
     63    qtest_outl(bus->qts, addr + 4, val >> 32);
     64}
     65
     66static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
     67{
     68    qtest_memread(bus->qts, addr, buf, len);
     69}
     70
     71static void qpci_pc_memwrite(QPCIBus *bus, uint32_t addr,
     72                             const void *buf, size_t len)
     73{
     74    qtest_memwrite(bus->qts, addr, buf, len);
     75}
     76
     77static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
     78{
     79    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     80    return qtest_inb(bus->qts, 0xcfc);
     81}
     82
     83static uint16_t qpci_pc_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
     84{
     85    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     86    return qtest_inw(bus->qts, 0xcfc);
     87}
     88
     89static uint32_t qpci_pc_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
     90{
     91    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     92    return qtest_inl(bus->qts, 0xcfc);
     93}
     94
     95static void qpci_pc_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
     96{
     97    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     98    qtest_outb(bus->qts, 0xcfc, value);
     99}
    100
    101static void qpci_pc_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
    102{
    103    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
    104    qtest_outw(bus->qts, 0xcfc, value);
    105}
    106
    107static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
    108{
    109    qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
    110    qtest_outl(bus->qts, 0xcfc, value);
    111}
    112
    113static void *qpci_pc_get_driver(void *obj, const char *interface)
    114{
    115    QPCIBusPC *qpci = obj;
    116    if (!g_strcmp0(interface, "pci-bus")) {
    117        return &qpci->bus;
    118    }
    119    fprintf(stderr, "%s not present in pci-bus-pc\n", interface);
    120    g_assert_not_reached();
    121}
    122
    123void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
    124{
    125    assert(qts);
    126
    127    /* tests can use pci-bus */
    128    qpci->bus.has_buggy_msi = false;
    129
    130    qpci->bus.pio_readb = qpci_pc_pio_readb;
    131    qpci->bus.pio_readw = qpci_pc_pio_readw;
    132    qpci->bus.pio_readl = qpci_pc_pio_readl;
    133    qpci->bus.pio_readq = qpci_pc_pio_readq;
    134
    135    qpci->bus.pio_writeb = qpci_pc_pio_writeb;
    136    qpci->bus.pio_writew = qpci_pc_pio_writew;
    137    qpci->bus.pio_writel = qpci_pc_pio_writel;
    138    qpci->bus.pio_writeq = qpci_pc_pio_writeq;
    139
    140    qpci->bus.memread = qpci_pc_memread;
    141    qpci->bus.memwrite = qpci_pc_memwrite;
    142
    143    qpci->bus.config_readb = qpci_pc_config_readb;
    144    qpci->bus.config_readw = qpci_pc_config_readw;
    145    qpci->bus.config_readl = qpci_pc_config_readl;
    146
    147    qpci->bus.config_writeb = qpci_pc_config_writeb;
    148    qpci->bus.config_writew = qpci_pc_config_writew;
    149    qpci->bus.config_writel = qpci_pc_config_writel;
    150
    151    qpci->bus.qts = qts;
    152    qpci->bus.pio_alloc_ptr = 0xc000;
    153    qpci->bus.mmio_alloc_ptr = 0xE0000000;
    154    qpci->bus.mmio_limit = 0x100000000ULL;
    155
    156    qpci->obj.get_driver = qpci_pc_get_driver;
    157}
    158
    159QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc)
    160{
    161    QPCIBusPC *qpci = g_new0(QPCIBusPC, 1);
    162    qpci_init_pc(qpci, qts, alloc);
    163
    164    return &qpci->bus;
    165}
    166
    167void qpci_free_pc(QPCIBus *bus)
    168{
    169    QPCIBusPC *s;
    170
    171    if (!bus) {
    172        return;
    173    }
    174    s = container_of(bus, QPCIBusPC, bus);
    175
    176    g_free(s);
    177}
    178
    179void qpci_unplug_acpi_device_test(QTestState *qts, const char *id, uint8_t slot)
    180{
    181    QDict *response;
    182
    183    response = qtest_qmp(qts, "{'execute': 'device_del',"
    184                              " 'arguments': {'id': %s}}", id);
    185    g_assert(response);
    186    g_assert(!qdict_haskey(response, "error"));
    187    qobject_unref(response);
    188
    189    qtest_outl(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot);
    190
    191    qtest_qmp_eventwait(qts, "DEVICE_DELETED");
    192}
    193
    194static void qpci_pc_register_nodes(void)
    195{
    196    qos_node_create_driver("pci-bus-pc", NULL);
    197    qos_node_produces("pci-bus-pc", "pci-bus");
    198}
    199
    200libqos_init(qpci_pc_register_nodes);