Date: Tue, 12 May 2026 16:55:30 +0000 From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Sarah Walker <sarah.walker2@arm.com> Subject: git: 76a2904c352b - main - arm64: Add RSI detection for CCA Message-ID: <6a035b82.3e295.91ae8c3@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=76a2904c352b497b32fc902523e3e485f7b06ffd commit 76a2904c352b497b32fc902523e3e485f7b06ffd Author: Sarah Walker <sarah.walker2@arm.com> AuthorDate: 2026-05-12 11:27:13 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2026-05-12 16:54:40 +0000 arm64: Add RSI detection for CCA Detect the presence of the Realm Services Interface (RSI). This detection is performed early in bootup; PSCI initialisation has been moved to initarm() to faciliate this. Reviewed by: andrew Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D56598 --- sys/arm64/arm64/machdep.c | 5 ++ sys/arm64/arm64/pmap.c | 2 + sys/arm64/arm64/rsi.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++ sys/arm64/include/pmap.h | 3 + sys/arm64/include/rsi.h | 129 ++++++++++++++++++++++++++++++++ sys/conf/files.arm64 | 1 + sys/dev/psci/psci.c | 11 ++- sys/dev/psci/psci.h | 3 + 8 files changed, 338 insertions(+), 1 deletion(-) diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index adfb509d4924..d219c737c215 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -86,6 +86,7 @@ #include <machine/metadata.h> #include <machine/md_var.h> #include <machine/pcb.h> +#include <machine/rsi.h> #include <machine/undefined.h> #include <machine/vmparam.h> @@ -103,6 +104,7 @@ #include <dev/ofw/openfirm.h> #endif +#include <dev/psci/psci.h> #include <dev/smbios/smbios.h> _Static_assert(sizeof(struct pcb) == 1248, "struct pcb is incorrect size"); @@ -889,6 +891,9 @@ initarm(struct arm64_bootparams *abp) valid = bus_probe(); + psci_init(NULL); + arm64_rsi_setup_memory(); + cninit(); set_ttbr0(abp->kern_ttbr0); pmap_s1_invalidate_all_kernel(); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 595fba2da411..2d2982fdfae7 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -205,6 +205,8 @@ __exclusive_cache_line static struct pmap_large_md_page pv_dummy_large; #define pv_dummy pv_dummy_large.pv_page __read_mostly static struct pmap_large_md_page *pv_table; +__read_mostly uint64_t prot_ns_shared_pa; + static struct pmap_large_md_page * _pa_to_pmdp(vm_paddr_t pa) { diff --git a/sys/arm64/arm64/rsi.c b/sys/arm64/arm64/rsi.c new file mode 100644 index 000000000000..85c7896e13ce --- /dev/null +++ b/sys/arm64/arm64/rsi.c @@ -0,0 +1,185 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Arm Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_platform.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/physmem.h> +#include <sys/rwlock.h> + +#include <vm/vm_page.h> + +#include <machine/rsi.h> +#include <machine/vmparam.h> + +#include <dev/psci/psci.h> +#include <dev/psci/smccc.h> + +static struct realm_config config; +static bool rsi_present = false; + +#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) + +static vm_paddr_t physmap[PHYSMAP_SIZE]; + +static unsigned long +rsi_request_version(unsigned long req, unsigned long *out_lower, + unsigned long *out_higher) +{ + struct arm_smccc_res res; + + arm_smccc_invoke_smc(SMC_RSI_ABI_VERSION, req, &res); + + if (out_lower != NULL) + *out_lower = res.a1; + if (out_higher != NULL) + *out_higher = res.a2; + + return (res.a0); +} + +static inline unsigned long +rsi_get_realm_config(struct realm_config *cfg) +{ + struct arm_smccc_res res; + + arm_smccc_invoke_smc(SMC_RSI_REALM_CONFIG, vtophys(cfg), &res); + return (res.a0); +} + +static bool +rsi_version_matches(void) +{ + unsigned long ver_lower, ver_higher; + unsigned long ret; + + ret = rsi_request_version(RSI_ABI_VERSION, &ver_lower, &ver_higher); + + if (ret == SMCCC_RET_NOT_SUPPORTED) + return (false); + + if (ret != RSI_SUCCESS) { + printf("RME: RMM doesn't support RSI version %lu.%lu. Supported range: %lu.%lu-%lu.%lu\n", + RSI_ABI_VERSION_MAJOR, RSI_ABI_VERSION_MINOR, + RSI_ABI_VERSION_GET_MAJOR(ver_lower), + RSI_ABI_VERSION_GET_MINOR(ver_lower), + RSI_ABI_VERSION_GET_MAJOR(ver_higher), + RSI_ABI_VERSION_GET_MINOR(ver_higher)); + return (false); + } + + printf("RME: Using RSI version %lu.%lu\n", + RSI_ABI_VERSION_GET_MAJOR(ver_lower), + RSI_ABI_VERSION_GET_MINOR(ver_lower)); + + return (true); +} + + +unsigned long +rsi_set_addr_range_state(vm_paddr_t start, vm_paddr_t end, enum ripas state, + unsigned long flags, vm_paddr_t *top) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state, flags, 0, 0, 0, + &res); + + if (top) + *top = res.a1; + + return (res.a0); +} + +static int +rsi_set_memory_range(vm_paddr_t start, vm_paddr_t end, enum ripas state, + unsigned long flags) +{ + unsigned long ret; + vm_paddr_t top; + + while (start != end) { + ret = rsi_set_addr_range_state(start, end, state, flags, &top); + if (ret || top < start || top > end) + return (-EINVAL); + start = top; + } + + return (0); +} + +/* + * Convert the specified range to RAM. Do not convert any pages that may have + * been DESTROYED, without our permission. + */ +static int +rsi_set_memory_range_protected_safe(vm_paddr_t start, vm_paddr_t end) +{ + return (rsi_set_memory_range(start, end, RSI_RIPAS_RAM, + RSI_NO_CHANGE_DESTROYED)); +} + +void +arm64_rsi_setup_memory(void) +{ + int physmap_idx; + int i; + + if (!psci_conduit_is_smc()) + return; + if (!rsi_version_matches()) + return; + if (rsi_get_realm_config(&config)) + return; + + prot_ns_shared_pa = 1ul << (config.ipa_bits - 1); + if (bootverbose) + printf("arm64_rsi_setup_memory: rsi_present, ipa_bits=%lu prot_ns_shared_pa=%lx\n", + config.ipa_bits, prot_ns_shared_pa); + rsi_present = true; + + physmap_idx = physmem_all(physmap, nitems(physmap)); + + if (bootverbose) + printf("physmap:\n"); + + for (i = 0; i < physmap_idx; i += 2) { + if (bootverbose) + printf(" %lx %lx\n", physmap[i], physmap[i + 1]); + + if (rsi_set_memory_range_protected_safe(physmap[i], + physmap[i + 1])) + panic("rsi_set_memory_range_protected_safe failed"); + } +} + +bool +in_realm(void) +{ + return (rsi_present); +} diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h index 2ee70fc754da..00b54a874e12 100644 --- a/sys/arm64/include/pmap.h +++ b/sys/arm64/include/pmap.h @@ -43,6 +43,7 @@ #ifndef LOCORE #include <sys/queue.h> +#include <sys/systm.h> #include <sys/_lock.h> #include <sys/_mutex.h> #include <sys/_pv_entry.h> @@ -132,6 +133,8 @@ extern vm_offset_t virtual_end; extern pt_entry_t pmap_sh_attr; +extern __read_mostly uint64_t prot_ns_shared_pa; + /* * Macros to test if a mapping is mappable with an L1 Section mapping * or an L2 Large Page mapping. diff --git a/sys/arm64/include/rsi.h b/sys/arm64/include/rsi.h new file mode 100644 index 000000000000..82e54f9c57e3 --- /dev/null +++ b/sys/arm64/include/rsi.h @@ -0,0 +1,129 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Arm Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_RSI_H_ +#define _MACHINE_RSI_H_ + +extern uint64_t prot_ns_shared; + +bool in_realm(void); + +void arm64_rsi_setup_memory(void); + +/* + * The major version number of the RSI implementation. This is increased when + * the binary format or semantics of the SMC calls change. + */ +#define RSI_ABI_VERSION_MAJOR UL(1) + +/* + * The minor version number of the RSI implementation. This is increased when + * a bug is fixed, or a feature is added without breaking binary compatibility. + */ +#define RSI_ABI_VERSION_MINOR UL(0) + +#define RSI_ABI_VERSION ((RSI_ABI_VERSION_MAJOR << 16) | \ + RSI_ABI_VERSION_MINOR) + +#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16) +#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF) + +#define RSI_SUCCESS UL(0) +#define RSI_ERROR_INPUT UL(1) +#define RSI_ERROR_STATE UL(2) +#define RSI_INCOMPLETE UL(3) +#define RSI_ERROR_UNKNOWN UL(4) + +#define SMC_RSI_FID(n) SMCCC_FUNC_ID(SMCCC_FAST_CALL, \ + SMCCC_64BIT_CALL, \ + SMCCC_STD_SECURE_SERVICE_CALLS, \ + n) + +/* + * Returns RSI version. + * + * arg1 == Requested interface revision + * ret0 == Status / error + * ret1 == Lower implemented interface revision + * ret2 == Higher implemented interface revision + */ +#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190) + +/* + * Read configuration for the current Realm. + * + * arg1 == struct realm_config addr + * ret0 == Status / error + */ +#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(0x196) + +struct realm_config { + union { + struct { + unsigned long ipa_bits; /* Width of IPA in bits */ + unsigned long hash_algo; /* Hash algorithm */ + }; + uint8_t pad[0x200]; + }; + union { + uint8_t rpv[64]; /* Realm Personalization Value */ + uint8_t pad2[0xe00]; + }; + /* + * The RMM requires the configuration structure to be aligned to a 4k + * boundary, ensure this happens by aligning this structure. + */ +} __aligned(0x1000); + +/* + * Request RIPAS of a target IPA range to be changed to a specified value. + * + * arg1 == Base IPA address of target region + * arg2 == Top of the region + * arg3 == RIPAS value + * arg4 == flags + * ret0 == Status / error + * ret1 == Top of modified IPA range + * ret2 == Whether the Host accepted or rejected the request + */ +#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(0x197) + +#define RSI_NO_CHANGE_DESTROYED UL(0) +#define RSI_CHANGE_DESTROYED UL(1) + +#define RSI_ACCEPT UL(0) +#define RSI_REJECT UL(1) + +enum ripas { + RSI_RIPAS_EMPTY = 0, + RSI_RIPAS_RAM +}; + +unsigned long rsi_set_addr_range_state(vm_paddr_t start, vm_paddr_t end, + enum ripas state, unsigned long flags, vm_paddr_t *top); + +#endif /* !_MACHINE_RSI_H_ */ diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 44f292d9048f..8f550a644db6 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -77,6 +77,7 @@ arm64/arm64/ptrauth.c standard \ compile-with "${NORMAL_C:N-mbranch-protection*} -mbranch-protection=bti" arm64/arm64/pmap.c standard arm64/arm64/ptrace_machdep.c standard +arm64/arm64/rsi.c standard arm64/arm64/sdt_machdep.c optional kdtrace_hooks arm64/arm64/sigtramp.S standard arm64/arm64/spec_workaround.c standard diff --git a/sys/dev/psci/psci.c b/sys/dev/psci/psci.c index 2b250401ae83..872fae056a4b 100644 --- a/sys/dev/psci/psci.c +++ b/sys/dev/psci/psci.c @@ -133,7 +133,7 @@ static int psci_def_callfn(register_t, register_t, register_t, register_t, psci_callfn_t psci_callfn = psci_def_callfn; -static void +void psci_init(void *dummy) { psci_callfn_t new_callfn; @@ -146,8 +146,11 @@ psci_init(void *dummy) psci_callfn = new_callfn; psci_present = true; } + +#ifdef __arm__ /* This needs to be before cpu_mp at SI_SUB_CPU, SI_ORDER_THIRD */ SYSINIT(psci_start, SI_SUB_CPU, SI_ORDER_FIRST, psci_init, NULL); +#endif static int psci_def_callfn(register_t a __unused, register_t b __unused, @@ -631,3 +634,9 @@ psci_v0_2_init(device_t dev, int default_version) device_printf(dev, "PSCI version number mismatched with DT\n"); return (1); } + +bool +psci_conduit_is_smc(void) +{ + return (psci_callfn == arm_smccc_smc); +} diff --git a/sys/dev/psci/psci.h b/sys/dev/psci/psci.h index 6704eaf26c71..c250bf45d344 100644 --- a/sys/dev/psci/psci.h +++ b/sys/dev/psci/psci.h @@ -44,6 +44,9 @@ void psci_reset(void); int32_t psci_features(uint32_t); int psci_get_version(void); +void psci_init(void *dummy); +bool psci_conduit_is_smc(void); + /* Handler to let us call into the PSCI/SMCCC firmware */ extern psci_callfn_t psci_callfn; static inline inthome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a035b82.3e295.91ae8c3>
