Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153984229
D56598.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D56598.diff
View Options
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
--- 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");
@@ -890,6 +892,9 @@
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
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -205,6 +205,8 @@
#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
--- /dev/null
+++ b/sys/arm64/arm64/rsi.c
@@ -0,0 +1,181 @@
+/*-
+ * 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_smc(SMC_RSI_ABI_VERSION, req, 0, 0, 0, 0, 0, 0, &res);
+
+ if (out_lower)
+ *out_lower = res.a1;
+ if (out_higher)
+ *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_smc(SMC_RSI_REALM_CONFIG, vtophys(cfg), 0, 0, 0, 0, 0, 0,
+ &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
--- 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 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
--- /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
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -77,6 +77,7 @@
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.h b/sys/dev/psci/psci.h
--- a/sys/dev/psci/psci.h
+++ b/sys/dev/psci/psci.h
@@ -44,6 +44,9 @@
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 int
diff --git a/sys/dev/psci/psci.c b/sys/dev/psci/psci.c
--- a/sys/dev/psci/psci.c
+++ b/sys/dev/psci/psci.c
@@ -133,7 +133,7 @@
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_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 @@
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/kern/subr_physmem.c b/sys/kern/subr_physmem.c
--- a/sys/kern/subr_physmem.c
+++ b/sys/kern/subr_physmem.c
@@ -503,6 +503,12 @@
return (regions_to_avail(avail, EXFLAG_NOALLOC, maxavail, 0, NULL, NULL));
}
+size_t
+physmem_all(vm_paddr_t *avail, size_t maxavail)
+{
+ return (regions_to_avail(avail, 0, maxavail, 0, NULL, NULL));
+}
+
bool
physmem_excluded(vm_paddr_t pa, vm_size_t sz)
{
diff --git a/sys/sys/physmem.h b/sys/sys/physmem.h
--- a/sys/sys/physmem.h
+++ b/sys/sys/physmem.h
@@ -54,6 +54,7 @@
void physmem_hardware_region(uint64_t pa, uint64_t sz);
void physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t flags);
size_t physmem_avail(vm_paddr_t *avail, size_t maxavail);
+size_t physmem_all(vm_paddr_t *avail, size_t maxavail);
void physmem_init_kernel_globals(void);
void physmem_print_tables(void);
bool physmem_excluded(vm_paddr_t pa, vm_size_t sz);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 26, 6:29 AM (18 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32169251
Default Alt Text
D56598.diff (13 KB)
Attached To
Mode
D56598: arm64: Add RSI detection for CCA
Attached
Detach File
Event Timeline
Log In to Comment