qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v1 2/3] hw/pci: Add PCIe RCEC support


From: Mayuresh Chitale
Subject: [RFC PATCH v1 2/3] hw/pci: Add PCIe RCEC support
Date: Thu, 9 Sep 2021 16:32:20 +0530

This patch adds support for PCIe Root Complex Event Collector
(RCEC) emulation. Further, if a RCiEP supports AER capability
then a mapping is created for that RCiEP in the RCEC's
endpoint association capability.

Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
---
 hw/pci/meson.build         |   2 +-
 hw/pci/pcie.c              |  18 ++++++
 hw/pci/pcie_aer.c          |   9 +++
 hw/pci/pcie_rcec.c         | 119 +++++++++++++++++++++++++++++++++++++
 include/hw/pci/pci.h       |   1 +
 include/hw/pci/pci_ids.h   |   1 +
 include/hw/pci/pcie.h      |   1 +
 include/hw/pci/pcie_regs.h |   3 +
 8 files changed, 153 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci/pcie_rcec.c

diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index 5c4bbac817..34ae7d4a44 100644
--- a/hw/pci/meson.build
+++ b/hw/pci/meson.build
@@ -11,7 +11,7 @@ pci_ss.add(files(
 # The functions in these modules can be used by devices too.  Since we
 # allow plugging PCIe devices into PCI buses, include them even if
 # CONFIG_PCI_EXPRESS=n.
-pci_ss.add(files('pcie.c', 'pcie_aer.c'))
+pci_ss.add(files('pcie.c', 'pcie_aer.c', 'pcie_rcec.c'))
 softmmu_ss.add(when: 'CONFIG_PCI_EXPRESS', if_true: files('pcie_port.c', 
'pcie_host.c'))
 softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
 
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 017d5075ae..55938a1798 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -747,6 +747,24 @@ void pcie_cap_slot_push_attention_button(PCIDevice *dev)
     pcie_cap_slot_event(dev, PCI_EXP_HP_EV_ABP);
 }
 
+void pcie_rcec_ep_map(PCIDevice *dev)
+{
+    int devnum = PCI_SLOT(dev->devfn);
+    uint32_t ep_bitmap;
+    PCIDevice *rcec;
+    uint16_t cap;
+
+    /* RCEC is always expected to be at 00:01.0 */
+    rcec = pci_find_device(pci_get_bus(dev), 0, PCI_DEVFN(1,0));
+    if (!rcec)
+        return;
+
+    pcie_cap_deverr_init(dev);
+    cap = pcie_find_capability(rcec, PCI_EXT_CAP_ID_RCEC);
+    ep_bitmap = pci_get_long(rcec->config + cap + 0x4);
+    pci_set_long(rcec->config + cap + 0x4, ep_bitmap | 1 << devnum);
+}
+
 /* root control/capabilities/status. PME isn't emulated for now */
 void pcie_cap_root_init(PCIDevice *dev)
 {
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 27f9cc56af..ba4a1e6d78 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -166,6 +166,15 @@ int pcie_aer_init(PCIDevice *dev, uint8_t cap_ver, 
uint16_t offset,
         /* nothing */
         break;
     }
+
+    /*
+     * If this is a RCiEP, map it into the RCEC's endpoint association bitmap
+     * capability
+     */
+    if (pci_bus_is_express(pci_get_bus(dev))
+        && pci_bus_is_root(pci_get_bus(dev)))
+           pcie_rcec_ep_map(dev);
+
     return 0;
 }
 
diff --git a/hw/pci/pcie_rcec.c b/hw/pci/pcie_rcec.c
new file mode 100644
index 0000000000..9a51d7b9b4
--- /dev/null
+++ b/hw/pci/pcie_rcec.c
@@ -0,0 +1,119 @@
+/*
+ * pcie_rcec.c
+ * PCIe Root Complex Event Collector emulation
+ *
+ * Copyright (c) 2021 Mayuresh Chitale <mchitale@ventanamicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/module.h"
+#include "qemu/range.h"
+#include "sysemu/sysemu.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+
+#define TYPE_RCEC_DEVICE "pcie-rcec"
+#define PCIE_RCEC_EXP_CAP_OFF 0x40
+#define PCIE_RCEC_EP_ECAP_OFF 0x100
+#define PCIE_RCEC_AER_ECAP_OFF 0x120
+
+struct RcecState {
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+};
+
+
+static int pcie_rcec_cap_init(PCIDevice *dev, uint8_t offset)
+{
+    int rc;
+
+    dev->config[PCI_INTERRUPT_PIN] = 1;
+    rc = pcie_endpoint_cap_common_init(dev, offset,
+            PCI_EXP_VER2_SIZEOF, PCI_EXP_TYPE_RC_EC);
+    pcie_cap_root_init(dev);
+    pcie_cap_deverr_init(dev);
+
+    return rc;
+}
+
+static void pcie_rcec_ep_cap_init(PCIDevice *dev, uint8_t cap_ver, uint16_t 
offset,
+                  uint16_t size, Error **errp)
+{
+    pcie_add_capability(dev, PCI_EXT_CAP_ID_RCEC, cap_ver, offset, size);
+    /* Map device (bit) 1 which is RCEC by default */
+    pci_set_long(dev->config + offset + 0x4, 0x2);
+}
+
+static void pcie_rcec_realize(PCIDevice *pci_dev, Error **errp)
+{
+    if (pcie_rcec_cap_init(pci_dev, PCIE_RCEC_EXP_CAP_OFF) < 0)
+        hw_error("Failed to initialize RCEC express capability");
+
+    pcie_rcec_ep_cap_init(pci_dev, PCI_RCEC_EP_VER, PCIE_RCEC_EP_ECAP_OFF,
+        PCI_RCEC_EP_SIZEOF, errp);
+
+    if (pcie_aer_init(pci_dev, PCI_ERR_VER, PCIE_RCEC_AER_ECAP_OFF,
+        PCI_ERR_SIZEOF, errp) < 0)
+        hw_error("Failed to initialize RCEC AER capability");
+}
+
+static const VMStateDescription vmstate_rcec = {
+    .name = "rcec",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(parent_obj, struct RcecState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void rcec_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+    dc->desc = "QEMU generic RCEC";
+    dc->vmsd = &vmstate_rcec;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT;
+    k->device_id = PCI_DEVICE_ID_REDHAT_RCEC;
+    k->revision = 0;
+    k->class_id = PCI_CLASS_SYSTEM_RCEC;
+    k->realize = pcie_rcec_realize;
+}
+
+static const TypeInfo pcie_rcec_info = {
+    .name = TYPE_RCEC_DEVICE,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct RcecState),
+    .class_init = rcec_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { INTERFACE_PCIE_DEVICE },
+        { },
+    },
+};
+
+
+static void pcie_rcec_register_types(void)
+{
+    type_register_static(&pcie_rcec_info);
+}
+
+type_init(pcie_rcec_register_types)
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index d0f4266e37..d580c9e6cf 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -109,6 +109,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_NVME        0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC     0x0011
 #define PCI_DEVICE_ID_REDHAT_QXL         0x0100
+#define PCI_DEVICE_ID_REDHAT_RCEC        0x0101
 
 #define FMT_PCIBUS                      PRIx64
 
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index 11abe22d46..d5214d2764 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -88,6 +88,7 @@
 #define PCI_CLASS_SYSTEM_RTC             0x0803
 #define PCI_CLASS_SYSTEM_PCI_HOTPLUG     0x0804
 #define PCI_CLASS_SYSTEM_SDHCI           0x0805
+#define PCI_CLASS_SYSTEM_RCEC            0x0807
 #define PCI_CLASS_SYSTEM_OTHER           0x0880
 
 #define PCI_BASE_CLASS_INPUT             0x09
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index b40b088604..482fefe704 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -149,4 +149,5 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler 
*hotplug_dev,
                                      DeviceState *dev, Error **errp);
 int pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset,
                                          uint8_t cap_size, uint8_t type);
+void pcie_rcec_ep_map(PCIDevice *dev);
 #endif /* QEMU_PCIE_H */
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 1db86b0ec4..7b8f2616e9 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -179,4 +179,7 @@ typedef enum PCIExpLinkWidth {
 #define PCI_ACS_VER                     0x1
 #define PCI_ACS_SIZEOF                  8
 
+#define PCI_RCEC_EP_VER        1
+#define PCI_RCEC_EP_SIZEOF     0x8
+
 #endif /* QEMU_PCIE_REGS_H */
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]