[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 4/6] VFIO: Introduce EEH handler
From: |
Gavin Shan |
Subject: |
[Qemu-ppc] [PATCH 4/6] VFIO: Introduce EEH handler |
Date: |
Wed, 14 May 2014 14:27:27 +1000 |
The patch introduces vfio_eeh_handler(), which is going to handle
EEH RTAS request routed by sPAPR platform.
Signed-off-by: Gavin Shan <address@hidden>
---
hw/misc/vfio.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/misc/vfio.h | 1 +
2 files changed, 112 insertions(+)
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index fdeba9e..3399601 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -224,6 +224,7 @@ typedef struct VFIODevice {
typedef struct VFIOGroup {
int fd;
int groupid;
+ int pe_addr;
VFIOContainer *container;
QLIST_HEAD(, VFIODevice) device_list;
QLIST_ENTRY(VFIOGroup) next;
@@ -3631,6 +3632,7 @@ static VFIOGroup *vfio_get_group(int groupid,
AddressSpace *as)
}
group->groupid = groupid;
+ group->pe_addr = -1;
QLIST_INIT(&group->device_list);
if (vfio_connect_container(group, as)) {
@@ -3969,6 +3971,40 @@ static void vfio_eeh_addr_map(VFIODevice *vdev, bool map)
ioctl(vdev->group->container->fd, VFIO_EEH_INFO, &info);
}
+static VFIODevice *vfio_eeh_dev_find(uint64_t buid, uint32_t bdn)
+{
+ VFIOGroup *group;
+ VFIODevice *vdev;
+ PCIDevice *pdev;
+ PCIBus *rootbus;
+
+ QLIST_FOREACH(group, &group_list, next) {
+ QLIST_FOREACH(vdev, &group->device_list, next) {
+ pdev = &vdev->pdev;
+ rootbus = pci_device_root_bus(pdev);
+ if (rootbus->sysdata == buid &&
+ bdn == ((pci_bus_num(pdev->bus) << 8) | pdev->devfn)) {
+ return vdev;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static VFIOGroup *vfio_eeh_pe_find(uint64_t buid, uint32_t pe_addr)
+{
+ VFIOGroup *group;
+
+ QLIST_FOREACH(group, &group_list, next) {
+ if (group->pe_addr == pe_addr) {
+ return group;
+ }
+ }
+
+ return NULL;
+}
+
static int vfio_initfn(PCIDevice *pdev)
{
VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
@@ -4305,6 +4341,81 @@ put_group_exit:
return -1;
}
+int vfio_eeh_handler(struct vfio_eeh_info *info)
+{
+ int ret = 0;
+ uint64_t buid;
+ uint32_t pe_addr;
+ VFIODevice *vdev;
+ VFIOGroup *group;
+
+ switch (info->op) {
+ case VFIO_EEH_OP_SET_OPTION:
+ if (info->option.option == 1) {
+ vdev = vfio_eeh_dev_find(info->option.buid,
+ info->option.addr >> 8);
+ group = vdev ? vdev->group : NULL;
+ } else {
+ group = vfio_eeh_pe_find(info->option.buid,
+ info->option.addr);
+ }
+
+ if (!group) {
+ return 7;
+ }
+
+ ret = ioctl(group->container->fd, VFIO_EEH_INFO, info);
+ break;
+ case VFIO_EEH_OP_GET_ADDR:
+ vdev = vfio_eeh_dev_find(info->addr.buid,
+ info->addr.cfg_addr >> 8);
+ if (!vdev) {
+ return 7;
+ }
+ group = vdev->group;
+
+ if (info->addr.option == 0) {
+ if (group->pe_addr != -1) {
+ info->addr.ret = group->pe_addr;
+ } else {
+ ret = ioctl(group->container->fd, VFIO_EEH_INFO, info);
+ if (ret == 0) {
+ group->pe_addr = info->addr.ret;
+ }
+ }
+ } else {
+ info->addr.ret = 1;
+ }
+
+ break;
+ case VFIO_EEH_OP_GET_STATE:
+ case VFIO_EEH_OP_PE_RESET:
+ case VFIO_EEH_OP_PE_CONFIG:
+ if (info->op == VFIO_EEH_OP_GET_STATE) {
+ buid = info->state.buid;
+ pe_addr = info->state.pe_addr;
+ } else if (info->op == VFIO_EEH_OP_PE_RESET) {
+ buid = info->reset.buid;
+ pe_addr = info->reset.pe_addr;
+ } else {
+ buid = info->config.buid;
+ pe_addr = info->config.pe_addr;
+ }
+
+ group = vfio_eeh_pe_find(buid, pe_addr);
+ if (!group) {
+ return 7;
+ }
+
+ ret = ioctl(group->container->fd, VFIO_EEH_INFO, info);
+ break;
+ default:
+ ret = 3;
+ }
+
+ return ret;
+}
+
Notifier *vfio_get_kvm_notifier(AddressSpace *as, int32_t groupid,
MemoryRegion *iommu)
{
diff --git a/include/hw/misc/vfio.h b/include/hw/misc/vfio.h
index 53ec665..70ac8c4 100644
--- a/include/hw/misc/vfio.h
+++ b/include/hw/misc/vfio.h
@@ -13,6 +13,7 @@ extern int vfio_container_spapr_set_liobn(AddressSpace *as,
extern int vfio_container_spapr_get_info(AddressSpace *as,
int32_t groupid,
struct vfio_iommu_spapr_tce_info
*info);
+extern int vfio_eeh_handler(struct vfio_eeh_info *info);
struct vfio_kvm_ioctl {
unsigned long request;
--
1.8.3.2
- [Qemu-ppc] [PATCH RFC v3 0/6] EEH Support for VFIO PCI Device, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 3/6] VFIO: EEH address mapping, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 6/6] sPAPR: Support error injection, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 1/6] headers: Sync with Linux header, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 2/6] PCI: Add sysdata to PCI bus, Gavin Shan, 2014/05/14
- [Qemu-ppc] [PATCH 4/6] VFIO: Introduce EEH handler,
Gavin Shan <=
- [Qemu-ppc] [PATCH 5/6] sPAPR: Support EEH RTAS services, Gavin Shan, 2014/05/14