* [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support
@ 2025-12-05 9:45 Narayana Murty N
2025-12-05 9:45 ` [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT Narayana Murty N
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Narayana Murty N @ 2025-12-05 9:45 UTC (permalink / raw)
To: mahesh, maddy, mpe, christophe.leroy, gregkh, oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr,
sourabhjain
The series introduces complete support for RTAS-based hardware error
injection on pseries platforms. The implementation replaces the legacy
MMIO-based approach with a full PAPR-compliant workflow built around the
RTAS services:
ibm,open-errinjct
ibm,errinjct
ibm,close-errinjct
The new pseries_eeh_err_inject() interface enables controlled injection
of synthetic PCI, memory, and cache/TLB faults for platform validation,
EEH testing, firmware diagnostics, and tooling (e.g., bpftrace-based
tracing).
Current testing scope:
At this stage, the feature can be triggered only from VFIO-passthrough
devices assigned to a guest, and from userspace-exposed VFIO devices
using the VFIO_EEH_PE_INJECT_ERR ioctl.
Key Highlights
Dynamic acquisition of all required RTAS tokens and correct
open/errinjct/close session handling as defined by PAPR. A 1KB
naturally-aligned, zero-initialized RTAS working buffer is populated
exactly per PAPR buffer definitions.
Support for a wide range of error types:
0x03 - recovered-special-event
0x04 - corrupted-page
0x07 - ioa-bus-error (32-bit)
0x0F - ioa-bus-error-64 (64-bit)
0x09 - corrupted-dcache-start
0x0A - corrupted-dcache-end
0x0B - corrupted-icache-start
0x0C - corrupted-icache-end
0x0D - corrupted-tlb-start
0x0E - corrupted-tlb-end
All RTAS parameters use proper big-endian formatting (cpu_to_be32()).
Robust status-handling, printk-based diagnostics, and thorough
validation for invalid or unsupported conditions.
Error-specific buffer population logic is factored into helpers for
clarity and maintainability.
Fully tested on PowerVM with firmware that supports RTAS error
injection, along with the companion QEMU support posted here:
https://lore.kernel.org/all/20251029150618.186803-1-nnmlinux@linux.ibm.com/
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
Change Log:
RFC v0: https://lore.kernel.org/all/20251107091009.43034-1-nnmlinux@linux.ibm.com/
* Fixed PAPR ibm,open-errinjct output format (token,status order)
* Added pr_fmt handling for EEH subsystem compatibility
* Split into logical 4-patch series
* Addressed all review feedback on validation + rtas.c
Narayana Murty N (4):
powerpc/rtas: Handle special return format for
RTAS_FN_IBM_OPEN_ERRINJCT
powerpc/pseries: Add RTAS error injection buffer infrastructure
powerpc/pseries: Add RTAS error injection validation helpers
powerpc/pseries: Implement RTAS error injection via
pseries_eeh_err_inject
arch/powerpc/include/asm/rtas.h | 21 +
arch/powerpc/include/uapi/asm/eeh.h | 18 +
arch/powerpc/kernel/rtas.c | 42 +-
arch/powerpc/platforms/pseries/eeh_pseries.c | 428 ++++++++++++++++++-
4 files changed, 485 insertions(+), 24 deletions(-)
--
2.51.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT
2025-12-05 9:45 [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support Narayana Murty N
@ 2025-12-05 9:45 ` Narayana Murty N
2025-12-12 9:09 ` Sourabh Jain
2025-12-05 9:45 ` [PATCH 2/4] powerpc/pseries: Add RTAS error injection buffer infrastructure Narayana Murty N
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Narayana Murty N @ 2025-12-05 9:45 UTC (permalink / raw)
To: mahesh, maddy, mpe, christophe.leroy, gregkh, oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr,
sourabhjain
RTAS_FN_IBM_OPEN_ERRINJCT returns results in special format:
rets[0] = session token (output)
rets[1] = status code
rets[2..] = additional outputs (if any)
Unlike standard RTAS calls where:
rets[0] = status code
rets[1..] = outputs
This patch adds special handling for OPEN_ERRINJCT to:
1. Check correct status position (rets[1]) for __fetch_rtas_last_error()
2. Copy all rets[0..nret-1] to outputs[] (including token at rets[0])
3. Return status from rets[1] instead of rets[0]
Reference: OpenPOWER PAPR documentation
https://files.openpower.foundation/s/XFgfMaqLMD5Bcm8
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
arch/powerpc/kernel/rtas.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 8d81c1e7a8db..04c8438aadda 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1183,7 +1183,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
unsigned long flags;
struct rtas_args *args;
char *buff_copy = NULL;
- int ret;
+ int ret = 0;
if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
return -1;
@@ -1213,15 +1213,33 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
va_rtas_call_unlocked(args, token, nargs, nret, list);
va_end(list);
+ /* Special handling for RTAS_FN_IBM_OPEN_ERRINJCT for error fetching */
/* A -1 return code indicates that the last command couldn't
be completed due to a hardware error. */
- if (be32_to_cpu(args->rets[0]) == -1)
+
+ if (token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT) && nret > 1)
+ ret = be32_to_cpu(args->rets[1]);
+ else if (nret > 0)
+ ret = be32_to_cpu(args->rets[0]);
+
+ if (ret == -1)
buff_copy = __fetch_rtas_last_error(NULL);
- if (nret > 1 && outputs != NULL)
- for (i = 0; i < nret-1; ++i)
- outputs[i] = be32_to_cpu(args->rets[i + 1]);
- ret = (nret > 0) ? be32_to_cpu(args->rets[0]) : 0;
+ /* Handle outputs and return status */
+ if (nret > 1 && outputs != NULL) {
+ if (token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT)) {
+ /* Special case: rets[0]=token, rets[1]=status, rets[2..]=outputs */
+ for (i = 0; i < nret; ++i)
+ outputs[i] = be32_to_cpu(args->rets[i]);
+ } else {
+ /* Normal case: rets[0]=status, rets[1..]=outputs */
+ for (i = 0; i < nret - 1; ++i)
+ outputs[i] = be32_to_cpu(args->rets[i + 1]);
+ }
+ } else {
+ /* No outputs: just ret is status */
+ ret = (nret > 0) ? be32_to_cpu(args->rets[0]) : 0;
+ }
lockdep_unpin_lock(&rtas_lock, cookie);
raw_spin_unlock_irqrestore(&rtas_lock, flags);
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] powerpc/pseries: Add RTAS error injection buffer infrastructure
2025-12-05 9:45 [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support Narayana Murty N
2025-12-05 9:45 ` [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT Narayana Murty N
@ 2025-12-05 9:45 ` Narayana Murty N
2025-12-05 9:45 ` [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers Narayana Murty N
2025-12-05 9:45 ` [PATCH 4/4] powerpc/pseries: Implement RTAS error injection via pseries_eeh_err_inject Narayana Murty N
3 siblings, 0 replies; 8+ messages in thread
From: Narayana Murty N @ 2025-12-05 9:45 UTC (permalink / raw)
To: mahesh, maddy, mpe, christophe.leroy, gregkh, oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr,
sourabhjain
Adds global infrastructure required by the injection engine:
- a 1KB aligned RTAS working buffer in rtas.c
- a spinlock to serialize buffer access
- UAPI definitions for error-injection tokens (added to eeh.h)
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
arch/powerpc/include/asm/rtas.h | 21 +++++++++++++++++++++
arch/powerpc/include/uapi/asm/eeh.h | 18 ++++++++++++++++++
arch/powerpc/kernel/rtas.c | 12 ++++++++++++
3 files changed, 51 insertions(+)
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index d046bbd5017d..82512f822c7a 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -519,6 +519,27 @@ int rtas_get_error_log_max(void);
extern spinlock_t rtas_data_buf_lock;
extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
+/*
+ * RTAS Error Injection Buffer (PAPR-compliant)
+ * ============================================
+ *
+ * 1KB aligned, zero-initialized buffer for ibm,errinjct RTAS work area.
+ * Protected by rtas_errinjct_buf_lock for concurrent access safety.
+ *
+ * PAPR Requirement: ibm,errinjct requires a caller-allocated buffer passed
+ * via physical address. Buffer must accommodate largest error type layouts:
+ * - IOA bus error (64-bit): 8x32-bit words (32 bytes)
+ * - All other types: <=4x32-bit words (16 bytes)
+ *
+ * Usage:
+ * prepare_errinjct_buffer() -> spin_lock() -> rtas_call() -> spin_unlock()
+ *
+ * Alignment: SZ_1K ensures PAPR firmware requirements and cache-line safety.
+ */
+#define RTAS_ERRINJCT_BUF_SIZE 1024
+extern spinlock_t rtas_errinjct_buf_lock;
+extern char rtas_errinjct_buf[RTAS_ERRINJCT_BUF_SIZE];
+
/* RMO buffer reserved for user-space RTAS use */
extern unsigned long rtas_rmo_buf;
diff --git a/arch/powerpc/include/uapi/asm/eeh.h b/arch/powerpc/include/uapi/asm/eeh.h
index 3b5c47ff3fc4..86645cab2827 100644
--- a/arch/powerpc/include/uapi/asm/eeh.h
+++ b/arch/powerpc/include/uapi/asm/eeh.h
@@ -41,4 +41,22 @@
#define EEH_ERR_FUNC_DMA_WR_TARGET 19
#define EEH_ERR_FUNC_MAX 19
+/* RTAS PCI Error Injection Token Types */
+#define RTAS_ERR_TYPE_FATAL 0x1
+#define RTAS_ERR_TYPE_RECOVERED_RANDOM_EVENT 0x2
+#define RTAS_ERR_TYPE_RECOVERED_SPECIAL_EVENT 0x3
+#define RTAS_ERR_TYPE_CORRUPTED_PAGE 0x4
+#define RTAS_ERR_TYPE_CORRUPTED_SLB 0x5
+#define RTAS_ERR_TYPE_TRANSLATOR_FAILURE 0x6
+#define RTAS_ERR_TYPE_IOA_BUS_ERROR 0x7
+#define RTAS_ERR_TYPE_PLATFORM_SPECIFIC 0x8
+#define RTAS_ERR_TYPE_CORRUPTED_DCACHE_START 0x9
+#define RTAS_ERR_TYPE_CORRUPTED_DCACHE_END 0xA
+#define RTAS_ERR_TYPE_CORRUPTED_ICACHE_START 0xB
+#define RTAS_ERR_TYPE_CORRUPTED_ICACHE_END 0xC
+#define RTAS_ERR_TYPE_CORRUPTED_TLB_START 0xD
+#define RTAS_ERR_TYPE_CORRUPTED_TLB_END 0xE
+#define RTAS_ERR_TYPE_IOA_BUS_ERROR_64 0xF
+#define RTAS_ERR_TYPE_UPSTREAM_IO_ERROR 0x10
+
#endif /* _ASM_POWERPC_EEH_H */
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 04c8438aadda..ae1cd7964bae 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -769,6 +769,18 @@ EXPORT_SYMBOL_GPL(rtas_data_buf);
unsigned long rtas_rmo_buf;
+/*
+ * RTAS Error Injection Buffer - Global Definitions
+ * Global 1KB buffer and spinlock for ibm,errinjct RTAS service.
+ * Exported for pseries EEH error injection usage.
+ */
+
+DEFINE_SPINLOCK(rtas_errinjct_buf_lock);
+EXPORT_SYMBOL_GPL(rtas_errinjct_buf_lock);
+
+char rtas_errinjct_buf[1024] __aligned(SZ_1K);
+EXPORT_SYMBOL_GPL(rtas_errinjct_buf);
+
/*
* If non-NULL, this gets called when the kernel terminates.
* This is done like this so rtas_flash can be a module.
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers
2025-12-05 9:45 [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support Narayana Murty N
2025-12-05 9:45 ` [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT Narayana Murty N
2025-12-05 9:45 ` [PATCH 2/4] powerpc/pseries: Add RTAS error injection buffer infrastructure Narayana Murty N
@ 2025-12-05 9:45 ` Narayana Murty N
2025-12-06 5:30 ` kernel test robot
2025-12-10 4:02 ` kernel test robot
2025-12-05 9:45 ` [PATCH 4/4] powerpc/pseries: Implement RTAS error injection via pseries_eeh_err_inject Narayana Murty N
3 siblings, 2 replies; 8+ messages in thread
From: Narayana Murty N @ 2025-12-05 9:45 UTC (permalink / raw)
To: mahesh, maddy, mpe, christophe.leroy, gregkh, oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr,
sourabhjain
Add comprehensive validation helpers for RTAS error injection parameters:
- validate_addr_mask_in_pe(): BAR range validation
- validate_err_type(): Token range check
- Type-specific validators (special-event, corrupted-page, ioa-bus-error)
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
arch/powerpc/platforms/pseries/eeh_pseries.c | 261 +++++++++++++++++++
1 file changed, 261 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index b12ef382fec7..110e8cf10985 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -33,6 +33,10 @@
#include <asm/ppc-pci.h>
#include <asm/rtas.h>
+#ifndef pr_fmt
+#define pr_fmt(fmt) "EEH: " fmt
+#endif
+
/* RTAS tokens */
static int ibm_set_eeh_option;
static int ibm_set_slot_reset;
@@ -786,6 +790,263 @@ static int pseries_notify_resume(struct eeh_dev *edev)
}
#endif
+/**
+ * validate_addr_mask_in_pe - Validate that an addr+mask fall within PE's BARs
+ * @pe: EEH PE containing one or more PCI devices
+ * @addr: Address to validate
+ * @mask: Address mask to validate
+ *
+ * Checks that @addr is mapped into a BAR/MMIO region of any device belonging
+ * to the PE. If @mask is non-zero, ensures it is consistent with @addr.
+ *
+ * Return: 0 if valid, RTAS_INVALID_PARAMETER on failure.
+ */
+
+static int validate_addr_mask_in_pe(struct eeh_pe *pe, unsigned long addr,
+ unsigned long mask)
+{
+ struct eeh_dev *edev, *tmp;
+ struct pci_dev *pdev;
+ int bar;
+ resource_size_t bar_start, bar_len;
+ bool valid = false;
+
+ /* nothing to validate */
+ if (addr == 0 && mask == 0)
+ return 0;
+
+ eeh_pe_for_each_dev(pe, edev, tmp) {
+ pdev = eeh_dev_to_pci_dev(edev);
+ if (!pdev)
+ continue;
+
+ for (bar = 0; bar < PCI_NUM_RESOURCES; bar++) {
+ bar_start = pci_resource_start(pdev, bar);
+ bar_len = pci_resource_len(pdev, bar);
+
+ if (!bar_len)
+ continue;
+
+ if (addr >= bar_start && addr < (bar_start + bar_len)) {
+ /* ensure mask makes sense for the addr value */
+ if ((addr & mask) != addr) {
+ pr_err("Mask 0x%lx invalid for addr 0x%lx in BAR[%d] range 0x%llx-0x%llx\n",
+ mask, addr, bar,
+ (unsigned long long)bar_start,
+ (unsigned long long)(bar_start + bar_len));
+ return RTAS_INVALID_PARAMETER;
+ }
+
+ pr_debug("addr=0x%lx with mask=0x%lx validated in BAR[%d] of %s\n",
+ addr, mask, bar, pci_name(pdev));
+ valid = true;
+ }
+ }
+ }
+
+ if (!valid) {
+ pr_err("addr=0x%lx not valid within any BAR of any device in PE\n",
+ addr);
+ return RTAS_INVALID_PARAMETER;
+ }
+
+ return 0;
+}
+
+/**
+ * validate_err_type - Basic sanity check for RTAS error type
+ * @type: RTAS error type
+ *
+ * Ensures that the error type is within the valid RTAS error type range.
+ *
+ * Return: true if valid, false otherwise.
+ */
+
+static bool validate_err_type(int type)
+{
+ if (type < RTAS_ERR_TYPE_FATAL ||
+ type > RTAS_ERR_TYPE_UPSTREAM_IO_ERROR)
+ return false;
+
+ return true;
+}
+
+/**
+ * validate_special_event - Validate parameters for special-event injection
+ * @addr: Address parameter (should be zero)
+ * @mask: Mask parameter (should be zero)
+ *
+ * Special-event error injection should not take addr/mask. Rejects if either
+ * is set.
+ *
+ * Return: 0 if valid, RTAS_INVALID_PARAMETER otherwise.
+ */
+
+static int validate_special_event(unsigned long addr, unsigned long mask)
+{
+ if (addr || mask) {
+ pr_err("Special-event should not specify addr/mask\n");
+ return RTAS_INVALID_PARAMETER;
+ }
+ return 0;
+}
+
+/**
+ * validate_corrupted_page - Validate parameters for corrupted-page injection
+ * @pe: EEH PE (unused here, for consistency)
+ * @addr: Physical page address (required)
+ * @mask: Address mask (ignored if non-zero)
+ *
+ * Ensures a valid non-zero page address is provided. Warns if mask is set.
+ *
+ * Return: 0 if valid, RTAS_INVALID_PARAMETER otherwise.
+ */
+
+static int validate_corrupted_page(struct eeh_pe *pe __maybe_unused,
+ unsigned long addr, unsigned long mask)
+{
+ if (!addr) {
+ pr_err("corrupted-page requires non-zero addr\n");
+ return RTAS_INVALID_PARAMETER;
+ }
+ /* Mask not meaningful for corrupted-page */
+ if (mask)
+ pr_warn("corrupted-page ignoring mask=0x%lx\n", mask);
+
+ return 0;
+}
+
+/**
+ * validate_ioa_bus_error - Validate parameters for IOA bus error injection
+ * @pe: EEH PE whose BARs are validated against
+ * @addr: Address parameter (optional)
+ * @mask: Mask parameter (optional)
+ *
+ * For IOA bus error injections, @addr and @mask are optional. If present,
+ * they must map into the PE's MMIO/CFG space.
+ *
+ * Return: 0 if valid or addr/mask absent, RTAS_INVALID_PARAMETER otherwise.
+ */
+
+static int validate_ioa_bus_error(struct eeh_pe *pe,
+ unsigned long addr, unsigned long mask)
+{
+ /* Must map into BAR/MMIO/CFG space of PE */
+ return validate_addr_mask_in_pe(pe, addr, mask);
+}
+
+
+/**
+ * prepare_errinjct_buffer - Prepare RTAS error injection work buffer
+ * @pe: EEH PE for the target device(s)
+ * @type: RTAS error type
+ * @func: Error function selector (semantics vary by type)
+ * @addr: Address argument (type-dependent)
+ * @mask: Mask argument (type-dependent)
+ *
+ * Clears the global error injection work buffer and populates it based on
+ * the error type and parameters provided. Performs inline validation of the
+ * arguments for each supported error type.
+ *
+ * Return: 0 on success, or RTAS_INVALID_PARAMETER / -EINVAL on failure.
+ */
+
+static int prepare_errinjct_buffer(struct eeh_pe *pe, int type, int func,
+ unsigned long addr, unsigned long mask)
+{
+ u64 *buf64;
+ u32 *buf32;
+
+ memset(rtas_errinjct_buf, 0, RTAS_ERRINJCT_BUF_SIZE);
+ buf64 = (u64 *)rtas_errinjct_buf;
+ buf32 = (u32 *)rtas_errinjct_buf;
+
+ switch (type) {
+ case RTAS_ERR_TYPE_RECOVERED_SPECIAL_EVENT:
+ /* func must be 1 = non-persistent or 2 = persistent */
+ if (func < 1 || func > 2)
+ return RTAS_INVALID_PARAMETER;
+
+ if (validate_special_event(addr, mask))
+ return RTAS_INVALID_PARAMETER;
+
+ buf32[0] = cpu_to_be32(func);
+ break;
+
+ case RTAS_ERR_TYPE_CORRUPTED_PAGE:
+ /* addr required: physical page address */
+ if (addr == 0)
+ return RTAS_INVALID_PARAMETER;
+
+ if (validate_corrupted_page(pe, addr, mask))
+ return RTAS_INVALID_PARAMETER;
+
+ buf32[0] = cpu_to_be32(upper_32_bits(addr));
+ buf32[1] = cpu_to_be32(lower_32_bits(addr));
+ break;
+
+ case RTAS_ERR_TYPE_IOA_BUS_ERROR:
+ /* 32-bit IOA bus error: addr/mask optional */
+ if (func < EEH_ERR_FUNC_LD_MEM_ADDR || func > EEH_ERR_FUNC_MAX)
+ return RTAS_INVALID_PARAMETER;
+
+ if (addr || mask) {
+ if (validate_ioa_bus_error(pe, addr, mask))
+ return RTAS_INVALID_PARAMETER;
+ }
+
+ buf32[0] = cpu_to_be32((u32)addr);
+ buf32[1] = cpu_to_be32((u32)mask);
+ buf32[2] = cpu_to_be32(pe->addr);
+ buf32[3] = cpu_to_be32(BUID_HI(pe->phb->buid));
+ buf32[4] = cpu_to_be32(BUID_LO(pe->phb->buid));
+ buf32[5] = cpu_to_be32(func);
+ break;
+
+ case RTAS_ERR_TYPE_IOA_BUS_ERROR_64:
+ /* 64-bit IOA bus error: addr/mask optional */
+ if (func < EEH_ERR_FUNC_MIN || func > EEH_ERR_FUNC_MAX)
+ return RTAS_INVALID_PARAMETER;
+
+ if (addr || mask) {
+ if (validate_ioa_bus_error(pe, addr, mask))
+ return RTAS_INVALID_PARAMETER;
+ }
+
+ buf64[0] = cpu_to_be64(addr);
+ buf64[1] = cpu_to_be64(mask);
+ buf32[4] = cpu_to_be32(pe->addr);
+ buf32[5] = cpu_to_be32(BUID_HI(pe->phb->buid));
+ buf32[6] = cpu_to_be32(BUID_LO(pe->phb->buid));
+ buf32[7] = cpu_to_be32(func);
+ break;
+
+ case RTAS_ERR_TYPE_CORRUPTED_DCACHE_START:
+ case RTAS_ERR_TYPE_CORRUPTED_DCACHE_END:
+ case RTAS_ERR_TYPE_CORRUPTED_ICACHE_START:
+ case RTAS_ERR_TYPE_CORRUPTED_ICACHE_END:
+ /* addr/mask optional, no strict validation */
+ buf32[0] = cpu_to_be32(addr);
+ buf32[1] = cpu_to_be32(mask);
+ break;
+
+ case RTAS_ERR_TYPE_CORRUPTED_TLB_START:
+ case RTAS_ERR_TYPE_CORRUPTED_TLB_END:
+ /* only addr field relevant */
+ buf32[0] = cpu_to_be32(addr);
+ break;
+
+ default:
+ pr_err("Unsupported error type 0x%x\n", type);
+ return -EINVAL;
+ }
+
+ pr_debug("RTAS: errinjct buffer prepared: type=%d func=%d addr=0x%lx mask=0x%lx\n",
+ type, func, addr, mask);
+
+ return 0;
+}
+
/**
* pseries_eeh_err_inject - Inject specified error to the indicated PE
* @pe: the indicated PE
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] powerpc/pseries: Implement RTAS error injection via pseries_eeh_err_inject
2025-12-05 9:45 [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support Narayana Murty N
` (2 preceding siblings ...)
2025-12-05 9:45 ` [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers Narayana Murty N
@ 2025-12-05 9:45 ` Narayana Murty N
3 siblings, 0 replies; 8+ messages in thread
From: Narayana Murty N @ 2025-12-05 9:45 UTC (permalink / raw)
To: mahesh, maddy, mpe, christophe.leroy, gregkh, oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr,
sourabhjain
Replace legacy MMIO error injection with full PAPR-compliant RTAS error
injection supporting 14+ error types via
- ibm,open-errinjct
- ibm,errinjct
- ibm,close-errinjct.
Key features:
- Complete open-session-inject-close cycle management
- Special handling for ibm,open-errinjct output format (token,status)
- Comprehensive buffer preparation per PAPR layouts
- All pr_* logging uses pr_fmt("EEH: ") prefix
Tested with corresponding QEMU patches:
https://lore.kernel.org/all/20251029150618.186803-1-nnmlinux@linux.ibm.com/
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
arch/powerpc/platforms/pseries/eeh_pseries.c | 164 +++++++++++++++++--
1 file changed, 146 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 110e8cf10985..d0010f2fc656 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -1047,6 +1047,98 @@ static int prepare_errinjct_buffer(struct eeh_pe *pe, int type, int func,
return 0;
}
+/**
+ * rtas_open_errinjct_session - Open an RTAS error injection session
+ *
+ * Opens a session with the RTAS ibm,open-errinjct service.
+ *
+ * Return: Positive session token on success, negative error code on failure.
+ */
+static int rtas_open_errinjct_session(void)
+{
+ int open_token, args[2] = {0};
+ int rc, status, session_token = -1;
+
+ open_token = rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT);
+ if (open_token == RTAS_UNKNOWN_SERVICE) {
+ pr_err("RTAS: ibm,open-errinjct not available\n");
+ return RTAS_UNKNOWN_SERVICE;
+ }
+
+ /* Call open; original code treated rtas_call return as session token */
+ rc = rtas_call(open_token, 0, 2, args);
+ status = args[1];
+ if (status != 0) {
+ pr_err("RTAS: open-errinjct failed: status=%d args[1]=%d rc=%d\n",
+ status, args[1], rc);
+ return status ? status : -EIO;
+ }
+
+ session_token = args[0];
+ pr_info("Opened injection session: token=%d\n", session_token);
+ return session_token;
+}
+
+/**
+ * rtas_close_errinjct_session - Close an RTAS error injection session
+ * @session_token: Session token returned from open
+ *
+ * Attempts to close a previously opened error injection session. Best-effort;
+ * logs warnings if close fails or if service is unavailable.
+ */
+
+static void rtas_close_errinjct_session(int session_token)
+{
+ int close_token, args[2] = {0};
+
+ if (session_token <= 0)
+ return;
+
+ close_token = rtas_function_token(RTAS_FN_IBM_CLOSE_ERRINJCT);
+ if (close_token == RTAS_UNKNOWN_SERVICE) {
+ pr_warn("close-errinjct not available\n");
+ return;
+ }
+
+ args[0] = 0;
+ rtas_call(close_token, 1, 1, &session_token, args);
+ if (args[0]) {
+ pr_warn("close-errinjct args[0]=%d\n", args[0]);
+ }
+}
+
+/**
+ * do_errinjct_call - Invoke the RTAS error injection service
+ * @errinjct_token: RTAS token for ibm,errinjct
+ * @type: RTAS error type
+ * @session_token: RTAS error injection session token
+ *
+ * Issues the RTAS ibm,errinjct call with the prepared work buffer. Logs errors
+ * on failure.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+
+static int do_errinjct_call(int errinjct_token, int type, int session_token)
+{
+ int rc, status;
+
+ if (errinjct_token == RTAS_UNKNOWN_SERVICE)
+ return -ENODEV;
+
+ /* errinjct takes: type, session_token, workbuf pointer (3 in), returns status */
+ rc = rtas_call(errinjct_token, 3, 1, &status, type, session_token,
+ rtas_errinjct_buf);
+
+ if (rc || status != 0) {
+ pr_err("RTAS: errinjct failed: rc=%d, status=%d\n", rc, status);
+ return status ? status : -EIO;
+ }
+
+ pr_info("RTAS: errinjct ok: rc=%d, status=%d\n", rc, status);
+ return 0;
+}
+
/**
* pseries_eeh_err_inject - Inject specified error to the indicated PE
* @pe: the indicated PE
@@ -1060,30 +1152,66 @@ static int prepare_errinjct_buffer(struct eeh_pe *pe, int type, int func,
static int pseries_eeh_err_inject(struct eeh_pe *pe, int type, int func,
unsigned long addr, unsigned long mask)
{
- struct eeh_dev *pdev;
+ int rc = 0;
+ int session_token = -1;
+ int errinjct_token;
- /* Check on PCI error type */
- if (type != EEH_ERR_TYPE_32 && type != EEH_ERR_TYPE_64)
- return -EINVAL;
+ /* Validate type */
+ if (!validate_err_type(type)) {
+ pr_err("RTAS: invalid error type 0x%x\n", type);
+ return RTAS_INVALID_PARAMETER;
+ }
+ pr_debug("RTAS: error type 0x%x\n", type);
- switch (func) {
- case EEH_ERR_FUNC_LD_MEM_ADDR:
- case EEH_ERR_FUNC_LD_MEM_DATA:
- case EEH_ERR_FUNC_ST_MEM_ADDR:
- case EEH_ERR_FUNC_ST_MEM_DATA:
- /* injects a MMIO error for all pdev's belonging to PE */
- pci_lock_rescan_remove();
- list_for_each_entry(pdev, &pe->edevs, entry)
- eeh_pe_inject_mmio_error(pdev->pdev);
- pci_unlock_rescan_remove();
- break;
- default:
- return -ERANGE;
+ /* For IOA bus errors we must validate err_func and addr/mask in PE.
+ * For other types: if addr/mask present we'll still validate BAR range;
+ * otherwise skip function checks.
+ */
+ if (type == RTAS_ERR_TYPE_IOA_BUS_ERROR ||
+ type == RTAS_ERR_TYPE_IOA_BUS_ERROR_64) {
+ /* Validate that addr/mask fall in the PE's BAR ranges */
+ rc = validate_addr_mask_in_pe(pe, addr, mask);
+ if (rc)
+ return rc;
+ } else if (addr || mask) {
+ /* If caller provided addr/mask for a non-IOA type, do a BAR check too */
+ rc = validate_addr_mask_in_pe(pe, addr, mask);
+ if (rc)
+ return rc;
}
- return 0;
+ /* Open RTAS session */
+ session_token = rtas_open_errinjct_session();
+ if (session_token < 0)
+ return session_token;
+
+ /* get errinjct token */
+ errinjct_token = rtas_function_token(RTAS_FN_IBM_ERRINJCT);
+ if (errinjct_token == RTAS_UNKNOWN_SERVICE) {
+ pr_err("RTAS: ibm,errinjct not available\n");
+ rc = -ENODEV;
+ goto out_close;
+ }
+
+ /* prepare shared buffer while holding lock */
+ spin_lock(&rtas_errinjct_buf_lock);
+ rc = prepare_errinjct_buffer(pe, type, func, addr, mask);
+ if (rc) {
+ spin_unlock(&rtas_errinjct_buf_lock);
+ goto out_close;
+ }
+
+ /* perform the errinjct RTAS call */
+ rc = do_errinjct_call(errinjct_token, type, session_token);
+ spin_unlock(&rtas_errinjct_buf_lock);
+
+out_close:
+ /* always attempt close if we opened a session */
+ rtas_close_errinjct_session(session_token);
+ return rc;
}
+
static struct eeh_ops pseries_eeh_ops = {
.name = "pseries",
.probe = pseries_eeh_probe,
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers
2025-12-05 9:45 ` [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers Narayana Murty N
@ 2025-12-06 5:30 ` kernel test robot
2025-12-10 4:02 ` kernel test robot
1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-12-06 5:30 UTC (permalink / raw)
To: Narayana Murty N, mahesh, maddy, mpe, christophe.leroy, gregkh,
oohall, npiggin
Cc: oe-kbuild-all, linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat,
ganeshgr, sourabhjain
Hi Narayana,
kernel test robot noticed the following build warnings:
[auto build test WARNING on powerpc/next]
[also build test WARNING on powerpc/fixes linus/master v6.18 next-20251205]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Narayana-Murty-N/powerpc-rtas-Handle-special-return-format-for-RTAS_FN_IBM_OPEN_ERRINJCT/20251205-214855
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
patch link: https://lore.kernel.org/r/20251205094510.4671-4-nnmlinux%40linux.ibm.com
patch subject: [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers
config: powerpc64-randconfig-001-20251206 (https://download.01.org/0day-ci/archive/20251206/202512061324.kG0T41Tg-lkp@intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251206/202512061324.kG0T41Tg-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512061324.kG0T41Tg-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: arch/powerpc/platforms/pseries/eeh_pseries.c:906 function parameter '__maybe_unused' not described in 'validate_corrupted_page'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers
2025-12-05 9:45 ` [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers Narayana Murty N
2025-12-06 5:30 ` kernel test robot
@ 2025-12-10 4:02 ` kernel test robot
1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-12-10 4:02 UTC (permalink / raw)
To: Narayana Murty N, mahesh, maddy, mpe, christophe.leroy, gregkh,
oohall, npiggin
Cc: oe-kbuild-all, linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat,
ganeshgr, sourabhjain
Hi Narayana,
kernel test robot noticed the following build warnings:
[auto build test WARNING on powerpc/next]
[also build test WARNING on powerpc/fixes linus/master v6.18 next-20251209]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Narayana-Murty-N/powerpc-rtas-Handle-special-return-format-for-RTAS_FN_IBM_OPEN_ERRINJCT/20251205-214855
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
patch link: https://lore.kernel.org/r/20251205094510.4671-4-nnmlinux%40linux.ibm.com
patch subject: [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers
config: powerpc64-randconfig-r122-20251210 (https://download.01.org/0day-ci/archive/20251210/202512101130.EYUo0oZx-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 6ec8c4351cfc1d0627d1633b02ea787bd29c77d8)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251210/202512101130.EYUo0oZx-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512101130.EYUo0oZx-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
arch/powerpc/platforms/pseries/eeh_pseries.c:743:55: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short [usertype] @@ got restricted __be16 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:743:55: sparse: expected unsigned short [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:743:55: sparse: got restricted __be16 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:767:40: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short [usertype] @@ got restricted __be16 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:767:40: sparse: expected unsigned short [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:767:40: sparse: got restricted __be16 [usertype]
>> arch/powerpc/platforms/pseries/eeh_pseries.c:973:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:973:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:973:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:984:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:984:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:984:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:985:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:985:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:985:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:998:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:998:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:998:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:999:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:999:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:999:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1000:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1000:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1000:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1001:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1001:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1001:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1002:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1002:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1002:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1003:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1003:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1003:26: sparse: got restricted __be32 [usertype]
>> arch/powerpc/platforms/pseries/eeh_pseries.c:1016:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned long long [usertype] @@ got restricted __be64 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1016:26: sparse: expected unsigned long long [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1016:26: sparse: got restricted __be64 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1017:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned long long [usertype] @@ got restricted __be64 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1017:26: sparse: expected unsigned long long [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1017:26: sparse: got restricted __be64 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1018:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1018:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1018:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1019:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1019:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1019:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1020:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1020:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1020:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1021:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1021:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1021:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1029:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1029:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1029:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1030:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1030:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1030:26: sparse: got restricted __be32 [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1036:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] @@ got restricted __be32 [usertype] @@
arch/powerpc/platforms/pseries/eeh_pseries.c:1036:26: sparse: expected unsigned int [usertype]
arch/powerpc/platforms/pseries/eeh_pseries.c:1036:26: sparse: got restricted __be32 [usertype]
vim +973 arch/powerpc/platforms/pseries/eeh_pseries.c
937
938
939 /**
940 * prepare_errinjct_buffer - Prepare RTAS error injection work buffer
941 * @pe: EEH PE for the target device(s)
942 * @type: RTAS error type
943 * @func: Error function selector (semantics vary by type)
944 * @addr: Address argument (type-dependent)
945 * @mask: Mask argument (type-dependent)
946 *
947 * Clears the global error injection work buffer and populates it based on
948 * the error type and parameters provided. Performs inline validation of the
949 * arguments for each supported error type.
950 *
951 * Return: 0 on success, or RTAS_INVALID_PARAMETER / -EINVAL on failure.
952 */
953
954 static int prepare_errinjct_buffer(struct eeh_pe *pe, int type, int func,
955 unsigned long addr, unsigned long mask)
956 {
957 u64 *buf64;
958 u32 *buf32;
959
960 memset(rtas_errinjct_buf, 0, RTAS_ERRINJCT_BUF_SIZE);
961 buf64 = (u64 *)rtas_errinjct_buf;
962 buf32 = (u32 *)rtas_errinjct_buf;
963
964 switch (type) {
965 case RTAS_ERR_TYPE_RECOVERED_SPECIAL_EVENT:
966 /* func must be 1 = non-persistent or 2 = persistent */
967 if (func < 1 || func > 2)
968 return RTAS_INVALID_PARAMETER;
969
970 if (validate_special_event(addr, mask))
971 return RTAS_INVALID_PARAMETER;
972
> 973 buf32[0] = cpu_to_be32(func);
974 break;
975
976 case RTAS_ERR_TYPE_CORRUPTED_PAGE:
977 /* addr required: physical page address */
978 if (addr == 0)
979 return RTAS_INVALID_PARAMETER;
980
981 if (validate_corrupted_page(pe, addr, mask))
982 return RTAS_INVALID_PARAMETER;
983
984 buf32[0] = cpu_to_be32(upper_32_bits(addr));
985 buf32[1] = cpu_to_be32(lower_32_bits(addr));
986 break;
987
988 case RTAS_ERR_TYPE_IOA_BUS_ERROR:
989 /* 32-bit IOA bus error: addr/mask optional */
990 if (func < EEH_ERR_FUNC_LD_MEM_ADDR || func > EEH_ERR_FUNC_MAX)
991 return RTAS_INVALID_PARAMETER;
992
993 if (addr || mask) {
994 if (validate_ioa_bus_error(pe, addr, mask))
995 return RTAS_INVALID_PARAMETER;
996 }
997
998 buf32[0] = cpu_to_be32((u32)addr);
999 buf32[1] = cpu_to_be32((u32)mask);
1000 buf32[2] = cpu_to_be32(pe->addr);
1001 buf32[3] = cpu_to_be32(BUID_HI(pe->phb->buid));
1002 buf32[4] = cpu_to_be32(BUID_LO(pe->phb->buid));
1003 buf32[5] = cpu_to_be32(func);
1004 break;
1005
1006 case RTAS_ERR_TYPE_IOA_BUS_ERROR_64:
1007 /* 64-bit IOA bus error: addr/mask optional */
1008 if (func < EEH_ERR_FUNC_MIN || func > EEH_ERR_FUNC_MAX)
1009 return RTAS_INVALID_PARAMETER;
1010
1011 if (addr || mask) {
1012 if (validate_ioa_bus_error(pe, addr, mask))
1013 return RTAS_INVALID_PARAMETER;
1014 }
1015
> 1016 buf64[0] = cpu_to_be64(addr);
1017 buf64[1] = cpu_to_be64(mask);
1018 buf32[4] = cpu_to_be32(pe->addr);
1019 buf32[5] = cpu_to_be32(BUID_HI(pe->phb->buid));
1020 buf32[6] = cpu_to_be32(BUID_LO(pe->phb->buid));
1021 buf32[7] = cpu_to_be32(func);
1022 break;
1023
1024 case RTAS_ERR_TYPE_CORRUPTED_DCACHE_START:
1025 case RTAS_ERR_TYPE_CORRUPTED_DCACHE_END:
1026 case RTAS_ERR_TYPE_CORRUPTED_ICACHE_START:
1027 case RTAS_ERR_TYPE_CORRUPTED_ICACHE_END:
1028 /* addr/mask optional, no strict validation */
1029 buf32[0] = cpu_to_be32(addr);
1030 buf32[1] = cpu_to_be32(mask);
1031 break;
1032
1033 case RTAS_ERR_TYPE_CORRUPTED_TLB_START:
1034 case RTAS_ERR_TYPE_CORRUPTED_TLB_END:
1035 /* only addr field relevant */
1036 buf32[0] = cpu_to_be32(addr);
1037 break;
1038
1039 default:
1040 pr_err("Unsupported error type 0x%x\n", type);
1041 return -EINVAL;
1042 }
1043
1044 pr_debug("RTAS: errinjct buffer prepared: type=%d func=%d addr=0x%lx mask=0x%lx\n",
1045 type, func, addr, mask);
1046
1047 return 0;
1048 }
1049
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT
2025-12-05 9:45 ` [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT Narayana Murty N
@ 2025-12-12 9:09 ` Sourabh Jain
0 siblings, 0 replies; 8+ messages in thread
From: Sourabh Jain @ 2025-12-12 9:09 UTC (permalink / raw)
To: Narayana Murty N, mahesh, maddy, mpe, christophe.leroy, gregkh,
oohall, npiggin
Cc: linuxppc-dev, linux-kernel, tyreld, vaibhav, sbhat, ganeshgr
On 05/12/25 15:15, Narayana Murty N wrote:
> RTAS_FN_IBM_OPEN_ERRINJCT returns results in special format:
> rets[0] = session token (output)
> rets[1] = status code
> rets[2..] = additional outputs (if any)
>
> Unlike standard RTAS calls where:
> rets[0] = status code
> rets[1..] = outputs
>
> This patch adds special handling for OPEN_ERRINJCT to:
> 1. Check correct status position (rets[1]) for __fetch_rtas_last_error()
> 2. Copy all rets[0..nret-1] to outputs[] (including token at rets[0])
> 3. Return status from rets[1] instead of rets[0]
>
> Reference: OpenPOWER PAPR documentation
> https://files.openpower.foundation/s/XFgfMaqLMD5Bcm8
> Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
> ---
> arch/powerpc/kernel/rtas.c | 30 ++++++++++++++++++++++++------
> 1 file changed, 24 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index 8d81c1e7a8db..04c8438aadda 100644
> --- a/arch/powerpc/kernel/rtas.c
> +++ b/arch/powerpc/kernel/rtas.c
> @@ -1183,7 +1183,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
> unsigned long flags;
> struct rtas_args *args;
> char *buff_copy = NULL;
> - int ret;
> + int ret = 0;
>
> if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
> return -1;
> @@ -1213,15 +1213,33 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
> va_rtas_call_unlocked(args, token, nargs, nret, list);
> va_end(list);
>
> + /* Special handling for RTAS_FN_IBM_OPEN_ERRINJCT for error fetching */
It would be more helpful if we explain why special handling is needed.
> /* A -1 return code indicates that the last command couldn't
> be completed due to a hardware error. */
> - if (be32_to_cpu(args->rets[0]) == -1)
> +
The above empty line can be avoided.
> + if (token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT) && nret > 1)
> + ret = be32_to_cpu(args->rets[1]);
> + else if (nret > 0)
> + ret = be32_to_cpu(args->rets[0]);
> +
> + if (ret == -1)It would be more helpful if we explain why special handling is needed.
>
> buff_copy = __fetch_rtas_last_error(NULL);
>
> - if (nret > 1 && outputs != NULL)
> - for (i = 0; i < nret-1; ++i)
> - outputs[i] = be32_to_cpu(args->rets[i + 1]);
> - ret = (nret > 0) ? be32_to_cpu(args->rets[0]) : 0;
> + /* Handle outputs and return status */
Return status is already handled above, isn't it?
> + if (nret > 1 && outputs != NULL) {
> + if (token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT)) {
> + /* Special case: rets[0]=token, rets[1]=status, rets[2..]=outputs */
> + for (i = 0; i < nret; ++i)
> + outputs[i] = be32_to_cpu(args->rets[i]);
> + } else {
> + /* Normal case: rets[0]=status, rets[1..]=outputs */
> + for (i = 0; i < nret - 1; ++i)
> + outputs[i] = be32_to_cpu(args->rets[i + 1]);
> + }
> + } else {
> + /* No outputs: just ret is status */
> + ret = (nret > 0) ? be32_to_cpu(args->rets[0]) : 0;
> + }
Do we really need to calculated the ret again here?
>
> lockdep_unpin_lock(&rtas_lock, cookie);
> raw_spin_unlock_irqrestore(&rtas_lock, flags);
- Sourabh Jain
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-12-12 9:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-05 9:45 [PATCH 0/4] powerpc/pseries: Add full RTAS-based error injection support Narayana Murty N
2025-12-05 9:45 ` [PATCH 1/4] powerpc/rtas: Handle special return format for RTAS_FN_IBM_OPEN_ERRINJCT Narayana Murty N
2025-12-12 9:09 ` Sourabh Jain
2025-12-05 9:45 ` [PATCH 2/4] powerpc/pseries: Add RTAS error injection buffer infrastructure Narayana Murty N
2025-12-05 9:45 ` [PATCH 3/4] powerpc/pseries: Add RTAS error injection validation helpers Narayana Murty N
2025-12-06 5:30 ` kernel test robot
2025-12-10 4:02 ` kernel test robot
2025-12-05 9:45 ` [PATCH 4/4] powerpc/pseries: Implement RTAS error injection via pseries_eeh_err_inject Narayana Murty N
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).