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

sdhci.c (4907B)


      1/*
      2 * libqos driver framework
      3 *
      4 * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
      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 version 2.1 as published by the Free Software Foundation.
      9 *
     10 * This library is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13 * Lesser General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU Lesser General Public
     16 * License along with this library; if not, see <http://www.gnu.org/licenses/>
     17 */
     18
     19#include "qemu/osdep.h"
     20#include "libqtest.h"
     21#include "qgraph.h"
     22#include "pci.h"
     23#include "qemu/module.h"
     24#include "sdhci.h"
     25#include "hw/pci/pci.h"
     26
     27static void set_qsdhci_fields(QSDHCI *s, uint8_t version, uint8_t baseclock,
     28                              bool sdma, uint64_t reg)
     29{
     30    s->props.version = version;
     31    s->props.baseclock = baseclock;
     32    s->props.capab.sdma = sdma;
     33    s->props.capab.reg = reg;
     34}
     35
     36/* Memory mapped implementation of QSDHCI */
     37
     38static uint16_t sdhci_mm_readw(QSDHCI *s, uint32_t reg)
     39{
     40    QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci);
     41    return qtest_readw(smm->qts, smm->addr + reg);
     42}
     43
     44static uint64_t sdhci_mm_readq(QSDHCI *s, uint32_t reg)
     45{
     46    QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci);
     47    return qtest_readq(smm->qts, smm->addr + reg);
     48}
     49
     50static void sdhci_mm_writeq(QSDHCI *s, uint32_t reg, uint64_t val)
     51{
     52    QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci);
     53    qtest_writeq(smm->qts, smm->addr + reg, val);
     54}
     55
     56static void *sdhci_mm_get_driver(void *obj, const char *interface)
     57{
     58    QSDHCI_MemoryMapped *smm = obj;
     59    if (!g_strcmp0(interface, "sdhci")) {
     60        return &smm->sdhci;
     61    }
     62    fprintf(stderr, "%s not present in generic-sdhci\n", interface);
     63    g_assert_not_reached();
     64}
     65
     66void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts,
     67                       uint32_t addr, QSDHCIProperties *common)
     68{
     69    sdhci->obj.get_driver = sdhci_mm_get_driver;
     70    sdhci->sdhci.readw = sdhci_mm_readw;
     71    sdhci->sdhci.readq = sdhci_mm_readq;
     72    sdhci->sdhci.writeq = sdhci_mm_writeq;
     73    memcpy(&sdhci->sdhci.props, common, sizeof(QSDHCIProperties));
     74    sdhci->addr = addr;
     75    sdhci->qts = qts;
     76}
     77
     78/* PCI implementation of QSDHCI */
     79
     80static uint16_t sdhci_pci_readw(QSDHCI *s, uint32_t reg)
     81{
     82    QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci);
     83    return qpci_io_readw(&spci->dev, spci->mem_bar, reg);
     84}
     85
     86static uint64_t sdhci_pci_readq(QSDHCI *s, uint32_t reg)
     87{
     88    QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci);
     89    return qpci_io_readq(&spci->dev, spci->mem_bar, reg);
     90}
     91
     92static void sdhci_pci_writeq(QSDHCI *s, uint32_t reg, uint64_t val)
     93{
     94    QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci);
     95    return qpci_io_writeq(&spci->dev, spci->mem_bar, reg, val);
     96}
     97
     98static void *sdhci_pci_get_driver(void *object, const char *interface)
     99{
    100    QSDHCI_PCI *spci = object;
    101    if (!g_strcmp0(interface, "sdhci")) {
    102        return &spci->sdhci;
    103    }
    104
    105    fprintf(stderr, "%s not present in sdhci-pci\n", interface);
    106    g_assert_not_reached();
    107}
    108
    109static void sdhci_pci_start_hw(QOSGraphObject *obj)
    110{
    111    QSDHCI_PCI *spci = (QSDHCI_PCI *)obj;
    112    qpci_device_enable(&spci->dev);
    113}
    114
    115static void sdhci_destructor(QOSGraphObject *obj)
    116{
    117    QSDHCI_PCI *spci = (QSDHCI_PCI *)obj;
    118    qpci_iounmap(&spci->dev, spci->mem_bar);
    119}
    120
    121static void *sdhci_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
    122{
    123    QSDHCI_PCI *spci = g_new0(QSDHCI_PCI, 1);
    124    QPCIBus *bus = pci_bus;
    125    uint64_t barsize;
    126
    127    qpci_device_init(&spci->dev, bus, addr);
    128    spci->mem_bar = qpci_iomap(&spci->dev, 0, &barsize);
    129    spci->sdhci.readw = sdhci_pci_readw;
    130    spci->sdhci.readq = sdhci_pci_readq;
    131    spci->sdhci.writeq = sdhci_pci_writeq;
    132    set_qsdhci_fields(&spci->sdhci, 2, 0, 1, 0x057834b4);
    133
    134    spci->obj.get_driver = sdhci_pci_get_driver;
    135    spci->obj.start_hw = sdhci_pci_start_hw;
    136    spci->obj.destructor = sdhci_destructor;
    137    return &spci->obj;
    138}
    139
    140static void qsdhci_register_nodes(void)
    141{
    142    QPCIAddress addr = {
    143        .devfn = QPCI_DEVFN(4, 0),
    144        .vendor_id = PCI_VENDOR_ID_REDHAT,
    145        .device_id = PCI_DEVICE_ID_REDHAT_SDHCI,
    146    };
    147
    148    QOSGraphEdgeOptions opts = {
    149        .extra_device_opts = "addr=04.0",
    150    };
    151
    152    /* generic-sdhci */
    153    qos_node_create_driver("generic-sdhci", NULL);
    154    qos_node_produces("generic-sdhci", "sdhci");
    155
    156    /* sdhci-pci */
    157    add_qpci_address(&opts, &addr);
    158    qos_node_create_driver("sdhci-pci", sdhci_pci_create);
    159    qos_node_produces("sdhci-pci", "sdhci");
    160    qos_node_consumes("sdhci-pci", "pci-bus", &opts);
    161
    162}
    163
    164libqos_init(qsdhci_register_nodes);