* [RFC PATCH 1/4] arm64: acpi: Refactor FADT table verification
2026-04-29 10:35 [RFC PATCH 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
@ 2026-04-29 10:35 ` Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 2/4] psci: Add support for Early detection and init Suzuki K Poulose
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-04-29 10:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
Refactor the FADT sanity check, such that this could be reused. We are soon
going to consume the FADT early at boot for probing the PSCI conduit, and this
will be of use.
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/kernel/acpi.c | 55 +++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index af90128cfed5..30c7b11a8a9d 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -118,6 +118,34 @@ bool acpi_psci_use_hvc(void)
return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
}
+static int __init __acpi_fadt_sanity_check(struct acpi_table_fadt *fadt)
+{
+ struct acpi_table_header *table = (struct acpi_table_header *)fadt;
+
+ /*
+ * Revision in table header is the FADT Major revision, and there
+ * is a minor revision of FADT which was introduced by ACPI 5.1,
+ * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
+ * boot protocol configuration data.
+ */
+ if (table->revision < 5 ||
+ (table->revision == 5 && fadt->minor_revision < 1)) {
+ pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n",
+ table->revision, fadt->minor_revision);
+
+ if (!fadt->arm_boot_flags) {
+ return -EINVAL;
+ }
+ pr_err("FADT has ARM boot flags set, assuming 5.1\n");
+ }
+
+ if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
+ pr_err("FADT not ACPI hardware reduced compliant\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
/*
* acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
* checks on it
@@ -127,7 +155,6 @@ bool acpi_psci_use_hvc(void)
static int __init acpi_fadt_sanity_check(void)
{
struct acpi_table_header *table;
- struct acpi_table_fadt *fadt;
acpi_status status;
int ret = 0;
@@ -143,32 +170,8 @@ static int __init acpi_fadt_sanity_check(void)
return -ENODEV;
}
- fadt = (struct acpi_table_fadt *)table;
+ ret = __acpi_fadt_sanity_check((struct acpi_table_fadt *)table);
- /*
- * Revision in table header is the FADT Major revision, and there
- * is a minor revision of FADT which was introduced by ACPI 5.1,
- * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
- * boot protocol configuration data.
- */
- if (table->revision < 5 ||
- (table->revision == 5 && fadt->minor_revision < 1)) {
- pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n",
- table->revision, fadt->minor_revision);
-
- if (!fadt->arm_boot_flags) {
- ret = -EINVAL;
- goto out;
- }
- pr_err("FADT has ARM boot flags set, assuming 5.1\n");
- }
-
- if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
- pr_err("FADT not ACPI hardware reduced compliant\n");
- ret = -EINVAL;
- }
-
-out:
/*
* acpi_get_table() creates FADT table mapping that
* should be released after parsing and before resuming boot
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH 2/4] psci: Add support for Early detection and init
2026-04-29 10:35 [RFC PATCH 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 1/4] arm64: acpi: Refactor FADT table verification Suzuki K Poulose
@ 2026-04-29 10:35 ` Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 3/4] arm64: psci: Move detection and SMCCC probe earlier Suzuki K Poulose
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-04-29 10:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
Allow early detection of the PSCI conduit and presence of SMCCC. Primary motive
is to detect if we are a Realm as early as possible to make better decisions
1. For mapping the memory without BBML2_NOABORT
2. Making use of the earlycon, to be able to debug problems at early boot.
Add a new psci_early_init_conduit() which can probe the PSCI and SMCCC. This is
optional, and could really fallback to the normal if the architecture cannot
reliably detect the conduit. Later patches will make use of this.
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/firmware/psci/psci.c | 49 ++++++++++++++++++++++++++++++++++--
include/linux/psci.h | 2 ++
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 38ca190d4a22..fa0839513d64 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -80,6 +80,11 @@ static u32 psci_cpu_suspend_feature;
static bool psci_system_reset2_supported;
static bool psci_system_off2_hibernate_supported;
+static inline bool psci_probed(void)
+{
+ return psci_ops.get_version != NULL;
+}
+
static inline bool psci_has_ext_power_state(void)
{
return psci_cpu_suspend_feature &
@@ -270,6 +275,15 @@ static unsigned long psci_migrate_info_up_cpu(void)
static void set_conduit(enum arm_smccc_conduit conduit)
{
+ /*
+ * If we have set the conduit already, make sure
+ * it is the same as we have found.
+ */
+ if (psci_conduit != SMCCC_CONDUIT_NONE) {
+ WARN_ON(conduit != psci_conduit);
+ return;
+ }
+
switch (conduit) {
case SMCCC_CONDUIT_HVC:
invoke_psci_fn = __invoke_psci_fn_hvc;
@@ -679,7 +693,16 @@ static void __init psci_0_2_set_functions(void)
*/
static int __init psci_probe(void)
{
- u32 ver = psci_0_2_get_version();
+ u32 ver;
+
+ /* Make sure we have a set CONDUIT */
+ if (WARN_ON(psci_conduit == SMCCC_CONDUIT_NONE))
+ return -ENODEV;
+
+ if (WARN_ON(psci_probed()))
+ return 0;
+
+ ver = psci_0_2_get_version();
pr_info("PSCIv%d.%d detected in firmware.\n",
PSCI_VERSION_MAJOR(ver),
@@ -717,10 +740,12 @@ static int __init psci_0_2_init(const struct device_node *np)
{
int err;
+ if (psci_probed())
+ return 0;
+
err = get_set_conduit_method(np);
if (err)
return err;
-
/*
* Starting with v0.2, the PSCI specification introduced a call
* (PSCI_VERSION) that allows probing the firmware version, so
@@ -739,6 +764,9 @@ static int __init psci_0_1_init(const struct device_node *np)
u32 id;
int err;
+ if (psci_probed())
+ return 0;
+
err = get_set_conduit_method(np);
if (err)
return err;
@@ -816,6 +844,20 @@ int __init psci_dt_init(void)
return ret;
}
+int __init psci_early_init_conduit(enum arm_smccc_conduit conduit)
+{
+ switch (conduit) {
+ case SMCCC_CONDUIT_HVC:
+ case SMCCC_CONDUIT_SMC:
+ set_conduit(conduit);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ return psci_probe();
+}
+
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
@@ -823,6 +865,9 @@ int __init psci_dt_init(void)
*/
int __init psci_acpi_init(void)
{
+ if (psci_probed())
+ return 0;
+
if (!acpi_psci_present()) {
pr_info("is not implemented in ACPI.\n");
return -EOPNOTSUPP;
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 4ca0060a3fc4..8f98d61a69e4 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -59,4 +59,6 @@ static inline bool acpi_psci_present(void) { return false; }
static inline bool acpi_psci_use_hvc(void) {return false; }
#endif
+int __init psci_early_init_conduit(enum arm_smccc_conduit);
+
#endif /* __LINUX_PSCI_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH 3/4] arm64: psci: Move detection and SMCCC probe earlier
2026-04-29 10:35 [RFC PATCH 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 1/4] arm64: acpi: Refactor FADT table verification Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 2/4] psci: Add support for Early detection and init Suzuki K Poulose
@ 2026-04-29 10:35 ` Suzuki K Poulose
2026-04-29 10:35 ` [RFC PATCH 4/4] arm64: realm: Move RSI detection earlier Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
4 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-04-29 10:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
We parse the ACPI/DT for the PSCI conduit after the linear map is created via
paging_init(). This implies that we do not have all the information required to
decide whether block mappings are safe for the linear map.
e.g., With Realms, we cannot use Block mappings without BBML2_NOABORT support.
See [0] for more discussion.
This patch moves the detection of PSCI and SMCCC probing, before paging_init(),
after the efi_init(). We scan the ACPI and the DT (unflattened) for the conduit.
If we both have conduit set, we proceed only if they match. Otherwise, we can't
be sure what gets used eventually by the OS. e.g., if the ACPI table is corrupt,
DT may be used.
We do minimal validations on the ACPI tables (e.g. revision checks, FADT
checks etc.). TODO: Verify the checksum ? (acpi_table_checksum())
[0] https://lore.kernel.org/all/20260330161705.3349825-2-ryan.roberts@arm.com/
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/include/asm/acpi.h | 1 +
arch/arm64/kernel/acpi.c | 81 +++++++++++++++++++++++++++++++++++
arch/arm64/kernel/setup.c | 68 +++++++++++++++++++++++++++++
3 files changed, 150 insertions(+)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index c07a58b96329..a5198fa46088 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -188,4 +188,5 @@ static inline void acpi_map_cpus_to_nodes(void) { }
#define ACPI_TABLE_UPGRADE_MAX_PHYS MEMBLOCK_ALLOC_ACCESSIBLE
+enum arm_smccc_conduit __init acpi_early_psci_conduit(void);
#endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 30c7b11a8a9d..88d79def4c90 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -180,6 +180,87 @@ static int __init acpi_fadt_sanity_check(void)
return ret;
}
+/*
+ * Find the PSCI conduit from ACPI FADT table. We only proceed with the parsing
+ * if acpi *may be* used. i.e, acpi=force or acpi=on or DT is stub.
+ *
+ * FADT table is located as below:
+ *
+ * RSDP -> XSDT ptr -> array of pointers to different Tables
+ *
+ * Note: Arm64 requires ACPI v5.1+, thus we always use XSDT (not RSDT, for < 2.0)
+ * from RSDP.
+ *
+ * Returns : Conduit if system is PSCI compliant.
+ * Otherwise returns SMCCC_CONDUIT_NONE.
+ */
+enum arm_smccc_conduit __init acpi_early_psci_conduit(void)
+{
+ enum arm_smccc_conduit c = SMCCC_CONDUIT_NONE;
+ struct acpi_table_rsdp *rsdp;
+ struct acpi_table_xsdt *xsdt;
+ u64 *ptr, *end;
+ u64 xsdt_pa, xsdt_len;
+ bool found = false;
+
+ if (param_acpi_off ||
+ (!param_acpi_on && !param_acpi_force && !dt_is_stub()))
+ return SMCCC_CONDUIT_NONE;
+
+ if (efi.acpi20 == EFI_INVALID_TABLE_ADDR)
+ return SMCCC_CONDUIT_NONE;
+
+ rsdp = early_memremap(efi.acpi20, sizeof(*rsdp));
+ if (!rsdp)
+ return SMCCC_CONDUIT_NONE;
+
+ if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature) || rsdp->revision < 2 ||
+ rsdp->xsdt_physical_address == 0) {
+ early_memunmap(rsdp, sizeof(*rsdp));
+ return SMCCC_CONDUIT_NONE;
+ }
+
+ xsdt_pa = rsdp->xsdt_physical_address;
+
+ /* Now that XSDT is found, unmap the RSDP */
+ early_memunmap(rsdp, sizeof(*rsdp));
+
+ /*
+ * XSDT is mainly an array of table pointers, with standard header.
+ * So we map upto a PAGE_SIZE (and more with alignment) and only
+ * look there, with a WARNING.
+ */
+ xsdt = early_memremap(xsdt_pa, PAGE_SIZE);
+ if (!xsdt)
+ return SMCCC_CONDUIT_NONE;
+
+ xsdt_len = ((struct acpi_table_header*)xsdt)->length;
+ if (xsdt_len > (ALIGN(xsdt_pa + PAGE_SIZE, PAGE_SIZE) - xsdt_pa)) {
+ pr_warn("XSDT table is larger than a page\n");
+ }
+
+ /* Find FADT table from the XSDT */
+ ptr = &xsdt->table_offset_entry[0];
+ end = (u64*)((void *)xsdt + xsdt_len);
+ for (; ptr < end && !found; ptr++) {
+ struct acpi_table_fadt *fadt = early_memremap(*ptr, sizeof(*fadt));
+
+ if (ACPI_COMPARE_NAMESEG(&fadt->header.signature, ACPI_SIG_FADT) &&
+ __acpi_fadt_sanity_check(fadt) == 0) {
+ u16 arm_boot_flags = fadt->arm_boot_flags;
+
+ if (arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT) {
+ c = arm_boot_flags & ACPI_FADT_PSCI_USE_HVC ?
+ SMCCC_CONDUIT_HVC : SMCCC_CONDUIT_SMC;
+ }
+ found = true;
+ }
+ early_memunmap(fadt, sizeof(*fadt));
+ }
+ early_memunmap(xsdt, PAGE_SIZE);
+ return c;
+}
+
/*
* acpi_boot_table_init() called from setup_arch(), always.
* 1. find RSDP and get its address, and then find XSDT
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 23c05dc7a8f2..595aff6f17d5 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -278,6 +278,71 @@ u64 cpu_logical_map(unsigned int cpu)
return __cpu_logical_map[cpu];
}
+static enum arm_smccc_conduit early_dt_probe_psci_conduit(void)
+{
+ int len;
+ int psci_node;
+ const char *method;
+ enum arm_smccc_conduit conduit = SMCCC_CONDUIT_NONE;
+ unsigned long dt_root;
+
+ /* DT hasn't been unflattened yet, we have to work with the flat blob */
+ dt_root = of_get_flat_dt_root();
+ psci_node = of_get_flat_dt_subnode_by_name(dt_root, "psci");
+ if (psci_node <= 0)
+ return conduit;
+
+ method = of_get_flat_dt_prop(psci_node, "method", &len);
+ if (!method)
+ return conduit;
+
+ if (strncmp(method, "smc", len) == 0) {
+ conduit = SMCCC_CONDUIT_SMC;
+ } else if (strncmp(method, "hvc", len) == 0) {
+ conduit = SMCCC_CONDUIT_HVC;
+ }
+ return conduit;
+}
+
+/*
+ * Detect the PSCI conduit from both ACPI and DT, and probe the PSCI/SMCCC
+ * early if we can.
+ *
+ * Given both ACPI and DT could have valid configurations, we go forward with
+ * the early detection only if there is a valid conduit and both of them match.
+ */
+static void __init early_psci_init(void)
+{
+ enum arm_smccc_conduit dt_conduit = SMCCC_CONDUIT_NONE;
+ enum arm_smccc_conduit acpi_conduit = SMCCC_CONDUIT_NONE;
+ enum arm_smccc_conduit conduit = SMCCC_CONDUIT_NONE;
+
+ dt_conduit = early_dt_probe_psci_conduit();
+
+#ifdef CONFIG_ACPI
+ if (efi_enabled(EFI_BOOT))
+ acpi_conduit = acpi_early_psci_conduit();
+#endif
+ if (dt_conduit == SMCCC_CONDUIT_NONE &&
+ acpi_conduit == SMCCC_CONDUIT_NONE) {
+ pr_crit("PSCI: Early probe: no conduit found\n");
+ return;
+ }
+
+ if (acpi_conduit == SMCCC_CONDUIT_NONE) {
+ conduit = dt_conduit;
+ } else if (dt_conduit == SMCCC_CONDUIT_NONE) {
+ conduit = acpi_conduit;
+ } else if (dt_conduit == acpi_conduit) {
+ conduit = acpi_conduit;
+ } else {
+ WARN(1, "PSCI: Early probe: Mismatched PSCI conduit, skipping\n");
+ return;
+ }
+
+ psci_early_init_conduit(conduit);
+}
+
void __init __no_sanitize_address setup_arch(char **cmdline_p)
{
setup_initial_init_mm(_text, _etext, _edata, _end);
@@ -322,6 +387,9 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
xen_early_init();
efi_init();
+ /* Probe the PSCI early after the efi_init() */
+ early_psci_init();
+
if (!efi_enabled(EFI_BOOT)) {
if ((u64)_text % MIN_KIMG_ALIGN)
pr_warn(FW_BUG "Kernel image misaligned at boot, please fix your bootloader!");
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH 4/4] arm64: realm: Move RSI detection earlier
2026-04-29 10:35 [RFC PATCH 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
` (2 preceding siblings ...)
2026-04-29 10:35 ` [RFC PATCH 3/4] arm64: psci: Move detection and SMCCC probe earlier Suzuki K Poulose
@ 2026-04-29 10:35 ` Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
4 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-04-29 10:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
As discussed in [0], Realm world detection happens too late for making the
decision for the Linear map granularity for Arm64. If the boot CPU doesn't support
BBML2_NOABORT, it is difficult to break the mapping to PTE level. To solve this
try probing the Realm world earlier, now that we probe the PSCI/SMCCC earlier.
Like the PSCI probe, if we fall back to the later point if the SMCCC probe
wasn't successful. We should probably add a WARNING/panic the system if the
BBML2_NOABORT is not supported on the boot CPU and linear map was created
with block mappings. This may case avoided by using rodata=full.
[0] https://lore.kernel.org/all/20260330161705.3349825-2-ryan.roberts@arm.com/
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/include/asm/rsi.h | 1 +
arch/arm64/kernel/rsi.c | 23 ++++++++++++++++++++++-
arch/arm64/kernel/setup.c | 3 ++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
index 88b50d660e85..4456bf0a1f23 100644
--- a/arch/arm64/include/asm/rsi.h
+++ b/arch/arm64/include/asm/rsi.h
@@ -14,6 +14,7 @@
DECLARE_STATIC_KEY_FALSE(rsi_present);
+void __init arm64_early_rsi_init(void);
void __init arm64_rsi_init(void);
bool arm64_rsi_is_protected(phys_addr_t base, size_t size);
diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
index c64a06f58c0b..2d2befae2c75 100644
--- a/arch/arm64/kernel/rsi.c
+++ b/arch/arm64/kernel/rsi.c
@@ -138,10 +138,14 @@ static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
return 0;
}
-void __init arm64_rsi_init(void)
+static bool rsi_probed = 0;
+
+static void __init rsi_probe(void)
{
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
return;
+
+ rsi_probed = true;
if (!rsi_version_matches())
return;
if (WARN_ON(rsi_get_realm_config(&config)))
@@ -159,6 +163,23 @@ void __init arm64_rsi_init(void)
static_branch_enable(&rsi_present);
}
+void __init arm64_early_rsi_init(void)
+{
+ rsi_probe();
+}
+
+void __init arm64_rsi_init(void)
+{
+ if (rsi_probed)
+ return;
+
+ rsi_probe();
+ /*
+ * TODO: Warn if we don't have BBML2_NOABORT and page mapping is
+ * not used.
+ */
+}
+
static struct platform_device rsi_dev = {
.name = RSI_PDEV_NAME,
.id = PLATFORM_DEVID_NONE
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 595aff6f17d5..0664130dd791 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -340,7 +340,8 @@ static void __init early_psci_init(void)
return;
}
- psci_early_init_conduit(conduit);
+ if (!psci_early_init_conduit(conduit))
+ arm64_early_rsi_init();
}
void __init __no_sanitize_address setup_arch(char **cmdline_p)
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier
2026-04-29 10:35 [RFC PATCH 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
` (3 preceding siblings ...)
2026-04-29 10:35 ` [RFC PATCH 4/4] arm64: realm: Move RSI detection earlier Suzuki K Poulose
@ 2026-05-05 15:57 ` Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 1/4] arm64: acpi: Refactor FADT table verification Suzuki K Poulose
` (3 more replies)
4 siblings, 4 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-05-05 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
This is an updated series, addressing the review comments from AI agent on
the version 1 [0] of the series, (some of which were documented as short comings).
See below for the changes.
The Realm Guest linux support is broken without rodata=full (fortunately default
for arm64), as we detect the RSI support after we have created the Linear map
with Block/Contiguous mappings. If the boot CPU doesn't support BBML2_NOABORT
(there are CPUs out there with FEAT_RME and no - useable - BBML2_NOABORT)
we are then not able to split the page tables down to PTE level if the system
as such doesn't support BBML2.
See the following link for the discussion.
https://lore.kernel.org/all/20260330161705.3349825-2-ryan.roberts@arm.com/
The available options are :
1. Start with PTE level mappings at paging_init() and then "FOLD" the page tables
to Block/Cont mappings after we have the full picture available. Looking at the
future (with BBML3), this might mean "additional work" for most of the systems
at boot. But not bad as splitting them ?
2. Hold the secondary CPUs in busy loop with MMU disabled and split the mappings
by the boot CPU with MMU off (if Boot CPU can't support BBML2). This is tricky
with the page allocations required to add the page-tables.
3. Move the detection of Realm support earlier to make a better decision for
paging_init(), with an added bonus of earlycon support for Realms without
the user having to work out the "top bit" for the Realm.
This series is an attempt to implement (3) (without the earlycon support). We try
to probe the PSCI conduit early from the DT/ACPI. DT is not flattened at this time.
ACPI table is not mapped in full, so we have to map one table at a time and walk
from the Root of the table (RSDP) through to XSDT and find the FADT table from
the array of table pointers there. Minimal verification is performed on the
tables (e.g., revision checks, standard FADT sanity checks). Checksum is not
verified, but should be possible to do for the parts we consume.
With arm64, during the normal boot, we could fallback to using DT if the ACPI
tables are not useable. So, during the early probe, we try to follow the similar
logic and probe the conduit from both DT and ACPI where available. If both of
them contain a conduit, we only proceed if they match. Otherwise, we skip the
early probe and do things the normal way. (Any sane system shouldn't have such
a mismatch, but..)
Once we probe the PSCI conduit, PSCI is probed, along with the presence of SMCCC.
With that in place, we try to probe the RSI support after the early probe and
advertise the Realm World. If the early probe wasn't successful, we fall back
to the late mode, where we could end up with (on a possibly rare broken firmware).
NOTE: This is an early RFC attempt to moving the PSCI detection earlier. The other
option(s) that may be worth exploring are:
1. On systems with EFI, parse this from EFI Stub and pass the data back in the
DT Stub, under chosen node. e.g., "linux,uefi-arm-psci-conduit".
Challenge: EFI stub doesn't seem to be ACPI aware. We could make that change,
we only need a few table walks.
2. Have EFI firmware provide this information (with my limited knowledge on the
area, this looks like too much work, and bending the standards)
3. Append arm64 boot protocol to have this information passed to the kernel.
(Firmware provided) - (Steven's idea)
4. Any other options ?
This series is also available here :
git@git.gitlab.arm.com:linux-arm/linux-cca.git cca-guest/early-rsi-detection/rfc-v2
Thoughts ?
Suzuki
Changes since v1:
(Mainly addressing review comments from AI agent)
[0] https://lore.kernel.org/all/20260429103535.266728-1-suzuki.poulose@arm.com
- Handle ACPI XSDT table properly for tables greater than a PAGE_SIZE
- Stricter checking for the PSCI DT node, match the compatible to PSCI 0.2 or v1.0
and honor the "status" property of the node, to be more closer to the late check
Suzuki K Poulose (4):
arm64: acpi: Refactor FADT table verification
psci: Add support for Early detection and init
arm64: psci: Move detection and SMCCC probe earlier
arm64: realm: Move RSI detection earlier
arch/arm64/include/asm/acpi.h | 1 +
arch/arm64/include/asm/rsi.h | 1 +
arch/arm64/kernel/acpi.c | 151 ++++++++++++++++++++++++++++------
arch/arm64/kernel/rsi.c | 23 +++++-
arch/arm64/kernel/setup.c | 79 ++++++++++++++++++
drivers/firmware/psci/psci.c | 49 ++++++++++-
include/linux/psci.h | 2 +
7 files changed, 277 insertions(+), 29 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFC PATCH v2 1/4] arm64: acpi: Refactor FADT table verification
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
@ 2026-05-05 15:57 ` Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 2/4] psci: Add support for Early detection and init Suzuki K Poulose
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-05-05 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
Refactor the FADT sanity check, such that this could be reused. We are soon
going to consume the FADT early at boot for probing the PSCI conduit, and this
will be of use.
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/kernel/acpi.c | 55 +++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 5891f92c2035..d6050e9cde89 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -118,6 +118,34 @@ bool acpi_psci_use_hvc(void)
return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
}
+static int __init __acpi_fadt_sanity_check(struct acpi_table_fadt *fadt)
+{
+ struct acpi_table_header *table = (struct acpi_table_header *)fadt;
+
+ /*
+ * Revision in table header is the FADT Major revision, and there
+ * is a minor revision of FADT which was introduced by ACPI 5.1,
+ * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
+ * boot protocol configuration data.
+ */
+ if (table->revision < 5 ||
+ (table->revision == 5 && fadt->minor_revision < 1)) {
+ pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n",
+ table->revision, fadt->minor_revision);
+
+ if (!fadt->arm_boot_flags) {
+ return -EINVAL;
+ }
+ pr_err("FADT has ARM boot flags set, assuming 5.1\n");
+ }
+
+ if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
+ pr_err("FADT not ACPI hardware reduced compliant\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
/*
* acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
* checks on it
@@ -127,7 +155,6 @@ bool acpi_psci_use_hvc(void)
static int __init acpi_fadt_sanity_check(void)
{
struct acpi_table_header *table;
- struct acpi_table_fadt *fadt;
acpi_status status;
int ret = 0;
@@ -143,32 +170,8 @@ static int __init acpi_fadt_sanity_check(void)
return -ENODEV;
}
- fadt = (struct acpi_table_fadt *)table;
+ ret = __acpi_fadt_sanity_check((struct acpi_table_fadt *)table);
- /*
- * Revision in table header is the FADT Major revision, and there
- * is a minor revision of FADT which was introduced by ACPI 5.1,
- * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
- * boot protocol configuration data.
- */
- if (table->revision < 5 ||
- (table->revision == 5 && fadt->minor_revision < 1)) {
- pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n",
- table->revision, fadt->minor_revision);
-
- if (!fadt->arm_boot_flags) {
- ret = -EINVAL;
- goto out;
- }
- pr_err("FADT has ARM boot flags set, assuming 5.1\n");
- }
-
- if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
- pr_err("FADT not ACPI hardware reduced compliant\n");
- ret = -EINVAL;
- }
-
-out:
/*
* acpi_get_table() creates FADT table mapping that
* should be released after parsing and before resuming boot
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v2 2/4] psci: Add support for Early detection and init
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 1/4] arm64: acpi: Refactor FADT table verification Suzuki K Poulose
@ 2026-05-05 15:57 ` Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 3/4] arm64: psci: Move detection and SMCCC probe earlier Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 4/4] arm64: realm: Move RSI detection earlier Suzuki K Poulose
3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-05-05 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
Allow early detection of the PSCI conduit and presence of SMCCC. Primary motive
is to detect if we are a Realm as early as possible to make better decisions
1. For mapping the memory without BBML2_NOABORT
2. Making use of the earlycon, to be able to debug problems at early boot.
Add a new psci_early_init_conduit() which can probe the PSCI and SMCCC. This is
optional, and could really fallback to the normal if the architecture cannot
reliably detect the conduit. Later patches will make use of this.
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/firmware/psci/psci.c | 49 ++++++++++++++++++++++++++++++++++--
include/linux/psci.h | 2 ++
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 38ca190d4a22..fa0839513d64 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -80,6 +80,11 @@ static u32 psci_cpu_suspend_feature;
static bool psci_system_reset2_supported;
static bool psci_system_off2_hibernate_supported;
+static inline bool psci_probed(void)
+{
+ return psci_ops.get_version != NULL;
+}
+
static inline bool psci_has_ext_power_state(void)
{
return psci_cpu_suspend_feature &
@@ -270,6 +275,15 @@ static unsigned long psci_migrate_info_up_cpu(void)
static void set_conduit(enum arm_smccc_conduit conduit)
{
+ /*
+ * If we have set the conduit already, make sure
+ * it is the same as we have found.
+ */
+ if (psci_conduit != SMCCC_CONDUIT_NONE) {
+ WARN_ON(conduit != psci_conduit);
+ return;
+ }
+
switch (conduit) {
case SMCCC_CONDUIT_HVC:
invoke_psci_fn = __invoke_psci_fn_hvc;
@@ -679,7 +693,16 @@ static void __init psci_0_2_set_functions(void)
*/
static int __init psci_probe(void)
{
- u32 ver = psci_0_2_get_version();
+ u32 ver;
+
+ /* Make sure we have a set CONDUIT */
+ if (WARN_ON(psci_conduit == SMCCC_CONDUIT_NONE))
+ return -ENODEV;
+
+ if (WARN_ON(psci_probed()))
+ return 0;
+
+ ver = psci_0_2_get_version();
pr_info("PSCIv%d.%d detected in firmware.\n",
PSCI_VERSION_MAJOR(ver),
@@ -717,10 +740,12 @@ static int __init psci_0_2_init(const struct device_node *np)
{
int err;
+ if (psci_probed())
+ return 0;
+
err = get_set_conduit_method(np);
if (err)
return err;
-
/*
* Starting with v0.2, the PSCI specification introduced a call
* (PSCI_VERSION) that allows probing the firmware version, so
@@ -739,6 +764,9 @@ static int __init psci_0_1_init(const struct device_node *np)
u32 id;
int err;
+ if (psci_probed())
+ return 0;
+
err = get_set_conduit_method(np);
if (err)
return err;
@@ -816,6 +844,20 @@ int __init psci_dt_init(void)
return ret;
}
+int __init psci_early_init_conduit(enum arm_smccc_conduit conduit)
+{
+ switch (conduit) {
+ case SMCCC_CONDUIT_HVC:
+ case SMCCC_CONDUIT_SMC:
+ set_conduit(conduit);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ return psci_probe();
+}
+
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
@@ -823,6 +865,9 @@ int __init psci_dt_init(void)
*/
int __init psci_acpi_init(void)
{
+ if (psci_probed())
+ return 0;
+
if (!acpi_psci_present()) {
pr_info("is not implemented in ACPI.\n");
return -EOPNOTSUPP;
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 4ca0060a3fc4..8f98d61a69e4 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -59,4 +59,6 @@ static inline bool acpi_psci_present(void) { return false; }
static inline bool acpi_psci_use_hvc(void) {return false; }
#endif
+int __init psci_early_init_conduit(enum arm_smccc_conduit);
+
#endif /* __LINUX_PSCI_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v2 3/4] arm64: psci: Move detection and SMCCC probe earlier
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 1/4] arm64: acpi: Refactor FADT table verification Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 2/4] psci: Add support for Early detection and init Suzuki K Poulose
@ 2026-05-05 15:57 ` Suzuki K Poulose
2026-05-05 15:57 ` [RFC PATCH v2 4/4] arm64: realm: Move RSI detection earlier Suzuki K Poulose
3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-05-05 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
We parse the ACPI/DT for the PSCI conduit after the linear map is created via
paging_init(). This implies that we do not have all the information required to
decide whether block mappings are safe for the linear map.
e.g., With Realms, we cannot use Block mappings without BBML2_NOABORT support.
See [0] for more discussion.
This patch moves the detection of PSCI and SMCCC probing, before paging_init(),
after the efi_init(). We scan the ACPI and the DT (unflattened) for the conduit.
If we both have conduit set, we proceed only if they match. Otherwise, we can't
be sure what gets used eventually by the OS. e.g., if the ACPI table is corrupt,
DT may be used.
We do minimal validations on the ACPI tables (e.g. revision checks, FADT
checks etc.). TODO: Verify the checksum ? (acpi_table_checksum())
[0] https://lore.kernel.org/all/20260330161705.3349825-2-ryan.roberts@arm.com/
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/include/asm/acpi.h | 1 +
arch/arm64/kernel/acpi.c | 96 +++++++++++++++++++++++++++++++++++
arch/arm64/kernel/setup.c | 78 ++++++++++++++++++++++++++++
3 files changed, 175 insertions(+)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 8a54ca6ba602..448320ffba98 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -173,4 +173,5 @@ static inline void acpi_map_cpus_to_nodes(void) { }
#define ACPI_TABLE_UPGRADE_MAX_PHYS MEMBLOCK_ALLOC_ACCESSIBLE
+enum arm_smccc_conduit __init acpi_early_psci_conduit(void);
#endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index d6050e9cde89..a36a9881a4f7 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -180,6 +180,102 @@ static int __init acpi_fadt_sanity_check(void)
return ret;
}
+/*
+ * Find the PSCI conduit from ACPI FADT table. We only proceed with the parsing
+ * if acpi *may be* used. i.e, acpi=force or acpi=on or DT is stub.
+ *
+ * FADT table is located as below:
+ *
+ * RSDP -> XSDT ptr -> array of pointers to different Tables
+ *
+ * Note: Arm64 requires ACPI v5.1+, thus we always use XSDT (not RSDT, for < 2.0)
+ * from RSDP.
+ *
+ * Returns : Conduit if system is PSCI compliant.
+ * Otherwise returns SMCCC_CONDUIT_NONE.
+ */
+enum arm_smccc_conduit __init acpi_early_psci_conduit(void)
+{
+ enum arm_smccc_conduit c = SMCCC_CONDUIT_NONE;
+ struct acpi_table_rsdp *rsdp;
+ struct acpi_table_xsdt *xsdt;
+ u64 *ptr, *end;
+ u64 xsdt_pa, xsdt_len, xsdt_map_len;
+ bool found = false;
+
+ if (param_acpi_off ||
+ (!param_acpi_on && !param_acpi_force && !dt_is_stub()))
+ return SMCCC_CONDUIT_NONE;
+
+ if (efi.acpi20 == EFI_INVALID_TABLE_ADDR)
+ return SMCCC_CONDUIT_NONE;
+
+ rsdp = early_memremap(efi.acpi20, sizeof(*rsdp));
+ if (!rsdp)
+ return SMCCC_CONDUIT_NONE;
+
+ if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature) || rsdp->revision < 2 ||
+ rsdp->xsdt_physical_address == 0) {
+ early_memunmap(rsdp, sizeof(*rsdp));
+ return SMCCC_CONDUIT_NONE;
+ }
+
+ xsdt_pa = rsdp->xsdt_physical_address;
+
+ /* Now that XSDT is found, unmap the RSDP */
+ early_memunmap(rsdp, sizeof(*rsdp));
+
+ /*
+ * XSDT is mainly an array of table pointers, with standard header.
+ * So we map upto a PAGE_SIZE (and more with alignment) and check
+ * the length. If the current mapping doesn't cover the full table,
+ * we remap it upto the actual length.
+ */
+ xsdt_map_len = PAGE_SIZE;
+ xsdt = early_memremap(xsdt_pa, xsdt_map_len);
+ if (!xsdt)
+ return SMCCC_CONDUIT_NONE;
+
+ /* Length of the mapped region */
+ xsdt_len = ALIGN(xsdt_pa + xsdt_map_len, PAGE_SIZE) - xsdt_pa;
+
+ if (xsdt_len < ((struct acpi_table_header*)xsdt)->length) {
+ xsdt_len = ((struct acpi_table_header*)xsdt)->length;
+ early_memunmap(xsdt, xsdt_map_len);
+ xsdt_map_len = xsdt_len;
+ xsdt = early_memremap(xsdt_pa, xsdt_map_len);
+ if (!xsdt)
+ return SMCCC_CONDUIT_NONE;
+ } else {
+ xsdt_len = ((struct acpi_table_header*)xsdt)->length;
+ }
+
+ /* Find FADT table from the XSDT */
+ ptr = &xsdt->table_offset_entry[0];
+ end = (u64*)((void *)xsdt + xsdt_len);
+ for (; ptr < end && !found; ptr++) {
+ struct acpi_table_fadt *fadt = early_memremap(*ptr, sizeof(*fadt));
+
+ if (!fadt) {
+ pr_warn("Unable to map ACPI table at 0x%llx\n", *ptr);
+ continue;
+ }
+ if (ACPI_COMPARE_NAMESEG(&fadt->header.signature, ACPI_SIG_FADT) &&
+ __acpi_fadt_sanity_check(fadt) == 0) {
+ u16 arm_boot_flags = fadt->arm_boot_flags;
+
+ if (arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT) {
+ c = arm_boot_flags & ACPI_FADT_PSCI_USE_HVC ?
+ SMCCC_CONDUIT_HVC : SMCCC_CONDUIT_SMC;
+ }
+ found = true;
+ }
+ early_memunmap(fadt, sizeof(*fadt));
+ }
+ early_memunmap(xsdt, xsdt_map_len);
+ return c;
+}
+
/*
* acpi_boot_table_init() called from setup_arch(), always.
* 1. find RSDP and get its address, and then find XSDT
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 23c05dc7a8f2..af35a0f3b7d0 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -278,6 +278,81 @@ u64 cpu_logical_map(unsigned int cpu)
return __cpu_logical_map[cpu];
}
+static enum arm_smccc_conduit early_dt_probe_psci_conduit(void)
+{
+ int len = 0;
+ int psci_node;
+ const char *method, *status;
+ enum arm_smccc_conduit conduit = SMCCC_CONDUIT_NONE;
+ unsigned long dt_root;
+
+ /* DT hasn't been unflattened yet, we have to work with the flat blob */
+ dt_root = of_get_flat_dt_root();
+ psci_node = of_get_flat_dt_subnode_by_name(dt_root, "psci");
+ if (psci_node <= 0)
+ return conduit;
+
+ if (!of_flat_dt_is_compatible(psci_node, "arm,psci-0.2") &&
+ !of_flat_dt_is_compatible(psci_node, "arm,psci-1.0"))
+ return conduit;
+
+ status = of_get_flat_dt_prop(psci_node, "status", &len);
+ if (status) {
+ if (strncmp(status, "ok", len) && strncmp(status, "okay", len))
+ return conduit;
+ }
+
+ method = of_get_flat_dt_prop(psci_node, "method", &len);
+ if (!method)
+ return conduit;
+
+ if (strncmp(method, "smc", len) == 0) {
+ conduit = SMCCC_CONDUIT_SMC;
+ } else if (strncmp(method, "hvc", len) == 0) {
+ conduit = SMCCC_CONDUIT_HVC;
+ }
+ return conduit;
+}
+
+/*
+ * Detect the PSCI conduit from both ACPI and DT, and probe the PSCI/SMCCC
+ * early if we can.
+ *
+ * Given both ACPI and DT could have valid configurations, we go forward with
+ * the early detection only if there is a valid conduit and both of them match.
+ */
+static void __init early_psci_init(void)
+{
+ enum arm_smccc_conduit dt_conduit = SMCCC_CONDUIT_NONE;
+ enum arm_smccc_conduit acpi_conduit = SMCCC_CONDUIT_NONE;
+ enum arm_smccc_conduit conduit = SMCCC_CONDUIT_NONE;
+
+ dt_conduit = early_dt_probe_psci_conduit();
+
+#ifdef CONFIG_ACPI
+ if (efi_enabled(EFI_BOOT))
+ acpi_conduit = acpi_early_psci_conduit();
+#endif
+ if (dt_conduit == SMCCC_CONDUIT_NONE &&
+ acpi_conduit == SMCCC_CONDUIT_NONE) {
+ pr_crit("PSCI: Early probe: no conduit found\n");
+ return;
+ }
+
+ if (acpi_conduit == SMCCC_CONDUIT_NONE) {
+ conduit = dt_conduit;
+ } else if (dt_conduit == SMCCC_CONDUIT_NONE) {
+ conduit = acpi_conduit;
+ } else if (dt_conduit == acpi_conduit) {
+ conduit = acpi_conduit;
+ } else {
+ WARN(1, "PSCI: Early probe: Mismatched PSCI conduit, skipping\n");
+ return;
+ }
+
+ psci_early_init_conduit(conduit);
+}
+
void __init __no_sanitize_address setup_arch(char **cmdline_p)
{
setup_initial_init_mm(_text, _etext, _edata, _end);
@@ -322,6 +397,9 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
xen_early_init();
efi_init();
+ /* Probe the PSCI early after the efi_init() */
+ early_psci_init();
+
if (!efi_enabled(EFI_BOOT)) {
if ((u64)_text % MIN_KIMG_ALIGN)
pr_warn(FW_BUG "Kernel image misaligned at boot, please fix your bootloader!");
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v2 4/4] arm64: realm: Move RSI detection earlier
2026-05-05 15:57 ` [RFC PATCH v2 0/4] arm64: realm: Support for probing RSI earlier Suzuki K Poulose
` (2 preceding siblings ...)
2026-05-05 15:57 ` [RFC PATCH v2 3/4] arm64: psci: Move detection and SMCCC probe earlier Suzuki K Poulose
@ 2026-05-05 15:57 ` Suzuki K Poulose
3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K Poulose @ 2026-05-05 15:57 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, ardb, lpieralisi,
mark.rutland, steven.price, aneesh.kumar, sudeep.holla, robh, maz,
Suzuki K Poulose
As discussed in [0], Realm world detection happens too late for making the
decision for the Linear map granularity for Arm64. If the boot CPU doesn't support
BBML2_NOABORT, it is difficult to break the mapping to PTE level. To solve this
try probing the Realm world earlier, now that we probe the PSCI/SMCCC earlier.
Like the PSCI probe, if we fall back to the later point if the SMCCC probe
wasn't successful. We should probably add a WARNING/panic the system if the
BBML2_NOABORT is not supported on the boot CPU and linear map was created
with block mappings. This may case avoided by using rodata=full.
[0] https://lore.kernel.org/all/20260330161705.3349825-2-ryan.roberts@arm.com/
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
arch/arm64/include/asm/rsi.h | 1 +
arch/arm64/kernel/rsi.c | 23 ++++++++++++++++++++++-
arch/arm64/kernel/setup.c | 3 ++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
index 88b50d660e85..4456bf0a1f23 100644
--- a/arch/arm64/include/asm/rsi.h
+++ b/arch/arm64/include/asm/rsi.h
@@ -14,6 +14,7 @@
DECLARE_STATIC_KEY_FALSE(rsi_present);
+void __init arm64_early_rsi_init(void);
void __init arm64_rsi_init(void);
bool arm64_rsi_is_protected(phys_addr_t base, size_t size);
diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
index 92160f2e57ff..f0fd0922609d 100644
--- a/arch/arm64/kernel/rsi.c
+++ b/arch/arm64/kernel/rsi.c
@@ -139,10 +139,14 @@ static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
return 0;
}
-void __init arm64_rsi_init(void)
+static bool rsi_probed = 0;
+
+static void __init rsi_probe(void)
{
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
return;
+
+ rsi_probed = true;
if (!rsi_version_matches())
return;
if (WARN_ON(rsi_get_realm_config(lm_alias(&config))))
@@ -160,6 +164,23 @@ void __init arm64_rsi_init(void)
static_branch_enable(&rsi_present);
}
+void __init arm64_early_rsi_init(void)
+{
+ rsi_probe();
+}
+
+void __init arm64_rsi_init(void)
+{
+ if (rsi_probed)
+ return;
+
+ rsi_probe();
+ /*
+ * TODO: Warn if we don't have BBML2_NOABORT and page mapping is
+ * not used.
+ */
+}
+
static struct platform_device rsi_dev = {
.name = RSI_PDEV_NAME,
.id = PLATFORM_DEVID_NONE
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index af35a0f3b7d0..0b530a090150 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -350,7 +350,8 @@ static void __init early_psci_init(void)
return;
}
- psci_early_init_conduit(conduit);
+ if (!psci_early_init_conduit(conduit))
+ arm64_early_rsi_init();
}
void __init __no_sanitize_address setup_arch(char **cmdline_p)
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread