Page MenuHomeFreeBSD

D56598.diff
No OneTemporary

D56598.diff

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

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)

Event Timeline