* [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest
@ 2015-05-25 10:06 Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 01/13] vfio: extract vfio_get_hot_reset_info as a single function Chen Fan
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
For now, for vfio pci passthough devices when qemu receives
an error from host aer report, there just terminate the guest,
but usually user want to know what error occurred but stop the
guest, so this patches add aer capability support for vfio device,
and pass the error to guest, and have guest driver to recover
from the error.
and turning on SERR# for error forwording in bridge control register
patch in seabios has been merged.
v7-v8:
1. some bug fixes requested by Alex
v6-v7:
1. add has_bus_reset to support reset host bus.
v5-v6:
1. add secondary bus callbacks to reset host bus.
v3-v4:
1. add 'x-aer' for user to off aer capability.
2. refactor vfio device to parse extended capabilities.
v2-v3:
1. refactor vfio device to parse extended capability.
2. add global property for piix4 to disable vfio aer cap.
v1-v2:
1. turn on SERR# for bridge control register in firmware.
2. initilize aer capability for vfio device.
3. fix some trivial bug.
Chen Fan (13):
vfio: extract vfio_get_hot_reset_info as a single function
vfio: squeeze out vfio_pci_do_hot_reset for support bus reset
vfio: add pcie extanded capability support
aer: impove pcie_aer_init to support vfio device
vfio: add aer support for vfio device
vfio: add check host bus reset is support or not
vfio: add check for vfio devices which enable aer should support bus
reset
pci: add bus reset_notifiers callbacks for host bus reset
vfio: add sec_bus_reset notifier to notify physical bus reset is
needed
vfio: do hot bus reset when do virtual secondary bus reset
pcie_aer: expose pcie_aer_msg() interface
vfio-pci: pass the aer error to guest
vfio: add 'aer' property to expose aercap
hw/pci-bridge/ioh3420.c | 2 +-
hw/pci-bridge/xio3130_downstream.c | 2 +-
hw/pci-bridge/xio3130_upstream.c | 2 +-
hw/pci/pci.c | 16 ++
hw/pci/pci_bridge.c | 5 +
hw/pci/pcie_aer.c | 6 +-
hw/vfio/pci.c | 509 +++++++++++++++++++++++++++++++++----
include/hw/pci/pci.h | 4 +
include/hw/pci/pci_bus.h | 2 +
include/hw/pci/pcie_aer.h | 3 +-
10 files changed, 488 insertions(+), 63 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 01/13] vfio: extract vfio_get_hot_reset_info as a single function
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 02/13] vfio: squeeze out vfio_pci_do_hot_reset for support bus reset Chen Fan
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
the function is used to get affected devices by bus reset.
so here extract it, and can used for aer soon.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 67 +++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 49 insertions(+), 18 deletions(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index e0e339a..9c05304 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2641,6 +2641,50 @@ static void vfio_check_af_flr(VFIOPCIDevice *vdev, uint8_t pos)
}
}
+/*
+ * return negative with errno, return 0 on success.
+ * if success, the point of ret_info fill with the affected device reset info.
+ *
+ */
+static int vfio_get_hot_reset_info(VFIOPCIDevice *vdev,
+ struct vfio_pci_hot_reset_info **ret_info)
+{
+ struct vfio_pci_hot_reset_info *info;
+ int ret, count;
+
+ *ret_info = NULL;
+
+ info = g_malloc0(sizeof(*info));
+ info->argsz = sizeof(*info);
+
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+ if (ret && errno != ENOSPC) {
+ ret = -errno;
+ goto error;
+ }
+
+ count = info->count;
+
+ info = g_realloc(info, sizeof(*info) +
+ (count * sizeof(struct vfio_pci_dependent_device)));
+ info->argsz = sizeof(*info) +
+ (count * sizeof(struct vfio_pci_dependent_device));
+
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+ if (ret) {
+ ret = -errno;
+ goto error;
+ }
+
+ *ret_info = info;
+ info = NULL;
+
+ ret = 0;
+error:
+ g_free(info);
+ return ret;
+}
+
static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos)
{
PCIDevice *pdev = &vdev->pdev;
@@ -2780,7 +2824,7 @@ static bool vfio_pci_host_match(PCIHostDeviceAddress *host1,
static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
{
VFIOGroup *group;
- struct vfio_pci_hot_reset_info *info;
+ struct vfio_pci_hot_reset_info *info = NULL;
struct vfio_pci_dependent_device *devices;
struct vfio_pci_hot_reset *reset;
int32_t *fds;
@@ -2792,32 +2836,19 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
vfio_pci_pre_reset(vdev);
vdev->vbasedev.needs_reset = false;
- info = g_malloc0(sizeof(*info));
- info->argsz = sizeof(*info);
-
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
- if (ret && errno != ENOSPC) {
- ret = -errno;
+ ret = vfio_get_hot_reset_info(vdev, &info);
+ if (ret) {
if (!vdev->has_pm_reset) {
error_report("vfio: Cannot reset device %04x:%02x:%02x.%x, "
"no available reset mechanism.", vdev->host.domain,
vdev->host.bus, vdev->host.slot, vdev->host.function);
+ } else {
+ error_report("vfio: hot reset info failed: %m");
}
goto out_single;
}
- count = info->count;
- info = g_realloc(info, sizeof(*info) + (count * sizeof(*devices)));
- info->argsz = sizeof(*info) + (count * sizeof(*devices));
devices = &info->devices[0];
-
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
- if (ret) {
- ret = -errno;
- error_report("vfio: hot reset info failed: %m");
- goto out_single;
- }
-
trace_vfio_pci_hot_reset_has_dep_devices(vdev->vbasedev.name);
/* Verify that we have all the groups required */
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 02/13] vfio: squeeze out vfio_pci_do_hot_reset for support bus reset
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 01/13] vfio: extract vfio_get_hot_reset_info as a single function Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 03/13] vfio: add pcie extanded capability support Chen Fan
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
squeeze out vfio_pci_do_hot_reset to do host bus reset when AER recovery.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 75 +++++++++++++++++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 31 deletions(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 9c05304..78f4c82 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2685,6 +2685,48 @@ error:
return ret;
}
+static int vfio_pci_do_hot_reset(VFIOPCIDevice *vdev,
+ struct vfio_pci_hot_reset_info *info)
+{
+ VFIOGroup *group;
+ struct vfio_pci_hot_reset *reset;
+ int32_t *fds;
+ int ret, i, count;
+ struct vfio_pci_dependent_device *devices;
+
+ /* Determine how many group fds need to be passed */
+ count = 0;
+ devices = &info->devices[0];
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ for (i = 0; i < info->count; i++) {
+ if (group->groupid == devices[i].group_id) {
+ count++;
+ break;
+ }
+ }
+ }
+
+ reset = g_malloc0(sizeof(*reset) + (count * sizeof(*fds)));
+ reset->argsz = sizeof(*reset) + (count * sizeof(*fds));
+ fds = &reset->group_fds[0];
+
+ /* Fill in group fds */
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ for (i = 0; i < info->count; i++) {
+ if (group->groupid == devices[i].group_id) {
+ fds[reset->count++] = group->fd;
+ break;
+ }
+ }
+ }
+
+ /* Bus reset! */
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
+ g_free(reset);
+
+ return ret;
+}
+
static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos)
{
PCIDevice *pdev = &vdev->pdev;
@@ -2826,9 +2868,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
VFIOGroup *group;
struct vfio_pci_hot_reset_info *info = NULL;
struct vfio_pci_dependent_device *devices;
- struct vfio_pci_hot_reset *reset;
- int32_t *fds;
- int ret, i, count;
+ int ret, i;
bool multi = false;
trace_vfio_pci_hot_reset(vdev->vbasedev.name, single ? "one" : "multi");
@@ -2909,34 +2949,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
goto out_single;
}
- /* Determine how many group fds need to be passed */
- count = 0;
- QLIST_FOREACH(group, &vfio_group_list, next) {
- for (i = 0; i < info->count; i++) {
- if (group->groupid == devices[i].group_id) {
- count++;
- break;
- }
- }
- }
-
- reset = g_malloc0(sizeof(*reset) + (count * sizeof(*fds)));
- reset->argsz = sizeof(*reset) + (count * sizeof(*fds));
- fds = &reset->group_fds[0];
-
- /* Fill in group fds */
- QLIST_FOREACH(group, &vfio_group_list, next) {
- for (i = 0; i < info->count; i++) {
- if (group->groupid == devices[i].group_id) {
- fds[reset->count++] = group->fd;
- break;
- }
- }
- }
-
- /* Bus reset! */
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
- g_free(reset);
+ ret = vfio_pci_do_hot_reset(vdev, info);
trace_vfio_pci_hot_reset_result(vdev->vbasedev.name,
ret ? "%m" : "Success");
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 03/13] vfio: add pcie extanded capability support
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 01/13] vfio: extract vfio_get_hot_reset_info as a single function Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 02/13] vfio: squeeze out vfio_pci_do_hot_reset for support bus reset Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 04/13] aer: impove pcie_aer_init to support vfio device Chen Fan
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
For vfio pcie device, we could expose the extended capability on
PCIE bus. in order to avoid config space broken, we introduce
a copy config for parsing extended caps. and rebuild the pcie
extended config space.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 78f4c82..81a4a9a 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2493,6 +2493,21 @@ static uint8_t vfio_std_cap_max_size(PCIDevice *pdev, uint8_t pos)
return next - pos;
}
+
+static uint16_t vfio_ext_cap_max_size(const uint8_t *config, uint16_t pos)
+{
+ uint16_t tmp, next = PCIE_CONFIG_SPACE_SIZE - 1;
+
+ for (tmp = PCI_CONFIG_SPACE_SIZE; tmp;
+ tmp = PCI_EXT_CAP_NEXT(pci_get_long(config + tmp))) {
+ if (tmp > pos && tmp < next) {
+ next = tmp;
+ }
+ }
+
+ return next - pos;
+}
+
static void vfio_set_word_bits(uint8_t *buf, uint16_t val, uint16_t mask)
{
pci_set_word(buf, (pci_get_word(buf) & ~mask) | val);
@@ -2802,16 +2817,72 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos)
return 0;
}
+static int vfio_add_ext_cap(VFIOPCIDevice *vdev, const uint8_t *config)
+{
+ PCIDevice *pdev = &vdev->pdev;
+ uint32_t header;
+ uint16_t cap_id, next, size;
+ uint8_t cap_ver;
+
+ for (next = PCI_CONFIG_SPACE_SIZE; next;
+ next = PCI_EXT_CAP_NEXT(pci_get_long(config + next))) {
+ header = pci_get_long(config + next);
+ cap_id = PCI_EXT_CAP_ID(header);
+ cap_ver = PCI_EXT_CAP_VER(header);
+
+ /*
+ * If it becomes important to configure extended capabilities to their
+ * actual size, use this as the default when it's something we don't
+ * recognize. Since QEMU doesn't actually handle many of the config
+ * accesses, exact size doesn't seem worthwhile.
+ */
+ size = vfio_ext_cap_max_size(config, next);
+
+ pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+ if (next == PCI_CONFIG_SPACE_SIZE) {
+ /* Begin the rebuild, we should set the next offset zero. */
+ pci_set_long(pdev->config + next, PCI_EXT_CAP(cap_id, cap_ver, 0));
+ }
+
+ /* Use emulated header pointer to allow dropping extended caps */
+ pci_set_long(vdev->emulated_config_bits + next, 0xffffffff);
+ }
+
+ return 0;
+}
+
static int vfio_add_capabilities(VFIOPCIDevice *vdev)
{
PCIDevice *pdev = &vdev->pdev;
+ int ret;
+ uint8_t *config;
if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST) ||
!pdev->config[PCI_CAPABILITY_LIST]) {
return 0; /* Nothing to add */
}
- return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
+ ret = vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
+ if (ret) {
+ return ret;
+ }
+
+ /* on PCI bus, it doesn't make sense to expose extended capabilities. */
+ if (!pci_is_express(pdev) ||
+ !pci_bus_is_express(pdev->bus) ||
+ !pci_get_long(pdev->config + PCI_CONFIG_SPACE_SIZE)) {
+ return 0;
+ }
+
+ /*
+ * In order to avoid config space broken, here using a copy config to
+ * parse extended capabilities.
+ */
+ config = g_memdup(pdev->config, vdev->config_size);
+ ret = vfio_add_ext_cap(vdev, config);
+
+ g_free(config);
+ return ret;
}
static void vfio_pci_pre_reset(VFIOPCIDevice *vdev)
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 04/13] aer: impove pcie_aer_init to support vfio device
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (2 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 03/13] vfio: add pcie extanded capability support Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 05/13] vfio: add aer support for " Chen Fan
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
pcie_aer_init was used to emulate an aer capability for pcie device,
but for vfio device, the aer config space size is mutable and is not
always equal to PCI_ERR_SIZEOF(0x48). it depends on where the TLP Prefix
register required, so here we add a size argument.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/pci-bridge/ioh3420.c | 2 +-
hw/pci-bridge/xio3130_downstream.c | 2 +-
hw/pci-bridge/xio3130_upstream.c | 2 +-
hw/pci/pcie_aer.c | 4 ++--
include/hw/pci/pcie_aer.h | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index cce2fdd..4d9cd3f 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -129,7 +129,7 @@ static int ioh3420_initfn(PCIDevice *d)
goto err_pcie_cap;
}
pcie_cap_root_init(d);
- rc = pcie_aer_init(d, IOH_EP_AER_OFFSET);
+ rc = pcie_aer_init(d, IOH_EP_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
}
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index b3a6479..9737041 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -92,7 +92,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
goto err_pcie_cap;
}
pcie_cap_arifwd_init(d);
- rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+ rc = pcie_aer_init(d, XIO3130_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
}
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index eada582..4d7f894 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -81,7 +81,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
}
pcie_cap_flr_init(d);
pcie_cap_deverr_init(d);
- rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+ rc = pcie_aer_init(d, XIO3130_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
}
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index b48c09c..ccf577e 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -94,12 +94,12 @@ static void aer_log_clear_all_err(PCIEAERLog *aer_log)
aer_log->log_num = 0;
}
-int pcie_aer_init(PCIDevice *dev, uint16_t offset)
+int pcie_aer_init(PCIDevice *dev, uint16_t offset, uint16_t size)
{
PCIExpressDevice *exp;
pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, PCI_ERR_VER,
- offset, PCI_ERR_SIZEOF);
+ offset, size);
exp = &dev->exp;
exp->aer_cap = offset;
diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h
index 2fb8388..156acb0 100644
--- a/include/hw/pci/pcie_aer.h
+++ b/include/hw/pci/pcie_aer.h
@@ -87,7 +87,7 @@ struct PCIEAERErr {
extern const VMStateDescription vmstate_pcie_aer_log;
-int pcie_aer_init(PCIDevice *dev, uint16_t offset);
+int pcie_aer_init(PCIDevice *dev, uint16_t offset, uint16_t size);
void pcie_aer_exit(PCIDevice *dev);
void pcie_aer_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 05/13] vfio: add aer support for vfio device
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (3 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 04/13] aer: impove pcie_aer_init to support vfio device Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 06/13] vfio: add check host bus reset is support or not Chen Fan
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
Calling pcie_aer_init to initilize aer related registers for
vfio device, then reload physical related registers to expose
device capability.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 82 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 81a4a9a..f4e7855 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -32,6 +32,7 @@
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bridge.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "qemu/event_notifier.h"
@@ -160,6 +161,8 @@ typedef struct VFIOPCIDevice {
#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
#define VFIO_FEATURE_ENABLE_REQ_BIT 1
#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT)
+#define VFIO_FEATURE_ENABLE_AER_BIT 2
+#define VFIO_FEATURE_ENABLE_AER (1 << VFIO_FEATURE_ENABLE_AER_BIT)
int32_t bootindex;
uint8_t pm_cap;
bool has_vga;
@@ -2817,12 +2820,78 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos)
return 0;
}
+static int vfio_setup_aer(VFIOPCIDevice *vdev, int pos, uint16_t size)
+{
+ PCIDevice *pdev = &vdev->pdev;
+ uint8_t *exp_cap = pdev->config + pdev->exp.exp_cap;
+ PCIDevice *dev_iter;
+ uint8_t type;
+ uint32_t severity, errcap;
+ int ret;
+
+ if (!(vdev->features & VFIO_FEATURE_ENABLE_AER)) {
+ return 0;
+ }
+
+ dev_iter = pci_bridge_get_device(pdev->bus);
+ if (!dev_iter) {
+ goto error;
+ }
+
+ while (dev_iter) {
+ type = pcie_cap_get_type(dev_iter);
+ if ((type != PCI_EXP_TYPE_ROOT_PORT &&
+ type != PCI_EXP_TYPE_UPSTREAM &&
+ type != PCI_EXP_TYPE_DOWNSTREAM)) {
+ goto error;
+ }
+
+ if (!dev_iter->exp.aer_cap) {
+ goto error;
+ }
+
+ dev_iter = pci_bridge_get_device(dev_iter->bus);
+ }
+
+ errcap = vfio_pci_read_config(pdev, pdev->exp.aer_cap + PCI_ERR_CAP, 4);
+ /*
+ * The ability to record multiple headers is depending on
+ * the state of the Multiple Header Recording Capable bit and
+ * enabled by the Multiple Header Recording Enable bit.
+ */
+ if ((errcap & PCI_ERR_CAP_MHRC) &&
+ (errcap & PCI_ERR_CAP_MHRE)) {
+ pdev->exp.aer_log.log_max = PCIE_AER_LOG_MAX_DEFAULT;
+ } else {
+ pdev->exp.aer_log.log_max = 0;
+ }
+
+ pcie_cap_deverr_init(pdev);
+ ret = pcie_aer_init(pdev, pos, size);
+ if (ret) {
+ return ret;
+ }
+
+ /* load physical registers */
+ severity = vfio_pci_read_config(pdev,
+ pdev->exp.aer_cap + PCI_ERR_UNCOR_SEVER, 4);
+ pci_long_test_and_clear_mask(exp_cap + PCI_ERR_UNCOR_SEVER, ~severity);
+
+ return 0;
+
+error:
+ error_report("vfio: Unable to enable AER for device %s, parent bus "
+ "do not support signal AER", vdev->vbasedev.name);
+ return -1;
+}
+
static int vfio_add_ext_cap(VFIOPCIDevice *vdev, const uint8_t *config)
{
PCIDevice *pdev = &vdev->pdev;
uint32_t header;
uint16_t cap_id, next, size;
uint8_t cap_ver;
+ int ret = 0;
for (next = PCI_CONFIG_SPACE_SIZE; next;
next = PCI_EXT_CAP_NEXT(pci_get_long(config + next))) {
@@ -2838,7 +2907,19 @@ static int vfio_add_ext_cap(VFIOPCIDevice *vdev, const uint8_t *config)
*/
size = vfio_ext_cap_max_size(config, next);
- pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+ switch (cap_id) {
+ case PCI_EXT_CAP_ID_ERR:
+ ret = vfio_setup_aer(vdev, next, size);
+ break;
+ default:
+ pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+ break;
+ }
+
+ if (ret) {
+ return ret;
+ }
+
if (next == PCI_CONFIG_SPACE_SIZE) {
/* Begin the rebuild, we should set the next offset zero. */
pci_set_long(pdev->config + next, PCI_EXT_CAP(cap_id, cap_ver, 0));
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 06/13] vfio: add check host bus reset is support or not
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (4 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 05/13] vfio: add aer support for " Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 07/13] vfio: add check for vfio devices which enable aer should support bus reset Chen Fan
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
we introduce a has_bus_reset capability to sign the vfio
devices if support host bus reset.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index f4e7855..15f182c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -33,6 +33,7 @@
#include "hw/pci/msix.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "qemu/event_notifier.h"
@@ -170,6 +171,7 @@ typedef struct VFIOPCIDevice {
bool req_enabled;
bool has_flr;
bool has_pm_reset;
+ bool has_bus_reset;
bool rom_read_failed;
} VFIOPCIDevice;
@@ -203,6 +205,7 @@ static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
uint32_t val, int len);
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
+static void vfio_check_host_bus_reset(VFIOPCIDevice *vdev);
/*
* Disabling BAR mmaping can be slow, but toggling it around INTx can
@@ -2853,6 +2856,20 @@ static int vfio_setup_aer(VFIOPCIDevice *vdev, int pos, uint16_t size)
dev_iter = pci_bridge_get_device(dev_iter->bus);
}
+ /*
+ * Don't check reset when device is enabled during qemu machine creation:
+ * which is done by machine init function.
+ */
+ if (DEVICE(vdev)->hotplugged) {
+ vfio_check_host_bus_reset(vdev);
+ if (!vdev->has_bus_reset) {
+ error_report("vfio: Cannot enable AER for device %s, "
+ "which is not support host bus reset.",
+ vdev->vbasedev.name);
+ goto error;
+ }
+ }
+
errcap = vfio_pci_read_config(pdev, pdev->exp.aer_cap + PCI_ERR_CAP, 4);
/*
* The ability to record multiple headers is depending on
@@ -3678,6 +3695,102 @@ static void vfio_setup_resetfn(VFIOPCIDevice *vdev)
}
}
+struct VfioDeviceFind {
+ PCIDevice *pdev;
+ bool found;
+};
+
+static void find_devices(PCIBus *bus, void *opaque)
+{
+ struct VfioDeviceFind *find = opaque;
+ int i;
+
+ if (find->found == true) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bus->devices); i++) {
+ if (!bus->devices[i]) {
+ continue;
+ }
+
+ if (bus->devices[i] == find->pdev) {
+ find->found = true;
+ break;
+ }
+ }
+}
+
+static void vfio_check_host_bus_reset(VFIOPCIDevice *vdev)
+{
+ PCIBus *bus = vdev->pdev.bus;
+ struct vfio_pci_hot_reset_info *info = NULL;
+ struct vfio_pci_dependent_device *devices;
+ VFIOGroup *group;
+ int ret, i;
+
+ ret = vfio_get_hot_reset_info(vdev, &info);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* List all affected devices by bus reset */
+ devices = &info->devices[0];
+
+ /* Verify that we have all the groups required */
+ for (i = 0; i < info->count; i++) {
+ PCIHostDeviceAddress host;
+ VFIOPCIDevice *tmp;
+ VFIODevice *vbasedev_iter;
+ bool found = false;
+
+ host.domain = devices[i].segment;
+ host.bus = devices[i].bus;
+ host.slot = PCI_SLOT(devices[i].devfn);
+ host.function = PCI_FUNC(devices[i].devfn);
+
+ /* Skip the current device */
+ if (vfio_pci_host_match(&host, &vdev->host)) {
+ continue;
+ }
+
+ /* Ensure we own the group of the affected device */
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ if (group->groupid == devices[i].group_id) {
+ break;
+ }
+ }
+
+ if (!group) {
+ goto out;
+ }
+
+ /* Ensure affected devices for reset under the same bus */
+ QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
+ if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ continue;
+ }
+ tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
+ if (vfio_pci_host_match(&host, &tmp->host)) {
+ struct VfioDeviceFind find = { .pdev = &tmp->pdev, .found = false };
+
+ pci_for_each_bus(bus, find_devices, &find);
+ found = find.found;
+ break;
+ }
+ }
+
+ if (!found) {
+ goto out;
+ }
+ }
+
+ vdev->has_bus_reset = true;
+
+out:
+ g_free(info);
+}
+
static int vfio_initfn(PCIDevice *pdev)
{
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 07/13] vfio: add check for vfio devices which enable aer should support bus reset
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (5 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 06/13] vfio: add check host bus reset is support or not Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 08/13] pci: add bus reset_notifiers callbacks for host " Chen Fan
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 15f182c..6de268d 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3791,6 +3791,32 @@ out:
g_free(info);
}
+static void vfio_pci_machine_done_notify(Notifier *notifier, void *unused)
+{
+ VFIOGroup *group;
+ VFIODevice *vbasedev;
+ VFIOPCIDevice *vdev;
+
+ /* Check All support AER devices if has bus reset capability */
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ QLIST_FOREACH(vbasedev, &group->device_list, next) {
+ vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
+ vfio_check_host_bus_reset(vdev);
+ if ((vdev->features & VFIO_FEATURE_ENABLE_AER) &&
+ !vdev->has_bus_reset) {
+ error_report("vfio: Cannot enable AER for device %s, "
+ "which is not support host bus reset.",
+ vdev->vbasedev.name);
+ exit(1);
+ }
+ }
+ }
+}
+
+static Notifier machine_notifier = {
+ .notify = vfio_pci_machine_done_notify,
+};
+
static int vfio_initfn(PCIDevice *pdev)
{
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
@@ -4076,6 +4102,11 @@ static const TypeInfo vfio_pci_dev_info = {
static void register_vfio_pci_dev_type(void)
{
type_register_static(&vfio_pci_dev_info);
+ /*
+ * Register notifier when machine init is done, since we need
+ * check the configration manner after all vfio devices are inited.
+ */
+ qemu_add_machine_init_done_notifier(&machine_notifier);
}
type_init(register_vfio_pci_dev_type)
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 08/13] pci: add bus reset_notifiers callbacks for host bus reset
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (6 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 07/13] vfio: add check for vfio devices which enable aer should support bus reset Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 09/13] vfio: add sec_bus_reset notifier to notify physical bus reset is needed Chen Fan
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson, Michael S. Tsirkin
Particularly, For vfio devices, Once need to recovery devices
by bus reset such as AER, we always need to reset the host bus
to recovery the devices under the bus, so we need to add pci bus
callbacks to specify to do host bus reset.
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/pci/pci.c | 16 ++++++++++++++++
hw/pci/pci_bridge.c | 5 +++++
include/hw/pci/pci.h | 4 ++++
include/hw/pci/pci_bus.h | 2 ++
4 files changed, 27 insertions(+)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 48f19a3..0878834 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -74,11 +74,27 @@ static const VMStateDescription vmstate_pcibus = {
}
};
+void pci_bus_add_reset_notifier(PCIBus *bus, Notifier *notify)
+{
+ notifier_list_add(&bus->reset_notifiers, notify);
+}
+
+void pci_bus_remove_reset_notifier(Notifier *notify)
+{
+ notifier_remove(notify);
+}
+
+void pci_bus_run_reset_notifier(PCIBus *bus, void *opaque)
+{
+ notifier_list_notify(&bus->reset_notifiers, opaque);
+}
+
static void pci_bus_realize(BusState *qbus, Error **errp)
{
PCIBus *bus = PCI_BUS(qbus);
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
+ notifier_list_init(&bus->reset_notifiers);
}
static void pci_bus_unrealize(BusState *qbus, Error **errp)
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 40c97b1..75d2b4b 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -267,6 +267,11 @@ void pci_bridge_write_config(PCIDevice *d,
newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
+ /*
+ * Notify all vfio-pci devices under the bus
+ * to do physical bus reset.
+ */
+ pci_for_each_bus(&s->sec_bus, pci_bus_run_reset_notifier, NULL);
/* Trigger hot reset on 0->1 transition. */
qbus_reset_all(&s->sec_bus.qbus);
}
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 5d050c8..5a9357c 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -7,6 +7,7 @@
#include "exec/memory.h"
#include "sysemu/dma.h"
#include "qapi/error.h"
+#include "qemu/notify.h"
/* PCI includes legacy ISA access. */
#include "hw/isa/isa.h"
@@ -371,6 +372,9 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
void pci_device_set_intx_routing_notifier(PCIDevice *dev,
PCIINTxRoutingNotifier notifier);
void pci_device_reset(PCIDevice *dev);
+void pci_bus_add_reset_notifier(PCIBus *bus, Notifier *notify);
+void pci_bus_remove_reset_notifier(Notifier *notify);
+void pci_bus_run_reset_notifier(PCIBus *bus, void *opaque);
PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
const char *default_model,
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
index fabaeee..3b551d7 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -29,6 +29,8 @@ struct PCIBus {
Keep a count of the number of devices with raised IRQs. */
int nirq;
int *irq_count;
+
+ NotifierList reset_notifiers;
};
typedef struct PCIBridgeWindows PCIBridgeWindows;
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 09/13] vfio: add sec_bus_reset notifier to notify physical bus reset is needed
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (7 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 08/13] pci: add bus reset_notifiers callbacks for host " Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 10/13] vfio: do hot bus reset when do virtual secondary bus reset Chen Fan
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 6de268d..94ff4e1 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -156,6 +156,7 @@ typedef struct VFIOPCIDevice {
PCIHostDeviceAddress host;
EventNotifier err_notifier;
EventNotifier req_notifier;
+ Notifier sec_bus_reset_notifier;
int (*resetfn)(struct VFIOPCIDevice *);
uint32_t features;
#define VFIO_FEATURE_ENABLE_VGA_BIT 0
@@ -172,6 +173,7 @@ typedef struct VFIOPCIDevice {
bool has_flr;
bool has_pm_reset;
bool has_bus_reset;
+ bool needs_bus_reset;
bool rom_read_failed;
} VFIOPCIDevice;
@@ -3695,6 +3697,17 @@ static void vfio_setup_resetfn(VFIOPCIDevice *vdev)
}
}
+static void vfio_pci_host_needs_bus_reset(Notifier *n, void *opaque)
+{
+ VFIOPCIDevice *vdev = container_of(n, VFIOPCIDevice, sec_bus_reset_notifier);
+ VFIODevice *vbasedev = &vdev->vbasedev;
+
+ if (vdev->has_bus_reset) {
+ vdev->needs_bus_reset = true;
+ vbasedev->needs_reset = true;
+ }
+}
+
struct VfioDeviceFind {
PCIDevice *pdev;
bool found;
@@ -3967,6 +3980,9 @@ static int vfio_initfn(PCIDevice *pdev)
vfio_register_req_notifier(vdev);
vfio_setup_resetfn(vdev);
+ vdev->sec_bus_reset_notifier.notify = vfio_pci_host_needs_bus_reset;
+ pci_bus_add_reset_notifier(pdev->bus, &vdev->sec_bus_reset_notifier);
+
return 0;
out_teardown:
@@ -3995,6 +4011,7 @@ static void vfio_exitfn(PCIDevice *pdev)
vfio_unregister_req_notifier(vdev);
vfio_unregister_err_notifier(vdev);
+ pci_bus_remove_reset_notifier(&vdev->sec_bus_reset_notifier);
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
vfio_disable_interrupts(vdev);
if (vdev->intx.mmap_timer) {
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 10/13] vfio: do hot bus reset when do virtual secondary bus reset
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (8 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 09/13] vfio: add sec_bus_reset notifier to notify physical bus reset is needed Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 11/13] pcie_aer: expose pcie_aer_msg() interface Chen Fan
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
when do virtual secondary bus reset, the vfio device under
this bus need to do host bus reset to reset the device.
so add this case.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 94ff4e1..29a2b12 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -4028,6 +4028,14 @@ static void vfio_pci_reset(DeviceState *dev)
trace_vfio_pci_reset(vdev->vbasedev.name);
+ if (vdev->needs_bus_reset) {
+ vdev->needs_bus_reset = false;
+ if (vdev->vbasedev.needs_reset) {
+ vfio_pci_hot_reset(vdev, false);
+ }
+ return;
+ }
+
vfio_pci_pre_reset(vdev);
if (vdev->resetfn && !vdev->resetfn(vdev)) {
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 11/13] pcie_aer: expose pcie_aer_msg() interface
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (9 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 10/13] vfio: do hot bus reset when do virtual secondary bus reset Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 12/13] vfio-pci: pass the aer error to guest Chen Fan
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
For vfio device, we need to propagate the aer error to
Guest OS. we use the pcie_aer_msg() to send aer error
to guest.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/pci/pcie_aer.c | 2 +-
include/hw/pci/pcie_aer.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index ccf577e..58010c4 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -370,7 +370,7 @@ static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
*
* Walk up the bus tree from the device, propagate the error message.
*/
-static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
{
uint8_t type;
diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h
index 156acb0..c2ee4e2 100644
--- a/include/hw/pci/pcie_aer.h
+++ b/include/hw/pci/pcie_aer.h
@@ -102,5 +102,6 @@ void pcie_aer_root_write_config(PCIDevice *dev,
/* error injection */
int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err);
+void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg);
#endif /* QEMU_PCIE_AER_H */
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 12/13] vfio-pci: pass the aer error to guest
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (10 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 11/13] pcie_aer: expose pcie_aer_msg() interface Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 13/13] vfio: add 'aer' property to expose aercap Chen Fan
2015-05-27 2:51 ` [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
when the vfio device encounters an uncorrectable error in host,
the vfio_pci driver will signal the eventfd registered by this
vfio device, the results in the qemu eventfd handler getting
invoked.
this patch is to pass the error to guest and have the guest driver
recover from the error.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 42 ++++++++++++++++++++++++++++++++++++------
1 file changed, 36 insertions(+), 6 deletions(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 29a2b12..b297d7c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3348,18 +3348,48 @@ static void vfio_put_device(VFIOPCIDevice *vdev)
static void vfio_err_notifier_handler(void *opaque)
{
VFIOPCIDevice *vdev = opaque;
+ PCIDevice *dev = &vdev->pdev;
+ PCIEAERMsg msg = {
+ .severity = 0,
+ .source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn,
+ };
if (!event_notifier_test_and_clear(&vdev->err_notifier)) {
return;
}
/*
- * TBD. Retrieve the error details and decide what action
- * needs to be taken. One of the actions could be to pass
- * the error to the guest and have the guest driver recover
- * from the error. This requires that PCIe capabilities be
- * exposed to the guest. For now, we just terminate the
- * guest to contain the error.
+ * in case the real hardware configration has been changed,
+ * here we should recheck the bus reset capability.
+ */
+ vfio_check_host_bus_reset(vdev);
+
+ /*
+ * we should read the error details from the real hardware
+ * configuration spaces, here we only need to do is signaling
+ * to guest an uncorrectable error has occurred.
+ */
+ if (dev->exp.aer_cap &&
+ vdev->has_bus_reset) {
+ uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+ uint32_t uncor_status;
+ bool isfatal;
+
+ uncor_status = vfio_pci_read_config(dev,
+ dev->exp.aer_cap + PCI_ERR_UNCOR_STATUS, 4);
+
+ isfatal = uncor_status & pci_get_long(aer_cap + PCI_ERR_UNCOR_SEVER);
+
+ msg.severity = isfatal ? PCI_ERR_ROOT_CMD_FATAL_EN :
+ PCI_ERR_ROOT_CMD_NONFATAL_EN;
+
+ pcie_aer_msg(dev, &msg);
+ return;
+ }
+
+ /*
+ * If the aer capability is not exposed to the guest. we just
+ * terminate the guest to contain the error.
*/
error_report("%s(%04x:%02x:%02x.%x) Unrecoverable error detected. "
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [RFC v8 13/13] vfio: add 'aer' property to expose aercap
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (11 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 12/13] vfio-pci: pass the aer error to guest Chen Fan
@ 2015-05-25 10:06 ` Chen Fan
2015-05-27 2:51 ` [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-25 10:06 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
add 'aer' property to let user able to decide whether expose
the aer capability. by default we should disable aer feature,
because it needs configuration restrictions.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
hw/vfio/pci.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index b297d7c..3804e41 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -4113,6 +4113,8 @@ static Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_VGA_BIT, false),
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_REQ_BIT, true),
+ DEFINE_PROP_BIT("aer", VFIOPCIDevice, features,
+ VFIO_FEATURE_ENABLE_AER_BIT, false),
DEFINE_PROP_INT32("bootindex", VFIOPCIDevice, bootindex, -1),
DEFINE_PROP_BOOL("x-mmap", VFIOPCIDevice, vbasedev.allow_mmap, true),
/*
--
1.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
` (12 preceding siblings ...)
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 13/13] vfio: add 'aer' property to expose aercap Chen Fan
@ 2015-05-27 2:51 ` Chen Fan
13 siblings, 0 replies; 15+ messages in thread
From: Chen Fan @ 2015-05-27 2:51 UTC (permalink / raw)
To: qemu-devel; +Cc: izumi.taku, alex.williamson
Hi,
Because having no body comment it.
and I have made some updates on this patches.
which are:
1. add check the case when one aer devices is re-hotplugged
to upper bus which will conflict the present which enable aer.
2. add vfio_pci_affect_devices_is_multi to specify signal or
multi in-use when call hot reset.
meantime I have sent the new v8.1 version out.
please ignore this patches.
Thanks,
Chen
On 05/25/2015 06:06 PM, Chen Fan wrote:
> For now, for vfio pci passthough devices when qemu receives
> an error from host aer report, there just terminate the guest,
> but usually user want to know what error occurred but stop the
> guest, so this patches add aer capability support for vfio device,
> and pass the error to guest, and have guest driver to recover
> from the error.
> and turning on SERR# for error forwording in bridge control register
> patch in seabios has been merged.
>
> v7-v8:
> 1. some bug fixes requested by Alex
>
> v6-v7:
> 1. add has_bus_reset to support reset host bus.
>
> v5-v6:
> 1. add secondary bus callbacks to reset host bus.
>
> v3-v4:
> 1. add 'x-aer' for user to off aer capability.
> 2. refactor vfio device to parse extended capabilities.
>
> v2-v3:
> 1. refactor vfio device to parse extended capability.
> 2. add global property for piix4 to disable vfio aer cap.
>
> v1-v2:
> 1. turn on SERR# for bridge control register in firmware.
> 2. initilize aer capability for vfio device.
> 3. fix some trivial bug.
>
> Chen Fan (13):
> vfio: extract vfio_get_hot_reset_info as a single function
> vfio: squeeze out vfio_pci_do_hot_reset for support bus reset
> vfio: add pcie extanded capability support
> aer: impove pcie_aer_init to support vfio device
> vfio: add aer support for vfio device
> vfio: add check host bus reset is support or not
> vfio: add check for vfio devices which enable aer should support bus
> reset
> pci: add bus reset_notifiers callbacks for host bus reset
> vfio: add sec_bus_reset notifier to notify physical bus reset is
> needed
> vfio: do hot bus reset when do virtual secondary bus reset
> pcie_aer: expose pcie_aer_msg() interface
> vfio-pci: pass the aer error to guest
> vfio: add 'aer' property to expose aercap
>
> hw/pci-bridge/ioh3420.c | 2 +-
> hw/pci-bridge/xio3130_downstream.c | 2 +-
> hw/pci-bridge/xio3130_upstream.c | 2 +-
> hw/pci/pci.c | 16 ++
> hw/pci/pci_bridge.c | 5 +
> hw/pci/pcie_aer.c | 6 +-
> hw/vfio/pci.c | 509 +++++++++++++++++++++++++++++++++----
> include/hw/pci/pci.h | 4 +
> include/hw/pci/pci_bus.h | 2 +
> include/hw/pci/pcie_aer.h | 3 +-
> 10 files changed, 488 insertions(+), 63 deletions(-)
>
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2015-05-27 2:54 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-25 10:06 [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 01/13] vfio: extract vfio_get_hot_reset_info as a single function Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 02/13] vfio: squeeze out vfio_pci_do_hot_reset for support bus reset Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 03/13] vfio: add pcie extanded capability support Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 04/13] aer: impove pcie_aer_init to support vfio device Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 05/13] vfio: add aer support for " Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 06/13] vfio: add check host bus reset is support or not Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 07/13] vfio: add check for vfio devices which enable aer should support bus reset Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 08/13] pci: add bus reset_notifiers callbacks for host " Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 09/13] vfio: add sec_bus_reset notifier to notify physical bus reset is needed Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 10/13] vfio: do hot bus reset when do virtual secondary bus reset Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 11/13] pcie_aer: expose pcie_aer_msg() interface Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 12/13] vfio-pci: pass the aer error to guest Chen Fan
2015-05-25 10:06 ` [Qemu-devel] [RFC v8 13/13] vfio: add 'aer' property to expose aercap Chen Fan
2015-05-27 2:51 ` [Qemu-devel] [RFC v8 00/13] vfio-pci: pass the aer error to guest Chen Fan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).