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

pcie_host.c (4173B)


      1/*
      2 * pcie_host.c
      3 * utility functions for pci express host bridge.
      4 *
      5 * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
      6 *                    VA Linux Systems Japan K.K.
      7 *
      8 * This program is free software; you can redistribute it and/or modify
      9 * it under the terms of the GNU General Public License as published by
     10 * the Free Software Foundation; either version 2 of the License, or
     11 * (at your option) any later version.
     12
     13 * This program is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 * GNU General Public License for more details.
     17
     18 * You should have received a copy of the GNU General Public License along
     19 * with this program; if not, see <http://www.gnu.org/licenses/>.
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "hw/pci/pci.h"
     24#include "hw/pci/pcie_host.h"
     25#include "qemu/module.h"
     26
     27/* a helper function to get a PCIDevice for a given mmconfig address */
     28static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
     29                                                     uint32_t mmcfg_addr)
     30{
     31    return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
     32                           PCIE_MMCFG_DEVFN(mmcfg_addr));
     33}
     34
     35static void pcie_mmcfg_data_write(void *opaque, hwaddr mmcfg_addr,
     36                                  uint64_t val, unsigned len)
     37{
     38    PCIExpressHost *e = opaque;
     39    PCIBus *s = e->pci.bus;
     40    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
     41    uint32_t addr;
     42    uint32_t limit;
     43
     44    if (!pci_dev) {
     45        return;
     46    }
     47    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
     48    limit = pci_config_size(pci_dev);
     49    pci_host_config_write_common(pci_dev, addr, limit, val, len);
     50}
     51
     52static uint64_t pcie_mmcfg_data_read(void *opaque,
     53                                     hwaddr mmcfg_addr,
     54                                     unsigned len)
     55{
     56    PCIExpressHost *e = opaque;
     57    PCIBus *s = e->pci.bus;
     58    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
     59    uint32_t addr;
     60    uint32_t limit;
     61
     62    if (!pci_dev) {
     63        return ~0x0;
     64    }
     65    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
     66    limit = pci_config_size(pci_dev);
     67    return pci_host_config_read_common(pci_dev, addr, limit, len);
     68}
     69
     70static const MemoryRegionOps pcie_mmcfg_ops = {
     71    .read = pcie_mmcfg_data_read,
     72    .write = pcie_mmcfg_data_write,
     73    .endianness = DEVICE_LITTLE_ENDIAN,
     74};
     75
     76static void pcie_host_init(Object *obj)
     77{
     78    PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
     79
     80    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
     81    memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, "pcie-mmcfg-mmio",
     82                          PCIE_MMCFG_SIZE_MAX);
     83}
     84
     85void pcie_host_mmcfg_unmap(PCIExpressHost *e)
     86{
     87    if (e->base_addr != PCIE_BASE_ADDR_UNMAPPED) {
     88        memory_region_del_subregion(get_system_memory(), &e->mmio);
     89        e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
     90    }
     91}
     92
     93void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size)
     94{
     95    assert(!(size & (size - 1)));       /* power of 2 */
     96    assert(size >= PCIE_MMCFG_SIZE_MIN);
     97    assert(size <= PCIE_MMCFG_SIZE_MAX);
     98    e->size = size;
     99    memory_region_set_size(&e->mmio, e->size);
    100}
    101
    102void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr,
    103                         uint32_t size)
    104{
    105    pcie_host_mmcfg_init(e, size);
    106    e->base_addr = addr;
    107    memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio);
    108}
    109
    110void pcie_host_mmcfg_update(PCIExpressHost *e,
    111                            int enable,
    112                            hwaddr addr,
    113                            uint32_t size)
    114{
    115    memory_region_transaction_begin();
    116    pcie_host_mmcfg_unmap(e);
    117    if (enable) {
    118        pcie_host_mmcfg_map(e, addr, size);
    119    }
    120    memory_region_transaction_commit();
    121}
    122
    123static const TypeInfo pcie_host_type_info = {
    124    .name = TYPE_PCIE_HOST_BRIDGE,
    125    .parent = TYPE_PCI_HOST_BRIDGE,
    126    .abstract = true,
    127    .instance_size = sizeof(PCIExpressHost),
    128    .instance_init = pcie_host_init,
    129};
    130
    131static void pcie_host_register_types(void)
    132{
    133    type_register_static(&pcie_host_type_info);
    134}
    135
    136type_init(pcie_host_register_types)