Skip to contentSkip to conversation

Split RX and RW regions for separate pmp entries

PATCH Superseded Himanshu Chauhan 2 participants 9 messages Jan 18, 2023 – Jan 19, 2023

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover Split RX and RW regions for separate pmp entries

This is second installment of the patch series sent earlier with the subject: Split region permissions into M-mode and SU-mode. The version 2 was recently posted, for which below is the link:
http://lists.infradead.org/pipermail/opensbi/2023-January/004127.html

This patch series splits the RX (text and read-only data) and RW data regions so that each can have its independent pmp entries with correct permissions. The linker script provides a new symbol _fw_rw_offset that marks the beginning of the RW section. It also ensures that the split is a power-of-2 as required by pmp.

This lays ground work for enforcing the permissions from M-mode.

New in v2:
* Added a check if fw_rw_offset is a power of w
* Added a check if fw_start and fw_rw_offset are aligned

Himanshu Chauhan (5):
firmware: Split RO/RX and RW sections
firmware: Move dynsym and reladyn sections to RX section
firmware: Add RW section offset in scratch
lib: sbi: Print the RW section offset
Add two entries:

 firmware/fw_base.S        |  5 +++++
 firmware/fw_base.ldS      | 43 ++++++++++++++++++++++++---------------
 include/sbi/sbi_scratch.h | 24 +++++++++++++---------
 lib/sbi/sbi_domain.c      | 23 +++++++++++++++++++--
 lib/sbi/sbi_init.c        |  1 +
 5 files changed, 68 insertions(+), 28 deletions(-)
Signature · 1 line
2.39.0
#1 lore raw

PATCH v2 1/5 firmware: Split RO/RX and RW sections

Split the RO/RX and RW sections so that they can have independent pmp entries with required permissions. The split size is ensured to be a power-of-2 as required by pmp.

_fw_rw_offset symbol marks the beginning of the data section.

---
 firmware/fw_base.ldS | 8 ++++++++
 1 file changed, 8 insertions(+)
firmware/fw_base.ldS +8 -0
index 563ae25..5411bbd 100644
@@ -42,6 +42,14 @@
 
 	. = ALIGN(0x1000); /* Ensure next section is page aligned */
 
+	/*
+	 * PMP regions must be to be power-of-2. RO/RW will have separate
+	 * regions, so ensure that the split is power-of-2.
+	 */
+	. = ALIGN(1 << LOG2CEIL(SIZEOF(.rodata) + SIZEOF(.text)));
+
+	PROVIDE(_fw_rw_offset = (.  - _fw_start));
+
 	/* Beginning of the read-write data sections */
 
 	.data :
Signature · 1 line
2.39.0
#2 lore raw

PATCH v2 2/5 firmware: Move dynsym and reladyn sections to RX section

In reply to Himanshu Chauhan

Currently, the dynsym and reladyn sections are under RW data. They are moved to the Read-only/Executable region.

---
 firmware/fw_base.ldS | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)
firmware/fw_base.ldS +22 -19
index 5411bbd..9a1304e 100644
@@ -30,23 +30,39 @@
 
 	/* Beginning of the read-only data sections */
 
+	PROVIDE(_rodata_start = .);
+
 	.rodata :
 	{
-		PROVIDE(_rodata_start = .);
 		*(.rodata .rodata.*)
 		. = ALIGN(8);
-		PROVIDE(_rodata_end = .);
 	}
 
-	/* End of the read-only data sections */
-
 	. = ALIGN(0x1000); /* Ensure next section is page aligned */
 
+	.dynsym : {
+		PROVIDE(__dyn_sym_start = .);
+		*(.dynsym)
+		PROVIDE(__dyn_sym_end = .);
+	}
+
+	.rela.dyn : {
+		PROVIDE(__rel_dyn_start = .);
+		*(.rela*)
+		. = ALIGN(8);
+		PROVIDE(__rel_dyn_end = .);
+	}
+
+	PROVIDE(_rodata_end = .);
+
+	/* End of the read-only data sections */
+
 	/*
-	 * PMP regions must be to be power-of-2. RO/RW will have separate
+	 * PMP regions must be to be power-of-2. RX/RW will have separate
 	 * regions, so ensure that the split is power-of-2.
 	 */
-	. = ALIGN(1 << LOG2CEIL(SIZEOF(.rodata) + SIZEOF(.text)));
+	. = ALIGN(1 << LOG2CEIL((SIZEOF(.rodata) + SIZEOF(.text)
+				+ SIZEOF(.dynsym) + SIZEOF(.rela.dyn))));
 
 	PROVIDE(_fw_rw_offset = (.  - _fw_start));
 
@@ -67,19 +83,6 @@
 		PROVIDE(_data_end = .);
 	}
 
-	.dynsym : {
-		PROVIDE(__dyn_sym_start = .);
-		*(.dynsym)
-		PROVIDE(__dyn_sym_end = .);
-	}
-
-	.rela.dyn : {
-		PROVIDE(__rel_dyn_start = .);
-		*(.rela*)
-		. = ALIGN(8);
-		PROVIDE(__rel_dyn_end = .);
-	}
-
 	. = ALIGN(0x1000); /* Ensure next section is page aligned */
 
 	.bss :
Signature · 1 line
2.39.0
#3 lore raw

PATCH v2 3/5 firmware: Add RW section offset in scratch

In reply to Himanshu Chauhan

Add the RW section offset, provided by _fw_rw_offset symbol, to the scratch structure. This will be used to program separate pmp entry for RW section.

---
 firmware/fw_base.S        |  5 +++++
 include/sbi/sbi_scratch.h | 24 ++++++++++++++----------
 2 files changed, 19 insertions(+), 10 deletions(-)
firmware/fw_base.S +5 -0
index 3f622b3..ce1f782 100644
@@ -298,6 +298,11 @@ _scratch_init:
 	sub	a5, t3, a4
 	REG_S	a4, SBI_SCRATCH_FW_START_OFFSET(tp)
 	REG_S	a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp)
+
+	/* Store R/W section's offset in scratch space */
+	lla	a4, _fw_rw_offset
+	REG_S	a4, SBI_SCRATCH_FW_RW_OFFSET(tp)
+
 	/* Store next arg1 in scratch space */
 	MOV_3R	s0, a0, s1, a1, s2, a2
 	call	fw_next_arg1
include/sbi/sbi_scratch.h +14 -10
index 40a3bc9..2966188 100644
@@ -18,26 +18,28 @@
 #define SBI_SCRATCH_FW_START_OFFSET		(0 * __SIZEOF_POINTER__)
 /** Offset of fw_size member in sbi_scratch */
 #define SBI_SCRATCH_FW_SIZE_OFFSET		(1 * __SIZEOF_POINTER__)
+/** Offset (in sbi_scratch) of the R/W Offset */
+#define SBI_SCRATCH_FW_RW_OFFSET		(2 * __SIZEOF_POINTER__)
 /** Offset of next_arg1 member in sbi_scratch */
-#define SBI_SCRATCH_NEXT_ARG1_OFFSET		(2 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_NEXT_ARG1_OFFSET		(3 * __SIZEOF_POINTER__)
 /** Offset of next_addr member in sbi_scratch */
-#define SBI_SCRATCH_NEXT_ADDR_OFFSET		(3 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_NEXT_ADDR_OFFSET		(4 * __SIZEOF_POINTER__)
 /** Offset of next_mode member in sbi_scratch */
-#define SBI_SCRATCH_NEXT_MODE_OFFSET		(4 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_NEXT_MODE_OFFSET		(5 * __SIZEOF_POINTER__)
 /** Offset of warmboot_addr member in sbi_scratch */
-#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET	(5 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET	(6 * __SIZEOF_POINTER__)
 /** Offset of platform_addr member in sbi_scratch */
-#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET	(6 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET	(7 * __SIZEOF_POINTER__)
 /** Offset of hartid_to_scratch member in sbi_scratch */
-#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET	(7 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET	(8 * __SIZEOF_POINTER__)
 /** Offset of trap_exit member in sbi_scratch */
-#define SBI_SCRATCH_TRAP_EXIT_OFFSET		(8 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_TRAP_EXIT_OFFSET		(9 * __SIZEOF_POINTER__)
 /** Offset of tmp0 member in sbi_scratch */
-#define SBI_SCRATCH_TMP0_OFFSET			(9 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_TMP0_OFFSET			(10 * __SIZEOF_POINTER__)
 /** Offset of options member in sbi_scratch */
-#define SBI_SCRATCH_OPTIONS_OFFSET		(10 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_OPTIONS_OFFSET		(11 * __SIZEOF_POINTER__)
 /** Offset of extra space in sbi_scratch */
-#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(11 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(12 * __SIZEOF_POINTER__)
 /** Maximum size of sbi_scratch (4KB) */
 #define SBI_SCRATCH_SIZE			(0x1000)
 
@@ -53,6 +55,8 @@ struct sbi_scratch {
 	unsigned long fw_start;
 	/** Size (in bytes) of firmware linked to OpenSBI library */
 	unsigned long fw_size;
+	/** Offset (in bytes) of the R/W section */
+	unsigned long fw_rw_offset;
 	/** Arg1 (or 'a1' register) of next booting stage for this HART */
 	unsigned long next_arg1;
 	/** Address of next booting stage for this HART */
Signature · 1 line
2.39.0
#4 lore raw

PATCH v2 4/5 lib: sbi: Print the RW section offset

In reply to Himanshu Chauhan

Print the RW section offset when firmware base and size is being printed.

---
 lib/sbi/sbi_init.c | 1 +
 1 file changed, 1 insertion(+)
lib/sbi/sbi_init.c +1 -0
index 259a191..e353c33 100644
@@ -108,6 +108,7 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
 	sbi_printf("Firmware Base             : 0x%lx\n", scratch->fw_start);
 	sbi_printf("Firmware Size             : %d KB\n",
 		   (u32)(scratch->fw_size / 1024));
+	sbi_printf("Firmware RW Offset        : 0x%lx\n", scratch->fw_rw_offset);
 
 	/* SBI details */
 	sbi_printf("Runtime SBI Version       : %d.%d\n",
Signature · 1 line
2.39.0
#5 lore raw

PATCH v2 5/5 Add two entries:

In reply to Himanshu Chauhan

1. TEXT: fw_start to _fw_rw_offset with RX permissions
2. DATA: _fw_rw_offset to fw_size with RW permissions

These permissions are still not enforced from M-mode but lay the ground work for enforcing them for M-mode. SU-mode don't have any access to these regions.

Sample output:
Domain0 Region01 : 0x0000000080000000-0x000000008001ffff M: (R,X) S/U: () Domain0 Region02 : 0x0000000080020000-0x000000008003ffff M: (R,W) S/U: ()

---
 lib/sbi/sbi_domain.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
lib/sbi/sbi_domain.c +21 -2
index f6addc4..3dceb6a 100644
@@ -637,12 +637,31 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 	u32 i;
 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
 
+	if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {
+		sbi_printf("%s: Firmware read-write offset not a power of 2 (0x%lx)\n",
+			   __func__, scratch->fw_rw_offset);
+		return SBI_EINVAL;
+	}
+
+	if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+		sbi_printf("%s: Firmware start and read-write offset not aligned\n",
+			   __func__);
+		return SBI_EINVAL;
+	}
+
 	/* Root domain firmware memory region */
-	sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size,
-				  SBI_DOMAIN_MEMREGION_M_RWX,
+	sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset,
+				  (SBI_DOMAIN_MEMREGION_M_READABLE |
+				   SBI_DOMAIN_MEMREGION_M_EXECUTABLE),
 				  &root_fw_region);
 	domain_memregion_initfw(&root_memregs[root_memregs_count++]);
 
+	sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset),
+				  (scratch->fw_size - scratch->fw_rw_offset),
+				  (SBI_DOMAIN_MEMREGION_M_READABLE |
+				   SBI_DOMAIN_MEMREGION_M_WRITABLE),
+				  &root_memregs[root_memregs_count++]);
+
 	/* Root domain allow everything memory region */
 	sbi_domain_memregion_init(0, ~0UL,
 				  (SBI_DOMAIN_MEMREGION_READABLE |
Signature · 1 line
2.39.0
#6 lore raw

PATCH v2 5/5 Add two entries:

? 2023-01-18???? 17:07 +0530?Himanshu Chauhan???

Quoted 23 lines

? 1. TEXT: fw_start to _fw_rw_offset with RX permissions ? 2. DATA: _fw_rw_offset to fw_size with RW permissions

These permissions are still not enforced from M-mode but lay the ground work for enforcing them for M-mode. SU-mode don't have any access to these regions.

Sample output:
?Domain0 Region01? : 0x0000000080000000-0x000000008001ffff M: (R,X) S/U: () ?Domain0 Region02? : 0x0000000080020000-0x000000008003ffff M: (R,W) S/U: ()

---
?lib/sbi/sbi_domain.c | 23 +++++++++++++++++++++-- ?1 file changed, 21 insertions(+), 2 deletions(-)

lib/sbi/sbi_domain.c +0 -0
index f6addc4..3dceb6a 100644
@@ -637,12 +637,31 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 ????????u32 i;
 ????????const struct sbi_platform *plat = sbi_platform_ptr(scratch);
Quoted 2 lines

?
+???????if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {

This expression is false at scratch-> fw_rw_offset = 0. 0 is not a power of 2.
suggestion:

    if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0 || scratch->fw_rw_offset == 0) {

Regards,
Xiang W

Quoted 33 lines

+???????????????sbi_printf("%s: Firmware read-write offset not a power of 2 (0x%lx)\n", +????????????????????????? __func__, scratch->fw_rw_offset); +???????????????return SBI_EINVAL;
+???????}

lib/sbi/sbi_domain.c +7 -0
+
+???????if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+???????????????sbi_printf("%s: Firmware start and read-write offset not aligned\n",
+????????????????????????? __func__);
+???????????????return SBI_EINVAL;
+???????}
+

????????/* Root domain firmware memory region */ -???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size, -???????????????????????????????? SBI_DOMAIN_MEMREGION_M_RWX, +???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset, +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_EXECUTABLE), ????????????????????????????????? &root_fw_region); ????????domain_memregion_initfw(&root_memregs[root_memregs_count++]); ?
+???????sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset), +???????????????????????????????? (scratch->fw_size - scratch->fw_rw_offset), +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_WRITABLE), +???????????????????????????????? &root_memregs[root_memregs_count++]); +
????????/* Root domain allow everything memory region */ ????????sbi_domain_memregion_init(0, ~0UL, ????????????????????????????????? (SBI_DOMAIN_MEMREGION_READABLE |

Signature · 1 line
2.39.0
#7 lore raw

PATCH v2 5/5 Add two entries:

Quoted 30 lines · Xiang W

? 2023-01-18???? 17:07 +0530?Himanshu Chauhan???

Quoted 23 lines

? 1. TEXT: fw_start to _fw_rw_offset with RX permissions ? 2. DATA: _fw_rw_offset to fw_size with RW permissions

These permissions are still not enforced from M-mode but lay the ground work for enforcing them for M-mode. SU-mode don't have any access to these regions.

Sample output:
?Domain0 Region01? : 0x0000000080000000-0x000000008001ffff M: (R,X) S/U: () ?Domain0 Region02? : 0x0000000080020000-0x000000008003ffff M: (R,W) S/U: ()

---
?lib/sbi/sbi_domain.c | 23 +++++++++++++++++++++-- ?1 file changed, 21 insertions(+), 2 deletions(-)

lib/sbi/sbi_domain.c +0 -0
index f6addc4..3dceb6a 100644
@@ -637,12 +637,31 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 ????????u32 i;
 ????????const struct sbi_platform *plat = sbi_platform_ptr(scratch);
Quoted 2 lines

?
+???????if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {

This expression is false at scratch-> fw_rw_offset = 0. 0 is not a power of 2.
suggestion:

Quoted 1 line
    if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0 || scratch->fw_rw_offset == 0) {

fw_rw_offset is provided by the linker. It will fall after text, ro, and symbols and then it is protected by LOG2CEIL. Unless everything is preceding fw_rw_offset is zero, fw_rw_offset can't be zero. So I think this check is safe here.

Regards
Himanshu

Quoted 38 lines

Regards,
Xiang W

Quoted 33 lines

+???????????????sbi_printf("%s: Firmware read-write offset not a power of 2 (0x%lx)\n", +????????????????????????? __func__, scratch->fw_rw_offset); +???????????????return SBI_EINVAL;
+???????}

lib/sbi/sbi_domain.c +7 -0
+
+???????if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+???????????????sbi_printf("%s: Firmware start and read-write offset not aligned\n",
+????????????????????????? __func__);
+???????????????return SBI_EINVAL;
+???????}
+

????????/* Root domain firmware memory region */ -???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size, -???????????????????????????????? SBI_DOMAIN_MEMREGION_M_RWX, +???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset, +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_EXECUTABLE), ????????????????????????????????? &root_fw_region); ????????domain_memregion_initfw(&root_memregs[root_memregs_count++]); ?
+???????sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset), +???????????????????????????????? (scratch->fw_size - scratch->fw_rw_offset), +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_WRITABLE), +???????????????????????????????? &root_memregs[root_memregs_count++]); +
????????/* Root domain allow everything memory region */ ????????sbi_domain_memregion_init(0, ~0UL, ????????????????????????????????? (SBI_DOMAIN_MEMREGION_READABLE |

Signature · 1 line
2.39.0
#8 lore raw

PATCH v2 5/5 Add two entries:

? 2023-01-19???? 08:11 +0530?Himanshu Chauhan???

Quoted 33 lines · Xiang W
Quoted 17 lines

? 2023-01-18???? 17:07 +0530?Himanshu Chauhan???

Quoted 16 lines

? 1. TEXT: fw_start to _fw_rw_offset with RX permissions ? 2. DATA: _fw_rw_offset to fw_size with RW permissions

These permissions are still not enforced from M-mode but lay the ground work for enforcing them for M-mode. SU-mode don't have any access to these regions.

Sample output:
?Domain0 Region01? : 0x0000000080000000-0x000000008001ffff M: (R,X) S/U: () ?Domain0 Region02? : 0x0000000080020000-0x000000008003ffff M: (R,W) S/U: ()

---
?lib/sbi/sbi_domain.c | 23 +++++++++++++++++++++-- ?1 file changed, 21 insertions(+), 2 deletions(-)

Quoted 14 lines
Quoted 9 lines
lib/sbi/sbi_domain.c +0 -0
index f6addc4..3dceb6a 100644
@@ -637,12 +637,31 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 ????????u32 i;
 ????????const struct sbi_platform *plat = sbi_platform_ptr(scratch);

?
+???????if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {

This expression is false at scratch-> fw_rw_offset = 0.
0 is not a power of 2.
suggestion:
??? if ((scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0 || scratch->fw_rw_offset == 0) {

Quoted 3 lines

fw_rw_offset is provided by the linker. It will fall after text, ro, and symbols and then it is protected by LOG2CEIL. Unless everything is preceding fw_rw_offset is zero, fw_rw_offset can't be zero. So I think this check is safe here.

I know fw_rw_offset is provieded by the linker script. This check prevents linker scripts from being incorrectly modified.

Regards,
Xiang W

Quoted 42 lines

Regards
Himanshu

Quoted 38 lines

Regards,
Xiang W

Quoted 33 lines

+???????????????sbi_printf("%s: Firmware read-write offset not a power of 2 (0x%lx)\n", +????????????????????????? __func__, scratch->fw_rw_offset); +???????????????return SBI_EINVAL;
+???????}

lib/sbi/sbi_domain.c +7 -0
+
+???????if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+???????????????sbi_printf("%s: Firmware start and read-write offset not aligned\n",
+????????????????????????? __func__);
+???????????????return SBI_EINVAL;
+???????}
+

????????/* Root domain firmware memory region */ -???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size, -???????????????????????????????? SBI_DOMAIN_MEMREGION_M_RWX, +???????sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset, +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_EXECUTABLE), ????????????????????????????????? &root_fw_region); ????????domain_memregion_initfw(&root_memregs[root_memregs_count++]); ?
+???????sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset), +???????????????????????????????? (scratch->fw_size - scratch->fw_rw_offset), +???????????????????????????????? (SBI_DOMAIN_MEMREGION_M_READABLE | +????????????????????????????????? SBI_DOMAIN_MEMREGION_M_WRITABLE), +???????????????????????????????? &root_memregs[root_memregs_count++]); +
????????/* Root domain allow everything memory region */ ????????sbi_domain_memregion_init(0, ~0UL, ????????????????????????????????? (SBI_DOMAIN_MEMREGION_READABLE |

Signature · 1 line
2.39.0