* [PATCH v3 1/5] dt-bindings: arm: ras: Introduce ARM RAS error sources
2026-09-18 9:57 [PATCH v3 0/5] arm: ras: Add DT frontend support for ARM RAS Umang Chheda
@ 2026-09-18 9:57 ` Umang Chheda
2026-09-18 9:57 ` [PATCH v3 2/5] arm64: ras: Add Device Tree frontend Umang Chheda
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Umang Chheda @ 2026-09-18 9:57 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt, conor+dt, richardcochran,
Borislav Petkov, Catalin Marinas, Will Deacon, Lorenzo Pieralisi,
Sudeep Holla, Rafael J . Wysocki, Len Brown, Tony Luck,
Robin Murphy, Peter Zijlstra, James Morse
Cc: linux-arm-msm, devicetree, linux-kernel, linux-edac, Ruidong Tian,
umang.chheda, avaneesh.dwivedi
ARMv8 and later processors implement the RAS (Reliability,
Availability and Serviceability) extensions, exposing hardware
error records through a standardised register interface.
Add Device Tree bindings to describe RAS error sources.
Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
---
.../devicetree/bindings/arm/arm,ras.yaml | 235 ++++++++++++++++++
include/dt-bindings/arm/arm,ras.h | 11 +
2 files changed, 246 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/arm,ras.yaml
create mode 100644 include/dt-bindings/arm/arm,ras.h
diff --git a/Documentation/devicetree/bindings/arm/arm,ras.yaml b/Documentation/devicetree/bindings/arm/arm,ras.yaml
new file mode 100644
index 000000000000..8bff222f77c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,ras.yaml
@@ -0,0 +1,235 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/arm,ras.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM RAS error source
+
+maintainers:
+ - Umang Chheda <umang.chheda@oss.qualcomm.com>
+
+description: |
+ ARMv8 and later processors implement the Reliability, Availability and
+ Serviceability (RAS) extensions. Hardware blocks that support RAS expose
+ one or more error records through a standardised register interface. Each
+ error record captures information about a detected hardware error (cache
+ ECC fault, TLB parity error, interconnect error, etc.) and can optionally
+ signal the OS via an interrupt.
+
+ Each DT node described by this binding represents one RAS error source —
+ a hardware block that exposes a set of error records. Error records are
+ accessed either through system registers (for processor-local resources
+ such as L1/L2 caches and TLBs) or through a memory-mapped register window
+ (for shared or off-core resources such as L3 caches, SMMUs and GICs).
+
+properties:
+ compatible:
+ description:
+ Identifies the class of hardware block this error source belongs to.
+ arm,ras-processor covers processor error sources (cache, TLB, etc.).
+ arm,ras-smmu covers SMMU error sources.
+ arm,ras-gic covers GIC error sources.
+ enum:
+ - arm,ras-processor
+ - arm,ras-smmu
+ - arm,ras-gic
+
+ reg:
+ description:
+ Register windows for this error source. When absent the error records
+ are accessed through system registers (ERRSELR_EL1 + ERX*_EL1).
+ When present, each range must have a corresponding entry in reg-names.
+ The primary error-record window is named "err-records"; additional
+ optional windows are named "err-group", "fault-inject", and "irq-config".
+ minItems: 1
+ maxItems: 4
+
+ reg-names:
+ description:
+ Names for the register windows listed in reg. The first entry must be
+ "err-records" for the primary error-record window.
+ err-group is the error group status register window (ERRGSR).
+ fault-inject is the fault injection register window (ERXPFG*).
+ irq-config is the interrupt routing configuration window.
+ minItems: 1
+ maxItems: 4
+ items:
+ enum:
+ - err-records
+ - err-group
+ - fault-inject
+ - irq-config
+
+ interrupts:
+ minItems: 1
+ items:
+ - description:
+ Fault Handling Interrupt (FHI), fired when a corrected error
+ counter overflows or a deferred error is detected.
+ - description:
+ Error Recovery Interrupt (ERI), fired when an uncorrected
+ recoverable error is detected.
+
+ interrupt-names:
+ minItems: 1
+ items:
+ - const: fhi
+ - const: eri
+
+ arm,group-format:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Layout of the memory-mapped error-record group window.
+ Determines the number of ERRGSR registers available.
+ A 4 KiB group provides 1 ERRGSR, a 16 KiB group provides
+ 4 ERRGSRs, and a 64 KiB group provides 14 ERRGSRs.
+ Each ERRGSR reports status for up to 56 error records.
+ enum: [0, 1, 2]
+
+ arm,num-records:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Total number of error records in this error source, including both
+ implemented and unimplemented slots.
+ minimum: 1
+
+ arm,record-impl:
+ $ref: /schemas/types.yaml#/definitions/uint64-array
+ description:
+ Bitmap of implemented error records. Bit N set to 1 means error
+ record N is present and active in this error source. Bit N set to 0
+ means record N is not implemented and must be skipped. The array
+ length must equal the number of ERRGSRs implied by arm,group-format
+ (1 element for 4K, 4 for 16K, 14 for 64K). For system-register
+ nodes (no reg property) a single u64 element is used.
+ minItems: 1
+ maxItems: 14
+
+ arm,status-reporting:
+ $ref: /schemas/types.yaml#/definitions/uint64-array
+ description:
+ Bitmap indicating which implemented error records require direct
+ polling of ERX_STATUS by software. Bit N set to 1 means error
+ record N is not represented in an ERRGSR status register and must
+ be checked by reading ERX_STATUS directly. Bit N set to 0 means
+ error record N is represented in an ERRGSR status register and can
+ be discovered through the ERRGSR scan path.
+ For system-register error sources (no reg property), ERRGSR
+ registers are not present. Therefore all implemented error records
+ must be polled directly and arm,status-reporting shall be identical
+ to arm,record-impl.
+ The number of array elements shall match arm,record-impl.
+ minItems: 1
+ maxItems: 14
+
+ arm,addressing-mode:
+ $ref: /schemas/types.yaml#/definitions/uint64-array
+ description:
+ Bitmap indicating the address type reported in ERR_ADDR for each
+ implemented error record. Bit N set to 1 means error record N
+ reports a Logical Address (LA); bit N set to 0 means it reports a
+ System Physical Address (SPA). When absent all records are assumed
+ to report SPA. The number of array elements shall match
+ arm,record-impl.
+ minItems: 1
+ maxItems: 14
+
+ # Processor error source properties (arm,ras-processor only)
+ arm,cache-ref:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the cache node (L1, L2, or L3) that this processor error
+ source monitors.
+
+ # SMMU error source properties (arm,ras-smmu only)
+ arm,smmu-ref:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the SMMU node that this error source monitors.
+
+ # GIC error source properties (arm,ras-gic only)
+ arm,gic-ref:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the GIC node that this error source monitors.
+
+required:
+ - compatible
+ - arm,num-records
+ - arm,record-impl
+ - arm,status-reporting
+
+dependentRequired:
+ reg: ['arm,group-format']
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: arm,ras-processor
+ then:
+ required:
+ - arm,cache-ref
+ else:
+ properties:
+ arm,cache-ref: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: arm,ras-smmu
+ then:
+ required:
+ - arm,smmu-ref
+ else:
+ properties:
+ arm,smmu-ref: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: arm,ras-gic
+ then:
+ required:
+ - arm,gic-ref
+ else:
+ properties:
+ arm,gic-ref: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/arm/arm,ras.h>
+
+ cache-error-l2 {
+ compatible = "arm,ras-processor";
+ arm,num-records = <1>;
+ arm,record-impl = /bits/ 64 <0x1>;
+ arm,status-reporting = /bits/ 64 <0x1>;
+ arm,cache-ref = <&l2_0>;
+ interrupts = <GIC_PPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/arm/arm,ras.h>
+
+ gic-error@17a00000 {
+ compatible = "arm,ras-gic";
+ reg = <0x0 0x17a00000 0x0 0x10000>;
+ reg-names = "err-records";
+ arm,group-format = <ARM_RAS_GROUP_4K>;
+ arm,num-records = <1>;
+ arm,record-impl = /bits/ 64 <0x1>;
+ arm,status-reporting = /bits/ 64 <0x0>;
+ arm,gic-ref = <&gic>;
+ interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
diff --git a/include/dt-bindings/arm/arm,ras.h b/include/dt-bindings/arm/arm,ras.h
new file mode 100644
index 000000000000..cd11e360fdae
--- /dev/null
+++ b/include/dt-bindings/arm/arm,ras.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef _DT_BINDINGS_ARM_RAS_H
+#define _DT_BINDINGS_ARM_RAS_H
+
+/* arm,group-format - error record group register window layout */
+#define ARM_RAS_GROUP_4K 0 /* 4 KiB, 1 ERRGSR */
+#define ARM_RAS_GROUP_16K 1 /* 16 KiB, 4 ERRGSRs */
+#define ARM_RAS_GROUP_64K 2 /* 64 KiB, 14 ERRGSRs */
+
+#endif /* _DT_BINDINGS_ARM_RAS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/5] arm64: ras: Add Device Tree frontend
2026-09-18 9:57 [PATCH v3 0/5] arm: ras: Add DT frontend support for ARM RAS Umang Chheda
2026-09-18 9:57 ` [PATCH v3 1/5] dt-bindings: arm: ras: Introduce ARM RAS error sources Umang Chheda
@ 2026-09-18 9:57 ` Umang Chheda
2026-09-18 9:57 ` [PATCH v3 3/5] arm64: dts: qcom: monaco: add RAS error source nodes Umang Chheda
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Umang Chheda @ 2026-09-18 9:57 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt, conor+dt, richardcochran,
Borislav Petkov, Catalin Marinas, Will Deacon, Lorenzo Pieralisi,
Sudeep Holla, Rafael J . Wysocki, Len Brown, Tony Luck,
Robin Murphy, Peter Zijlstra, James Morse
Cc: linux-arm-msm, devicetree, linux-kernel, linux-edac, Ruidong Tian,
umang.chheda, avaneesh.dwivedi
Add a Device Tree frontend for the ARM64 RAS driver, allowing it
to be used on platforms without ACPI firmware.
The error sources defined in DT are registered as arm64_ras platform
devices at boot. The frontend produces the same software fwnode properties
as the ACPI path, so the core driver probes DT and ACPI nodes identically
without any firmware-specific knowledge.
Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
---
drivers/ras/arm64/Kconfig | 25 ++-
drivers/ras/arm64/Makefile | 2 +
drivers/ras/arm64/ras-of.c | 383 +++++++++++++++++++++++++++++++++++++
3 files changed, 405 insertions(+), 5 deletions(-)
create mode 100644 drivers/ras/arm64/ras-of.c
diff --git a/drivers/ras/arm64/Kconfig b/drivers/ras/arm64/Kconfig
index dcdeaa216d67..8bdb219bc90f 100644
--- a/drivers/ras/arm64/Kconfig
+++ b/drivers/ras/arm64/Kconfig
@@ -1,16 +1,31 @@
# SPDX-License-Identifier: GPL-2.0
#
-# ARM Error Source Table Support
+# ARM RAS driver
#
# Copyright (c) 2025, Alibaba Group.
#
+config ARM64_RAS_DT
+ bool "ARM64 RAS Device Tree support"
+ depends on ARM64_RAS_EXTN && OF
+ help
+ Enable Device Tree support for the ARM64 RAS driver.
+
+ When selected, RAS error sources described in the Device Tree
+ (arm,ras-processor, arm,ras-smmu, arm,ras-gic etc) are registered
+ as platform devices at boot, allowing the driver to be used on
+ platforms without ACPI firmware.
+
config ARM64_RAS_DRIVER
tristate "ARM64 RAS Driver"
- depends on ARM64 && ACPI_AEST && RAS
+ depends on ARM64 && (ACPI_AEST || ARM64_RAS_DT) && RAS
help
- This is the RAS driver for the arm64 architecture. It depends on
- the Arm Error Source Table (AEST) to provide basic register and
- interrupt information.
+ This is the RAS driver for the arm64 architecture. It uses the
+ ARMv8 RAS extension register interface to discover, configure,
+ and handle hardware errors from processor caches, SMMUs, and GICs.
+
+ On ACPI systems the error source topology is provided by the AEST
+ ACPI table (requires ACPI_AEST). On Device Tree systems it is
+ provided by "arm,ras-*" nodes in the DT root (requires ARM64_RAS_DT).
If set, the kernel will report and process hardware errors.
diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile
index 6897798f7314..aee2f9de37f6 100644
--- a/drivers/ras/arm64/Makefile
+++ b/drivers/ras/arm64/Makefile
@@ -7,3 +7,5 @@ arm64_ras-y += ras-sysfs.o
arm64_ras-y += ras-inject.o
arm64_ras-y += ras-cmn.o
arm64_ras-y += ras-storm.o
+
+obj-$(CONFIG_ARM64_RAS_DT) += ras-of.o
diff --git a/drivers/ras/arm64/ras-of.c b/drivers/ras/arm64/ras-of.c
new file mode 100644
index 000000000000..d876031f2474
--- /dev/null
+++ b/drivers/ras/arm64/ras-of.c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+
+#include <linux/acpi_aest.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "DT RAS: " fmt
+
+/* Maximum number of software fwnode properties per RAS node */
+#define RAS_OF_MAX_PROPS 20
+
+static const unsigned long ras_of_type_processor __initconst =
+ ACPI_AEST_PROCESSOR_ERROR_NODE;
+static const unsigned long ras_of_type_smmu __initconst =
+ ACPI_AEST_SMMU_ERROR_NODE;
+static const unsigned long ras_of_type_gic __initconst =
+ ACPI_AEST_GIC_ERROR_NODE;
+
+static const struct of_device_id ras_of_match[] __initconst = {
+ { .compatible = "arm,ras-processor", .data = &ras_of_type_processor },
+ { .compatible = "arm,ras-smmu", .data = &ras_of_type_smmu },
+ { .compatible = "arm,ras-gic", .data = &ras_of_type_gic },
+ { }
+};
+
+static const char * const __initconst ras_of_irq_res_names[] = {
+ [ACPI_AEST_NODE_FAULT_HANDLING] = AEST_FHI_NAME,
+ [ACPI_AEST_NODE_ERROR_RECOVERY] = AEST_ERI_NAME,
+};
+
+static const char * const __initconst ras_of_dt_irq_names[] = {
+ "fhi", "eri"
+};
+
+static int __init ras_of_build_node_data(struct device_node *np,
+ u8 node_type, int index,
+ int fhi_virq,
+ u8 **data_out, u32 *size_out)
+{
+ *data_out = NULL;
+ *size_out = 0;
+
+ switch (node_type) {
+ case ACPI_AEST_PROCESSOR_ERROR_NODE: {
+ /*
+ * Allocate the processor header plus the cache sub-structure.
+ * resource_type is inferred from the presence of the 'cache'
+ * phandle: if present the resource is a cache, otherwise it
+ * is treated as a generic processor resource.
+ * flags (SHARED/GLOBAL) are inferred from the interrupt type:
+ * a PPI is per-PE (global); an SPI is shared across a cluster.
+ */
+ size_t total = sizeof(struct acpi_aest_processor) +
+ sizeof(struct acpi_aest_processor_cache);
+ struct acpi_aest_processor_cache *c;
+ struct acpi_aest_processor *proc;
+ struct device_node *cache_np;
+ u8 pflags;
+
+ proc = kzalloc(total, GFP_KERNEL);
+ if (!proc)
+ return -ENOMEM;
+
+ cache_np = of_parse_phandle(np, "arm,cache-ref", 0);
+ if (cache_np) {
+ proc->resource_type = ACPI_AEST_CACHE_RESOURCE;
+ c = (struct acpi_aest_processor_cache *)(proc + 1);
+ /*
+ * alloc_ras_node_name() reads c->cache_reference as
+ * the name disambiguator for shared/global nodes.
+ */
+ c->cache_reference = cache_np->phandle;
+ of_node_put(cache_np);
+ } else {
+ proc->resource_type = ACPI_AEST_GENERIC_RESOURCE;
+ }
+
+ /*
+ * Infer scope from the FHI interrupt type: a PPI is
+ * per-PE (set GLOBAL); an SPI is cluster-shared (set SHARED).
+ * alloc_ras_node_name() uses flags to choose the name format.
+ */
+ pflags = irq_is_percpu(fhi_virq) ?
+ ACPI_AEST_PROC_FLAG_GLOBAL :
+ ACPI_AEST_PROC_FLAG_SHARED;
+ proc->flags = pflags;
+ proc->processor_id = (u32)index;
+
+ *data_out = (u8 *)proc;
+ *size_out = (u32)total;
+ break;
+ }
+ case ACPI_AEST_SMMU_ERROR_NODE: {
+ struct acpi_aest_smmu *smmu;
+ struct device_node *smmu_np;
+
+ smmu = kzalloc_obj(*smmu, GFP_KERNEL);
+ if (!smmu)
+ return -ENOMEM;
+
+ smmu_np = of_parse_phandle(np, "arm,smmu-ref", 0);
+ if (smmu_np) {
+ smmu->iort_node_reference = smmu_np->phandle;
+ of_node_put(smmu_np);
+ }
+
+ *data_out = (u8 *)smmu;
+ *size_out = sizeof(*smmu);
+ break;
+ }
+ case ACPI_AEST_GIC_ERROR_NODE: {
+ struct acpi_aest_gic *gic;
+ struct device_node *gic_np;
+
+ gic = kzalloc_obj(*gic, GFP_KERNEL);
+ if (!gic)
+ return -ENOMEM;
+
+ gic_np = of_parse_phandle(np, "arm,gic-ref", 0);
+ if (gic_np) {
+ gic->instance_id = gic_np->phandle;
+ of_node_put(gic_np);
+ }
+ *data_out = (u8 *)gic;
+ *size_out = sizeof(*gic);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Determine the register access type from the DT node:
+ * no reg -> system-register access (ERRSELR_EL1 + ERX*_EL1)
+ * 1 range -> memory-mapped access
+ * 2+ ranges -> single-record memory-mapped access
+ */
+static u8 __init ras_of_interface_type(struct device_node *np)
+{
+ int addr_cells, size_cells, reg_len;
+
+ if (!of_property_present(np, "reg"))
+ return ACPI_AEST_NODE_SYSTEM_REGISTER;
+
+ addr_cells = of_n_addr_cells(np);
+ size_cells = of_n_size_cells(np);
+ if (addr_cells <= 0 || size_cells <= 0)
+ return ACPI_AEST_NODE_SYSTEM_REGISTER;
+
+ reg_len = of_property_count_elems_of_size(np, "reg", sizeof(u32));
+ if (reg_len <= 0)
+ return ACPI_AEST_NODE_SYSTEM_REGISTER;
+
+ if (reg_len <= addr_cells + size_cells)
+ return ACPI_AEST_NODE_MEMORY_MAPPED;
+
+ return ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED;
+}
+
+static resource_size_t __init ras_of_mem_size(u32 gfmt)
+{
+ switch (gfmt) {
+ case ACPI_AEST_NODE_GROUP_FORMAT_16K:
+ return SZ_16K;
+ case ACPI_AEST_NODE_GROUP_FORMAT_64K:
+ return SZ_64K;
+ default:
+ return SZ_4K;
+ }
+}
+
+static u32 __init ras_of_virq_to_gsiv(int virq)
+{
+ struct irq_data *irqd = irq_get_irq_data(virq);
+
+ return irqd ? (u32)irqd->hwirq : 0;
+}
+
+static int __init ras_of_attach_fwnode(struct device_node *np,
+ struct platform_device *pdev,
+ u8 node_type, u8 itype, u32 gfmt,
+ int index, int fhi_virq,
+ u32 fhi_gsiv, u32 eri_gsiv)
+{
+ u64 rec_impl[14] = { };
+ u64 stat_rep[14] = { };
+ u64 addr_mode[14] = { };
+ u64 err_group_base = 0, fault_inject_base = 0, irq_cfg_base = 0;
+ struct property_entry props[RAS_OF_MAX_PROPS] = { };
+ struct resource res;
+ u8 *node_data = NULL;
+ u32 node_data_size = 0;
+ u32 nrec = 1;
+ int group_len, p = 0, i, ret;
+
+ of_property_read_u32(np, "arm,num-records", &nrec);
+
+ switch (gfmt) {
+ case ACPI_AEST_NODE_GROUP_FORMAT_16K:
+ group_len = 4;
+ break;
+ case ACPI_AEST_NODE_GROUP_FORMAT_64K:
+ group_len = 14;
+ break;
+ default:
+ group_len = 1;
+ break;
+ }
+
+ of_property_read_u64_array(np, "arm,record-impl", rec_impl, group_len);
+ of_property_read_u64_array(np, "arm,status-reporting", stat_rep, group_len);
+ of_property_read_u64_array(np, "arm,addressing-mode", addr_mode, group_len);
+
+ /*
+ * DT binding: bit=1 means record IS implemented.
+ * ras-core.c uses for_each_clear_bit() on record_implemented, so
+ * bit=0 means implemented internally. Invert before storing.
+ */
+ for (i = 0; i < group_len; i++)
+ rec_impl[i] = ~rec_impl[i];
+
+ /* Named MMIO windows — only present on memory-mapped nodes */
+ if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) {
+ int idx;
+
+ idx = of_property_match_string(np, "reg-names", "err-group");
+ if (idx >= 0 && !of_address_to_resource(np, idx, &res))
+ err_group_base = res.start;
+
+ idx = of_property_match_string(np, "reg-names", "fault-inject");
+ if (idx >= 0 && !of_address_to_resource(np, idx, &res))
+ fault_inject_base = res.start;
+
+ idx = of_property_match_string(np, "reg-names", "irq-config");
+ if (idx >= 0 && !of_address_to_resource(np, idx, &res))
+ irq_cfg_base = res.start;
+ }
+
+ ret = ras_of_build_node_data(np, node_type, index, fhi_virq,
+ &node_data, &node_data_size);
+ if (ret)
+ return ret;
+
+ props[p++] = PROPERTY_ENTRY_U8("arm,node-type", node_type);
+ props[p++] = PROPERTY_ENTRY_U8("arm,interface-type", itype);
+ props[p++] = PROPERTY_ENTRY_U8("arm,group-format", (u8)gfmt);
+ props[p++] = PROPERTY_ENTRY_U32("arm,error-records-count", nrec);
+ props[p++] = PROPERTY_ENTRY_U32("arm,error-records-index", 0);
+ props[p++] = PROPERTY_ENTRY_U32("arm,interface-flags", 0);
+ props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,record-implemented",
+ rec_impl, group_len);
+ props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,status-reporting",
+ stat_rep, group_len);
+ props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,addressing-mode",
+ addr_mode, group_len);
+ props[p++] = PROPERTY_ENTRY_U64("arm,error-group-base", err_group_base);
+ props[p++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", fault_inject_base);
+ props[p++] = PROPERTY_ENTRY_U64("arm,interrupt-config-base", irq_cfg_base);
+ props[p++] = PROPERTY_ENTRY_U32("arm,fhi-gsiv", fhi_gsiv);
+ props[p++] = PROPERTY_ENTRY_U32("arm,eri-gsiv", eri_gsiv);
+
+ if (node_data && node_data_size)
+ props[p++] = PROPERTY_ENTRY_U8_ARRAY_LEN("arm,node-specific-data",
+ node_data, node_data_size);
+
+ ret = device_create_managed_software_node(&pdev->dev, props, NULL);
+
+ kfree(node_data);
+ return ret;
+}
+
+static int __init ras_of_init_one_node(struct device_node *np, u8 node_type,
+ int index)
+{
+ struct resource res[AEST_MAX_INTERRUPT_PER_NODE + 1] = { };
+ struct platform_device *pdev;
+ u32 gfmt = ACPI_AEST_NODE_GROUP_FORMAT_4K;
+ u32 gsiv[AEST_MAX_INTERRUPT_PER_NODE] = { };
+ int virq[AEST_MAX_INTERRUPT_PER_NODE] = { };
+ int nres = 0, ret, i;
+ u8 itype;
+
+ itype = ras_of_interface_type(np);
+ of_property_read_u32(np, "arm,group-format", &gfmt);
+
+ pdev = platform_device_alloc("arm64_ras", PLATFORM_DEVID_AUTO);
+ if (!pdev)
+ return -ENOMEM;
+
+ if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) {
+ struct resource mmio_res;
+
+ ret = of_address_to_resource(np, 0, &mmio_res);
+ if (ret) {
+ pr_err("node %pOF: missing 'reg' for MMIO interface\n", np);
+ goto err_put;
+ }
+ res[nres].name = AEST_NODE_NAME;
+ res[nres].start = mmio_res.start;
+ res[nres].end = mmio_res.start + ras_of_mem_size(gfmt) - 1;
+ res[nres].flags = IORESOURCE_MEM;
+ nres++;
+ }
+
+ for (i = 0; i < AEST_MAX_INTERRUPT_PER_NODE; i++) {
+ int irq_num = of_irq_get_byname(np, ras_of_dt_irq_names[i]);
+
+ if (irq_num <= 0)
+ continue;
+
+ gsiv[i] = ras_of_virq_to_gsiv(irq_num);
+ virq[i] = irq_num;
+
+ res[nres].name = ras_of_irq_res_names[i];
+ res[nres].start = irq_num;
+ res[nres].end = irq_num;
+ res[nres].flags = IORESOURCE_IRQ;
+ nres++;
+ }
+
+ ret = platform_device_add_resources(pdev, res, nres);
+ if (ret)
+ goto err_put;
+
+ ret = ras_of_attach_fwnode(np, pdev, node_type, itype, gfmt, index,
+ virq[ACPI_AEST_NODE_FAULT_HANDLING],
+ gsiv[ACPI_AEST_NODE_FAULT_HANDLING],
+ gsiv[ACPI_AEST_NODE_ERROR_RECOVERY]);
+ if (ret)
+ goto err_put;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto err_put;
+
+ pr_debug("registered RAS node %pOF as arm64_ras.%d\n", np, pdev->id);
+ return 0;
+
+err_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init ras_of_init(void)
+{
+ const struct of_device_id *match;
+ struct device_node *np;
+ int index = 0, ret;
+
+ if (!acpi_disabled)
+ return 0;
+
+ for_each_matching_node_and_match(np, ras_of_match, &match) {
+ u8 node_type = *(const unsigned long *)match->data;
+
+ ret = ras_of_init_one_node(np, node_type, index++);
+ if (ret) {
+ pr_err("failed to register RAS node %pOF: %d\n",
+ np, ret);
+ of_node_put(np);
+ return ret;
+ }
+ }
+
+ if (index)
+ pr_info("registered %d RAS error source(s) from DT\n", index);
+
+ return 0;
+}
+subsys_initcall_sync(ras_of_init);
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 3/5] arm64: dts: qcom: monaco: add RAS error source nodes
2026-09-18 9:57 [PATCH v3 0/5] arm: ras: Add DT frontend support for ARM RAS Umang Chheda
2026-09-18 9:57 ` [PATCH v3 1/5] dt-bindings: arm: ras: Introduce ARM RAS error sources Umang Chheda
2026-09-18 9:57 ` [PATCH v3 2/5] arm64: ras: Add Device Tree frontend Umang Chheda
@ 2026-09-18 9:57 ` Umang Chheda
2026-09-18 9:57 ` [PATCH v3 4/5] arm64: dts: qcom: lemans: " Umang Chheda
2026-09-18 9:57 ` [PATCH v3 5/5] arm64: dts: qcom: shikra: " Umang Chheda
4 siblings, 0 replies; 6+ messages in thread
From: Umang Chheda @ 2026-09-18 9:57 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt, conor+dt, richardcochran,
Borislav Petkov, Catalin Marinas, Will Deacon, Lorenzo Pieralisi,
Sudeep Holla, Rafael J . Wysocki, Len Brown, Tony Luck,
Robin Murphy, Peter Zijlstra, James Morse
Cc: linux-arm-msm, devicetree, linux-kernel, linux-edac, Ruidong Tian,
umang.chheda, avaneesh.dwivedi, Faruque Ansari
ARM Reliability, Availability and Serviceability (RAS) enables
processor components(for eg cache, tlb etc) to record and signal
hardware faults through architected error records and fault handling
interrupts. This allows software to detect, report and, where possible,
recover from hardware errors.
The Monaco CPU subsystem implements RAS error records for the L1/L2
cache hierarchy and the shared L3 caches. Describe these error sources
in Device Tree so that the ARM RAS framework can discover them and
handle cache-related error reports.
Co-developed-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/monaco.dtsi | 30 ++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
index 395d32d36844..1728932e52b0 100644
--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
+++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
@@ -617,6 +617,36 @@ scm: scm {
};
};
+ l2-cache-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <1>;
+ arm,record-impl = /bits/ 64 <0x1>;
+ arm,status-reporting = /bits/ 64 <0x1>;
+ arm,cache-ref = <&l2_0>;
+ interrupts = <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "fhi";
+ };
+
+ l3-cluster0-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <2>;
+ arm,record-impl = /bits/ 64 <0x2>;
+ arm,status-reporting = /bits/ 64 <0x2>;
+ arm,cache-ref = <&l3_0>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
+
+ l3-cluster1-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <2>;
+ arm,record-impl = /bits/ 64 <0x2>;
+ arm,status-reporting = /bits/ 64 <0x2>;
+ arm,cache-ref = <&l3_1>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
+
memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the size */
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 4/5] arm64: dts: qcom: lemans: add RAS error source nodes
2026-09-18 9:57 [PATCH v3 0/5] arm: ras: Add DT frontend support for ARM RAS Umang Chheda
` (2 preceding siblings ...)
2026-09-18 9:57 ` [PATCH v3 3/5] arm64: dts: qcom: monaco: add RAS error source nodes Umang Chheda
@ 2026-09-18 9:57 ` Umang Chheda
2026-09-18 9:57 ` [PATCH v3 5/5] arm64: dts: qcom: shikra: " Umang Chheda
4 siblings, 0 replies; 6+ messages in thread
From: Umang Chheda @ 2026-09-18 9:57 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt, conor+dt, richardcochran,
Borislav Petkov, Catalin Marinas, Will Deacon, Lorenzo Pieralisi,
Sudeep Holla, Rafael J . Wysocki, Len Brown, Tony Luck,
Robin Murphy, Peter Zijlstra, James Morse
Cc: linux-arm-msm, devicetree, linux-kernel, linux-edac, Ruidong Tian,
umang.chheda, avaneesh.dwivedi, Faruque Ansari
ARM Reliability, Availability and Serviceability (RAS) enables
processor components(for eg cache, tlb etc) to record and signal
hardware faults through architected error records and fault handling
interrupts. This allows software to detect, report and, where possible,
recover from hardware errors.
The Lemans CPU subsystem implements RAS error records for the L1/L2
cache hierarchy and the shared L3 caches. Describe these error sources
in Device Tree so that the ARM RAS framework can discover them and
handle cache-related error reports.
Co-developed-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/lemans.dtsi | 30 ++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
index 695eae1b7256..dc4cbb6e3496 100644
--- a/arch/arm64/boot/dts/qcom/lemans.dtsi
+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
@@ -524,6 +524,36 @@ clk_virt: interconnect-clk-virt {
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ l2-cache-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <1>;
+ arm,record-impl = /bits/ 64 <0x1>;
+ arm,status-reporting = /bits/ 64 <0x1>;
+ arm,cache-ref = <&l2_0>;
+ interrupts = <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "fhi";
+ };
+
+ l3-cluster0-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <2>;
+ arm,record-impl = /bits/ 64 <0x2>;
+ arm,status-reporting = /bits/ 64 <0x2>;
+ arm,cache-ref = <&l3_0>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
+
+ l3-cluster1-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <2>;
+ arm,record-impl = /bits/ 64 <0x2>;
+ arm,status-reporting = /bits/ 64 <0x2>;
+ arm,cache-ref = <&l3_1>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "fhi";
+ };
+
mc_virt: interconnect-mc-virt {
compatible = "qcom,sa8775p-mc-virt";
#interconnect-cells = <2>;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 5/5] arm64: dts: qcom: shikra: add RAS error source nodes
2026-09-18 9:57 [PATCH v3 0/5] arm: ras: Add DT frontend support for ARM RAS Umang Chheda
` (3 preceding siblings ...)
2026-09-18 9:57 ` [PATCH v3 4/5] arm64: dts: qcom: lemans: " Umang Chheda
@ 2026-09-18 9:57 ` Umang Chheda
4 siblings, 0 replies; 6+ messages in thread
From: Umang Chheda @ 2026-09-18 9:57 UTC (permalink / raw)
To: andersson, konradybcio, robh, krzk+dt, conor+dt, richardcochran,
Borislav Petkov, Catalin Marinas, Will Deacon, Lorenzo Pieralisi,
Sudeep Holla, Rafael J . Wysocki, Len Brown, Tony Luck,
Robin Murphy, Peter Zijlstra, James Morse
Cc: linux-arm-msm, devicetree, linux-kernel, linux-edac, Ruidong Tian,
umang.chheda, avaneesh.dwivedi, Faruque Ansari
ARM Reliability, Availability and Serviceability (RAS) enables
processor components (for eg cache, tlb etc) to record and signal
hardware faults through architected error records and fault handling
interrupts. This allows software to detect, report and, where possible,
recover from hardware errors.
The Shikra CPU subsystem implements RAS error records for the L1/L2
cache hierarchy and the shared L3 caches. Describe these error sources
in Device Tree so that the ARM RAS framework can discover them and
handle cache-related error reports.
Co-developed-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
index c1f06f692f66..c5bbf1f8e46a 100644
--- a/arch/arm64/boot/dts/qcom/shikra.dtsi
+++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
@@ -330,6 +330,26 @@ opp-2208000000 {
};
};
+ l2-cache-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <1>;
+ arm,record-impl = /bits/ 64 <0x1>;
+ arm,status-reporting = /bits/ 64 <0x1>;
+ arm,cache-ref = <&l2_3>;
+ interrupts = <GIC_PPI 6 IRQ_TYPE_LEVEL_LOW 0>;
+ interrupt-names = "fhi";
+ };
+
+ l3-cache-error {
+ compatible = "arm,ras-processor";
+ arm,num-records = <2>;
+ arm,record-impl = /bits/ 64 <0x2>;
+ arm,status-reporting = /bits/ 64 <0x2>;
+ arm,cache-ref = <&l3>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "fhi";
+ };
+
modem-etm0 {
compatible = "arm,coresight-dummy-source";
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread