Introduce 'spapr_phb_vfio_errinjct()' to inject PCI PHB error events via
the VFIO passthrough backend. This function translates RTAS error injection
parameters into VFIO EEH injection commands suitable for hardware emulation.
The patch adds:
- A minimal 'enum rtas_err_type' for error types used in VFIO path
- EEH function code macros ('EEH_ERR_FUNC_...')
- Backend stub and integration into 'spapr_pci_vfio.c'
- Necessary header declarations for interfacing
This forms the foundational layer for PCI error injection testing using VFIO
passthrough devices on pseries guests.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
include/hw/pci-host/spapr.h | 7 +++++
include/hw/ppc/spapr.h | 44 ++++++++++++++++++++++++++++++
hw/ppc/spapr_pci_vfio.c | 53 +++++++++++++++++++++++++++++++++++++
3 files changed, 104 insertions(+)
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 0db87f1281..2e91e0fb38 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -125,6 +125,8 @@ int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state);
int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option);
int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb);
void spapr_phb_vfio_reset(DeviceState *qdev);
+int spapr_phb_vfio_errinjct(SpaprPhbState *sphb, uint32_t func,
+ uint64_t addr, uint64_t mask, uint32_t type);
#else
static inline bool spapr_phb_eeh_available(SpaprPhbState *sphb)
{
@@ -151,6 +153,11 @@ static inline int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
static inline void spapr_phb_vfio_reset(DeviceState *qdev)
{
}
+static int spapr_phb_vfio_errinjct(SpaprPhbState *sphb, uint32_t func,
+ uint64_t addr, uint64_t mask, uint32_t type)
+{
+ return RTAS_OUT_HW_ERROR;
+}
#endif
void spapr_phb_dma_reset(SpaprPhbState *sphb);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 39bd5bd5ed..331946ee57 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -691,6 +691,50 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr);
#define RTAS_EEH_PE_UNAVAIL_INFO 1000
#define RTAS_EEH_PE_RECOVER_INFO 0
+/* EEH error types and functions */
+#define EEH_ERR_FUNC_MIN 0
+#define EEH_ERR_FUNC_LD_MEM_ADDR 0 /* Memory load */
+#define EEH_ERR_FUNC_LD_MEM_DATA 1
+#define EEH_ERR_FUNC_LD_IO_ADDR 2 /* IO load */
+#define EEH_ERR_FUNC_LD_IO_DATA 3
+#define EEH_ERR_FUNC_LD_CFG_ADDR 4 /* Config load */
+#define EEH_ERR_FUNC_LD_CFG_DATA 5
+#define EEH_ERR_FUNC_ST_MEM_ADDR 6 /* Memory store */
+#define EEH_ERR_FUNC_ST_MEM_DATA 7
+#define EEH_ERR_FUNC_ST_IO_ADDR 8 /* IO store */
+#define EEH_ERR_FUNC_ST_IO_DATA 9
+#define EEH_ERR_FUNC_ST_CFG_ADDR 10 /* Config store */
+#define EEH_ERR_FUNC_ST_CFG_DATA 11
+#define EEH_ERR_FUNC_DMA_RD_ADDR 12 /* DMA read */
+#define EEH_ERR_FUNC_DMA_RD_DATA 13
+#define EEH_ERR_FUNC_DMA_RD_MASTER 14
+#define EEH_ERR_FUNC_DMA_RD_TARGET 15
+#define EEH_ERR_FUNC_DMA_WR_ADDR 16 /* DMA write */
+#define EEH_ERR_FUNC_DMA_WR_DATA 17
+#define EEH_ERR_FUNC_DMA_WR_MASTER 18
+#define EEH_ERR_FUNC_DMA_WR_TARGET 19
+#define EEH_ERR_FUNC_MAX EEH_ERR_FUNC_DMA_WR_TARGET
+
+/* RTAS PCI Error Injection Token Types */
+enum rtas_err_type {
+ RTAS_ERR_TYPE_FATAL = 0x1,
+ RTAS_ERR_TYPE_RECOVERED_RANDOM_EVENT = 0x2,
+ RTAS_ERR_TYPE_RECOVERED_SPECIAL_EVENT = 0x3,
+ RTAS_ERR_TYPE_CORRUPTED_PAGE = 0x4,
+ RTAS_ERR_TYPE_CORRUPTED_SLB = 0x5,
+ RTAS_ERR_TYPE_TRANSLATOR_FAILURE = 0x6,
+ RTAS_ERR_TYPE_IOA_BUS_ERROR = 0x7,
+ RTAS_ERR_TYPE_PLATFORM_SPECIFIC = 0x8,
+ RTAS_ERR_TYPE_CORRUPTED_DCACHE_START = 0x9,
+ RTAS_ERR_TYPE_CORRUPTED_DCACHE_END = 0xA,
+ RTAS_ERR_TYPE_CORRUPTED_ICACHE_START = 0xB,
+ RTAS_ERR_TYPE_CORRUPTED_ICACHE_END = 0xC,
+ RTAS_ERR_TYPE_CORRUPTED_TLB_START = 0xD,
+ RTAS_ERR_TYPE_CORRUPTED_TLB_END = 0xE,
+ RTAS_ERR_TYPE_IOA_BUS_ERROR_64 = 0xF,
+ RTAS_ERR_TYPE_UPSTREAM_IO_ERROR = 0x10
+};
+
/* ibm,set-slot-reset */
#define RTAS_SLOT_RESET_DEACTIVATE 0
#define RTAS_SLOT_RESET_HOT 1
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index a748a0bf4c..ed0b22a84a 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -317,6 +317,55 @@ int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
return RTAS_OUT_SUCCESS;
}
+int spapr_phb_vfio_errinjct(SpaprPhbState *sphb,
+ uint32_t func, uint64_t addr,
+ uint64_t mask, uint32_t type)
+{
+ VFIOLegacyContainer *container = vfio_eeh_as_container(&sphb->iommu_as);
+ struct vfio_eeh_pe_op op = {
+ .op = VFIO_EEH_PE_INJECT_ERR,
+ .argsz = sizeof(op),
+ };
+
+ /* Set error type, address, and mask */
+ op.err.type = type;
+ op.err.addr = addr;
+ op.err.mask = mask;
+
+ /* Validate and set function code */
+ switch (func) {
+ case EEH_ERR_FUNC_LD_MEM_ADDR:
+ case EEH_ERR_FUNC_LD_MEM_DATA:
+ case EEH_ERR_FUNC_LD_IO_ADDR:
+ case EEH_ERR_FUNC_LD_IO_DATA:
+ case EEH_ERR_FUNC_LD_CFG_ADDR:
+ case EEH_ERR_FUNC_LD_CFG_DATA:
+ case EEH_ERR_FUNC_ST_MEM_ADDR:
+ case EEH_ERR_FUNC_ST_MEM_DATA:
+ case EEH_ERR_FUNC_ST_IO_ADDR:
+ case EEH_ERR_FUNC_ST_IO_DATA:
+ case EEH_ERR_FUNC_ST_CFG_ADDR:
+ case EEH_ERR_FUNC_ST_CFG_DATA:
+ case EEH_ERR_FUNC_DMA_RD_ADDR:
+ case EEH_ERR_FUNC_DMA_RD_DATA:
+ case EEH_ERR_FUNC_DMA_RD_MASTER:
+ case EEH_ERR_FUNC_DMA_RD_TARGET:
+ case EEH_ERR_FUNC_DMA_WR_ADDR:
+ case EEH_ERR_FUNC_DMA_WR_DATA:
+ case EEH_ERR_FUNC_DMA_WR_MASTER:
+ op.err.func = func;
+ break;
+ default:
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ /* Perform the ioctl to inject the error */
+ if (ioctl(container->fd, VFIO_EEH_PE_OP, &op) < 0) {
+ return RTAS_OUT_HW_ERROR;
+ }
+
+ return RTAS_OUT_SUCCESS;
+}
#else
bool spapr_phb_eeh_available(SpaprPhbState *sphb)
@@ -349,4 +398,8 @@ int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
return RTAS_OUT_NOT_SUPPORTED;
}
+int spapr_phb_vfio_errinjct(SpaprPhbState *sphb, int option)
+{
+ return RTAS_OUT_NOT_SUPPORTED;
+}
#endif /* CONFIG_VFIO_PCI */
--
2.51.0
© 2016 - 2025 Red Hat, Inc.