hw/pcie: Introduce Generic PCI Express Root Port

The Generic Root Port behaves almost the same as the
Intel's IOH device with id 3420, without having
Intel specific attributes.

The device has two purposes:
 (1) Can be used on both X86 and ARM machines.
 (2) It will allow us to tweak the behaviour
    (e.g add vendor-specific PCI capabilities)
     - something that obviously cannot be done
       on a known device.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Andrea Bolognani <abologna@redhat.com>
This commit is contained in:
Marcel Apfelbaum 2017-01-23 21:20:20 +02:00 committed by Michael S. Tsirkin
parent fed23cb4e8
commit f7d6f3fac8
3 changed files with 90 additions and 1 deletions

View file

@ -1,6 +1,6 @@
common-obj-y += pci_bridge_dev.o
common-obj-y += pci_expander_bridge.o
common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o
common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
common-obj-$(CONFIG_IOH3420) += ioh3420.o
common-obj-$(CONFIG_I82801B11) += i82801b11.o

View file

@ -0,0 +1,88 @@
/*
* Generic PCI Express Root Port emulation
*
* Copyright (C) 2017 Red Hat Inc
*
* Authors:
* Marcel Apfelbaum <marcel@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/pci/msix.h"
#include "hw/pci/pcie_port.h"
#define TYPE_GEN_PCIE_ROOT_PORT "pcie-root-port"
#define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100
#define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1
static uint8_t gen_rp_aer_vector(const PCIDevice *d)
{
return 0;
}
static int gen_rp_interrupts_init(PCIDevice *d, Error **errp)
{
int rc;
rc = msix_init_exclusive_bar(d, GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR, 0);
if (rc < 0) {
assert(rc == -ENOTSUP);
error_setg(errp, "Unable to init msix vectors");
} else {
msix_vector_use(d, 0);
}
return rc;
}
static void gen_rp_interrupts_uninit(PCIDevice *d)
{
msix_uninit_exclusive_bar(d);
}
static const VMStateDescription vmstate_rp_dev = {
.name = "pcie-root-port",
.version_id = 1,
.minimum_version_id = 1,
.post_load = pcie_cap_slot_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
}
};
static void gen_rp_dev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
k->vendor_id = PCI_VENDOR_ID_REDHAT;
k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_RP;
dc->desc = "PCI Express Root Port";
dc->vmsd = &vmstate_rp_dev;
rpc->aer_vector = gen_rp_aer_vector;
rpc->interrupts_init = gen_rp_interrupts_init;
rpc->interrupts_uninit = gen_rp_interrupts_uninit;
rpc->aer_offset = GEN_PCIE_ROOT_PORT_AER_OFFSET;
}
static const TypeInfo gen_rp_dev_info = {
.name = TYPE_GEN_PCIE_ROOT_PORT,
.parent = TYPE_PCIE_ROOT_PORT,
.class_init = gen_rp_dev_class_init,
};
static void gen_rp_register_types(void)
{
type_register_static(&gen_rp_dev_info);
}
type_init(gen_rp_register_types)

View file

@ -96,6 +96,7 @@
#define PCI_DEVICE_ID_REDHAT_PXB 0x0009
#define PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT 0x000a
#define PCI_DEVICE_ID_REDHAT_PXB_PCIE 0x000b
#define PCI_DEVICE_ID_REDHAT_PCIE_RP 0x000c
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
#define FMT_PCIBUS PRIx64