From gaoshanliukou at 163.com  Thu Feb  1 02:30:20 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Thu,  1 Feb 2024 18:30:20 +0800
Subject: [PATCH] lib: sbi: Add sparse hartid support for mtimer/ipi
Message-ID: <20240201103020.21181-1-gaoshanliukou@163.com>

If hartid is sparse, such as 0, 7, 16..., mtimer/mswi
can't work well.

Test:
1.Our platform support SMT, one core contains many harts
whoes number is configurable, so the hartids is sparse when
enter Opensbi?
2.I just simply simulate a scenario on qemu, like below
"qemu-system-riscv64 -M virt,aia=aplic -m 2g -smp 8 -dtb qemu2cpu.dtb
 -bios fw_jump.bin ..."
There are total 8 cpus, but the dts only suppor 2 cpu nodes, hartid are
0 and 7, so when enter opensbi, just hartid 0 and 7 are running, the others
are hanged, like sparse hartid.Then the issue happened.
Logs:
OpenSBI v1.4-11-g0dcc2e6
   ____                    _____ ____ _____
  / __ \                  / ____|  _ \_   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  \____/| .__/ \___|_| |_|_____/|____/_____|
        | |
        |_|

init_coldboot: timer init failed (error -1000)

Signed-off-by: yang.zhang <gaoshanliukou at 163.com>
---
 lib/utils/ipi/aclint_mswi.c     | 2 +-
 lib/utils/timer/aclint_mtimer.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
index 4ae6bb1..3bbab8b 100644
--- a/lib/utils/ipi/aclint_mswi.c
+++ b/lib/utils/ipi/aclint_mswi.c
@@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
 
 	/* Update MSWI pointer in scratch space */
 	for (i = 0; i < mswi->hart_count; i++) {
-		scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
+		scratch = sbi_hartindex_to_scratch(i);
 		/*
 		 * We don't need to fail if scratch pointer is not available
 		 * because we might be dealing with hartid of a HART disabled
diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
index 271e625..77d5522 100644
--- a/lib/utils/timer/aclint_mtimer.c
+++ b/lib/utils/timer/aclint_mtimer.c
@@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 
 	/* Update MTIMER pointer in scratch space */
 	for (i = 0; i < mt->hart_count; i++) {
-		scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
+		scratch = sbi_hartindex_to_scratch(i);
 		/*
 		 * We don't need to fail if scratch pointer is not available
 		 * because we might be dealing with hartid of a HART disabled
-- 
2.25.1



From inochiama at outlook.com  Thu Feb  1 20:04:38 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri,  2 Feb 2024 12:04:38 +0800
Subject: [PATCH 0/4] Add relocatable address support for jump and payload firmware
Message-ID: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>

If FW_PIC=y is defined, the jump and payload firmware and will
be broken if FW_TEXT_START is wrong. This is not the desired behavior.

Add some new variable to support relocatable address.

build command:
make BUILD_INFO=y DEBUG=1 FW_PIC=y PLATFORM=generic FW_TEXT_START=0x0

test command:
qemu-system-riscv64 -smp cpus=4 -M virt -m 256M \
  -bios build/platform/generic/firmware/fw_payload.bin

Inochi Amaoto (4):
  firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
  firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
  platform: Apply relocatable address
  doc/firmware: add new configuration options for jump and payload
    firmware

 docs/firmware/fw_jump.md    | 17 ++++++++++++++---
 docs/firmware/fw_payload.md |  6 ++++++
 firmware/fw_jump.S          | 20 ++++++++++++++++----
 firmware/fw_payload.S       |  4 ++++
 firmware/objects.mk         | 21 +++++++++++++++++++++
 platform/generic/objects.mk |  8 ++++----
 6 files changed, 65 insertions(+), 11 deletions(-)

--
2.43.0



From inochiama at outlook.com  Thu Feb  1 20:05:33 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri,  2 Feb 2024 12:05:33 +0800
Subject: [PATCH 1/4] firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
In-Reply-To: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>

If FW_PIC=y is defined, the fw_jump.bin will be broken if
FW_TEXT_START is wrong. This is not the desired behavior.

Add two new variables to identify relocatable jump address:
FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
are defined. And these two new variables will convert to
the old one if compiler does not support PIC.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 firmware/fw_jump.S  | 20 ++++++++++++++++----
 firmware/objects.mk | 15 +++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
index ac74dc6..0ad2398 100644
--- a/firmware/fw_jump.S
+++ b/firmware/fw_jump.S
@@ -46,6 +46,10 @@ fw_save_info:
 fw_next_arg1:
 #ifdef FW_JUMP_FDT_ADDR
 	li	a0, FW_JUMP_FDT_ADDR
+#elif defined(FW_JUMP_FDT_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_JUMP_FDT_OFFSET
+	add	a0, a0, a1
 #else
 	add	a0, a1, zero
 #endif
@@ -59,7 +63,13 @@ fw_next_arg1:
 	 * The next address should be returned in 'a0'.
 	 */
 fw_next_addr:
+#ifdef FW_JUMP_ADDR
 	lla	a0, _jump_addr
+#elif defined(FW_JUMP_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_JUMP_OFFSET
+	add	a0, a0, a1
+#endif
 	REG_L	a0, (a0)
 	ret
 
@@ -86,11 +96,13 @@ fw_options:
 	add	a0, zero, zero
 	ret
 
-#ifndef FW_JUMP_ADDR
-#error "Must define FW_JUMP_ADDR"
-#endif
-
+#ifdef FW_JUMP_ADDR
 	.section .rodata
 	.align 3
 _jump_addr:
 	RISCV_PTR FW_JUMP_ADDR
+#else
+#ifndef FW_JUMP_OFFSET
+#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
+#endif
+#endif
diff --git a/firmware/objects.mk b/firmware/objects.mk
index a1704c4..248706d 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -35,12 +35,27 @@ firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
 endif
 endif
 
+ifeq ($(FW_PIC),n)
+  ifndef FW_JUMP_ADDR
+    FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_OFFSET))))
+  endif
+  ifndef FW_JUMP_FDT_ADDR
+    FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
+  endif
+endif
+
 firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
 
 firmware-bins-$(FW_JUMP) += fw_jump.bin
+ifdef FW_JUMP_OFFSET
+firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
+endif
 ifdef FW_JUMP_ADDR
 firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
 endif
+ifdef FW_JUMP_FDT_OFFSET
+firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
+endif
 ifdef FW_JUMP_FDT_ADDR
 firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
 endif
-- 
2.43.0



From inochiama at outlook.com  Thu Feb  1 20:05:34 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri,  2 Feb 2024 12:05:34 +0800
Subject: [PATCH 2/4] firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
In-Reply-To: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB49539A729C9350C1714D7DA4BB422@IA1PR20MB4953.namprd20.prod.outlook.com>

The fw_payload.bin has the same issue as described in commit 80129c2.
But only FW_PAYLOAD_FDT_ADDR is affected.

Add FW_PAYLOAD_FDT_OFFSET to identify relocatable payload fdt address.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 firmware/fw_payload.S | 4 ++++
 firmware/objects.mk   | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
index c53a3bb..3c8433e 100644
--- a/firmware/fw_payload.S
+++ b/firmware/fw_payload.S
@@ -46,6 +46,10 @@ fw_save_info:
 fw_next_arg1:
 #ifdef FW_PAYLOAD_FDT_ADDR
 	li	a0, FW_PAYLOAD_FDT_ADDR
+#elif defined(FW_PAYLOAD_FDT_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_PAYLOAD_FDT_OFFSET
+	add	a0, a0, a1
 #else
 	add	a0, a1, zero
 #endif
diff --git a/firmware/objects.mk b/firmware/objects.mk
index 248706d..a761b9e 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -42,6 +42,9 @@ ifeq ($(FW_PIC),n)
   ifndef FW_JUMP_FDT_ADDR
     FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
   endif
+  ifndef FW_PAYLOAD_FDT_ADDR
+    FW_PAYLOAD_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_PAYLOAD_FDT_OFFSET))))
+  endif
 endif
 
 firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
@@ -74,6 +77,9 @@ ifdef FW_PAYLOAD_ALIGN
 firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
 endif
 
+ifdef FW_PAYLOAD_FDT_OFFSET
+firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
+endif
 ifdef FW_PAYLOAD_FDT_ADDR
 firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
 endif
-- 
2.43.0



From inochiama at outlook.com  Thu Feb  1 20:05:35 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri,  2 Feb 2024 12:05:35 +0800
Subject: [PATCH 3/4] platform: Apply relocatable address
In-Reply-To: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB49538AFD74ED9DA26246603CBB422@IA1PR20MB4953.namprd20.prod.outlook.com>

Since jump and payload firmware support relocatable address, make
general platform use runtime relocatable address.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 platform/generic/objects.mk | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
index 136853e..85aa723 100644
--- a/platform/generic/objects.mk
+++ b/platform/generic/objects.mk
@@ -27,12 +27,12 @@ FW_DYNAMIC=y
 FW_JUMP=y
 ifeq ($(PLATFORM_RISCV_XLEN), 32)
   # This needs to be 4MB aligned for 32-bit system
-  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000)))
+  FW_JUMP_OFFSET=0x400000
 else
   # This needs to be 2MB aligned for 64-bit system
-  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000)))
+  FW_JUMP_OFFSET=0x200000
 endif
-FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000)))
+FW_JUMP_FDT_OFFSET=0x2200000
 FW_PAYLOAD=y
 ifeq ($(PLATFORM_RISCV_XLEN), 32)
   # This needs to be 4MB aligned for 32-bit system
@@ -41,4 +41,4 @@ else
   # This needs to be 2MB aligned for 64-bit system
   FW_PAYLOAD_OFFSET=0x200000
 endif
-FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
+FW_PAYLOAD_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
-- 
2.43.0



From inochiama at outlook.com  Thu Feb  1 20:05:36 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri,  2 Feb 2024 12:05:36 +0800
Subject: [PATCH 4/4] doc/firmware: add new configuration options for jump and payload firmware
In-Reply-To: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB4953DC1AF6AA5F0240E348EDBB422@IA1PR20MB4953.namprd20.prod.outlook.com>

Adding relocatable address brings new configuration options.
Add these new options in doc.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 docs/firmware/fw_jump.md    | 17 ++++++++++++++---
 docs/firmware/fw_payload.md |  6 ++++++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/docs/firmware/fw_jump.md b/docs/firmware/fw_jump.md
index 3e883fa..4484393 100644
--- a/docs/firmware/fw_jump.md
+++ b/docs/firmware/fw_jump.md
@@ -31,9 +31,15 @@ follows:
 
 * **FW_JUMP_ADDR** - Address of the entry point of the booting stage to be
   executed following OpenSBI firmware. This address generally corresponds
-  exactly to the address where this next booting stage was loaded. This is a
-  mandatory parameter. Compilation errors will result from not defining this
-  address.
+  exactly to the address where this next booting stage was loaded.
+  At least one of *FW_JUMP_ADDR* and *FW_JUMP_OFFSET* (see below) should be
+  defined. Compilation errors will result from not defining one of them.
+
+* **FW_JUMP_OFFSET** - Address offset from the *FW_TEXT_START* of *FW_JUMP_ADDR*.
+  This offset is used as relocatable *FW_JUMP_ADDR* when "FW_PIC=y".
+  If *FW_JUMP_ADDR* is also defined, the firmware will prefer *FW_JUMP_ADDR*.
+  This offset will convert to *FW_JUMP_ADDR* at build time if "FW_PIC=n"
+  and *FW_JUMP_ADDR* is not defined.
 
 * **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
   passed by the prior booting stage will be placed in memory before executing
@@ -56,6 +62,11 @@ follows:
   (( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) &&
   echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR
   ```
+* **FW_JUMP_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
+  *FW_JUMP_FDT_ADDR*. This offset is used as relocatable *FW_JUMP_FDT_ADDR*
+  when "FW_PIC=y". If *FW_JUMP_FDT_ADDR* is also defined, the firmware will
+  prefer *FW_JUMP_FDT_ADDR*. This offset will convert to *FW_JUMP_FDT_ADDR*
+  at build time if "FW_PIC=n" and *FW_JUMP_FDT_ADDR* is not defined.
 
 *FW_JUMP* Example
 -----------------
diff --git a/docs/firmware/fw_payload.md b/docs/firmware/fw_payload.md
index 113604a..3a5ffe8 100644
--- a/docs/firmware/fw_payload.md
+++ b/docs/firmware/fw_payload.md
@@ -62,6 +62,12 @@ file. The parameters currently defined are as follows:
   firmware will pass the FDT address passed by the previous booting stage
   to the next booting stage.
 
+* **FW_PAYLOAD_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
+  *FW_PAYLOAD_FDT_ADDR*. This offset is used as relocatable *FW_PAYLOAD_FDT_ADDR*
+  when "FW_PIC=y". If *FW_PAYLOAD_FDT_ADDR* is also defined, the firmware will
+  prefer *FW_PAYLOAD_FDT_ADDR*. This offset will convert to *FW_PAYLOAD_FDT_ADDR*
+  at build time if "FW_PIC=n" and *FW_PAYLOAD_FDT_ADDR* is not defined.
+
 *FW_PAYLOAD* Example
 --------------------
 
-- 
2.43.0



From gaoshanliukou at 163.com  Thu Feb  1 23:20:08 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Fri, 2 Feb 2024 15:20:08 +0800 (CST)
Subject: [PATCH] lib: sbi: Add sparse hartid support for mtimer/ipi
In-Reply-To: <20240201103020.21181-1-gaoshanliukou@163.com>
References: <20240201103020.21181-1-gaoshanliukou@163.com>
Message-ID: <52d7cf12.5c73.18d68b06b3f.Coremail.gaoshanliukou@163.com>



The purpose of mentioning the "trap-n-emulate AMO" case is just to explain the context when issue happened.
The key point mayebe not the lock which i used, so i also emulate another case which is rdtime, if the platform does not
support read time csr, then it would trap, then sbi_emulate_csr_read can handle it correctly.But if trap earlier, then?
the issue is the same with us.
I completely agree with you ?If we are talking about other earlier traps,to me, that only means we have a bug in opensbi??So
i mentioned "?Of course, the above situation will not occur at present".
But, once we have a bug in opensbi in future, once phs_ptr_offset is zero? then?pmu_thishart_state_ptr would return scratch.fw_base,
for qemu is 0x80000000, if we don't add a check, it maybe intentionally breake text segment of opensbi, add additional debug difficulty meaningless.













At 2024-02-01 18:30:20, "yang.zhang" <gaoshanliukou at 163.com> wrote:
>If hartid is sparse, such as 0, 7, 16..., mtimer/mswi
>can't work well.
>
>Test:
>1.Our platform support SMT, one core contains many harts
>whoes number is configurable, so the hartids is sparse when
>enter Opensbi?
>2.I just simply simulate a scenario on qemu, like below
>"qemu-system-riscv64 -M virt,aia=aplic -m 2g -smp 8 -dtb qemu2cpu.dtb
> -bios fw_jump.bin ..."
>There are total 8 cpus, but the dts only suppor 2 cpu nodes, hartid are
>0 and 7, so when enter opensbi, just hartid 0 and 7 are running, the others
>are hanged, like sparse hartid.Then the issue happened.
>Logs:
>OpenSBI v1.4-11-g0dcc2e6
>   ____                    _____ ____ _____
>  / __ \                  / ____|  _ \_   _|
> | |  | |_ __   ___ _ __ | (___ | |_) || |
> | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> | |__| | |_) |  __/ | | |____) | |_) || |_
>  \____/| .__/ \___|_| |_|_____/|____/_____|
>        | |
>        |_|
>
>init_coldboot: timer init failed (error -1000)
>
>Signed-off-by: yang.zhang <gaoshanliukou at 163.com>
>---
> lib/utils/ipi/aclint_mswi.c     | 2 +-
> lib/utils/timer/aclint_mtimer.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
>diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
>index 4ae6bb1..3bbab8b 100644
>--- a/lib/utils/ipi/aclint_mswi.c
>+++ b/lib/utils/ipi/aclint_mswi.c
>@@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
> 
> 	/* Update MSWI pointer in scratch space */
> 	for (i = 0; i < mswi->hart_count; i++) {
>-		scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
>+		scratch = sbi_hartindex_to_scratch(i);
> 		/*
> 		 * We don't need to fail if scratch pointer is not available
> 		 * because we might be dealing with hartid of a HART disabled
>diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
>index 271e625..77d5522 100644
>--- a/lib/utils/timer/aclint_mtimer.c
>+++ b/lib/utils/timer/aclint_mtimer.c
>@@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> 
> 	/* Update MTIMER pointer in scratch space */
> 	for (i = 0; i < mt->hart_count; i++) {
>-		scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
>+		scratch = sbi_hartindex_to_scratch(i);
> 		/*
> 		 * We don't need to fail if scratch pointer is not available
> 		 * because we might be dealing with hartid of a HART disabled
>-- 
>2.25.1

From minda.chen at starfivetech.com  Fri Feb  2 02:47:16 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Fri, 2 Feb 2024 10:47:16 +0000
Subject: [PATCH 0/5] starfive reboot cleanup & fix
In-Reply-To: <20240201080107.2c02ea72@namcao>
References: <cover.1706705649.git.namcao@linutronix.de>
	<CAK9=C2WDjtb_xtC5FtqYMhB5ZY6Bb4EgaDA+_KccCDAkz+xFOg@mail.gmail.com>
	<SHXPR01MB0863DF11E5652E164AF74026E643A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
 <20240201080107.2c02ea72@namcao>
Message-ID: <SHXPR01MB08631A3FD01906F1F148003DE642A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> 
> On Thu, 1 Feb 2024 05:38:16 +0000 Minda Chen
> <minda.chen at starfivetech.com> wrote:
> > > On Wed, Jan 31, 2024 at 6:39?PM Nam Cao <namcao at linutronix.de> wrote:
> > > >
> > > > This series:
> > > >   - add gracefully error handling when reboot devices are not present
> > > >   - correct a device tree compatibility string
> > > >   - some minor cleanup
> > > >
> > > > This series complements my other series:
> > > > http://lists.infradead.org/pipermail/opensbi/2024-January/006300.h
> > > > tml
> > > >
> > > > Nam Cao (5):
> > > >   platform: starfive: remove redundant compatibility check in pmic_ops
> > > >   platform: starfive: rename "stf,axp15060-regulator" ->
> > > >     "x-powers,axp15060"
> > > >   platform: starfive: drop "compatible" from struct pmic
> > > >   platform: starfive: return error if needed devices are not present
> > > >   platform: starfive: call starfive_jh7110_inst_init() in
> > > >     pm_reset_init()
> > >
> > > Can someone from StarFive review and test this series ?
> > >
> > > Regards,
> > > Anup
> > >
> > Let me review these. But I don't receive this series patch.
> 
> I only sent it to the list. Can you grab the series from there?
> 
> Or I can also resend the series and include you as a recipient, if that's more
> convenient.
> 
> Best regards,
> Nam

Resend the patchset is better. Thanks
Minda 

From namcao at linutronix.de  Fri Feb  2 05:43:21 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:21 +0100
Subject: [PATCH v3 0/7] Starfive reboot fix & cleanup
Message-ID: <cover.1706880734.git.namcao@linutronix.de>

Hi,

I previously sent 2 separate series fixing the reboot of the Visionfive2
board. However the Starfive folks did not receive both series, and also
because the 2 series are closely related; I am merging those 2 separate
series together and re-send them as a v3.

This series:
 - Rename device tree compatible strings to match U-Boot
 - Fix code that extract I2C address from device tree
 - Cleanup

The device tree nodes in this series have just been merged to U-Boot a few
days ago. So please use most recent upstream U-Boot for testing this
series.

Nam Cao (7):
  platform: starfive: correct system clock device tree node
  platform: starfive: get I2C offset address from clocks property
  platform: starfive: remove redundant compatibility check in pmic_ops
  platform: starfive: rename "stf,axp15060-regulator" ->
    "x-powers,axp15060"
  platform: starfive: drop "compatible" from struct pmic
  platform: starfive: return error if needed devices are not present
  platform: starfive: call starfive_jh7110_inst_init() in
    pm_reset_init()

 platform/generic/starfive/jh7110.c | 70 ++++++++++++++++--------------
 1 file changed, 38 insertions(+), 32 deletions(-)

-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:24 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:24 +0100
Subject: [PATCH v3 3/7] platform: starfive: remove redundant compatibility check in pmic_ops
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <16ada695eb73656550b0474b6640dc0d42f1f1fe.1706880734.git.namcao@linutronix.de>

pmic_ops() is only called if a compatible device is found in device
tree. It is redundant for this function to check the compability again.
Remove this check.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 36 ++++++++++++++----------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 846b068..d3647c2 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -134,28 +134,26 @@ static void pmic_ops(struct pmic *pmic, int type)
 	if (ret)
 		return;
 
-	if (!sbi_strcmp("stf,axp15060-regulator", pmic->compatible)) {
-		ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
-					   AXP15060_POWER_REG, &val);
-
-		if (ret) {
-			sbi_printf("%s: cannot read pmic power register\n",
-				   __func__);
-			return;
-		}
+	ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, &val);
+
+	if (ret) {
+		sbi_printf("%s: cannot read pmic power register\n",
+				__func__);
+		return;
+	}
 
+	val |= AXP15060_POWER_OFF_BIT;
+	if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
 		val |= AXP15060_POWER_OFF_BIT;
-		if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
-			val |= AXP15060_POWER_OFF_BIT;
-		else
-			val |= AXP15060_RESET_BIT;
+	else
+		val |= AXP15060_RESET_BIT;
 
-		ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
-					    AXP15060_POWER_REG, val);
-		if (ret)
-			sbi_printf("%s: cannot write pmic power register\n",
-				   __func__);
-	}
+	ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, val);
+	if (ret)
+		sbi_printf("%s: cannot write pmic power register\n",
+				__func__);
 }
 
 static void pmic_i2c_clk_enable(void)
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:22 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:22 +0100
Subject: [PATCH v3 1/7] platform: starfive: correct system clock device tree node
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <063d675dcf59e79892091b0ef085a6a2ca4f6bee.1706880734.git.namcao@linutronix.de>

Starfive names the system clock device tree node "starfive,jh7110-clkgen"
in all their git repositories. However, a different name is used in
upstream U-Boot (and also Linux): "starfive,jh7110-syscrg". Since
OpenSBI gets the device tree from U-Boot, this inconsistency leads the
problem that OpenSBI doesn't know the system clock device exists.

Correct this name to keep the consistency.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index dcd6306..4b22175 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -252,7 +252,7 @@ static int starfive_jh7110_inst_init(void *fdt)
 		jh7110_inst.pmu_reg_base = addr;
 	}
 
-	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen");
+	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
 	if (-1 < noff) {
 		rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
 		if (rc)
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:23 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:23 +0100
Subject: [PATCH v3 2/7] platform: starfive: get I2C offset address from clocks property
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>

The current code gets the I2C offset address using the device tree node
name: it get the I2C device index from the 4th character in the node
name (for example, "i2c5" -> i2c device 5). However, the device tree
node's name in U-Boot is actually just "i2c" without the number, so the
current code cannot be used with the device tree from U-Boot.

Get the I2C offset address from the "clocks" property instead.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 4b22175..846b068 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -29,7 +29,7 @@ struct pmic {
 struct jh7110 {
 	u64 pmu_reg_base;
 	u64 clk_reg_base;
-	u32 i2c_index;
+	u32 i2c_clk_offset;
 };
 
 static struct pmic pmic_inst;
@@ -163,10 +163,7 @@ static void pmic_i2c_clk_enable(void)
 	unsigned long clock_base;
 	unsigned int val;
 
-	clock_base = jh7110_inst.clk_reg_base +
-		I2C_APB_CLK_OFFSET +
-		(jh7110_inst.i2c_index << 2);
-
+	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
 	val = readl((void *)clock_base);
 
 	if (!val)
@@ -241,7 +238,8 @@ static struct fdt_reset fdt_reset_pmic = {
 static int starfive_jh7110_inst_init(void *fdt)
 {
 	int noff, rc = 0;
-	const char *name;
+	const fdt32_t *val;
+	int len;
 	u64 addr;
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu");
@@ -261,9 +259,12 @@ static int starfive_jh7110_inst_init(void *fdt)
 	}
 
 	if (pmic_inst.adapter) {
-		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
-		if (!sbi_strncmp(name, "i2c", 3))
-			jh7110_inst.i2c_index = name[3] - '0';
+		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
+		/* The clocks property looks like this: clocks = <&syscrg JH7110_SYSCLK_I2C5_APB>;
+		 * So check that the length is 8 bytes, and get the offset from the second value
+		 */
+		if (val && len == 8)
+			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
 		else
 			rc = SBI_EINVAL;
 	}
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:25 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:25 +0100
Subject: [PATCH v3 4/7] platform: starfive: rename "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <e885fedc2fb483d5349eda4170890ed7dbabe510.1706880734.git.namcao@linutronix.de>

OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
for the regulator node. However, the string used by U-Boot (and Linux)
is actually "x-powers,axp15060". As OpenSBI gets the device tree from
U-Boot, this causes the regulator device to be undetected, and OpenSBI
does not use this device to perform board reset/shutdown.

Rename this device tree compatible string to match U-Boot (and Linux).

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index d3647c2..385e09c 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -224,7 +224,7 @@ static int pm_reset_init(void *fdt, int nodeoff,
 }
 
 static const struct fdt_match pm_reset_match[] = {
-	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
+	{ .compatible = "x-powers,axp15060", .data = (void *)true },
 	{ },
 };
 
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:26 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:26 +0100
Subject: [PATCH v3 5/7] platform: starfive: drop "compatible" from struct pmic
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <ab05513e09ddbef539fedd7e9da7a1cecf526971.1706880734.git.namcao@linutronix.de>

The member "compatible" of struct pmic is not used. Delete it.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 385e09c..f64e016 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -23,7 +23,6 @@
 struct pmic {
 	struct i2c_adapter *adapter;
 	u32 dev_addr;
-	const char *compatible;
 };
 
 struct jh7110 {
@@ -205,7 +204,6 @@ static int pm_reset_init(void *fdt, int nodeoff,
 		return rc;
 
 	pmic_inst.dev_addr = addr;
-	pmic_inst.compatible = match->compatible;
 
 	i2c_bus = fdt_parent_offset(fdt, nodeoff);
 	if (i2c_bus < 0)
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:27 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:27 +0100
Subject: [PATCH v3 6/7] platform: starfive: return error if needed devices are not present
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <4f1504484813d64f8e8190e0174c4f5802cbbd6d.1706880734.git.namcao@linutronix.de>

Jh7110's reset driver needs power management device and clock controller
device to work. Currently, the driver proceed anyway without these
devices, and invalid addresses (jh7110_inst.pmu_reg_base and
jh7110_inst.clk_reg_base) are used during reboot, which causes
unpredictable broken behaviors.

If these devices are not present, return -SBI_ENODEV.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index f64e016..63baddb 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -244,6 +244,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.pmu_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
@@ -252,6 +254,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.clk_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	if (pmic_inst.adapter) {
-- 
2.39.2



From namcao at linutronix.de  Fri Feb  2 05:43:28 2024
From: namcao at linutronix.de (Nam Cao)
Date: Fri,  2 Feb 2024 14:43:28 +0100
Subject: [PATCH v3 7/7] platform: starfive: call starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <cover.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
Message-ID: <5e478ee9042b05c53ff4d38a65bd5842591f960d.1706880734.git.namcao@linutronix.de>

The function starfive_jh7110_inst_init() initialize some power
management unit address and clock addresses, needed for the reset
driver. It doesn't do anything else, and also the reset driver doesn't
work without calling this function. Thus, it does not make much sense
that this function is independent from pm_reset_init().

Delete the separate call to starfive_jh7110_inst_init(), and instead
just call this function inside pm_reset_init().

Doing this also fixes another problem: if starfive_jh7110_inst_init()
returns an error code, it gets propagated to final_init() and OpenSBI
hangs. This hang is not necessary, because failures within
starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
shutdown, but the system can still function normally.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 63baddb..1577cb4 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -191,6 +191,8 @@ static struct sbi_system_reset_device pm_reset = {
 	.system_reset = pm_system_reset
 };
 
+static int starfive_jh7110_inst_init(void *fdt);
+
 static int pm_reset_init(void *fdt, int nodeoff,
 			 const struct fdt_match *match)
 {
@@ -216,6 +218,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
 
 	pmic_inst.adapter = adapter;
 
+	rc = starfive_jh7110_inst_init(fdt);
+	if (rc)
+		return rc;
+
 	sbi_system_reset_add_device(&pm_reset);
 
 	return 0;
@@ -279,7 +285,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
 
 	if (cold_boot) {
 		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
-		return starfive_jh7110_inst_init(fdt);
 	}
 
 	return 0;
-- 
2.39.2



From minda.chen at starfivetech.com  Sat Feb  3 17:02:57 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Sun, 4 Feb 2024 01:02:57 +0000
Subject: [PATCH v3 2/7] platform: starfive: get I2C offset address from
 clocks property
In-Reply-To: <e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
 <e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB08633A9427C78CAE2C9397DFE640A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> The current code gets the I2C offset address using the device tree node
> name: it get the I2C device index from the 4th character in the node name (for
> example, "i2c5" -> i2c device 5). However, the device tree node's name in
> U-Boot is actually just "i2c" without the number, so the current code cannot be
> used with the device tree from U-Boot.
> 
> Get the I2C offset address from the "clocks" property instead.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 4b22175..846b068 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -29,7 +29,7 @@ struct pmic {
>  struct jh7110 {
>  	u64 pmu_reg_base;
>  	u64 clk_reg_base;
> -	u32 i2c_index;
> +	u32 i2c_clk_offset;
>  };
> 
>  static struct pmic pmic_inst;
> @@ -163,10 +163,7 @@ static void pmic_i2c_clk_enable(void)
>  	unsigned long clock_base;
>  	unsigned int val;
> 
> -	clock_base = jh7110_inst.clk_reg_base +
> -		I2C_APB_CLK_OFFSET +
> -		(jh7110_inst.i2c_index << 2);
> -
> +	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
>  	val = readl((void *)clock_base);
> 
Yes , I want to upstream this patch, Thanks
Delete this macro too.

-#define I2C_APB_CLK_OFFSET             0x228

>  	if (!val)
> @@ -241,7 +238,8 @@ static struct fdt_reset fdt_reset_pmic = {  static int
> starfive_jh7110_inst_init(void *fdt)  {
>  	int noff, rc = 0;
> -	const char *name;
> +	const fdt32_t *val;
> +	int len;
>  	u64 addr;
> 
>  	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu"); @@
> -261,9 +259,12 @@ static int starfive_jh7110_inst_init(void *fdt)
>  	}
> 
>  	if (pmic_inst.adapter) {
> -		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
> -		if (!sbi_strncmp(name, "i2c", 3))
> -			jh7110_inst.i2c_index = name[3] - '0';
> +		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
> +		/* The clocks property looks like this: clocks = <&syscrg
> JH7110_SYSCLK_I2C5_APB>;
> +		 * So check that the length is 8 bytes, and get the offset from the
> second value
> +		 */
> +		if (val && len == 8)
> +			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
>  		else
>  			rc = SBI_EINVAL;
>  	}
> --
> 2.39.2



From minda.chen at starfivetech.com  Sat Feb  3 17:12:27 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Sun, 4 Feb 2024 01:12:27 +0000
Subject: [PATCH v3 4/7] platform: starfive: rename
 "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <e885fedc2fb483d5349eda4170890ed7dbabe510.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
 <e885fedc2fb483d5349eda4170890ed7dbabe510.1706880734.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB0863C62431DF20ABB8779D54E640A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> 
> OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
> for the regulator node. However, the string used by U-Boot (and Linux) is
> actually "x-powers,axp15060". As OpenSBI gets the device tree from U-Boot,
> this causes the regulator device to be undetected, and OpenSBI does not use
> this device to perform board reset/shutdown.
> 
> Rename this device tree compatible string to match U-Boot (and Linux).
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index d3647c2..385e09c 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -224,7 +224,7 @@ static int pm_reset_init(void *fdt, int nodeoff,  }
> 
>  static const struct fdt_match pm_reset_match[] = {
> -	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
> +	{ .compatible = "x-powers,axp15060", .data = (void *)true },
>  	{ },
>  };
> 
It is OK.
But upstream u-boot jh7110 dts file do not contain this compatible?
Can you also upstream this in u-boot? or I will do this myself
> --
> 2.39.2


From minda.chen at starfivetech.com  Sun Feb  4 17:54:07 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Mon, 5 Feb 2024 01:54:07 +0000
Subject: [PATCH v3 7/7] platform: starfive: call
 starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <5e478ee9042b05c53ff4d38a65bd5842591f960d.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
 <5e478ee9042b05c53ff4d38a65bd5842591f960d.1706880734.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB08635C8CF48CE8DA7C0353A2E647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>


> 
> The function starfive_jh7110_inst_init() initialize some power management unit
> address and clock addresses, needed for the reset driver. It doesn't do anything
> else, and also the reset driver doesn't work without calling this function. Thus, it
> does not make much sense that this function is independent from
> pm_reset_init().
> 
> Delete the separate call to starfive_jh7110_inst_init(), and instead just call this
> function inside pm_reset_init().
> 
> Doing this also fixes another problem: if starfive_jh7110_inst_init() returns an
> error code, it gets propagated to final_init() and OpenSBI hangs. This hang is not
> necessary, because failures within
> starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
> shutdown, but the system can still function normally.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 63baddb..1577cb4 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -191,6 +191,8 @@ static struct sbi_system_reset_device pm_reset = {
>  	.system_reset = pm_system_reset
>  };
> 
> +static int starfive_jh7110_inst_init(void *fdt);
> +
>  static int pm_reset_init(void *fdt, int nodeoff,
>  			 const struct fdt_match *match)
>  {
> @@ -216,6 +218,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
> 
>  	pmic_inst.adapter = adapter;
> 
> +	rc = starfive_jh7110_inst_init(fdt);
> +	if (rc)
> +		return rc;
> +
>  	sbi_system_reset_add_device(&pm_reset);
> 
>  	return 0;
> @@ -279,7 +285,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
> 
>  	if (cold_boot) {
>  		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
> -		return starfive_jh7110_inst_init(fdt);
>  	}
> 
>  	return 0;
> --
> 2.39.2

Test with this series patch? function is work fine.
 This patch need Anup review. 

From minda.chen at starfivetech.com  Sun Feb  4 18:07:46 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Mon, 5 Feb 2024 02:07:46 +0000
Subject: =?gb2312?B?u9i4tDogW1BBVENIIHYzIDIvN10gcGxhdGZvcm06IHN0YXJmaXZlOiBnZXQg?=
 =?gb2312?Q?I2C_offset_address_from_clocks_property?=
In-Reply-To: <e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
 <e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB0863ACB0B544190AF3E7819EE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> -----????-----
> ???: Nam Cao <namcao at linutronix.de>
> ????: 2024?2?2? 21:43
> ???: opensbi at lists.infradead.org; Cheehong Ang
> <cheehong.ang at starfivetech.com>; Wei Liang Lim
> <weiliang.lim at starfivetech.com>; Minda Chen <minda.chen at starfivetech.com>
> ??: Nam Cao <namcao at linutronix.de>
> ??: [PATCH v3 2/7] platform: starfive: get I2C offset address from clocks
> property
> 
> The current code gets the I2C offset address using the device tree node
> name: it get the I2C device index from the 4th character in the node name (for
> example, "i2c5" -> i2c device 5). However, the device tree node's name in
> U-Boot is actually just "i2c" without the number, so the current code cannot be
> used with the device tree from U-Boot.
> 
> Get the I2C offset address from the "clocks" property instead.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 4b22175..846b068 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -29,7 +29,7 @@ struct pmic {
>  struct jh7110 {
>  	u64 pmu_reg_base;
>  	u64 clk_reg_base;
> -	u32 i2c_index;
> +	u32 i2c_clk_offset;
>  };
> 
>  static struct pmic pmic_inst;
> @@ -163,10 +163,7 @@ static void pmic_i2c_clk_enable(void)
>  	unsigned long clock_base;
>  	unsigned int val;
> 
> -	clock_base = jh7110_inst.clk_reg_base +
> -		I2C_APB_CLK_OFFSET +
> -		(jh7110_inst.i2c_index << 2);
> -
> +	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
>  	val = readl((void *)clock_base);
> 
>  	if (!val)
> @@ -241,7 +238,8 @@ static struct fdt_reset fdt_reset_pmic = {  static int
> starfive_jh7110_inst_init(void *fdt)  {
>  	int noff, rc = 0;
> -	const char *name;
> +	const fdt32_t *val;
> +	int len;
>  	u64 addr;
> 
>  	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu"); @@
> -261,9 +259,12 @@ static int starfive_jh7110_inst_init(void *fdt)
>  	}
> 
>  	if (pmic_inst.adapter) {
> -		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
> -		if (!sbi_strncmp(name, "i2c", 3))
> -			jh7110_inst.i2c_index = name[3] - '0';
> +		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
> +		/* The clocks property looks like this: clocks = <&syscrg
> JH7110_SYSCLK_I2C5_APB>;
> +		 * So check that the length is 8 bytes, and get the offset from the
> second value
> +		 */
> +		if (val && len == 8)
> +			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
>  		else
>  			rc = SBI_EINVAL;
>  	}
> --
> 2.39.2

Please delete this macro 
-#define I2C_APB_CLK_OFFSET             0x228

Reviewed-by: Minda Chen <minda.chen at starfivetech.com>

From anup at brainfault.org  Sun Feb  4 20:54:11 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 10:24:11 +0530
Subject: [PATCH] lib: sbi: Use mask to check the free bit during trigger allocation
In-Reply-To: <20240102164624.85482-1-hchauhan@ventanamicro.com>
References: <20240102164624.85482-1-hchauhan@ventanamicro.com>
Message-ID: <CAAhSdy2Vidj5KoKT1LjxZyAbjX-+7zad1bnN9TQLE=h5dRpqnQ@mail.gmail.com>

On Wed, Jan 17, 2024 at 10:33?AM Himanshu Chauhan
<hchauhan at ventanamicro.com> wrote:
>
> The trigger allocation function uses bit shift instead of mask to check the
> mapped status of the triggers. This causes index 0 to be return always. As a
> result, the older triggers are overwritten.
>
> Use the mask for MAPPED field in state word to check if the trigger is mapped.
>
> Fixes: 97f234f15 ("lib: sbi: Introduce the SBI debug triggers extension support")
> Signed-off-by: Himanshu Chauhan <hchauhan at ventanamicro.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  lib/sbi/sbi_dbtr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
> index 019e702..7142fed 100644
> --- a/lib/sbi/sbi_dbtr.c
> +++ b/lib/sbi/sbi_dbtr.c
> @@ -129,7 +129,7 @@ static inline struct sbi_dbtr_trigger *sbi_alloc_trigger(void)
>
>         for (i = 0; i < hart_state->total_trigs; i++) {
>                 f_trig = INDEX_TO_TRIGGER(i);
> -               if (f_trig->state & RV_DBTR_BIT(TS, MAPPED))
> +               if (f_trig->state & RV_DBTR_BIT_MASK(TS, MAPPED))
>                         continue;
>                 hart_state->available_trigs--;
>                 break;
> --
> 2.42.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Sun Feb  4 21:03:22 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 10:33:22 +0530
Subject: [PATCH] fw_base.S: Fix comment errors
In-Reply-To: <20231217134836.895-1-fmrt19zrmin@163.com>
References: <20231217134836.895-1-fmrt19zrmin@163.com>
Message-ID: <CAAhSdy1a-Tbf-8L+19QDkCNsro=t+JrTFmUcp2PB-9JB_FCpbg@mail.gmail.com>

On Sun, Dec 17, 2023 at 7:18?PM <fmrt19zrmin at 163.com> wrote:
>
> From: Zhang Runmin <fmrt19zrmin at 163.com>
>
> When calling '_reset_regs', it'll reset all registers except some
> specific registers (ra, a0, a1, and a2).
>
> Both boot HART and non-boot HARTs will execute the '_start_warm'
> function. Therefore, when '_reset_regs' is called in '_start_warm', it
> will reset all registers except some specific registers (ra, a0, a1 and
> a2) for both boot HART and non-boot HARTs.
>
> Signed-off-by: Zhang Runmin <fmrt19zrmin at 163.com>
> ---
>  firmware/fw_base.S | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index f7763f4..ab432ea 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -188,7 +188,7 @@ _relocate_done:
>
>         /* At this point we are running from link address */
>
> -       /* Reset all registers for boot HART */
> +       /* Reset all registers except ra, a0, a1 and a2 for boot HART */
>         li      ra, 0
>         call    _reset_regs
>
> @@ -415,7 +415,10 @@ _wait_for_boot_hart:
>         bne     t0, t1, _wait_for_boot_hart
>
>  _start_warm:
> -       /* Reset all registers for non-boot HARTs */
> +       /*
> +     * Reset all registers except ra, a0, a1 and a2 for both boot HART
> +     * and non-boot HARTs
> +     */
'
After cold-boot is done, all harts are non-boot harts so this statement
can be simplified.

>         li      ra, 0
>         call    _reset_regs
>
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

I have taken care of the above at the time of merging this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


From anup at brainfault.org  Sun Feb  4 23:43:07 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 13:13:07 +0530
Subject: [PATCH] Makefile: Remove unused code and data
In-Reply-To: <20231219033217.181779-1-wxjstz@126.com>
References: <20231219033217.181779-1-wxjstz@126.com>
Message-ID: <CAAhSdy3bHdex+uQgvU83Etis2Y-9kpE3Lz0bNkzK23OORsy0oA@mail.gmail.com>

On Tue, Dec 19, 2023 at 9:02?AM Xiang W <wxjstz at 126.com> wrote:
>
> Add compiler options to create separate sections for functions and
> static variables. And add options to the linker to remove unused
> sections.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

This patch breaks OpenSBI with LLVM.

Regards,
Anup

> ---
>  Makefile | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/Makefile b/Makefile
> index de4e73a..fbb64f2 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -331,7 +331,7 @@ GENFLAGS    +=      $(libsbiutils-genflags-y)
>  GENFLAGS       +=      $(platform-genflags-y)
>  GENFLAGS       +=      $(firmware-genflags-y)
>
> -CFLAGS         =       -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing
> +CFLAGS         =       -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing -ffunction-sections -fdata-sections
>  ifneq ($(DEBUG),)
>  CFLAGS         +=      -O0
>  else
> @@ -377,6 +377,7 @@ ARFLAGS             =       rcs
>  ELFFLAGS       +=      $(USE_LD_FLAG)
>  ELFFLAGS       +=      -Wl,--exclude-libs,ALL
>  ELFFLAGS       +=      -Wl,--build-id=none
> +ELFFLAGS       +=      -Wl,--gc-sections
>  ELFFLAGS       +=      $(platform-ldflags-y)
>  ELFFLAGS       +=      $(firmware-ldflags-y)
>
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From namcao at linutronix.de  Mon Feb  5 00:31:22 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon, 5 Feb 2024 09:31:22 +0100
Subject: [PATCH v3 4/7] platform: starfive: rename
 "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <SHXPR01MB0863C62431DF20ABB8779D54E640A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
References: <cover.1706880734.git.namcao@linutronix.de>
	<e885fedc2fb483d5349eda4170890ed7dbabe510.1706880734.git.namcao@linutronix.de>
	<SHXPR01MB0863C62431DF20ABB8779D54E640A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
Message-ID: <20240205093122.36c34f4a@namcao>

On 04/Feb/2024 Minda Chen wrote:
> > 
> > OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
> > for the regulator node. However, the string used by U-Boot (and Linux) is
> > actually "x-powers,axp15060". As OpenSBI gets the device tree from U-Boot,
> > this causes the regulator device to be undetected, and OpenSBI does not use
> > this device to perform board reset/shutdown.
> > 
> > Rename this device tree compatible string to match U-Boot (and Linux).
> > 
> > Signed-off-by: Nam Cao <namcao at linutronix.de>
> > ---
> >  platform/generic/starfive/jh7110.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/platform/generic/starfive/jh7110.c
> > b/platform/generic/starfive/jh7110.c
> > index d3647c2..385e09c 100644
> > --- a/platform/generic/starfive/jh7110.c
> > +++ b/platform/generic/starfive/jh7110.c
> > @@ -224,7 +224,7 @@ static int pm_reset_init(void *fdt, int nodeoff,  }
> > 
> >  static const struct fdt_match pm_reset_match[] = {
> > -	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
> > +	{ .compatible = "x-powers,axp15060", .data = (void *)true },
> >  	{ },
> >  };
> >   
> It is OK.
> But upstream u-boot jh7110 dts file do not contain this compatible?
> Can you also upstream this in u-boot? or I will do this myself

It is in upstream U-Boot, just a few days ago:
https://source.denx.de/u-boot/u-boot/-/commit/6882255ac3107c58e1153311df8a8270087f8cb3

Best regards,
Nam



From namcao at linutronix.de  Mon Feb  5 00:32:54 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon, 5 Feb 2024 09:32:54 +0100
Subject: =?UTF-8?B?5Zue5aSNOg==?= [PATCH v3 2/7] platform: starfive: get
 I2C offset address from clocks property
In-Reply-To: <SHXPR01MB0863ACB0B544190AF3E7819EE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
References: <cover.1706880734.git.namcao@linutronix.de>
	<e50c9ecfc7bb63ee0e3cd69d72bc2050d4c39d0c.1706880734.git.namcao@linutronix.de>
	<SHXPR01MB0863ACB0B544190AF3E7819EE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
Message-ID: <20240205093254.51b91791@namcao>

On 05/Feb/2024 Minda Chen wrote:
> > -----????-----
> > ???: Nam Cao <namcao at linutronix.de>
> > ????: 2024?2?2? 21:43
> > ???: opensbi at lists.infradead.org; Cheehong Ang
> > <cheehong.ang at starfivetech.com>; Wei Liang Lim
> > <weiliang.lim at starfivetech.com>; Minda Chen <minda.chen at starfivetech.com>
> > ??: Nam Cao <namcao at linutronix.de>
> > ??: [PATCH v3 2/7] platform: starfive: get I2C offset address from clocks
> > property
> > 
> > The current code gets the I2C offset address using the device tree node
> > name: it get the I2C device index from the 4th character in the node name (for
> > example, "i2c5" -> i2c device 5). However, the device tree node's name in
> > U-Boot is actually just "i2c" without the number, so the current code cannot be
> > used with the device tree from U-Boot.
> > 
> > Get the I2C offset address from the "clocks" property instead.
> > 
> > Signed-off-by: Nam Cao <namcao at linutronix.de>
> > ---
> >  platform/generic/starfive/jh7110.c | 19 ++++++++++---------
> >  1 file changed, 10 insertions(+), 9 deletions(-)
> > 
> > diff --git a/platform/generic/starfive/jh7110.c
> > b/platform/generic/starfive/jh7110.c
> > index 4b22175..846b068 100644
> > --- a/platform/generic/starfive/jh7110.c
> > +++ b/platform/generic/starfive/jh7110.c
> > @@ -29,7 +29,7 @@ struct pmic {
> >  struct jh7110 {
> >  	u64 pmu_reg_base;
> >  	u64 clk_reg_base;
> > -	u32 i2c_index;
> > +	u32 i2c_clk_offset;
> >  };
> > 
> >  static struct pmic pmic_inst;
> > @@ -163,10 +163,7 @@ static void pmic_i2c_clk_enable(void)
> >  	unsigned long clock_base;
> >  	unsigned int val;
> > 
> > -	clock_base = jh7110_inst.clk_reg_base +
> > -		I2C_APB_CLK_OFFSET +
> > -		(jh7110_inst.i2c_index << 2);
> > -
> > +	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
> >  	val = readl((void *)clock_base);
> > 
> >  	if (!val)
> > @@ -241,7 +238,8 @@ static struct fdt_reset fdt_reset_pmic = {  static int
> > starfive_jh7110_inst_init(void *fdt)  {
> >  	int noff, rc = 0;
> > -	const char *name;
> > +	const fdt32_t *val;
> > +	int len;
> >  	u64 addr;
> > 
> >  	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu"); @@
> > -261,9 +259,12 @@ static int starfive_jh7110_inst_init(void *fdt)
> >  	}
> > 
> >  	if (pmic_inst.adapter) {
> > -		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
> > -		if (!sbi_strncmp(name, "i2c", 3))
> > -			jh7110_inst.i2c_index = name[3] - '0';
> > +		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
> > +		/* The clocks property looks like this: clocks = <&syscrg  
> > JH7110_SYSCLK_I2C5_APB>;  
> > +		 * So check that the length is 8 bytes, and get the offset from the
> > second value
> > +		 */
> > +		if (val && len == 8)
> > +			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
> >  		else
> >  			rc = SBI_EINVAL;
> >  	}
> > --
> > 2.39.2  
> 
> Please delete this macro 
> -#define I2C_APB_CLK_OFFSET             0x228

Ahh, someone already made this comment in my first revision. But I think I
messed it up when I resent. Will remove this in the next version.

> Reviewed-by: Minda Chen <minda.chen at starfivetech.com>

Thanks for the review.

Best regards,
Nam


From namcao at linutronix.de  Mon Feb  5 00:48:55 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:48:55 +0100
Subject: [PATCH v4 0/7] starfive reboot cleanup & fix 
Message-ID: <cover.1707122766.git.namcao@linutronix.de>

This series:
 - Rename device tree compatible strings to match U-Boot
 - Fix code that extract I2C address from device tree
 - Cleanup

The device tree nodes in this series have just been merged to U-Boot a few
days ago. So please use most recent upstream U-Boot for testing this
series.

Nam Cao (7):
  platform: starfive: correct system clock device tree node
  platform: starfive: get I2C offset address from clocks property
  platform: starfive: remove redundant compatibility check in pmic_ops
  platform: starfive: rename "stf,axp15060-regulator" ->
    "x-powers,axp15060"
  platform: starfive: drop "compatible" from struct pmic
  platform: starfive: return error if needed devices are not present
  platform: starfive: call starfive_jh7110_inst_init() in
    pm_reset_init()

 platform/generic/starfive/jh7110.c | 71 ++++++++++++++++--------------
 1 file changed, 38 insertions(+), 33 deletions(-)

-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:48:56 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:48:56 +0100
Subject: [PATCH v4 1/7] platform: starfive: correct system clock device tree node
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <063d675dcf59e79892091b0ef085a6a2ca4f6bee.1707122766.git.namcao@linutronix.de>

Starfive names the system clock device tree node "starfive,jh7110-clkgen"
in all their git repositories. However, a different name is used in
upstream U-Boot (and also Linux): "starfive,jh7110-syscrg". Since
OpenSBI gets the device tree from U-Boot, this inconsistency leads the
problem that OpenSBI doesn't know the system clock device exists.

Correct this name to keep the consistency.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index dcd6306..4b22175 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -252,7 +252,7 @@ static int starfive_jh7110_inst_init(void *fdt)
 		jh7110_inst.pmu_reg_base = addr;
 	}
 
-	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen");
+	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
 	if (-1 < noff) {
 		rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
 		if (rc)
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:48:57 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:48:57 +0100
Subject: [PATCH v4 2/7] platform: starfive: get I2C offset address from clocks property
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <3784b87136c66eb78a980d258fad4dd4a8ba483f.1707122766.git.namcao@linutronix.de>

The current code gets the I2C offset address using the device tree node
name: it get the I2C device index from the 4th character in the node
name (for example, "i2c5" -> i2c device 5). However, the device tree
node's name in U-Boot is actually just "i2c" without the number, so the
current code cannot be used with the device tree from U-Boot.

Get the I2C offset address from the "clocks" property instead.

Reviewed-by: Minda Chen <minda.chen at starfivetech.com>
Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 4b22175..308fe39 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -29,7 +29,7 @@ struct pmic {
 struct jh7110 {
 	u64 pmu_reg_base;
 	u64 clk_reg_base;
-	u32 i2c_index;
+	u32 i2c_clk_offset;
 };
 
 static struct pmic pmic_inst;
@@ -67,7 +67,6 @@ static u32 selected_hartid = -1;
 #define AXP15060_POWER_OFF_BIT		BIT(7)
 #define AXP15060_RESET_BIT		BIT(6)
 
-#define I2C_APB_CLK_OFFSET		0x228
 #define I2C_APB_CLK_ENABLE_BIT		BIT(31)
 
 static int pm_system_reset_check(u32 type, u32 reason)
@@ -163,10 +162,7 @@ static void pmic_i2c_clk_enable(void)
 	unsigned long clock_base;
 	unsigned int val;
 
-	clock_base = jh7110_inst.clk_reg_base +
-		I2C_APB_CLK_OFFSET +
-		(jh7110_inst.i2c_index << 2);
-
+	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
 	val = readl((void *)clock_base);
 
 	if (!val)
@@ -241,7 +237,8 @@ static struct fdt_reset fdt_reset_pmic = {
 static int starfive_jh7110_inst_init(void *fdt)
 {
 	int noff, rc = 0;
-	const char *name;
+	const fdt32_t *val;
+	int len;
 	u64 addr;
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu");
@@ -261,9 +258,12 @@ static int starfive_jh7110_inst_init(void *fdt)
 	}
 
 	if (pmic_inst.adapter) {
-		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
-		if (!sbi_strncmp(name, "i2c", 3))
-			jh7110_inst.i2c_index = name[3] - '0';
+		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
+		/* The clocks property looks like this: clocks = <&syscrg JH7110_SYSCLK_I2C5_APB>;
+		 * So check that the length is 8 bytes, and get the offset from the second value
+		 */
+		if (val && len == 8)
+			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
 		else
 			rc = SBI_EINVAL;
 	}
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:48:59 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:48:59 +0100
Subject: [PATCH v4 4/7] platform: starfive: rename "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <e09ff63f70ea43b2e4d3a92815a5490e0c80d0ce.1707122766.git.namcao@linutronix.de>

OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
for the regulator node. However, the string used by U-Boot (and Linux)
is actually "x-powers,axp15060". As OpenSBI gets the device tree from
U-Boot, this causes the regulator device to be undetected, and OpenSBI
does not use this device to perform board reset/shutdown.

Rename this device tree compatible string to match U-Boot (and Linux).

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 1956fd8..1f7cfe2 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -223,7 +223,7 @@ static int pm_reset_init(void *fdt, int nodeoff,
 }
 
 static const struct fdt_match pm_reset_match[] = {
-	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
+	{ .compatible = "x-powers,axp15060", .data = (void *)true },
 	{ },
 };
 
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:48:58 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:48:58 +0100
Subject: [PATCH v4 3/7] platform: starfive: remove redundant compatibility check in pmic_ops
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <d250d91aa812e9da463d1025d668cd5dbd94f031.1707122766.git.namcao@linutronix.de>

pmic_ops() is only called if a compatible device is found in device
tree. It is redundant for this function to check the compability again.
Remove this check.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 36 ++++++++++++++----------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 308fe39..1956fd8 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -133,28 +133,26 @@ static void pmic_ops(struct pmic *pmic, int type)
 	if (ret)
 		return;
 
-	if (!sbi_strcmp("stf,axp15060-regulator", pmic->compatible)) {
-		ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
-					   AXP15060_POWER_REG, &val);
-
-		if (ret) {
-			sbi_printf("%s: cannot read pmic power register\n",
-				   __func__);
-			return;
-		}
+	ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, &val);
+
+	if (ret) {
+		sbi_printf("%s: cannot read pmic power register\n",
+				__func__);
+		return;
+	}
 
+	val |= AXP15060_POWER_OFF_BIT;
+	if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
 		val |= AXP15060_POWER_OFF_BIT;
-		if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
-			val |= AXP15060_POWER_OFF_BIT;
-		else
-			val |= AXP15060_RESET_BIT;
+	else
+		val |= AXP15060_RESET_BIT;
 
-		ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
-					    AXP15060_POWER_REG, val);
-		if (ret)
-			sbi_printf("%s: cannot write pmic power register\n",
-				   __func__);
-	}
+	ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, val);
+	if (ret)
+		sbi_printf("%s: cannot write pmic power register\n",
+				__func__);
 }
 
 static void pmic_i2c_clk_enable(void)
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:49:01 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:49:01 +0100
Subject: [PATCH v4 6/7] platform: starfive: return error if needed devices are not present
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <6cf247a45ca69412337ee7ff163c530263d5d8ed.1707122766.git.namcao@linutronix.de>

Jh7110's reset driver needs power management device and clock controller
device to work. Currently, the driver proceed anyway without these
devices, and invalid addresses (jh7110_inst.pmu_reg_base and
jh7110_inst.clk_reg_base) are used during reboot, which causes
unpredictable broken behaviors.

If these devices are not present, return -SBI_ENODEV.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index b0b1e35..6990425 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -243,6 +243,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.pmu_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
@@ -251,6 +253,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.clk_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	if (pmic_inst.adapter) {
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:49:02 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:49:02 +0100
Subject: [PATCH v4 7/7] platform: starfive: call starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <f868f77b9e776c53086e9d01352c60b04fe7102f.1707122766.git.namcao@linutronix.de>

The function starfive_jh7110_inst_init() initialize some power
management unit address and clock addresses, needed for the reset
driver. It doesn't do anything else, and also the reset driver doesn't
work without calling this function. Thus, it does not make much sense
that this function is independent from pm_reset_init().

Delete the separate call to starfive_jh7110_inst_init(), and instead
just call this function inside pm_reset_init().

Doing this also fixes another problem: if starfive_jh7110_inst_init()
returns an error code, it gets propagated to final_init() and OpenSBI
hangs. This hang is not necessary, because failures within
starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
shutdown, but the system can still function normally.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 6990425..c25e645 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -190,6 +190,8 @@ static struct sbi_system_reset_device pm_reset = {
 	.system_reset = pm_system_reset
 };
 
+static int starfive_jh7110_inst_init(void *fdt);
+
 static int pm_reset_init(void *fdt, int nodeoff,
 			 const struct fdt_match *match)
 {
@@ -215,6 +217,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
 
 	pmic_inst.adapter = adapter;
 
+	rc = starfive_jh7110_inst_init(fdt);
+	if (rc)
+		return rc;
+
 	sbi_system_reset_add_device(&pm_reset);
 
 	return 0;
@@ -278,7 +284,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
 
 	if (cold_boot) {
 		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
-		return starfive_jh7110_inst_init(fdt);
 	}
 
 	return 0;
-- 
2.39.2



From namcao at linutronix.de  Mon Feb  5 00:49:00 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon,  5 Feb 2024 09:49:00 +0100
Subject: [PATCH v4 5/7] platform: starfive: drop "compatible" from struct pmic
In-Reply-To: <cover.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
Message-ID: <23b797311f400cd737a7261a4f84fe30291695d0.1707122766.git.namcao@linutronix.de>

The member "compatible" of struct pmic is not used. Delete it.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 platform/generic/starfive/jh7110.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 1f7cfe2..b0b1e35 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -23,7 +23,6 @@
 struct pmic {
 	struct i2c_adapter *adapter;
 	u32 dev_addr;
-	const char *compatible;
 };
 
 struct jh7110 {
@@ -204,7 +203,6 @@ static int pm_reset_init(void *fdt, int nodeoff,
 		return rc;
 
 	pmic_inst.dev_addr = addr;
-	pmic_inst.compatible = match->compatible;
 
 	i2c_bus = fdt_parent_offset(fdt, nodeoff);
 	if (i2c_bus < 0)
-- 
2.39.2



From minda.chen at starfivetech.com  Mon Feb  5 00:50:06 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Mon, 5 Feb 2024 08:50:06 +0000
Subject: =?gb2312?B?u9i4tDogW1BBVENIIHYzIDUvN10gcGxhdGZvcm06IHN0YXJmaXZlOiBkcm9w?=
 =?gb2312?Q?_"compatible"_from_struct_pmic?=
In-Reply-To: <ab05513e09ddbef539fedd7e9da7a1cecf526971.1706880734.git.namcao@linutronix.de>
References: <cover.1706880734.git.namcao@linutronix.de>
 <ab05513e09ddbef539fedd7e9da7a1cecf526971.1706880734.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB08637BB7F20B80AC504FF34FE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>


> 
> The member "compatible" of struct pmic is not used. Delete it.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 385e09c..f64e016 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -23,7 +23,6 @@
>  struct pmic {
>  	struct i2c_adapter *adapter;
>  	u32 dev_addr;
> -	const char *compatible;
>  };
> 
>  struct jh7110 {
> @@ -205,7 +204,6 @@ static int pm_reset_init(void *fdt, int nodeoff,
>  		return rc;
> 
>  	pmic_inst.dev_addr = addr;
> -	pmic_inst.compatible = match->compatible;
> 
>  	i2c_bus = fdt_parent_offset(fdt, nodeoff);
>  	if (i2c_bus < 0)
> --
> 2.39.2
Maybe this patch can be squash to 3rd patch. It is my sugguestion.

From namcao at linutronix.de  Mon Feb  5 01:00:04 2024
From: namcao at linutronix.de (Nam Cao)
Date: Mon, 5 Feb 2024 10:00:04 +0100
Subject: =?UTF-8?B?5Zue5aSNOg==?= [PATCH v3 5/7] platform: starfive:
 drop "compatible" from struct pmic
In-Reply-To: <SHXPR01MB08637BB7F20B80AC504FF34FE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
References: <cover.1706880734.git.namcao@linutronix.de>
	<ab05513e09ddbef539fedd7e9da7a1cecf526971.1706880734.git.namcao@linutronix.de>
	<SHXPR01MB08637BB7F20B80AC504FF34FE647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
Message-ID: <20240205100004.737f5b64@namcao>

On 05/Feb/2024 Minda Chen wrote:
> > The member "compatible" of struct pmic is not used. Delete it.
> > 
> > Signed-off-by: Nam Cao <namcao at linutronix.de>
> > ---
> >  platform/generic/starfive/jh7110.c | 2 --
> >  1 file changed, 2 deletions(-)
> > 
> > diff --git a/platform/generic/starfive/jh7110.c
> > b/platform/generic/starfive/jh7110.c
> > index 385e09c..f64e016 100644
> > --- a/platform/generic/starfive/jh7110.c
> > +++ b/platform/generic/starfive/jh7110.c
> > @@ -23,7 +23,6 @@
> >  struct pmic {
> >  	struct i2c_adapter *adapter;
> >  	u32 dev_addr;
> > -	const char *compatible;
> >  };
> > 
> >  struct jh7110 {
> > @@ -205,7 +204,6 @@ static int pm_reset_init(void *fdt, int nodeoff,
> >  		return rc;
> > 
> >  	pmic_inst.dev_addr = addr;
> > -	pmic_inst.compatible = match->compatible;
> > 
> >  	i2c_bus = fdt_parent_offset(fdt, nodeoff);
> >  	if (i2c_bus < 0)
> > --
> > 2.39.2  
> Maybe this patch can be squash to 3rd patch. It is my sugguestion.

Makes sense. Unfortunately I just sent a v4 a few seconds before this. I
think it's not too important, so I don't really want to send a new series
just for this.

If okay with you, I will wait and see if there are any other comments. If
v5 is needed, I will squash them then.

Best regards,
Nam



From anup at brainfault.org  Mon Feb  5 02:40:01 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 16:10:01 +0530
Subject: [PATCH v2] Makefile: don't pass -mstrict-align if not supported
In-Reply-To: <20240118180231.30300-1-kalle.wachsmuth@gmail.com>
References: <20240118180231.30300-1-kalle.wachsmuth@gmail.com>
Message-ID: <CAAhSdy2w7dKvOESrVaDLFoL+x0acpCC-jjMpNjJ3CcY_cU7zLg@mail.gmail.com>

On Thu, Jan 18, 2024 at 11:32?PM Kalle Wachsmuth
<kalle.wachsmuth at gmail.com> wrote:
>
> Support for that option will be added in LLVM 18:
> https://github.com/llvm/llvm-project/commit/23ce5368409c760f3dd49d0f17f34772b0b869d8
>
> Clang 17.0.6, however, will error when passed the
> `-mstrict-align` flag.
> We should only use the flag if it is supported.
>
> Signed-off-by: Kalle Wachsmuth <kalle.wachsmuth at gmail.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
> (I'm using Homebrew Clang on macOS.)
>
>  Makefile | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index de4e73a..66048c3 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -170,6 +170,9 @@ OPENSBI_LD_PIE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) -fP
>  # Check whether the compiler supports -m(no-)save-restore
>  CC_SUPPORT_SAVE_RESTORE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mno-save-restore -x c /dev/null -o /dev/null 2>&1 | grep -e "-save-restore" >/dev/null && echo n || echo y)
>
> +# Check whether the compiler supports -m(no-)strict-align
> +CC_SUPPORT_STRICT_ALIGN := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mstrict-align -x c /dev/null -o /dev/null 2>&1 | grep -e "-mstrict-align\|-mno-unaligned-access" >/dev/null && echo n || echo y)
> +
>  # Check whether the assembler and the compiler support the Zicsr and Zifencei extensions
>  CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)imafd_zicsr_zifencei -x c /dev/null -o /dev/null 2>&1 | grep "zicsr\|zifencei" > /dev/null && echo n || echo y)
>
> @@ -337,11 +340,14 @@ CFLAGS            +=      -O0
>  else
>  CFLAGS         +=      -O2
>  endif
> -CFLAGS         +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls -mstrict-align
> -# enable -m(no-)save-restore option by CC_SUPPORT_SAVE_RESTORE
> +CFLAGS         +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
> +# Optionally supported flags
>  ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
>  CFLAGS         +=      -mno-save-restore
>  endif
> +ifeq ($(CC_SUPPORT_STRICT_ALIGN),y)
> +CFLAGS         +=      -mstrict-align
> +endif
>  CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
>  CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
>  CFLAGS         +=      $(RELAX_FLAG)
> @@ -355,11 +361,14 @@ CPPFLAGS  +=      $(platform-cppflags-y)
>  CPPFLAGS       +=      $(firmware-cppflags-y)
>
>  ASFLAGS                =       -g -Wall -nostdlib
> -ASFLAGS                +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls -mstrict-align
> -# enable -m(no-)save-restore option by CC_SUPPORT_SAVE_RESTORE
> +ASFLAGS                +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
> +# Optionally supported flags
>  ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
>  ASFLAGS                +=      -mno-save-restore
>  endif
> +ifeq ($(CC_SUPPORT_STRICT_ALIGN),y)
> +ASFLAGS                +=      -mstrict-align
> +endif
>  ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
>  ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
>  ASFLAGS                +=      $(RELAX_FLAG)
> --
> 2.39.3 (Apple Git-145)
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From ganboing at gmail.com  Mon Feb  5 02:49:57 2024
From: ganboing at gmail.com (Bo Gan)
Date: Mon,  5 Feb 2024 02:49:57 -0800
Subject: [PATCH v2 0/3] Allow platform to handle load/store faults
Message-ID: <1707130200-559404-1-git-send-email-ganboing@gmail.com>

Sometimes a platform wants to trap-n-emulate special devices or filter
access to physical devices. This patch makes sbi_trap_handler to call
platform_ops.emulate_load/store and ask platform to fixup the fault.

v2 changes:
-  Added const qualifier to *orig_trap on load/store fault handlers.
   That addressed Xiang W's comment.
-  Applied clang-format to changed lines.

Bo Gan (3):
  lib: sbi: rename sbi_misaligned_ldst.c to sbi_trap_ldst.c
  include: sbi: rename sbi_misaligned_ldst.h to sbi_trap_ldst.h
  lib: sbi: Allow platform to fixup load/store faults

 include/sbi/sbi_misaligned_ldst.h                  |  23 ---
 include/sbi/sbi_platform.h                         |  13 ++
 include/sbi/sbi_trap.h                             |   2 +-
 include/sbi/sbi_trap_ldst.h                        |  43 +++++
 lib/sbi/objects.mk                                 |   2 +-
 lib/sbi/sbi_trap.c                                 |  38 ++--
 lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} | 210 ++++++++++++++-------
 7 files changed, 218 insertions(+), 113 deletions(-)
 delete mode 100644 include/sbi/sbi_misaligned_ldst.h
 create mode 100644 include/sbi/sbi_trap_ldst.h
 rename lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} (61%)

-- 
2.7.4



From ganboing at gmail.com  Mon Feb  5 02:49:58 2024
From: ganboing at gmail.com (Bo Gan)
Date: Mon,  5 Feb 2024 02:49:58 -0800
Subject: [PATCH v2 1/3] lib: sbi: rename sbi_misaligned_ldst.c to sbi_trap_ldst.c
In-Reply-To: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
Message-ID: <1707130200-559404-2-git-send-email-ganboing@gmail.com>

Signed-off-by: Bo Gan <ganboing at gmail.com>
---
 lib/sbi/objects.mk                                 | 2 +-
 lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} (100%)

diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 0a50e95..204dd6b 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -70,7 +70,6 @@ libsbi-objs-y += sbi_illegal_insn.o
 libsbi-objs-y += sbi_init.o
 libsbi-objs-y += sbi_ipi.o
 libsbi-objs-y += sbi_irqchip.o
-libsbi-objs-y += sbi_misaligned_ldst.o
 libsbi-objs-y += sbi_platform.o
 libsbi-objs-y += sbi_pmu.o
 libsbi-objs-y += sbi_dbtr.o
@@ -80,6 +79,7 @@ libsbi-objs-y += sbi_system.o
 libsbi-objs-y += sbi_timer.o
 libsbi-objs-y += sbi_tlb.o
 libsbi-objs-y += sbi_trap.o
+libsbi-objs-y += sbi_trap_ldst.o
 libsbi-objs-y += sbi_unpriv.o
 libsbi-objs-y += sbi_expected_trap.o
 libsbi-objs-y += sbi_cppc.o
diff --git a/lib/sbi/sbi_misaligned_ldst.c b/lib/sbi/sbi_trap_ldst.c
similarity index 100%
rename from lib/sbi/sbi_misaligned_ldst.c
rename to lib/sbi/sbi_trap_ldst.c
-- 
2.7.4



From ganboing at gmail.com  Mon Feb  5 02:49:59 2024
From: ganboing at gmail.com (Bo Gan)
Date: Mon,  5 Feb 2024 02:49:59 -0800
Subject: [PATCH v2 2/3] include: sbi: rename sbi_misaligned_ldst.h to sbi_trap_ldst.h
In-Reply-To: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
Message-ID: <1707130200-559404-3-git-send-email-ganboing@gmail.com>

Signed-off-by: Bo Gan <ganboing at gmail.com>
---
 include/sbi/{sbi_misaligned_ldst.h => sbi_trap_ldst.h} | 0
 lib/sbi/sbi_trap.c                                     | 2 +-
 lib/sbi/sbi_trap_ldst.c                                | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename include/sbi/{sbi_misaligned_ldst.h => sbi_trap_ldst.h} (100%)

diff --git a/include/sbi/sbi_misaligned_ldst.h b/include/sbi/sbi_trap_ldst.h
similarity index 100%
rename from include/sbi/sbi_misaligned_ldst.h
rename to include/sbi/sbi_trap_ldst.h
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index dbf307c..145db4b 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -17,7 +17,7 @@
 #include <sbi/sbi_illegal_insn.h>
 #include <sbi/sbi_ipi.h>
 #include <sbi/sbi_irqchip.h>
-#include <sbi/sbi_misaligned_ldst.h>
+#include <sbi/sbi_trap_ldst.h>
 #include <sbi/sbi_pmu.h>
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_timer.h>
diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c
index aa512de..be9a394 100644
--- a/lib/sbi/sbi_trap_ldst.c
+++ b/lib/sbi/sbi_trap_ldst.c
@@ -11,7 +11,7 @@
 #include <sbi/riscv_encoding.h>
 #include <sbi/riscv_fp.h>
 #include <sbi/sbi_error.h>
-#include <sbi/sbi_misaligned_ldst.h>
+#include <sbi/sbi_trap_ldst.h>
 #include <sbi/sbi_pmu.h>
 #include <sbi/sbi_trap.h>
 #include <sbi/sbi_unpriv.h>
-- 
2.7.4



From ganboing at gmail.com  Mon Feb  5 02:50:00 2024
From: ganboing at gmail.com (Bo Gan)
Date: Mon,  5 Feb 2024 02:50:00 -0800
Subject: [PATCH v2 3/3] lib: sbi: Allow platform to fixup load/store faults
In-Reply-To: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com>
Message-ID: <1707130200-559404-4-git-send-email-ganboing@gmail.com>

This patch allows platforms to define load/store emulators to handle
load/store faults. Each platform can then use it to trap-and-emulate
special devices, or filter access to physical devices.

Two more functions are added to `sbi_platform_operations`.
emulate_load: called when trap.mcause == CAUSE_LOAD_ACCESS
emulate_store: called when trap.mcause == CAUSE_STORE_ACCESS
If not defined, sbi_trap_handler redirects the fault, same as before.

The code to decode load/store instruction is reused from
sbi_misaligned_load/store_handler, with additional lb/lbu/sb decoding.

Signed-off-by: Bo Gan <ganboing at gmail.com>
---
 include/sbi/sbi_platform.h  |  13 +++
 include/sbi/sbi_trap.h      |   2 +-
 include/sbi/sbi_trap_ldst.h |  28 +++++-
 lib/sbi/sbi_trap.c          |  36 +++++---
 lib/sbi/sbi_trap_ldst.c     | 208 +++++++++++++++++++++++++++++---------------
 5 files changed, 196 insertions(+), 91 deletions(-)

diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 2fb33e1..f8e4514 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -48,6 +48,7 @@
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_version.h>
+#include <sbi/sbi_trap_ldst.h>
 
 struct sbi_domain_memregion;
 struct sbi_ecall_return;
@@ -139,6 +140,18 @@ struct sbi_platform_operations {
 	int (*vendor_ext_provider)(long funcid,
 				   struct sbi_trap_regs *regs,
 				   struct sbi_ecall_return *out);
+
+	/**
+	 * platform specific handler to "fixup" load fault
+	 * If NULL, `sbi_trap_handler` will redirect the load fault
+	 */
+	sbi_trap_ld_emulator emulate_load;
+
+	/**
+	 * platform specific handler to "fixup" store fault
+	 * If NULL, `sbi_trap_handler` will redirect the store fault
+	 */
+	sbi_trap_st_emulator emulate_store;
 };
 
 /** Platform default per-HART stack size for exception/interrupt handling */
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index a562b95..2727bdb 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -225,7 +225,7 @@ static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
 }
 
 int sbi_trap_redirect(struct sbi_trap_regs *regs,
-		      struct sbi_trap_info *trap);
+		      const struct sbi_trap_info *trap);
 
 struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs);
 
diff --git a/include/sbi/sbi_trap_ldst.h b/include/sbi/sbi_trap_ldst.h
index ab27eb4..54df16e 100644
--- a/include/sbi/sbi_trap_ldst.h
+++ b/include/sbi/sbi_trap_ldst.h
@@ -13,11 +13,31 @@
 #include <sbi/sbi_types.h>
 
 struct sbi_trap_regs;
+struct sbi_trap_info;
 
-int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
-				struct sbi_trap_regs *regs);
+union reg_data {
+	u64 data_u64;
+	u32 data_u32;
+	u8 data_bytes[8];
+	ulong data_ulong;
+};
 
-int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
-				 struct sbi_trap_regs *regs);
+typedef int (*sbi_trap_ld_emulator)(ulong addr, int len, union reg_data *out_val,
+		struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap);
+
+typedef int (*sbi_trap_st_emulator)(ulong addr, int len, union reg_data in_val,
+		struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap);
+
+int sbi_misaligned_load_handler(struct sbi_trap_regs *regs,
+				const struct sbi_trap_info *orig_trap);
+
+int sbi_misaligned_store_handler(struct sbi_trap_regs *regs,
+				const struct sbi_trap_info *orig_trap);
+
+int sbi_load_fault_handler(struct sbi_trap_regs *regs,
+			const struct sbi_trap_info *orig_trap);
+
+int sbi_store_fault_handler(struct sbi_trap_regs *regs,
+			const struct sbi_trap_info *orig_trap);
 
 #endif
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index 145db4b..eb4cc0f 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -84,7 +84,7 @@ static void __noreturn sbi_trap_error(const char *msg, int rc,
  * @return 0 on success and negative error code on failure
  */
 int sbi_trap_redirect(struct sbi_trap_regs *regs,
-		      struct sbi_trap_info *trap)
+		      const struct sbi_trap_info *trap)
 {
 	ulong hstatus, vsstatus, prev_mode;
 #if __riscv_xlen == 32
@@ -285,6 +285,13 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
 		}
 		return regs;
 	}
+	/* Original trap_info */
+	trap.epc   = regs->mepc;
+	trap.cause = mcause;
+	trap.tval  = mtval;
+	trap.tval2 = mtval2;
+	trap.tinst = mtinst;
+	trap.gva   = sbi_regs_gva(regs);
 
 	switch (mcause) {
 	case CAUSE_ILLEGAL_INSTRUCTION:
@@ -292,11 +299,13 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
 		msg = "illegal instruction handler failed";
 		break;
 	case CAUSE_MISALIGNED_LOAD:
-		rc = sbi_misaligned_load_handler(mtval, mtval2, mtinst, regs);
+		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD);
+		rc  = sbi_misaligned_load_handler(regs, &trap);
 		msg = "misaligned load handler failed";
 		break;
 	case CAUSE_MISALIGNED_STORE:
-		rc  = sbi_misaligned_store_handler(mtval, mtval2, mtinst, regs);
+		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE);
+		rc  = sbi_misaligned_store_handler(regs, &trap);
 		msg = "misaligned store handler failed";
 		break;
 	case CAUSE_SUPERVISOR_ECALL:
@@ -305,20 +314,19 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
 		msg = "ecall handler failed";
 		break;
 	case CAUSE_LOAD_ACCESS:
+		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD);
+		rc  = sbi_load_fault_handler(regs, &trap);
+		msg = "load fault handler failed";
+		break;
 	case CAUSE_STORE_ACCESS:
-		sbi_pmu_ctr_incr_fw(mcause == CAUSE_LOAD_ACCESS ?
-			SBI_PMU_FW_ACCESS_LOAD : SBI_PMU_FW_ACCESS_STORE);
-		/* fallthrough */
+		sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE);
+		rc  = sbi_store_fault_handler(regs, &trap);
+		msg = "store fault handler failed";
+		break;
 	default:
 		/* If the trap came from S or U mode, redirect it there */
-		trap.epc = regs->mepc;
-		trap.cause = mcause;
-		trap.tval = mtval;
-		trap.tval2 = mtval2;
-		trap.tinst = mtinst;
-		trap.gva   = sbi_regs_gva(regs);
-
-		rc = sbi_trap_redirect(regs, &trap);
+		msg = "trap redirect failed";
+		rc  = sbi_trap_redirect(regs, &trap);
 		break;
 	}
 
diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c
index be9a394..93d4ce9 100644
--- a/lib/sbi/sbi_trap_ldst.c
+++ b/lib/sbi/sbi_trap_ldst.c
@@ -15,42 +15,24 @@
 #include <sbi/sbi_pmu.h>
 #include <sbi/sbi_trap.h>
 #include <sbi/sbi_unpriv.h>
+#include <sbi/sbi_platform.h>
 
-union reg_data {
-	u8 data_bytes[8];
-	ulong data_ulong;
-	u64 data_u64;
-};
-
-static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,
-					ulong addr_offset)
-{
-	if (new_tinst == INSN_PSEUDO_VS_LOAD ||
-	    new_tinst == INSN_PSEUDO_VS_STORE)
-		return new_tinst;
-	else if (orig_tinst == 0)
-		return 0UL;
-	else
-		return orig_tinst | (addr_offset << SH_RS1);
-}
-
-int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
-				struct sbi_trap_regs *regs)
+static int sbi_trap_emulate_load(struct sbi_trap_regs *regs,
+				 const struct sbi_trap_info *orig_trap,
+				 sbi_trap_ld_emulator emu)
 {
 	ulong insn, insn_len;
-	union reg_data val;
+	union reg_data val = { 0 };
 	struct sbi_trap_info uptrap;
-	int i, fp = 0, shift = 0, len = 0;
+	int rc, fp = 0, shift = 0, len = 0;
 
-	sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD);
-
-	if (tinst & 0x1) {
+	if (orig_trap->tinst & 0x1) {
 		/*
 		 * Bit[0] == 1 implies trapped instruction value is
 		 * transformed instruction or custom instruction.
 		 */
-		insn = tinst | INSN_16BIT_MASK;
-		insn_len = (tinst & 0x2) ? INSN_LEN(insn) : 2;
+		insn	 = orig_trap->tinst | INSN_16BIT_MASK;
+		insn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;
 	} else {
 		/*
 		 * Bit[0] == 0 implies trapped instruction value is
@@ -64,7 +46,12 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
 		insn_len = INSN_LEN(insn);
 	}
 
-	if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
+	if ((insn & INSN_MASK_LB) == INSN_MATCH_LB) {
+		len   = 1;
+		shift = 8 * (sizeof(ulong) - len);
+	} else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) {
+		len = 1;
+	} else if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
 		len   = 4;
 		shift = 8 * (sizeof(ulong) - len);
 #if __riscv_xlen == 64
@@ -124,26 +111,12 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
 #endif
 #endif
 	} else {
-		uptrap.epc = regs->mepc;
-		uptrap.cause = CAUSE_MISALIGNED_LOAD;
-		uptrap.tval = addr;
-		uptrap.tval2 = tval2;
-		uptrap.tinst = tinst;
-		uptrap.gva   = sbi_regs_gva(regs);
-		return sbi_trap_redirect(regs, &uptrap);
+		return sbi_trap_redirect(regs, orig_trap);
 	}
 
-	val.data_u64 = 0;
-	for (i = 0; i < len; i++) {
-		val.data_bytes[i] = sbi_load_u8((void *)(addr + i),
-						&uptrap);
-		if (uptrap.cause) {
-			uptrap.epc = regs->mepc;
-			uptrap.tinst = sbi_misaligned_tinst_fixup(
-				tinst, uptrap.tinst, i);
-			return sbi_trap_redirect(regs, &uptrap);
-		}
-	}
+	rc = emu(orig_trap->tval, len, &val, regs, orig_trap);
+	if (rc)
+		return rc;
 
 	if (!fp)
 		SET_RD(insn, regs, ((long)(val.data_ulong << shift)) >> shift);
@@ -159,23 +132,22 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
 	return 0;
 }
 
-int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
-				 struct sbi_trap_regs *regs)
+static int sbi_trap_emulate_store(struct sbi_trap_regs *regs,
+				  const struct sbi_trap_info *orig_trap,
+				  sbi_trap_st_emulator emu)
 {
 	ulong insn, insn_len;
 	union reg_data val;
 	struct sbi_trap_info uptrap;
-	int i, len = 0;
+	int rc, len = 0;
 
-	sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE);
-
-	if (tinst & 0x1) {
+	if (orig_trap->tinst & 0x1) {
 		/*
 		 * Bit[0] == 1 implies trapped instruction value is
 		 * transformed instruction or custom instruction.
 		 */
-		insn = tinst | INSN_16BIT_MASK;
-		insn_len = (tinst & 0x2) ? INSN_LEN(insn) : 2;
+		insn	 = orig_trap->tinst | INSN_16BIT_MASK;
+		insn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;
 	} else {
 		/*
 		 * Bit[0] == 0 implies trapped instruction value is
@@ -191,7 +163,9 @@ int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
 
 	val.data_ulong = GET_RS2(insn, regs);
 
-	if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {
+	if ((insn & INSN_MASK_SB) == INSN_MATCH_SB) {
+		len = 1;
+	} else if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {
 		len = 4;
 #if __riscv_xlen == 64
 	} else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) {
@@ -238,27 +212,117 @@ int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
 #endif
 #endif
 	} else {
-		uptrap.epc = regs->mepc;
-		uptrap.cause = CAUSE_MISALIGNED_STORE;
-		uptrap.tval = addr;
-		uptrap.tval2 = tval2;
-		uptrap.tinst = tinst;
-		uptrap.gva   = sbi_regs_gva(regs);
-		return sbi_trap_redirect(regs, &uptrap);
+		return sbi_trap_redirect(regs, orig_trap);
 	}
 
-	for (i = 0; i < len; i++) {
-		sbi_store_u8((void *)(addr + i), val.data_bytes[i],
-			     &uptrap);
-		if (uptrap.cause) {
-			uptrap.epc = regs->mepc;
-			uptrap.tinst = sbi_misaligned_tinst_fixup(
-				tinst, uptrap.tinst, i);
-			return sbi_trap_redirect(regs, &uptrap);
-		}
-	}
+	rc = emu(orig_trap->tval, len, val, regs, orig_trap);
+	if (rc)
+		return rc;
 
 	regs->mepc += insn_len;
 
 	return 0;
 }
+
+static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,
+					ulong addr_offset)
+{
+	if (new_tinst == INSN_PSEUDO_VS_LOAD ||
+	    new_tinst == INSN_PSEUDO_VS_STORE)
+		return new_tinst;
+	else if (orig_tinst == 0)
+		return 0UL;
+	else
+		return orig_tinst | (addr_offset << SH_RS1);
+}
+
+static int sbi_misaligned_ld_emulator(ulong addr, int len,
+				      union reg_data *out_val,
+				      struct sbi_trap_regs *regs,
+				      const struct sbi_trap_info *orig_trap)
+{
+	struct sbi_trap_info uptrap;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		out_val->data_bytes[i] =
+			sbi_load_u8((void *)(addr + i), &uptrap);
+		if (uptrap.cause) {
+			uptrap.epc   = regs->mepc;
+			uptrap.tinst = sbi_misaligned_tinst_fixup(
+				orig_trap->tinst, uptrap.tinst, i);
+			return sbi_trap_redirect(regs, &uptrap);
+		}
+	}
+	return 0;
+}
+
+static int sbi_misaligned_st_emulator(ulong addr, int len,
+				      union reg_data in_val,
+				      struct sbi_trap_regs *regs,
+				      const struct sbi_trap_info *orig_trap)
+{
+	struct sbi_trap_info uptrap;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		sbi_store_u8((void *)(addr + i), in_val.data_bytes[i], &uptrap);
+		if (uptrap.cause) {
+			uptrap.epc   = regs->mepc;
+			uptrap.tinst = sbi_misaligned_tinst_fixup(
+				orig_trap->tinst, uptrap.tinst, i);
+			return sbi_trap_redirect(regs, &uptrap);
+		}
+	}
+	return 0;
+}
+
+int sbi_misaligned_load_handler(struct sbi_trap_regs *regs,
+				const struct sbi_trap_info *orig_trap)
+{
+	return sbi_trap_emulate_load(regs, orig_trap,
+				     sbi_misaligned_ld_emulator);
+}
+
+int sbi_misaligned_store_handler(struct sbi_trap_regs *regs,
+				 const struct sbi_trap_info *orig_trap)
+{
+	return sbi_trap_emulate_store(regs, orig_trap,
+				      sbi_misaligned_st_emulator);
+}
+
+int sbi_load_fault_handler(struct sbi_trap_regs *regs,
+			   const struct sbi_trap_info *orig_trap)
+{
+	const struct sbi_platform *plat;
+
+	/* If fault came from M mode, just fail */
+	if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) {
+		return SBI_EINVAL;
+	}
+
+	plat = sbi_platform_ptr(sbi_scratch_thishart_ptr());
+	if (sbi_platform_ops(plat)->emulate_load) {
+		return sbi_trap_emulate_load(
+			regs, orig_trap, sbi_platform_ops(plat)->emulate_load);
+	}
+	return sbi_trap_redirect(regs, orig_trap);
+}
+
+int sbi_store_fault_handler(struct sbi_trap_regs *regs,
+			    const struct sbi_trap_info *orig_trap)
+{
+	const struct sbi_platform *plat;
+
+	/* If fault came from M mode, just fail */
+	if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) {
+		return SBI_EINVAL;
+	}
+
+	plat = sbi_platform_ptr(sbi_scratch_thishart_ptr());
+	if (sbi_platform_ops(plat)->emulate_store) {
+		return sbi_trap_emulate_store(
+			regs, orig_trap, sbi_platform_ops(plat)->emulate_store);
+	}
+	return sbi_trap_redirect(regs, orig_trap);
+}
-- 
2.7.4



From anup at brainfault.org  Mon Feb  5 03:13:28 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 16:43:28 +0530
Subject: [PATCH 1/2] check for --exclude-libs
In-Reply-To: <20240126152145.60488-1-leon@georgemail.eu>
References: <20240126152145.60488-1-leon@georgemail.eu>
Message-ID: <CAAhSdy3BVHxyHAcGf-sznmmNGhyyWzdwFqgs0x6do14x64s+_Q@mail.gmail.com>

On Fri, Jan 26, 2024 at 8:52?PM Leon M. Busch-George <leon at georgemail.eu> wrote:
>
> While writing to the dynsym is futile, the --exclude-libs options is not recognized by all linkers (e.g. riscv64-elf-ld.bfd)

The patch subject needs "Makefile: " prefix. Also, there is no Signed-off-by
in the commit description.

I have taken care of the above at the time of merging this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  Makefile | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/Makefile b/Makefile
> index de4e73a..630e35f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -167,6 +167,9 @@ endif
>  # Check whether the linker supports creating PIEs
>  OPENSBI_LD_PIE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) -fPIE -nostdlib -Wl,-pie -x c /dev/null -o /dev/null >/dev/null 2>&1 && echo y || echo n)
>
> +# Check whether the linker supports --exclude-libs
> +OPENSBI_LD_EXCLUDE_LIBS := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) "-Wl,--exclude-libs,ALL" -x c /dev/null -o /dev/null >/dev/null 2>&1 && echo y || echo n)
> +
>  # Check whether the compiler supports -m(no-)save-restore
>  CC_SUPPORT_SAVE_RESTORE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mno-save-restore -x c /dev/null -o /dev/null 2>&1 | grep -e "-save-restore" >/dev/null && echo n || echo y)
>
> @@ -375,7 +378,9 @@ ASFLAGS             +=      $(firmware-asflags-y)
>  ARFLAGS                =       rcs
>
>  ELFFLAGS       +=      $(USE_LD_FLAG)
> +ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y)
>  ELFFLAGS       +=      -Wl,--exclude-libs,ALL
> +endif
>  ELFFLAGS       +=      -Wl,--build-id=none
>  ELFFLAGS       +=      $(platform-ldflags-y)
>  ELFFLAGS       +=      $(firmware-ldflags-y)
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 03:13:57 2024
From: anup at brainfault.org (Anup Patel)
Date: Mon, 5 Feb 2024 16:43:57 +0530
Subject: [PATCH 2/2] firmware: always create dynsym section
In-Reply-To: <20240126152145.60488-2-leon@georgemail.eu>
References: <20240126152145.60488-1-leon@georgemail.eu> <20240126152145.60488-2-leon@georgemail.eu>
Message-ID: <CAAhSdy20fT-MhFkHhSNykvKMm9o_2QMK1z5mjDeBdj5NAe6A8w@mail.gmail.com>

On Fri, Jan 26, 2024 at 8:52?PM Leon M. Busch-George <leon at georgemail.eu> wrote:
>
> With a bare-metal linkers (e.g. riscv64-elf-ld), there exists no dynsym section.
> The dynsym section is not used by OpenSBI but discarding it makes linkers with dynamic library support unhappy.

There is no Signed-off-by  in the commit description.

I have taken care of the above at the time of merging this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_base.ldS | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/firmware/fw_base.ldS b/firmware/fw_base.ldS
> index c15ccdb..fb47984 100644
> --- a/firmware/fw_base.ldS
> +++ b/firmware/fw_base.ldS
> @@ -38,6 +38,11 @@
>                 . = ALIGN(8);
>         }
>
> +       .dynsym :
> +       {
> +               *(.dynsym)
> +       }
> +
>         . = ALIGN(0x1000); /* Ensure next section is page aligned */
>
>         .rela.dyn : {
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:23:28 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 12:53:28 +0530
Subject: [PATCH v3 01/10] firmware: fw_base.S: Improve loading u32
In-Reply-To: <20240117104212.1055737-2-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-2-wxjstz@126.com>
Message-ID: <CAAhSdy1bz0n=-7BAZ11rsTbUqtNpQ0a6iL4BMtRxSBrLRXbm=w@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> lwu exists under the current rv64 and should also exist under the rv128
> in the future, so I modified the conditions of conditional compilation
> so that it can adapt to the future situation
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_base.S | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index f7763f4..2f30d00 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -358,7 +358,7 @@ _scratch_init:
>         /* t0 = source FDT start address */
>         add     t0, a1, zero
>         /* t2 = source FDT size in big-endian */
> -#if __riscv_xlen == 64
> +#if __riscv_xlen > 32
>         lwu     t2, 4(t0)
>  #else
>         lw      t2, 4(t0)
> @@ -424,7 +424,7 @@ _start_warm:
>
>         /* Find HART count and HART stack size */
>         lla     a4, platform
> -#if __riscv_xlen == 64
> +#if __riscv_xlen > 32
>         lwu     s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
>         lwu     s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
>  #else
> @@ -440,7 +440,7 @@ _start_warm:
>         beqz    s9, 3f
>         li      a4, 0
>  1:
> -#if __riscv_xlen == 64
> +#if __riscv_xlen > 32
>         lwu     a5, (s9)
>  #else
>         lw      a5, (s9)
> @@ -527,7 +527,7 @@ _hartid_to_scratch:
>          * t2 -> Temporary
>          */
>         lla     t2, platform
> -#if __riscv_xlen == 64
> +#if __riscv_xlen > 32
>         lwu     t0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(t2)
>         lwu     t2, SBI_PLATFORM_HART_COUNT_OFFSET(t2)
>  #else
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:24:07 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 12:54:07 +0530
Subject: [PATCH v3 02/10] firmware: fw_base.S: remove _runtime_offset
In-Reply-To: <20240117104212.1055737-3-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-3-wxjstz@126.com>
Message-ID: <CAAhSdy21XBuUGWRtekVupsN2q-9s0BAo9Upt2FpVydL0LMpvvw@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> _runtime_offset is a variable not used elsewhere, so remove it.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_base.S | 6 ------
>  1 file changed, 6 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 2f30d00..0e1b6fb 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -74,8 +74,6 @@ _try_lottery:
>         REG_L   t0, 0(t0)
>         /* t1 shall has the address of _fw_start */
>         sub     t2, t1, t0
> -       lla     t3, _runtime_offset
> -       REG_S   t2, (t3)
>         lla     t0, __rel_dyn_start
>         lla     t1, __rel_dyn_end
>         beq     t0, t1, _relocate_done
> @@ -500,10 +498,6 @@ _skip_trap_exit_rv32_hyp:
>
>         .data
>         .align 3
> -#ifdef FW_PIC
> -_runtime_offset:
> -       RISCV_PTR       0
> -#endif
>  _relocate_lottery:
>         RISCV_PTR       0
>  _boot_status:
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:25:32 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 12:55:32 +0530
Subject: [PATCH v3 03/10] firmware: fw_base.S: Simplify address get in _relocate
In-Reply-To: <20240117104212.1055737-4-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-4-wxjstz@126.com>
Message-ID: <CAAhSdy2fHfgjBhKwqA65W=ObdkUNDpySK_i94y6_FtGiB4Qs4Q@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> Simplify address get in _relocate. Remove _link_end.

The copy-based _relocate is not needed anymore; better to remove
it and make FW_PIC=y mandatory.

Regards,
Anup

>
> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
>  firmware/fw_base.S | 17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 0e1b6fb..3d88704 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -97,17 +97,14 @@ _wait_relocate_copy_done:
>         /* Relocate if load address != link address */
>  _relocate:
>         lla     t0, _link_start
> -       REG_L   t0, 0(t0)
> -       lla     t1, _link_end
> -       REG_L   t1, 0(t1)
> -       lla     t2, _load_start
> -       REG_L   t2, 0(t2)
> +       REG_L   t0, 0(t0)         /* link start */
> +       lla     t2, _fw_start     /* load start */
>         beq     t0, t2, _relocate_done
> -       sub     t3, t1, t0
> -       add     t3, t3, t2
> +       sub     t6, t2, t0        /* runtime offset */
> +       lla     t3, _fw_reloc_end /* load end */
>         lla     t4, _relocate_done
> -       sub     t4, t4, t2
> -       add     t4, t4, t0
> +       sub     t1, t3, t6        /* link end */
> +       sub     t4, t4, t6        /* link _relocate_done */
>         blt     t2, t0, _relocate_copy_to_upper
>  _relocate_copy_to_lower:
>         ble     t1, t2, _relocate_copy_to_lower_loop
> @@ -506,8 +503,6 @@ _load_start:
>         RISCV_PTR       _fw_start
>  _link_start:
>         RISCV_PTR       FW_TEXT_START
> -_link_end:
> -       RISCV_PTR       _fw_reloc_end
>
>         .section .entry, "ax", %progbits
>         .align 3
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:26:22 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 12:56:22 +0530
Subject: [PATCH v3 05/10] firmware: fw_base.S: Move _link_start to .rodata section
In-Reply-To: <20240117104212.1055737-6-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-6-wxjstz@126.com>
Message-ID: <CAAhSdy0we4EkeRMi6+2CH=Cuze=E1_9Hn1QyzWVi_4RnU41RcQ@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> _link_start is readonly, so move it to rodata section.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup

> ---
>  firmware/fw_base.S | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 18dd0c5..7c7157d 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -482,6 +482,9 @@ _relocate_lottery:
>         RISCV_PTR       0
>  _boot_status:
>         RISCV_PTR       0
> +
> +       .section .rodata
> +       .align 3
>  _link_start:
>         RISCV_PTR       FW_TEXT_START
>
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:41:45 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 13:11:45 +0530
Subject: [PATCH v3 06/10] firmware: fw_base: Simplified setup trap handler
In-Reply-To: <20240117104212.1055737-7-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-7-wxjstz@126.com>
Message-ID: <CAAhSdy0BSAjPKjcHipNXzjzxcFFr9Le48b-PdeGpDP4KpSUQiw@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> The same detection was done twice when setting mtvec and trap_exit.
> Merging can reduce code size.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup

> ---
>  firmware/fw_base.S | 16 ++++------------
>  1 file changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 7c7157d..d4a6d3a 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -452,22 +452,14 @@ _start_warm:
>         srli    a5, a5, ('H' - 'A')
>         andi    a5, a5, 0x1
>         beq     a5, zero, _skip_trap_handler_rv32_hyp
> -       lla     a4, _trap_handler_rv32_hyp
> -_skip_trap_handler_rv32_hyp:
> -#endif
> -       csrw    CSR_MTVEC, a4
> -
> -#if __riscv_xlen == 32
>         /* Override trap exit for H-extension */
> -       csrr    a5, CSR_MISA
> -       srli    a5, a5, ('H' - 'A')
> -       andi    a5, a5, 0x1
> -       beq     a5, zero, _skip_trap_exit_rv32_hyp
> -       lla     a4, _trap_exit_rv32_hyp
>         csrr    a5, CSR_MSCRATCH
> +       lla     a4, _trap_exit_rv32_hyp
>         REG_S   a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(a5)
> -_skip_trap_exit_rv32_hyp:
> +       lla     a4, _trap_handler_rv32_hyp
> +_skip_trap_handler_rv32_hyp:
>  #endif
> +       csrw    CSR_MTVEC, a4
>
>         /* Initialize SBI runtime */
>         csrr    a0, CSR_MSCRATCH
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:43:25 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 13:13:25 +0530
Subject: [PATCH v3 07/10] firmware: fw_dynamic.S: Remove _bad_dynamic_info
In-Reply-To: <20240117104212.1055737-8-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-8-wxjstz@126.com>
Message-ID: <CAAhSdy2rNUG2AyHaiyRCsROXSHQ_Zz+Q4mUzwEbMj+gLgf=FNw@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> _bad_dynamic_info is same as _start_hang, so remove it.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup

> ---
>  firmware/fw_dynamic.S | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/firmware/fw_dynamic.S b/firmware/fw_dynamic.S
> index 7ff1c6a..5ee2883 100644
> --- a/firmware/fw_dynamic.S
> +++ b/firmware/fw_dynamic.S
> @@ -11,12 +11,6 @@
>
>  #include "fw_base.S"
>
> -       .section .entry, "ax", %progbits
> -       .align 3
> -_bad_dynamic_info:
> -       wfi
> -       j       _bad_dynamic_info
> -
>         .section .entry, "ax", %progbits
>         .align 3
>         .global fw_boot_hart
> @@ -30,10 +24,10 @@ fw_boot_hart:
>         /* Sanity checks */
>         li      a1, FW_DYNAMIC_INFO_MAGIC_VALUE
>         REG_L   a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
> -       bne     a0, a1, _bad_dynamic_info
> +       bne     a0, a1, _start_hang
>         li      a1, FW_DYNAMIC_INFO_VERSION_MAX
>         REG_L   a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
> -       bgt     a0, a1, _bad_dynamic_info
> +       bgt     a0, a1, _start_hang
>
>         /* Read boot HART id */
>         li      a1, FW_DYNAMIC_INFO_VERSION_2
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Feb  5 23:58:22 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 13:28:22 +0530
Subject: [PATCH v3 08/10] firmware: fw_base.S: Remove _relocate_lottery
In-Reply-To: <20240117104212.1055737-9-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-9-wxjstz@126.com>
Message-ID: <CAAhSdy04NhTP3DX4rZDvSWt2MYvZSeXM1ZF+eH=K=eVBJ+hPZg@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> Remove _relocate_lottery and use _boot_status instead
>
> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
>  firmware/fw_base.S | 14 ++++----------
>  1 file changed, 4 insertions(+), 10 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index d4a6d3a..56bffe8 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -14,8 +14,8 @@
>  #include <sbi/sbi_scratch.h>
>  #include <sbi/sbi_trap.h>
>
> -#define BOOT_STATUS_RELOCATE_DONE      1
> -#define BOOT_STATUS_BOOT_HART_DONE     2

Add here:
#define BOOT_STATUS_LOTTERY_DONE      1

> +#define BOOT_STATUS_RELOCATE_DONE      2
> +#define BOOT_STATUS_BOOT_HART_DONE     3
>
>  .macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
>         add     \__d0, \__s0, zero
> @@ -64,9 +64,9 @@ _start:
>         bne     a0, a6, _wait_relocate_copy_done
>  _try_lottery:
>         /* Jump to relocation wait loop if we don't get relocation lottery */
> -       lla     a6, _relocate_lottery
> +       lla     a6, _boot_status
>         li      a7, 1

Change this to:
li    a7, BOOT_STATUS_LOTTERY_DONE

> -       amoadd.w a6, a7, (a6)
> +       amoswap.w a6, a7, (a6)
>         bnez    a6, _wait_relocate_copy_done
>
>  #ifdef FW_PIC
> @@ -100,8 +100,6 @@ _relocate:
>         blt     t2, t0, _relocate_copy_to_upper
>  _relocate_copy_to_lower:
>         ble     t1, t2, _relocate_copy_to_lower_loop
> -       lla     t3, _relocate_lottery
> -       BRANGE  t2, t1, t3, _start_hang
>         lla     t3, _boot_status
>         BRANGE  t2, t1, t3, _start_hang
>         lla     t3, _relocate
> @@ -118,8 +116,6 @@ _relocate_copy_to_lower_loop:
>         jr      t4
>  _relocate_copy_to_upper:
>         ble     t3, t0, _relocate_copy_to_upper_loop
> -       lla     t2, _relocate_lottery
> -       BRANGE  t0, t3, t2, _start_hang
>         lla     t2, _boot_status
>         BRANGE  t0, t3, t2, _start_hang
>         lla     t2, _relocate
> @@ -470,8 +466,6 @@ _skip_trap_handler_rv32_hyp:
>
>         .data
>         .align 3
> -_relocate_lottery:
> -       RISCV_PTR       0
>  _boot_status:
>         RISCV_PTR       0
>
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup


From anup at brainfault.org  Tue Feb  6 00:08:19 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 13:38:19 +0530
Subject: [PATCH v3 09/10] firmware: Use C if possible
In-Reply-To: <20240117104212.1055737-10-wxjstz@126.com>
References: <20240117104212.1055737-1-wxjstz@126.com> <20240117104212.1055737-10-wxjstz@126.com>
Message-ID: <CAAhSdy2rd+ANj_La_OS30_vOm7vMgp6z7Rxo66akpC=Cuhj1cQ@mail.gmail.com>

On Wed, Jan 17, 2024 at 4:12?PM Xiang W <wxjstz at 126.com> wrote:
>
> Use C as soon as possible after setting up the stack.

The generic library lib/sbi is also used external firmware so
the C code (fw_coldboot_init) is just dead code for such
external firmware.

I suggest dropping this patch.

Regards,
Anup

>
> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
>  firmware/fw_base.S     | 206 +----------------------------------------
>  include/sbi/sbi_init.h |   3 +
>  lib/sbi/sbi_init.c     | 111 +++++++++++++++++++++-
>  3 files changed, 115 insertions(+), 205 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 56bffe8..aec683b 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -183,192 +183,7 @@ _bss_zero:
>         li      s5, (SBI_SCRATCH_SIZE * 2)
>         add     sp, s4, s5
>
> -       /* Allow main firmware to save info */
> -       MOV_5R  s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
> -       call    fw_save_info
> -       MOV_5R  a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
> -
> -#ifdef FW_FDT_PATH
> -       /* Override previous arg1 */
> -       lla     a1, fw_fdt_bin
> -#endif
> -
> -       /*
> -        * Initialize platform
> -        * Note: The a0 to a4 registers passed to the
> -        * firmware are parameters to this function.
> -        */
> -       MOV_5R  s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
> -       call    fw_platform_init
> -       add     t0, a0, zero
> -       MOV_5R  a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
> -       add     a1, t0, zero
> -
> -       /* Preload HART details
> -        * s7 -> HART Count
> -        * s8 -> HART Stack Size
> -        * s9 -> Heap Size
> -        * s10 -> Heap Offset
> -        */
> -       lla     a4, platform
> -#if __riscv_xlen > 32
> -       lwu     s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
> -       lwu     s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
> -       lwu     s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
> -#else
> -       lw      s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
> -       lw      s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
> -       lw      s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
> -#endif
> -
> -       /* Setup scratch space for all the HARTs*/
> -       lla     tp, _fw_end
> -       mul     a5, s7, s8
> -       add     tp, tp, a5
> -       /* Setup heap base address */
> -       lla     s10, _fw_start
> -       sub     s10, tp, s10
> -       add     tp, tp, s9
> -       /* Keep a copy of tp */
> -       add     t3, tp, zero
> -       /* Counter */
> -       li      t2, 1
> -       /* hartid 0 is mandated by ISA */
> -       li      t1, 0
> -_scratch_init:
> -       /*
> -        * The following registers hold values that are computed before
> -        * entering this block, and should remain unchanged.
> -        *
> -        * t3 -> the firmware end address
> -        * s7 -> HART count
> -        * s8 -> HART stack size
> -        * s9 -> Heap Size
> -        * s10 -> Heap Offset
> -        */
> -       add     tp, t3, zero
> -       sub     tp, tp, s9
> -       mul     a5, s8, t1
> -       sub     tp, tp, a5
> -       li      a5, SBI_SCRATCH_SIZE
> -       sub     tp, tp, a5
> -
> -       /* Initialize scratch space */
> -       /* Store fw_start and fw_size in scratch space */
> -       lla     a4, _fw_start
> -       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     a5, _fw_rw_start
> -       sub     a5, a5, a4
> -       REG_S   a5, SBI_SCRATCH_FW_RW_OFFSET(tp)
> -
> -       /* Store fw_heap_offset and fw_heap_size in scratch space */
> -       REG_S   s10, SBI_SCRATCH_FW_HEAP_OFFSET(tp)
> -       REG_S   s9, SBI_SCRATCH_FW_HEAP_SIZE_OFFSET(tp)
> -
> -       /* Store next arg1 in scratch space */
> -       MOV_3R  s0, a0, s1, a1, s2, a2
> -       call    fw_next_arg1
> -       REG_S   a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
> -       MOV_3R  a0, s0, a1, s1, a2, s2
> -       /* Store next address in scratch space */
> -       MOV_3R  s0, a0, s1, a1, s2, a2
> -       call    fw_next_addr
> -       REG_S   a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
> -       MOV_3R  a0, s0, a1, s1, a2, s2
> -       /* Store next mode in scratch space */
> -       MOV_3R  s0, a0, s1, a1, s2, a2
> -       call    fw_next_mode
> -       REG_S   a0, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
> -       MOV_3R  a0, s0, a1, s1, a2, s2
> -       /* Store warm_boot address in scratch space */
> -       lla     a4, _start_warm
> -       REG_S   a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
> -       /* Store platform address in scratch space */
> -       lla     a4, platform
> -       REG_S   a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
> -       /* Store hartid-to-scratch function address in scratch space */
> -       lla     a4, _hartid_to_scratch
> -       REG_S   a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
> -       /* Store trap-exit function address in scratch space */
> -       lla     a4, _trap_exit
> -       REG_S   a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(tp)
> -       /* Clear tmp0 in scratch space */
> -       REG_S   zero, SBI_SCRATCH_TMP0_OFFSET(tp)
> -       /* Store firmware options in scratch space */
> -       MOV_3R  s0, a0, s1, a1, s2, a2
> -#ifdef FW_OPTIONS
> -       li      a0, FW_OPTIONS
> -#else
> -       call    fw_options
> -#endif
> -       REG_S   a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
> -       MOV_3R  a0, s0, a1, s1, a2, s2
> -       /* Move to next scratch space */
> -       add     t1, t1, t2
> -       blt     t1, s7, _scratch_init
> -
> -       /*
> -        * Relocate Flatened Device Tree (FDT)
> -        * source FDT address = previous arg1
> -        * destination FDT address = next arg1
> -        *
> -        * Note: We will preserve a0 and a1 passed by
> -        * previous booting stage.
> -        */
> -       beqz    a1, _fdt_reloc_done
> -       /* Mask values in a4 */
> -       li      a4, 0xff
> -       /* t1 = destination FDT start address */
> -       MOV_3R  s0, a0, s1, a1, s2, a2
> -       call    fw_next_arg1
> -       add     t1, a0, zero
> -       MOV_3R  a0, s0, a1, s1, a2, s2
> -       beqz    t1, _fdt_reloc_done
> -       beq     t1, a1, _fdt_reloc_done
> -       /* t0 = source FDT start address */
> -       add     t0, a1, zero
> -       /* t2 = source FDT size in big-endian */
> -#if __riscv_xlen > 32
> -       lwu     t2, 4(t0)
> -#else
> -       lw      t2, 4(t0)
> -#endif
> -       /* t3 = bit[15:8] of FDT size */
> -       add     t3, t2, zero
> -       srli    t3, t3, 16
> -       and     t3, t3, a4
> -       slli    t3, t3, 8
> -       /* t4 = bit[23:16] of FDT size */
> -       add     t4, t2, zero
> -       srli    t4, t4, 8
> -       and     t4, t4, a4
> -       slli    t4, t4, 16
> -       /* t5 = bit[31:24] of FDT size */
> -       add     t5, t2, zero
> -       and     t5, t5, a4
> -       slli    t5, t5, 24
> -       /* t2 = bit[7:0] of FDT size */
> -       srli    t2, t2, 24
> -       and     t2, t2, a4
> -       /* t2 = FDT size in little-endian */
> -       or      t2, t2, t3
> -       or      t2, t2, t4
> -       or      t2, t2, t5
> -       /* t2 = destination FDT end address */
> -       add     t2, t1, t2
> -       /* FDT copy loop */
> -       ble     t2, t1, _fdt_reloc_done
> -_fdt_reloc_again:
> -       REG_L   t3, 0(t0)
> -       REG_S   t3, 0(t1)
> -       add     t0, t0, __SIZEOF_POINTER__
> -       add     t1, t1, __SIZEOF_POINTER__
> -       blt     t1, t2, _fdt_reloc_again
> -_fdt_reloc_done:
> +       call    fw_coldboot_init
>
>         /* mark boot hart done */
>         li      t0, BOOT_STATUS_BOOT_HART_DONE
> @@ -441,24 +256,7 @@ _start_warm:
>         /* Setup stack */
>         add     sp, tp, zero
>
> -       /* Setup trap handler */
> -       lla     a4, _trap_handler
> -#if __riscv_xlen == 32
> -       csrr    a5, CSR_MISA
> -       srli    a5, a5, ('H' - 'A')
> -       andi    a5, a5, 0x1
> -       beq     a5, zero, _skip_trap_handler_rv32_hyp
> -       /* Override trap exit for H-extension */
> -       csrr    a5, CSR_MSCRATCH
> -       lla     a4, _trap_exit_rv32_hyp
> -       REG_S   a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(a5)
> -       lla     a4, _trap_handler_rv32_hyp
> -_skip_trap_handler_rv32_hyp:
> -#endif
> -       csrw    CSR_MTVEC, a4
> -
> -       /* Initialize SBI runtime */
> -       csrr    a0, CSR_MSCRATCH
> +       add     a0, tp, zero
>         call    sbi_init
>
>         /* We don't expect to reach here hence just hang */
> diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h
> index 9640fee..bd07403 100644
> --- a/include/sbi/sbi_init.h
> +++ b/include/sbi/sbi_init.h
> @@ -14,6 +14,9 @@
>
>  struct sbi_scratch;
>
> +void fw_coldboot_init(unsigned long arg0, unsigned long arg1,
> +                 unsigned long arg2, unsigned long arg3, unsigned long arg4);
> +
>  void __noreturn sbi_init(struct sbi_scratch *scratch);
>
>  unsigned long sbi_entry_count(u32 hartid);
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 804b01c..1f6f70c 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -6,7 +6,7 @@
>   * Authors:
>   *   Anup Patel <anup.patel at wdc.com>
>   */
> -
> +#include <libfdt.h>
>  #include <sbi/riscv_asm.h>
>  #include <sbi/riscv_atomic.h>
>  #include <sbi/riscv_barrier.h>
> @@ -40,6 +40,104 @@
>         "        | |\n"                                     \
>         "        |_|\n\n"
>
> +
> +extern struct sbi_platform platform;
> +
> +extern char _fw_start[];
> +extern char _fw_end[];
> +extern char _fw_rw_start[];
> +extern char _start_warm[];
> +extern char fw_fdt_bin[];
> +extern char _hartid_to_scratch[];
> +extern char _trap_handler[];
> +extern char _trap_handler_rv32_hyp[];
> +extern char _trap_exit[];
> +extern char _trap_exit_rv32_hyp[];
> +
> +
> +extern void fw_save_info(unsigned long arg0,
> +                        unsigned long arg1,unsigned long arg2);
> +extern unsigned long fw_next_arg1(void);
> +extern unsigned long fw_next_addr(void);
> +extern unsigned long fw_next_mode(void);
> +extern unsigned long fw_options(void);
> +
> +extern unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
> +                 unsigned long arg2, unsigned long arg3, unsigned long arg4);
> +
> +void fw_coldboot_init(unsigned long arg0, unsigned long arg1,
> +                 unsigned long arg2, unsigned long arg3, unsigned long arg4)
> +{
> +       unsigned long top;
> +       unsigned long fw_start;
> +       unsigned long fw_rw_offset;
> +       unsigned long fw_heap_size;
> +       unsigned long fw_heap_offset;
> +       unsigned long fw_size;
> +       unsigned long warmboot_addr;
> +       unsigned long platform_addr;
> +       unsigned long hartid_to_scratch;
> +       unsigned long next_addr;
> +       unsigned long next_arg1;
> +       unsigned long next_mode;
> +       unsigned long options;
> +
> +       const void * fdt;
> +       void *target_fdt;
> +
> +       fw_save_info(arg0, arg1, arg2);
> +#ifdef FW_FDT_PATH
> +       arg1 = (unsigned long)fw_fdt_bin;
> +#endif
> +
> +       /* initialization platform */
> +       arg1 = fw_platform_init(arg0, arg1, arg2, arg3, arg4);
> +
> +       /* relocate fdt */
> +       fdt = (const void*)arg1;
> +       target_fdt = (void*)fw_next_arg1();
> +       fdt_move(fdt, target_fdt, fdt_totalsize(fdt));
> +
> +       /* initialization scratch for all harts */
> +       next_addr = fw_next_addr();
> +       next_arg1 = fw_next_arg1();
> +       next_mode = fw_next_mode();
> +#ifdef FW_OPTIONS
> +       options = FW_OPTIONS
> +#else
> +       options = fw_options();
> +#endif
> +       top = (unsigned long)_fw_end
> +               + platform.hart_stack_size * platform.hart_count;
> +       fw_start = (unsigned long)_fw_start;
> +       fw_rw_offset = (unsigned long)_fw_rw_start - fw_start;
> +       fw_heap_size = platform.heap_size;
> +       fw_heap_offset = top - fw_start;
> +       fw_size = top + fw_heap_size - fw_start;
> +       warmboot_addr = (unsigned long)_start_warm;
> +       platform_addr = (unsigned long)&platform;
> +       hartid_to_scratch = (unsigned long)_hartid_to_scratch;
> +
> +       for (u32 i = 0; i < platform.hart_count; i++) {
> +               struct sbi_scratch *scratch = (struct sbi_scratch *)(top
> +                       - i * platform.hart_stack_size - SBI_SCRATCH_SIZE);
> +
> +               scratch->fw_start = fw_start;
> +               scratch->fw_size = fw_size;
> +               scratch->fw_rw_offset = fw_rw_offset;
> +               scratch->fw_heap_size = fw_heap_size;
> +               scratch->fw_heap_offset = fw_heap_offset;
> +               scratch->warmboot_addr = warmboot_addr;
> +               scratch->platform_addr = platform_addr;
> +               scratch->hartid_to_scratch = hartid_to_scratch;
> +               scratch->next_addr = next_addr;
> +               scratch->next_arg1 = next_arg1;
> +               scratch->next_mode = next_mode;
> +               scratch->options = options;
> +               scratch->tmp0 = 0;
> +       }
> +}
> +
>  static void sbi_boot_print_banner(struct sbi_scratch *scratch)
>  {
>         if (scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS)
> @@ -543,6 +641,17 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
>         u32 hartid                      = current_hartid();
>         const struct sbi_platform *plat = sbi_platform_ptr(scratch);
>
> +       unsigned long trap_handler = (unsigned long)_trap_handler;
> +       unsigned long trap_exit = (unsigned long)_trap_exit;
> +#if __riscv_xlen == 32
> +       if (misa_extension('H')) {
> +               trap_handler = (unsigned long)_trap_handler_rv32_hyp;
> +               trap_exit = (unsigned long)_trap_exit_rv32_hyp;
> +       }
> +#endif
> +       csr_write(CSR_MTVEC, trap_handler);
> +       scratch->trap_exit = trap_exit;
> +
>         for (i = 0; i < plat->hart_count; i++) {
>                 h = (plat->hart_index2id) ? plat->hart_index2id[i] : i;
>                 if (h == hartid)
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From minda.chen at starfivetech.com  Tue Feb  6 01:34:24 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Tue, 6 Feb 2024 09:34:24 +0000
Subject: [PATCH v4 1/7] platform: starfive: correct system clock device
 tree node
In-Reply-To: <063d675dcf59e79892091b0ef085a6a2ca4f6bee.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
 <063d675dcf59e79892091b0ef085a6a2ca4f6bee.1707122766.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB0863A03F132BD5ECE044572FE646A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> Starfive names the system clock device tree node "starfive,jh7110-clkgen"
> in all their git repositories. However, a different name is used in upstream
> U-Boot (and also Linux): "starfive,jh7110-syscrg". Since OpenSBI gets the device
> tree from U-Boot, this inconsistency leads the problem that OpenSBI doesn't
> know the system clock device exists.
> 
> Correct this name to keep the consistency.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index dcd6306..4b22175 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -252,7 +252,7 @@ static int starfive_jh7110_inst_init(void *fdt)
>  		jh7110_inst.pmu_reg_base = addr;
>  	}
> 
> -	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen");
> +	noff = fdt_node_offset_by_compatible(fdt, -1,
> +"starfive,jh7110-syscrg");
>  	if (-1 < noff) {
>  		rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
>  		if (rc)
> --
> 2.39.2
The clock compatible is the same with upstream uboot and linux
Acked-by: Minda Chen <minda.chen at starfivetech.com>


From minda.chen at starfivetech.com  Tue Feb  6 01:35:27 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Tue, 6 Feb 2024 09:35:27 +0000
Subject: [PATCH v4 4/7] platform: starfive: rename
 "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <e09ff63f70ea43b2e4d3a92815a5490e0c80d0ce.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
 <e09ff63f70ea43b2e4d3a92815a5490e0c80d0ce.1707122766.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB08639E3D3E5550DA0F710D90E646A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>


> 
> OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
> for the regulator node. However, the string used by U-Boot (and Linux) is
> actually "x-powers,axp15060". As OpenSBI gets the device tree from U-Boot,
> this causes the regulator device to be undetected, and OpenSBI does not use
> this device to perform board reset/shutdown.
> 
> Rename this device tree compatible string to match U-Boot (and Linux).
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 1956fd8..1f7cfe2 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -223,7 +223,7 @@ static int pm_reset_init(void *fdt, int nodeoff,  }
> 
>  static const struct fdt_match pm_reset_match[] = {
> -	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
> +	{ .compatible = "x-powers,axp15060", .data = (void *)true },
>  	{ },
>  };
> 
> --
> 2.39.2
The pmic compatible is the same with upstream uboot and linux
Acked-by: Minda Chen <minda.chen at starfivetech.com>


From namcao at linutronix.de  Tue Feb  6 02:56:47 2024
From: namcao at linutronix.de (Nam Cao)
Date: Tue, 6 Feb 2024 11:56:47 +0100
Subject: [PATCH v3 7/7] platform: starfive: call
 starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <SHXPR01MB08635C8CF48CE8DA7C0353A2E647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
References: <cover.1706880734.git.namcao@linutronix.de>
	<5e478ee9042b05c53ff4d38a65bd5842591f960d.1706880734.git.namcao@linutronix.de>
	<SHXPR01MB08635C8CF48CE8DA7C0353A2E647A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>
Message-ID: <20240206115647.1d144f11@namcao>

On 05/Feb/2024 Minda Chen wrote:
> > 
> > The function starfive_jh7110_inst_init() initialize some power management unit
> > address and clock addresses, needed for the reset driver. It doesn't do anything
> > else, and also the reset driver doesn't work without calling this function. Thus, it
> > does not make much sense that this function is independent from
> > pm_reset_init().
> > 
> > Delete the separate call to starfive_jh7110_inst_init(), and instead just call this
> > function inside pm_reset_init().
> > 
> > Doing this also fixes another problem: if starfive_jh7110_inst_init() returns an
> > error code, it gets propagated to final_init() and OpenSBI hangs. This hang is not
> > necessary, because failures within
> > starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
> > shutdown, but the system can still function normally.
> > 
> > Signed-off-by: Nam Cao <namcao at linutronix.de>
> > ---
> >  platform/generic/starfive/jh7110.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/platform/generic/starfive/jh7110.c
> > b/platform/generic/starfive/jh7110.c
> > index 63baddb..1577cb4 100644
> > --- a/platform/generic/starfive/jh7110.c
> > +++ b/platform/generic/starfive/jh7110.c
> > @@ -191,6 +191,8 @@ static struct sbi_system_reset_device pm_reset = {
> >  	.system_reset = pm_system_reset
> >  };
> > 
> > +static int starfive_jh7110_inst_init(void *fdt);
> > +
> >  static int pm_reset_init(void *fdt, int nodeoff,
> >  			 const struct fdt_match *match)
> >  {
> > @@ -216,6 +218,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
> > 
> >  	pmic_inst.adapter = adapter;
> > 
> > +	rc = starfive_jh7110_inst_init(fdt);
> > +	if (rc)
> > +		return rc;
> > +
> >  	sbi_system_reset_add_device(&pm_reset);
> > 
> >  	return 0;
> > @@ -279,7 +285,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
> > 
> >  	if (cold_boot) {
> >  		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
> > -		return starfive_jh7110_inst_init(fdt);
> >  	}
> > 
> >  	return 0;
> > --
> > 2.39.2  
> 
> Test with this series patch? function is work fine.

Can I have your Tested-by tag?

Best regards,
Nam



From anup at brainfault.org  Tue Feb  6 04:34:05 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 18:04:05 +0530
Subject: [PATCH v3] lib: sbi: Add initial domain context management support
In-Reply-To: <63c27eb1e50752f499414ab37bd9e51d2364fbbc.1705028699.git.2931013282@sjtu.edu.cn>
References: <63c27eb1e50752f499414ab37bd9e51d2364fbbc.1705028699.git.2931013282@sjtu.edu.cn>
Message-ID: <CAAhSdy0G-7y-qzO2bft+XLTNebDhcCq=8yBFMYiqco8SMuWboA@mail.gmail.com>

On Fri, Jan 12, 2024 at 8:36?AM Qingyu Shang <2931013282 at sjtu.edu.cn> wrote:
>
> The domain context management component in OpenSBI provides basic CPU
> context management routines for existing OpenSBI domain. As domain
> extension, it was initially designed to facilitate the suspension
> and resumption of domains, enabling secure domains to efficiently
> share CPU resources.
>
> The patch also provides an addition to the OpenSBI domain to provide
> updates on hart-domain assignment and declarations of contexts within
> the domain.
>
> Signed-off-by: Qingyu Shang <2931013282 at sjtu.edu.cn>
> ---
>  docs/domain_support.md           |   2 +
>  include/sbi/sbi_domain.h         |   6 ++
>  include/sbi/sbi_domain_context.h |  80 ++++++++++++++++
>  lib/sbi/objects.mk               |   1 +
>  lib/sbi/sbi_domain.c             |  11 ++-
>  lib/sbi/sbi_domain_context.c     | 152 +++++++++++++++++++++++++++++++
>  6 files changed, 250 insertions(+), 2 deletions(-)
>  create mode 100755 include/sbi/sbi_domain_context.h
>  create mode 100755 lib/sbi/sbi_domain_context.c
>
> diff --git a/docs/domain_support.md b/docs/domain_support.md
> index b285d65ae..c98b83211 100644
> --- a/docs/domain_support.md
> +++ b/docs/domain_support.md
> @@ -41,6 +41,7 @@ has following details:
>  * **name** - Name of this domain
>  * **assigned_harts** - HARTs assigned to this domain
>  * **possible_harts** - HARTs possible in this domain
> +* **hartindex_to_context_table** - Contexts corresponding to possible HARTs
>  * **regions** - Array of memory regions terminated by a memory region
>    with order zero
>  * **boot_hartid** - HART id of the HART booting this domain. The domain
> @@ -80,6 +81,7 @@ following manner:
>    platform support
>  * **possible_harts** - All valid HARTs of a RISC-V platform are possible
>    HARTs of the ROOT domain
> +* **hartindex_to_context_table** - Contexts corresponding to ROOT domain's possible HARTs
>  * **regions** - Two memory regions available to the ROOT domain:
>    **A)** A memory region to protect OpenSBI firmware from S-mode and U-mode
>    **B)** A memory region of **order=__riscv_xlen** allowing S-mode and
> diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h
> index c88dbac63..4706cfca7 100644
> --- a/include/sbi/sbi_domain.h
> +++ b/include/sbi/sbi_domain.h
> @@ -12,6 +12,7 @@
>
>  #include <sbi/sbi_types.h>
>  #include <sbi/sbi_hartmask.h>
> +#include <sbi/sbi_domain_context.h>
>
>  struct sbi_scratch;
>
> @@ -176,6 +177,8 @@ struct sbi_domain {
>         char name[64];
>         /** Possible HARTs in this domain */
>         const struct sbi_hartmask *possible_harts;
> +       /** Contexts for possible HARTs indexed by hartindex */
> +       struct sbi_context *hartindex_to_context_table[SBI_HARTMASK_MAX_BITS];
>         /** Array of memory regions terminated by a region with order zero */
>         struct sbi_domain_memregion *regions;
>         /** HART id of the HART booting this domain */
> @@ -200,6 +203,9 @@ extern struct sbi_domain root;
>  /** Get pointer to sbi_domain from HART index */
>  struct sbi_domain *sbi_hartindex_to_domain(u32 hartindex);
>
> +/** Update HART local pointer to point to specified domain */
> +void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom);
> +
>  /** Get pointer to sbi_domain for current HART */
>  #define sbi_domain_thishart_ptr() \
>         sbi_hartindex_to_domain(sbi_hartid_to_hartindex(current_hartid()))
> diff --git a/include/sbi/sbi_domain_context.h b/include/sbi/sbi_domain_context.h
> new file mode 100755
> index 000000000..89f779195
> --- /dev/null
> +++ b/include/sbi/sbi_domain_context.h
> @@ -0,0 +1,80 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) IPADS at SJTU 2023. All rights reserved.
> + */
> +
> +#ifndef __SBI_DOMAIN_CONTEXT_H__
> +#define __SBI_DOMAIN_CONTEXT_H__
> +
> +#include <sbi/sbi_types.h>
> +#include <sbi/sbi_trap.h>
> +#include <sbi/sbi_domain.h>
> +
> +/** Context representation for a hart within a domain */
> +struct sbi_context {
> +       /** Trap-related states such as GPRs, mepc, and mstatus */
> +       struct sbi_trap_regs regs;
> +
> +       /** Supervisor status register */
> +       unsigned long sstatus;
> +       /** Supervisor interrupt enable register */
> +       unsigned long sie;
> +       /** Supervisor trap vector base address register */
> +       unsigned long stvec;
> +       /** Supervisor scratch register for temporary storage */
> +       unsigned long sscratch;
> +       /** Supervisor exception program counter register */
> +       unsigned long sepc;
> +       /** Supervisor cause register */
> +       unsigned long scause;
> +       /** Supervisor trap value register */
> +       unsigned long stval;
> +       /** Supervisor interrupt pending register */
> +       unsigned long sip;
> +       /** Supervisor address translation and protection register */
> +       unsigned long satp;
> +       /** Counter-enable register */
> +       unsigned long scounteren;
> +       /** Supervisor environment configuration register */
> +       unsigned long senvcfg;
> +
> +       /** Reference to the owning domain */
> +       struct sbi_domain *dom;
> +       /** Previous context (caller) to jump to during context exits */
> +       struct sbi_context *prev_ctx;
> +       /** Is context initialized and runnable */
> +       bool initialized;
> +};
> +
> +/** Get the context pointer for a given hart index and domain */
> +#define sbi_hartindex_to_domain_context(__hartindex, __d) \
> +       (__d)->hartindex_to_context_table[__hartindex]
> +
> +/** Macro to obtain the current hart's context pointer */
> +#define sbi_domain_context_thishart_ptr()                  \
> +       sbi_hartindex_to_domain_context(                   \
> +               sbi_hartid_to_hartindex(current_hartid()), \
> +               sbi_domain_thishart_ptr())
> +
> +/**
> + * Enter a specific domain context synchronously
> + * @param dom pointer to domain
> + *
> + * @return 0 on success and negative error code on failure
> + */
> +int sbi_domain_context_enter(struct sbi_domain *dom);
> +
> +/**
> + * Exit the current domain context, and then return to the caller
> + * of sbi_domain_context_enter or attempt to start the next domain
> + * context to be initialized
> + *
> + * @return 0 on success and negative error code on failure
> + */
> +int sbi_domain_context_exit(void);
> +
> +/** Initialize contexts for all domains */
> +int sbi_domain_context_init(struct sbi_scratch *scratch);
> +
> +#endif // __SBI_DOMAIN_CONTEXT_H__
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 0a50e95c3..138be96fd 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -58,6 +58,7 @@ libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
>  libsbi-objs-y += sbi_bitmap.o
>  libsbi-objs-y += sbi_bitops.o
>  libsbi-objs-y += sbi_console.o
> +libsbi-objs-y += sbi_domain_context.o
>  libsbi-objs-y += sbi_domain.o
>  libsbi-objs-y += sbi_emulate_csr.o
>  libsbi-objs-y += sbi_fifo.o
> diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
> index 4e9f7428a..217116198 100644
> --- a/lib/sbi/sbi_domain.c
> +++ b/lib/sbi/sbi_domain.c
> @@ -51,7 +51,7 @@ struct sbi_domain *sbi_hartindex_to_domain(u32 hartindex)
>         return sbi_scratch_read_type(scratch, void *, domain_hart_ptr_offset);
>  }
>
> -static void update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom)
> +void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom)
>  {
>         struct sbi_scratch *scratch;
>
> @@ -567,7 +567,7 @@ int sbi_domain_register(struct sbi_domain *dom,
>                 if (tdom)
>                         sbi_hartmask_clear_hartindex(i,
>                                         &tdom->assigned_harts);
> -               update_hartindex_to_domain(i, dom);
> +               sbi_update_hartindex_to_domain(i, dom);
>                 sbi_hartmask_set_hartindex(i, &dom->assigned_harts);
>
>                 /*
> @@ -725,6 +725,13 @@ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
>                 }
>         }
>
> +       rc = sbi_domain_context_init(scratch);
> +       if (rc) {
> +               sbi_printf("%s: domain context init failed (error %d)\n",
> +                          __func__, rc);
> +               return rc;
> +       }
> +
>         /*
>          * Set the finalized flag so that the root domain
>          * regions can't be changed.
> diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
> new file mode 100755
> index 000000000..db7281862
> --- /dev/null
> +++ b/lib/sbi/sbi_domain_context.c
> @@ -0,0 +1,152 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) IPADS at SJTU 2023. All rights reserved.
> + */
> +
> +#include <sbi/sbi_error.h>
> +#include <sbi/riscv_locks.h>
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_hsm.h>
> +#include <sbi/sbi_hart.h>
> +#include <sbi/sbi_heap.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_string.h>
> +#include <sbi/sbi_domain_context.h>
> +
> +/**
> + * Switches the HART context from the current domain to the target domain.
> + * This includes changing domain assignments and reconfiguring PMP, as well
> + * as saving and restoring CSRs and trap states.
> + *
> + * @param ctx pointer to the current HART context
> + * @param dom_ctx pointer to the target domain context
> + */
> +static void switch_to_next_domain_context(struct sbi_context *ctx,
> +                                         struct sbi_context *dom_ctx)
> +{
> +       u32 hartindex;
> +       struct sbi_trap_regs *trap_regs;
> +       struct sbi_domain *dom      = dom_ctx->dom;
> +       struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
> +       unsigned int pmp_count      = sbi_hart_pmp_count(scratch);
> +
> +       /* Assign current hart to target domain */
> +       hartindex = sbi_hartid_to_hartindex(current_hartid());
> +       sbi_hartmask_clear_hartindex(
> +               hartindex, &sbi_domain_thishart_ptr()->assigned_harts);
> +       sbi_update_hartindex_to_domain(hartindex, dom);
> +       sbi_hartmask_set_hartindex(hartindex, &dom->assigned_harts);
> +
> +       /* Reconfigure PMP settings for the new domain */
> +       for (int i = 0; i < pmp_count; i++) {
> +               pmp_disable(i);
> +       }
> +       sbi_hart_pmp_configure(scratch);
> +
> +       /* Save current CSR context and restore target domain's CSR context */
> +       ctx->sstatus    = csr_swap(CSR_SSTATUS, dom_ctx->sstatus);
> +       ctx->sie        = csr_swap(CSR_SIE, dom_ctx->sie);
> +       ctx->stvec      = csr_swap(CSR_STVEC, dom_ctx->stvec);
> +       ctx->sscratch   = csr_swap(CSR_SSCRATCH, dom_ctx->sscratch);
> +       ctx->sepc       = csr_swap(CSR_SEPC, dom_ctx->sepc);
> +       ctx->scause     = csr_swap(CSR_SCAUSE, dom_ctx->scause);
> +       ctx->stval      = csr_swap(CSR_STVAL, dom_ctx->stval);
> +       ctx->sip        = csr_swap(CSR_SIP, dom_ctx->sip);
> +       ctx->satp       = csr_swap(CSR_SATP, dom_ctx->satp);
> +       ctx->scounteren = csr_swap(CSR_SCOUNTEREN, dom_ctx->scounteren);
> +       ctx->senvcfg    = csr_swap(CSR_SENVCFG, dom_ctx->senvcfg);
> +
> +       /* Save current trap state and restore target domain's trap state */
> +       trap_regs = (struct sbi_trap_regs *)(csr_read(CSR_MSCRATCH) -
> +                                            SBI_TRAP_REGS_SIZE);
> +       sbi_memcpy(&ctx->regs, trap_regs, sizeof(*trap_regs));
> +       sbi_memcpy(trap_regs, &dom_ctx->regs, sizeof(*trap_regs));
> +
> +       /* Mark current context structure initialized because context saved */
> +       ctx->initialized = true;
> +
> +       /* If target domain context is not initialized or runnable */
> +       if (!dom_ctx->initialized) {
> +               /* Startup boot HART of target domain */
> +               if (current_hartid() == dom->boot_hartid)
> +                       sbi_hart_switch_mode(dom->boot_hartid, dom->next_arg1,
> +                                            dom->next_addr, dom->next_mode,
> +                                            false);
> +               else
> +                       sbi_hsm_hart_stop(scratch, true);
> +       }
> +}
> +
> +int sbi_domain_context_enter(struct sbi_domain *dom)
> +{
> +       struct sbi_context *ctx     = sbi_domain_context_thishart_ptr();
> +       struct sbi_context *dom_ctx = sbi_hartindex_to_domain_context(
> +               sbi_hartid_to_hartindex(current_hartid()), dom);
> +
> +       /* Validate the domain context existence */
> +       if (!dom_ctx)
> +               return SBI_EINVAL;
> +
> +       /* Update target context's previous context to indicate the caller */
> +       dom_ctx->prev_ctx = ctx;
> +
> +       switch_to_next_domain_context(ctx, dom_ctx);
> +
> +       return 0;
> +}
> +
> +int sbi_domain_context_exit(void)
> +{
> +       u32 i, hartindex = sbi_hartid_to_hartindex(current_hartid());
> +       struct sbi_domain *dom;
> +       struct sbi_context *ctx     = sbi_domain_context_thishart_ptr();
> +       struct sbi_context *dom_ctx = ctx->prev_ctx, *tmp;
> +
> +       /* If no previous caller context */
> +       if (!dom_ctx) {
> +               /* Try to find next uninitialized user-defined domain's context */
> +               sbi_domain_for_each(i, dom) {
> +                       if (dom == &root || dom == sbi_domain_thishart_ptr())
> +                               continue;
> +
> +                       tmp = sbi_hartindex_to_domain_context(hartindex, dom);
> +                       if (tmp && !tmp->initialized) {
> +                               dom_ctx = tmp;
> +                               break;
> +                       }
> +               }
> +       }
> +
> +       /* Take the root domain context if fail to find */
> +       if (!dom_ctx)
> +               dom_ctx = sbi_hartindex_to_domain_context(hartindex, &root);
> +
> +       switch_to_next_domain_context(ctx, dom_ctx);
> +
> +       return 0;
> +}
> +
> +int sbi_domain_context_init(struct sbi_scratch *scratch)
> +{
> +       u32 i, j;
> +       struct sbi_domain *dom;
> +       struct sbi_context *dom_ctx;
> +
> +       /* Loop through each domain to configure its contexts */
> +       sbi_domain_for_each(i, dom) {
> +               /* Iterate over all possible HARTs and allocate context structure */
> +               sbi_hartmask_for_each_hartindex(j, dom->possible_harts) {
> +                       dom_ctx = sbi_zalloc(sizeof(struct sbi_context));
> +                       if (!dom_ctx)
> +                               return SBI_ENOMEM;
> +
> +                       /* Bind context and domain */
> +                       dom_ctx->dom                       = dom;
> +                       dom->hartindex_to_context_table[j] = dom_ctx;

Pre-allocating context for all domains will simply increase
the memory consumption even for users who don't
intend to use domain switching at runtime.

Once this is addressed, I think we are ready to merge
this patch.

How about allocating sbi_context on-demain in
sbi_domain_context_enter() ?

Regards,
Anup

> +               }
> +       }
> +
> +       return 0;
> +}
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Tue Feb  6 08:23:50 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 6 Feb 2024 21:53:50 +0530
Subject: [PATCH v2] lib:platform: Add support for specify coldboot harts
 in DT for generic.
In-Reply-To: <tencent_C591656EA4C816895747ACD9C6B0E22B3608@qq.com>
References: <tencent_C591656EA4C816895747ACD9C6B0E22B3608@qq.com>
Message-ID: <CAAhSdy3vxauaBogFVPa18XHSb69c+Ay5TmC9huiNWe8H0uhdQw@mail.gmail.com>

On Tue, Jan 30, 2024 at 5:09?PM Cheng Yang <yangcheng.work at foxmail.com> wrote:
>
> Added support for the generic platform to specify the set of coldboot
> hart in DT. If not specified in DT, all harts are allowed to coldboot
> as before.
>
> The functions related to sbi_hartmask are not available before coldboot,
> so I used bitmap, and added a new bitmap_test() function to test whether
> a certain bit of the bitmap is set.
>
> Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
> ---
> Changes v1 -> v2:
>   - Remove brackets.
>
>  include/sbi/sbi_bitmap.h    |  5 +++
>  lib/utils/fdt/fdt_fixup.c   | 17 ++++++++++
>  platform/generic/platform.c | 65 ++++++++++++++++++++++++++++++++++++-
>  3 files changed, 86 insertions(+), 1 deletion(-)

Overall, this looks good.

I suggest expanding this series with following patches:
1) Patch2 to add docs/opensbi_config.md which describes the
    "/chosen/opensbi-config" DT node and properties
2) Patch3 to update generic_domains_init() so that
    "system-suspend-test" is parsed from "/chosen/opensbi-config"
     DT node.
3) Patch4 to move documentation of "system-suspend-test"
   from docs/domain_support.md to docs/opensbi_config.md

Regards,
Anup

>
> diff --git a/include/sbi/sbi_bitmap.h b/include/sbi/sbi_bitmap.h
> index 4f0ebb6..354476c 100644
> --- a/include/sbi/sbi_bitmap.h
> +++ b/include/sbi/sbi_bitmap.h
> @@ -62,6 +62,11 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
>         }
>  }
>
> +static inline int bitmap_test(unsigned long *bmap, int bit)
> +{
> +       return __test_bit(bit, bmap);
> +}
> +
>  static inline void bitmap_zero_except(unsigned long *dst,
>                                       int exception, int nbits)
>  {
> diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
> index 5fc7673..55e6987 100644
> --- a/lib/utils/fdt/fdt_fixup.c
> +++ b/lib/utils/fdt/fdt_fixup.c
> @@ -385,6 +385,21 @@ int fdt_reserved_memory_fixup(void *fdt)
>         return 0;
>  }
>
> +void fdt_config_fixup(void *fdt) {
> +       int chosen_offset, config_offset;
> +
> +       chosen_offset = fdt_path_offset(fdt, "/chosen");
> +       if (chosen_offset < 0)
> +               return;
> +
> +
> +       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
> +       if (chosen_offset < 0)
> +               return;
> +
> +       fdt_nop_node(fdt, config_offset);
> +}
> +
>  void fdt_fixups(void *fdt)
>  {
>         fdt_aplic_fixup(fdt);
> @@ -398,4 +413,6 @@ void fdt_fixups(void *fdt)
>  #ifndef CONFIG_FDT_FIXUPS_PRESERVE_PMU_NODE
>         fdt_pmu_fixup(fdt);
>  #endif
> +
> +       fdt_config_fixup(fdt);
>  }
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index bfd7d31..5f76193 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -73,6 +73,61 @@ extern struct sbi_platform platform;
>  static bool platform_has_mlevel_imsic = false;
>  static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
>
> +DECLARE_BITMAP(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
> +
> +/*
> + * The fw_platform_coldboot_init() function is called by fw_platform_init()
> + * function to initialize the cold boot harts allowed by the generic platform
> + * according to the DT property "cold-boot-harts" in "/chosen/opensbi-config"
> + * DT node. If there is no "cold-boot-harts" in DT, all harts will be allowed.
> + */
> +static void fw_platform_coldboot_init(void *fdt)
> +{
> +       int chosen_offset, config_offset, cpu_offset, len, err;
> +       u32 val32;
> +       const u32 *val;
> +
> +       bitmap_zero(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
> +
> +       chosen_offset = fdt_path_offset(fdt, "/chosen");
> +       if (chosen_offset < 0)
> +               goto default_config;
> +
> +       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
> +       if (config_offset < 0)
> +               goto default_config;
> +
> +       val = fdt_getprop(fdt, config_offset, "cold-boot-harts", &len);
> +       len = len / sizeof(u32);
> +       if (val && len) {
> +               for (int i = 0; i < len; i++) {
> +                       cpu_offset = fdt_node_offset_by_phandle(fdt,
> +                                                       fdt32_to_cpu(val[i]));
> +                       if (cpu_offset < 0)
> +                               goto default_config;
> +
> +                       err = fdt_parse_hart_id(fdt, cpu_offset, &val32);
> +                       if (err)
> +                               goto default_config;
> +
> +                       if (!fdt_node_is_enabled(fdt, cpu_offset))
> +                               continue;
> +
> +                       for (int i = 0; i < platform.hart_count; i++) {
> +                               if (val32 == generic_hart_index2id[i])
> +                                       bitmap_set(generic_coldboot_harts, i, 1);
> +                       }
> +
> +               }
> +       }
> +
> +       return;
> +
> +default_config:
> +       bitmap_fill(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
> +       return;
> +}
> +
>  /*
>   * The fw_platform_init() function is called very early on the boot HART
>   * OpenSBI reference firmwares so that platform specific code get chance
> @@ -133,6 +188,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
>         platform.heap_size = fw_platform_calculate_heap_size(hart_count);
>         platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
>
> +       fw_platform_coldboot_init(fdt);
> +
>         /* Return original FDT pointer */
>         return arg1;
>
> @@ -146,7 +203,13 @@ static bool generic_cold_boot_allowed(u32 hartid)
>         if (generic_plat && generic_plat->cold_boot_allowed)
>                 return generic_plat->cold_boot_allowed(
>                                                 hartid, generic_plat_match);
> -       return true;
> +
> +       for (int i = 0; i < platform.hart_count; i++) {
> +               if (hartid == generic_hart_index2id[i])
> +                       return bitmap_test(generic_coldboot_harts, i);
> +       }
> +
> +       return false;
>  }
>
>  static int generic_nascent_init(void)
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From yangcheng.work at foxmail.com  Wed Feb  7 19:14:33 2024
From: yangcheng.work at foxmail.com (Cheng Yang)
Date: Thu,  8 Feb 2024 11:14:33 +0800
Subject: [PATCH v3 2/4] docs: Add OpenSBI DT configuration guide.
In-Reply-To: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
Message-ID: <tencent_5F0F58AA15AB481BB7126486C4FCA38FEC07@qq.com>

This patch add docs/opensbi_config.md which describes the
"/chosen/opensbi-config" DT node and properties

Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
---
 docs/opensbi_config.md | 83 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 docs/opensbi_config.md

diff --git a/docs/opensbi_config.md b/docs/opensbi_config.md
new file mode 100644
index 0000000..0c42443
--- /dev/null
+++ b/docs/opensbi_config.md
@@ -0,0 +1,83 @@
+OpenSBI Device Tree Configuration Guideline
+==================================
+
+Some configurations of OpenSBI's Generic Platform can be described
+in the **device tree (DT) blob** (or flattened device tree) passed
+to the OpenSBI firmwares by the previous booting stage. OpenSBI will
+parse and use these configurations during the boot phase, but delete
+them from the device tree at the end of cold boot.
+
+### OpenSBI Configuration Node
+
+All nodes related to OpenSBI configuration should be under the OpenSBI
+configuration DT node. The **/chosen** DT node is the preferred parent
+of the OpenSBI configuration DT node.
+
+The DT properties of a domain configuration DT node are as follows:
+
+* **compatible** (Mandatory) - The compatible string of the OpenSBI
+  configuration. This DT property should have value *"opensbi,config"*
+
+* **cold-boot-harts** (Optional) - If a platform lacks an override
+  cold_boot_allowed() mechanism, this DT property specifies that a
+  set of harts is permitted to perform a cold boot. Otherwise, all
+  harts are allowed to cold boot.
+
+The OpenSBI Configuration Node will be deleted at the end of cold boot
+(replace the node (subtree) with nop tags).
+
+### Example
+
+```text
+    chosen {
+        opensbi-config {
+            compatible = "opensbi,config";
+            cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
+        };
+    };
+
+    cpus {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        timebase-frequency = <10000000>;
+
+        cpu0: cpu at 0 {
+            device_type = "cpu";
+            reg = <0x00>;
+            compatible = "riscv";
+            ...
+        };
+
+        cpu1: cpu at 1 {
+            device_type = "cpu";
+            reg = <0x01>;
+            compatible = "riscv";
+            ...
+        };
+
+        cpu2: cpu at 2 {
+            device_type = "cpu";
+            reg = <0x02>;
+            compatible = "riscv";
+            ...
+        };
+
+        cpu3: cpu at 3 {
+            device_type = "cpu";
+            reg = <0x03>;
+            compatible = "riscv";
+            ...
+        };
+
+        cpu4: cpu at 4 {
+            device_type = "cpu";
+            reg = <0x04>;
+            compatible = "riscv";
+            ...
+        };
+    };
+
+    uart1: serial at 10011000 {
+        ...
+    };
+```
-- 
2.34.1



From yangcheng.work at foxmail.com  Wed Feb  7 19:14:32 2024
From: yangcheng.work at foxmail.com (Cheng Yang)
Date: Thu,  8 Feb 2024 11:14:32 +0800
Subject: [PATCH v3 1/4] lib:platform: Add support for specify coldboot harts in DT for generic.
Message-ID: <tencent_2B898B47FDD9EDB02C2B4291A06EC5C80108@qq.com>

Added support for the generic platform to specify the set of coldboot
hart in DT. If not specified in DT, all harts are allowed to coldboot
as before.

The functions related to sbi_hartmask are not available before coldboot,
so I used bitmap, and added a new bitmap_test() function to test whether
a certain bit of the bitmap is set.

Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
---
Changes v2 -> v3:
	Add patches to expand the series.

 include/sbi/sbi_bitmap.h    |  5 +++
 lib/utils/fdt/fdt_fixup.c   | 17 ++++++++++
 platform/generic/platform.c | 65 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/include/sbi/sbi_bitmap.h b/include/sbi/sbi_bitmap.h
index 4f0ebb6..354476c 100644
--- a/include/sbi/sbi_bitmap.h
+++ b/include/sbi/sbi_bitmap.h
@@ -62,6 +62,11 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
 	}
 }
 
+static inline int bitmap_test(unsigned long *bmap, int bit)
+{
+	return __test_bit(bit, bmap);
+}
+
 static inline void bitmap_zero_except(unsigned long *dst,
 				      int exception, int nbits)
 {
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index 5fc7673..55e6987 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -385,6 +385,21 @@ int fdt_reserved_memory_fixup(void *fdt)
 	return 0;
 }
 
+void fdt_config_fixup(void *fdt) {
+	int chosen_offset, config_offset;
+
+	chosen_offset = fdt_path_offset(fdt, "/chosen");
+	if (chosen_offset < 0)
+		return;
+
+
+	config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
+	if (chosen_offset < 0)
+		return;
+
+	fdt_nop_node(fdt, config_offset);
+}
+
 void fdt_fixups(void *fdt)
 {
 	fdt_aplic_fixup(fdt);
@@ -398,4 +413,6 @@ void fdt_fixups(void *fdt)
 #ifndef CONFIG_FDT_FIXUPS_PRESERVE_PMU_NODE
 	fdt_pmu_fixup(fdt);
 #endif
+
+	fdt_config_fixup(fdt);
 }
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index bfd7d31..5f76193 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -73,6 +73,61 @@ extern struct sbi_platform platform;
 static bool platform_has_mlevel_imsic = false;
 static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
 
+DECLARE_BITMAP(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+
+/*
+ * The fw_platform_coldboot_init() function is called by fw_platform_init() 
+ * function to initialize the cold boot harts allowed by the generic platform
+ * according to the DT property "cold-boot-harts" in "/chosen/opensbi-config" 
+ * DT node. If there is no "cold-boot-harts" in DT, all harts will be allowed.
+ */
+static void fw_platform_coldboot_init(void *fdt)
+{
+	int chosen_offset, config_offset, cpu_offset, len, err;
+	u32 val32;
+	const u32 *val;
+
+	bitmap_zero(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+
+	chosen_offset = fdt_path_offset(fdt, "/chosen");
+	if (chosen_offset < 0)
+		goto default_config;
+
+	config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
+	if (config_offset < 0)
+		goto default_config;
+
+	val = fdt_getprop(fdt, config_offset, "cold-boot-harts", &len);
+	len = len / sizeof(u32);
+	if (val && len) {
+		for (int i = 0; i < len; i++) {
+			cpu_offset = fdt_node_offset_by_phandle(fdt,
+							fdt32_to_cpu(val[i]));
+			if (cpu_offset < 0)
+				goto default_config;
+
+			err = fdt_parse_hart_id(fdt, cpu_offset, &val32);
+			if (err)
+				goto default_config;
+
+			if (!fdt_node_is_enabled(fdt, cpu_offset))
+				continue;
+
+			for (int i = 0; i < platform.hart_count; i++) {
+				if (val32 == generic_hart_index2id[i])
+					bitmap_set(generic_coldboot_harts, i, 1);
+			}
+
+		}
+	}
+
+	return;
+
+default_config:
+	bitmap_fill(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+	return;
+}
+
 /*
  * The fw_platform_init() function is called very early on the boot HART
  * OpenSBI reference firmwares so that platform specific code get chance
@@ -133,6 +188,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
 	platform.heap_size = fw_platform_calculate_heap_size(hart_count);
 	platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
 
+	fw_platform_coldboot_init(fdt);
+
 	/* Return original FDT pointer */
 	return arg1;
 
@@ -146,7 +203,13 @@ static bool generic_cold_boot_allowed(u32 hartid)
 	if (generic_plat && generic_plat->cold_boot_allowed)
 		return generic_plat->cold_boot_allowed(
 						hartid, generic_plat_match);
-	return true;
+
+	for (int i = 0; i < platform.hart_count; i++) {
+		if (hartid == generic_hart_index2id[i])
+			return bitmap_test(generic_coldboot_harts, i);
+	}
+
+	return false;
 }
 
 static int generic_nascent_init(void)
-- 
2.34.1



From yangcheng.work at foxmail.com  Wed Feb  7 19:14:34 2024
From: yangcheng.work at foxmail.com (Cheng Yang)
Date: Thu,  8 Feb 2024 11:14:34 +0800
Subject: [PATCH v3 3/4] platform: generic: Parse system suspend test from config node.
In-Reply-To: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
Message-ID: <tencent_BAE2CFD156362A6CF8CA52A4825B12727E06@qq.com>

This patch update generic_domains_init() so that "system-suspend-test"
is parsed from "/chosen/opensbi-config" DT node.

Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
---
 platform/generic/platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 5f76193..407d5b1 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -316,7 +316,7 @@ static int generic_domains_init(void)
 
 	if (offset >= 0) {
 		offset = fdt_node_offset_by_compatible(fdt, offset,
-						       "opensbi,domain,config");
+						       "opensbi,config");
 		if (offset >= 0 &&
 		    fdt_get_property(fdt, offset, "system-suspend-test", NULL))
 			sbi_system_suspend_test_enable();
-- 
2.34.1



From yangcheng.work at foxmail.com  Wed Feb  7 19:14:35 2024
From: yangcheng.work at foxmail.com (Cheng Yang)
Date: Thu,  8 Feb 2024 11:14:35 +0800
Subject: [PATCH v3 4/4] docs: move documentation of system suspend test.
In-Reply-To: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com>
Message-ID: <tencent_828AACE84732BAD1216325B61CBD668BC00A@qq.com>

This patch move documentation of "system-suspend-test" from
docs/domain_support.md to docs/opensbi_config.md

Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
---
 docs/domain_support.md | 4 ----
 docs/opensbi_config.md | 4 ++++
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/domain_support.md b/docs/domain_support.md
index b285d65..65b6142 100644
--- a/docs/domain_support.md
+++ b/docs/domain_support.md
@@ -126,9 +126,6 @@ The DT properties of a domain configuration DT node are as follows:
 * **compatible** (Mandatory) - The compatible string of the domain
   configuration. This DT property should have value *"opensbi,domain,config"*
 
-* **system-suspend-test** (Optional) - When present, enable a system
-  suspend test implementation which simply waits five seconds and issues a WFI.
-
 ### Domain Memory Region Node
 
 The domain memory region DT node describes details of a memory region and
@@ -237,7 +234,6 @@ be done:
     chosen {
         opensbi-domains {
             compatible = "opensbi,domain,config";
-            system-suspend-test;
 
             tmem: tmem {
                 compatible = "opensbi,domain,memregion";
diff --git a/docs/opensbi_config.md b/docs/opensbi_config.md
index 0c42443..1b710f1 100644
--- a/docs/opensbi_config.md
+++ b/docs/opensbi_config.md
@@ -23,6 +23,9 @@ The DT properties of a domain configuration DT node are as follows:
   set of harts is permitted to perform a cold boot. Otherwise, all
   harts are allowed to cold boot.
 
+* **system-suspend-test** (Optional) - When present, enable a system
+  suspend test implementation which simply waits five seconds and issues a WFI.
+
 The OpenSBI Configuration Node will be deleted at the end of cold boot
 (replace the node (subtree) with nop tags).
 
@@ -33,6 +36,7 @@ The OpenSBI Configuration Node will be deleted at the end of cold boot
         opensbi-config {
             compatible = "opensbi,config";
             cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
+            system-suspend-test;
         };
     };
 
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb  8 01:50:47 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu,  8 Feb 2024 09:50:47 +0000
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
Message-ID: <20240208095050.398522-1-ivan.orlov0322@gmail.com>

It is good when the code is covered with tests. Tests help us to keep
the code clean and avoid regressions. Also, a good test is always a nice
documentation for the code it covers.

This and the subsequent patches in this series introduce SBIUnit - the
set of macros and functions which simplify the unit test development
for OpenSBI and automate tests execution and evaluation. Also, this
patch series contains two of the tests: one which covers functions from
lib/sbi_bitmap.c, and another covering a part of functions from
lib/sbi_console.c.

This patch contains the documentation for SBIUnit. It describes:

- What is SBIUnit
- Simple test writing scenario
- How we can cover static functions
- How we can "mock" structures in order to test the functions which
operate on them
- SBIUnit API Reference

This thing is mainly inspired by the KUnit framework from the Linux
Kernel, where the similar unit-test development tooling have been used
successfully for a pretty long time now. I believe it would be good to
have such a thing in OpenSBI as well.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
 docs/writing_tests.md | 143 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 docs/writing_tests.md

diff --git a/docs/writing_tests.md b/docs/writing_tests.md
new file mode 100644
index 0000000..481f2ee
--- /dev/null
+++ b/docs/writing_tests.md
@@ -0,0 +1,143 @@
+Writing tests for OpenSBI
+=========================
+
+SBIUnit
+-------
+SBIUnit is a set of macros and functions which simplify the test development and automate the
+test execution and evaluation. All of the SBIUnit definitions could be found in
+`include/sbi/sbi_unit.h` header file, and implementations are available in `lib/sbi/sbi_unit.c`.
+
+Simple SBIUnit test
+-------------------
+
+For instance, we would like to test the following function from `lib/sbi/sbi_string.c`:
+
+```c
+size_t sbi_strlen(const char *str)
+{
+	unsigned long ret = 0;
+
+	while (*str != '\0') {
+		ret++;
+		str++;
+	}
+
+	return ret;
+}
+```
+
+Apparently, it calculates the string length.
+
+Create the file `lib/sbi/sbi_string_test.c` with the following content:
+
+```c
+#include <sbi/sbi_unit.h>
+#include <sbi/sbi_string.h>
+
+static void strlen_test(struct sbiunit_test_case *test)
+{
+	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
+	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
+}
+
+static struct sbiunit_test_case string_test_cases[] = {
+	SBIUNIT_TEST_CASE(strlen_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
+```
+
+After that, add the corresponding entry to `lib/sbi/sbi_unit.c` and update the `test_suites` array:
+```c
+...
+extern struct sbiunit_test_suite string_test_suite;
+...
+static struct sbiunit_test_suite *test_suites[] = {
+    ...
+    &string_test_suite,
+};
+...
+```
+
+Add the corresponding Makefile entry to `lib/sbi/objects.mk`:
+```lang-makefile
+...
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
+```
+
+Now recompile OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU. You will see
+something like this:
+```
+# make PLATFORM=generic run
+...
+# Running SBIUNIT tests #
+...
+## Running test suite: string_test_suite
+[OK] strlen_test
+1 SUCCESS / 0 FAIL / 1 TOTAL
+```
+
+Now let's try to change this test in the way that it will fail:
+
+```c
+- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
+```
+
+Compile and run it again:
+```
+...
+# Running SBIUNIT tests #
+...
+## Running test suite: string_test_suite
+strlen_test: Condition "sbi_strlen("Hello") == 100" expected to be true!
+[FAIL] strlen_test
+0 SUCCESS / 1 FAIL / 1 TOTAL
+```
+Covering the static functions / using the static definitions
+------------------------------------------------------------
+
+SBIUnit also allows you to test static functions. In order to do so, simply include your test source
+in the file you would like to test. Complementing the example above, just add this to the
+`lib/sbi/sbi_string.c` file:
+
+```c
+#ifdef CONFIG_SBIUNIT
+#include "sbi_string_test.c"
+#endif
+```
+
+In this case you should not add a new entry to `lib/sbi/objects.mk`, because the test code will be
+included into the `sbi_string` object file.
+
+See example in `lib/sbi/sbi_console_test.c`, where statically declared `console_dev` variable is
+used to mock the `sbi_console_device` structure.
+
+"Mocking" the structures
+------------------------
+See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`, where the
+sbi_console_device structure was mocked to be used in various console-related functions in order to
+test them.
+
+API Reference
+-------------
+All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the corresponding conditions
+are not met, however, the execution of a particular test case will not be stopped.
+
+All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop immediately.
+
+- `SBIUNIT_EXPECT(test_case, condition)` - sets an expectation that 'condition' is true
+- `SBIUNIT_ASSERT(test_case, condition)` - sets an assertion that 'condition' is true
+- `SBIUNIT_EXPECT_EQ(test_case, a, b)` - sets an expectation that a = b
+- `SBIUNIT_ASSERT_EQ(test_case, a, b)` - sets an assertion that a = b
+- `SBIUNIT_EXPECT_NE(test_case, a, b)` - sets an expectation that a != b
+- `SBIUNIT_ASSERT_NE(test_case, a, b)` - sets an assertion that a != b
+- `SBIUNIT_EXPECT_MEMEQ(test_case, a, b, len)` - performs sbi_memcmp on memory regions a and b with
+a length 'len', and sets an expectation that they are equal
+- `SBIUNIT_ASSERT_MEMEQ(test_case, a, b, len)` - performs sbi_memcmp on memory regions a and b with
+a length 'len', and sets an assertion that they are equal
+- `SBIUNIT_EXPECT_STREQ(test_case, a, b)` - performs sbi_strcmp on strings a and b and sets
+an expectation that they are equal
+- `SBIUNIT_ASSERT_STREQ(test_case, a, b)` - performs sbi_strcmp on strings a and b and sets
+an assertion that they are equal
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb  8 01:50:48 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu,  8 Feb 2024 09:50:48 +0000
Subject: [PATCH 2/4] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
Message-ID: <20240208095050.398522-2-ivan.orlov0322@gmail.com>

It is good when the code is covered with tests. Tests help us to keep
the code clean and avoid regressions. Also, a good test is always a nice
documentation for the code it covers.

This and the subsequent patches in this series introduce SBIUnit - the
set of macros and functions which simplify the unit test development for
OpenSBI and automate tests execution and evaluation.

This patch introduces all of the SBIUnit macros and functions which
can be used during the test development process. Also, it defines
the 'run_all_tests' function, which is being called during the
'init_coldboot' right after printing the boot hart information.

Also, add the CONFIG_SBIUNIT Kconfig entry in order to be able to
turn the tests on and off. When the CONFIG_SBIUNIT is disabled,
the tests and all related code should be excluded completely on the
compilation stage (and, apparently, it works in this way).

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
 include/sbi/sbi_unit.h | 69 ++++++++++++++++++++++++++++++++++++++++++
 lib/sbi/Kconfig        |  4 +++
 lib/sbi/objects.mk     |  1 +
 lib/sbi/sbi_init.c     |  8 +++++
 lib/sbi/sbi_unit.c     | 44 +++++++++++++++++++++++++++
 5 files changed, 126 insertions(+)
 create mode 100644 include/sbi/sbi_unit.h
 create mode 100644 lib/sbi/sbi_unit.c

diff --git a/include/sbi/sbi_unit.h b/include/sbi/sbi_unit.h
new file mode 100644
index 0000000..685e58d
--- /dev/null
+++ b/include/sbi/sbi_unit.h
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#ifndef __SBI_UNIT_H__
+#define __SBI_UNIT_H__
+
+extern struct sbiunit_test_suite *__start_sbiunit_test_suites;
+extern struct sbiunit_test_suite *__end_sbiunit_test_suites;
+
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_string.h>
+
+#define _CONCAT(a, b) a ## b
+#define CONCAT(a, b) _CONCAT(a, b)
+
+struct sbiunit_test_case {
+	char *name;
+	bool should_run;
+	bool result;
+	void (*test_func)(struct sbiunit_test_case *test);
+	void (*onerr)(struct sbiunit_test_case *test);
+};
+
+struct sbiunit_test_suite {
+	struct sbiunit_test_case *cases;
+	const char *name;
+};
+
+#define SBIUNIT_TEST_CASE(func)	\
+	{ .name = #func, .should_run = 1, .result = 0, .test_func = &func }
+
+#define SBIUNIT_TEST_SUITE(suite_name, cases_arr) \
+	struct sbiunit_test_suite suite_name = { .name = #suite_name, .cases = cases_arr }
+
+#define SBIUNIT_INFO(test, msg) sbi_printf("%s: %s", test->name, msg)
+
+#define SBIUNIT_EXPECT(test, cond) do {							\
+	if (!(cond)) {									\
+		test->result = 0;							\
+		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
+	}										\
+} while (0)
+
+#define SBIUNIT_ASSERT(test, cond) do {						\
+	if (!(cond)) {								\
+		test->result = 0;						\
+		SBIUNIT_INFO(test, "Condition \"" #cond "\" must be true!\n");	\
+		return;								\
+	}									\
+} while (0)
+
+#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, a == b)
+#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, a == b)
+#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, a != b)
+#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, a != b)
+#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) \
+	SBIUNIT_EXPECT(test, sbi_memcmp(a, b, len) == 0)
+#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) \
+	SBIUNIT_ASSERT(test, sbi_memcmp(a, b, len) == 0)
+#define SBIUNIT_EXPECT_STREQ(test, a, b) \
+	SBIUNIT_EXPECT(test, sbi_strcmp(a, b) == 0)
+#define SBIUNIT_ASSERT_STREQ(test, a, b) \
+	SBIUNIT_ASSERT(test, sbi_strcmp(a, b) == 0)
+
+void run_all_tests(void);
+#endif
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index 81dd2db..e3038ee 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
 	bool "Debug Trigger Extension"
 	default y
 
+config SBIUNIT
+	bool "Enable SBIUNIT tests"
+	default n
+
 endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 0a50e95..0a2318b 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -11,6 +11,7 @@ libsbi-objs-y += riscv_asm.o
 libsbi-objs-y += riscv_atomic.o
 libsbi-objs-y += riscv_hardfp.o
 libsbi-objs-y += riscv_locks.o
+libsbi-objs-y += sbi_unit.o
 
 libsbi-objs-y += sbi_ecall.o
 libsbi-objs-y += sbi_ecall_exts.o
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 804b01c..16d0a00 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -30,6 +30,10 @@
 #include <sbi/sbi_tlb.h>
 #include <sbi/sbi_version.h>
 
+#ifdef CONFIG_SBIUNIT
+#include <sbi/sbi_unit.h>
+#endif
+
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
 	"  / __ \\                  / ____|  _ \\_   _|\n"  \
@@ -398,6 +402,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 
 	sbi_boot_print_hart(scratch, hartid);
 
+#ifdef CONFIG_SBIUNIT
+	run_all_tests();
+#endif
+
 	/*
 	 * Configure PMP at last because if SMEPMP is detected,
 	 * M-mode access to the S/U space will be rescinded.
diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
new file mode 100644
index 0000000..9c7efec
--- /dev/null
+++ b/lib/sbi/sbi_unit.c
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_unit.h>
+#include <sbi/sbi_console.h>
+
+static struct sbiunit_test_suite *test_suites[] = {
+};
+
+static void run_test_suite(struct sbiunit_test_suite *suite)
+{
+	struct sbiunit_test_case *s_case;
+	u32 count_pass, count_fail;
+
+	sbi_printf("## Running test suite: %s\n", suite->name);
+	count_pass = 0;
+	count_fail = 0;
+
+	s_case = suite->cases;
+	while (s_case->should_run) {
+		s_case->result = 1;
+		s_case->test_func(s_case);
+		if (s_case->result)
+			count_pass++;
+		else
+			count_fail++;
+		sbi_printf("[%s] %s\n", s_case->result ? "OK" : "FAIL", s_case->name);
+		s_case++;
+	}
+	sbi_printf("%u SUCCESS / %u FAIL / %u TOTAL\n", count_pass, count_fail,
+		   count_pass + count_fail);
+}
+
+void run_all_tests(void)
+{
+	u32 i;
+
+	sbi_printf("\n# Running SBIUNIT tests #\n");
+
+	for (i = 0; i < sizeof(test_suites) / sizeof(test_suites[0]); i++)
+		run_test_suite(test_suites[i]);
+}
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb  8 01:50:49 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu,  8 Feb 2024 09:50:49 +0000
Subject: [PATCH 3/4] lib: tests: Add a test for sbi_bitmap
In-Reply-To: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
Message-ID: <20240208095050.398522-3-ivan.orlov0322@gmail.com>

Add test suite covering all of the functions from lib/sbi/sbi_bitmap.c:
__bitmap_and, __bitmap_or and __bitmap_xor.

This patch depends on the previous patches in this series as it uses
SBIUnit macros, functions and definitions

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
 lib/sbi/objects.mk        |   2 +
 lib/sbi/sbi_bitmap_test.c | 104 ++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_unit.c        |   2 +
 3 files changed, 108 insertions(+)
 create mode 100644 lib/sbi/sbi_bitmap_test.c

diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 0a2318b..b29e63f 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -56,6 +56,8 @@ libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_DBTR) += ecall_dbtr
 libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
 
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
+
 libsbi-objs-y += sbi_bitmap.o
 libsbi-objs-y += sbi_bitops.o
 libsbi-objs-y += sbi_console.o
diff --git a/lib/sbi/sbi_bitmap_test.c b/lib/sbi/sbi_bitmap_test.c
new file mode 100644
index 0000000..0fd0091
--- /dev/null
+++ b/lib/sbi/sbi_bitmap_test.c
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_bitmap.h>
+#include <sbi/sbi_unit.h>
+#include <sbi/sbi_console.h>
+
+static u64 data_a[] = { 0xDEADBEEF, 0x00BAB10C, 0x1BADB002, 0xABADBABE };
+static u64 data_b[] = { 0xC00010FF, 0x00BAB10C, 0xBAAAAAAD, 0xBADDCAFE };
+static u64 data_zero[] = { 0, 0, 0, 0 };
+
+
+#define DATA_SIZE sizeof(data_zero)
+#define DATA_BIT_SIZE (DATA_SIZE * 8)
+
+static void bitmap_and_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_and_b[] = { 0xDEADBEEF & 0xC00010FF, 0x00BAB10C & 0x00BAB10C,
+			  0x1BADB002 & 0xBAAAAAAD, 0xABADBABE & 0xBADDCAFE };
+
+	__bitmap_and(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_and_b, DATA_SIZE);
+
+	// a & a = a
+	__bitmap_and(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_ASSERT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	// a & 0 = 0
+	__bitmap_and(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	// 0 & 0 = 0
+	__bitmap_and(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	// Cover zero 'bits' argument
+	__bitmap_and(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static void bitmap_or_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_or_b[] = { 0xDEADBEEF | 0xC00010FF, 0x00BAB10C | 0x00BAB10C,
+		       0x1BADB002 | 0xBAAAAAAD, 0xABADBABE | 0xBADDCAFE };
+
+	__bitmap_or(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_or_b, DATA_SIZE);
+
+	// a | a = a
+	__bitmap_or(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	// a | 0 = a
+	__bitmap_or(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	// 0 | 0 = 0
+	__bitmap_or(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	__bitmap_or(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static void bitmap_xor_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_xor_b[] = { 0xDEADBEEF ^ 0xC00010FF, 0x00BAB10C ^ 0x00BAB10C,
+			  0x1BADB002 ^ 0xBAAAAAAD, 0xABADBABE ^ 0xBADDCAFE };
+
+	__bitmap_xor(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_xor_b, DATA_SIZE);
+
+	// a ^ 0 = a
+	__bitmap_xor(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	// a ^ a = 0
+	__bitmap_xor(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	// 0 ^ 0 = 0
+	__bitmap_xor(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	__bitmap_xor(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static struct sbiunit_test_case bitmap_test_cases[] = {
+	SBIUNIT_TEST_CASE(bitmap_and_test),
+	SBIUNIT_TEST_CASE(bitmap_or_test),
+	SBIUNIT_TEST_CASE(bitmap_xor_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(bitmap_test_suite, bitmap_test_cases);
diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
index 9c7efec..2d3da7f 100644
--- a/lib/sbi/sbi_unit.c
+++ b/lib/sbi/sbi_unit.c
@@ -6,7 +6,9 @@
 #include <sbi/sbi_unit.h>
 #include <sbi/sbi_console.h>
 
+extern struct sbiunit_test_suite bitmap_test_suite;
 static struct sbiunit_test_suite *test_suites[] = {
+	&bitmap_test_suite,
 };
 
 static void run_test_suite(struct sbiunit_test_suite *suite)
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb  8 01:50:50 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu,  8 Feb 2024 09:50:50 +0000
Subject: [PATCH 4/4] lib: tests: Add sbi_console test
In-Reply-To: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
Message-ID: <20240208095050.398522-4-ivan.orlov0322@gmail.com>

Add the test suite covering some of the functions from
lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
of format specifiers for printf and different strings and characters for
putc and puts.

In order to do that, the test "mocks" the sbi_console_device structure
by setting the 'console_dev' variable to the virtual console.

This patch depends on the previous patches from the series as it uses
SBIUnit macros, functions and definitions.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
 lib/sbi/sbi_console.c      |   4 ++
 lib/sbi/sbi_console_test.c | 104 +++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_unit.c         |   2 +
 3 files changed, 110 insertions(+)
 create mode 100644 lib/sbi/sbi_console_test.c

diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
index ab09a5c..d1229d0 100644
--- a/lib/sbi/sbi_console.c
+++ b/lib/sbi/sbi_console.c
@@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
 
 	return rc;
 }
+
+#ifdef CONFIG_SBIUNIT
+#include "sbi_console_test.c"
+#endif
diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
new file mode 100644
index 0000000..8c3b215
--- /dev/null
+++ b/lib/sbi/sbi_console_test.c
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_unit.h>
+#include <sbi/sbi_heap.h>
+
+/*
+ * Console functions are wrapped in order to mock the console object and don't affect the actual
+ * console output
+ */
+#define CONSOLE_DO(action) ({		\
+	old_dev = console_dev;		\
+	console_dev = &new_dev;		\
+	action;				\
+	console_dev = old_dev;		\
+})
+
+// We are using a GCC extension here, which allows us to return a value from a block
+#define CONSOLE_DO_RET(action) ({	\
+	old_dev = console_dev;		\
+	console_dev = &new_dev;		\
+	u64 res = action;		\
+	console_dev = old_dev;		\
+	res;				\
+})
+
+#define BUF_LEN 1024
+
+static const struct sbi_console_device *old_dev;
+
+static char buf[BUF_LEN];
+static u32 pos;
+static void test_console_putc(char c)
+{
+	buf[pos] = c;
+	pos = (pos + 1) % BUF_LEN;
+}
+
+static void clear_buf(void)
+{
+	pos = 0;
+	sbi_memset(buf, 0, BUF_LEN);
+}
+
+// Mocking the console
+static const struct sbi_console_device new_dev = {
+	.name = "Test console device",
+	.console_putc = test_console_putc,
+};
+
+static void putc_test(struct sbiunit_test_case *test)
+{
+	clear_buf();
+
+	CONSOLE_DO(sbi_putc('a'));
+	SBIUNIT_ASSERT_EQ(test, buf[0], 'a');
+}
+
+#define PUTS_TEST(test, expected, param) do {				\
+	clear_buf();							\
+	CONSOLE_DO(sbi_puts(param));					\
+	SBIUNIT_ASSERT_STREQ(test, buf, expected);			\
+} while (0)
+
+static void puts_test(struct sbiunit_test_case *test)
+{
+	PUTS_TEST(test, "Hello, OpenSBI!", "Hello, OpenSBI!");
+	PUTS_TEST(test, "Hello,\r\nOpenSBI!", "Hello,\nOpenSBI!");
+	PUTS_TEST(test, "Hello,", "Hello,\0OpenSBI!");
+}
+
+#define PRINTF_TEST(test, expected, format, ...) do {					\
+	clear_buf();									\
+	SBIUNIT_ASSERT_EQ(test, CONSOLE_DO_RET(sbi_printf(format, ##__VA_ARGS__)),	\
+			  sbi_strlen(expected));					\
+	SBIUNIT_ASSERT_STREQ(test, buf, expected);					\
+} while (0)
+
+static void printf_test(struct sbiunit_test_case *test)
+{
+	PRINTF_TEST(test, "Hello", "Hello");
+	PRINTF_TEST(test, "3 5 7", "%d %d %d", 3, 5, 7);
+	PRINTF_TEST(test, "Hello", "%s", "Hello");
+	PRINTF_TEST(test, "-1", "%d", -1);
+	PRINTF_TEST(test, "FF", "%X", 255);
+	PRINTF_TEST(test, "ff", "%x", 255);
+	PRINTF_TEST(test, "A", "%c", 'A');
+	PRINTF_TEST(test, "1fe", "%p", (void *)0x1fe);
+	PRINTF_TEST(test, "4294967295", "%u", 4294967295U);
+	PRINTF_TEST(test, "-2147483647", "%ld", -2147483647l);
+	PRINTF_TEST(test, "-9223372036854775807", "%lld", -9223372036854775807LL);
+	PRINTF_TEST(test, "18446744073709551615", "%llu", 18446744073709551615ULL);
+}
+
+static struct sbiunit_test_case console_test_cases[] = {
+	SBIUNIT_TEST_CASE(putc_test),
+	SBIUNIT_TEST_CASE(puts_test),
+	SBIUNIT_TEST_CASE(printf_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(console_test_suite, console_test_cases);
diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
index 2d3da7f..b2f2063 100644
--- a/lib/sbi/sbi_unit.c
+++ b/lib/sbi/sbi_unit.c
@@ -7,8 +7,10 @@
 #include <sbi/sbi_console.h>
 
 extern struct sbiunit_test_suite bitmap_test_suite;
+extern struct sbiunit_test_suite console_test_suite;
 static struct sbiunit_test_suite *test_suites[] = {
 	&bitmap_test_suite,
+	&console_test_suite,
 };
 
 static void run_test_suite(struct sbiunit_test_suite *suite)
-- 
2.34.1



From wxjstz at 126.com  Sun Feb 11 08:11:25 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:25 +0800
Subject: [PATCH v4 1/8] firmware: remove copy-base relocation
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-2-wxjstz@126.com>

Remove copy-base relocations that are no longer needed.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 Makefile            |   8 +++-
 README.md           |   5 --
 docs/firmware/fw.md |   6 ---
 firmware/fw_base.S  | 110 ++------------------------------------------
 firmware/objects.mk |  11 -----
 5 files changed, 10 insertions(+), 130 deletions(-)

diff --git a/Makefile b/Makefile
index 680c19a..d8cffa6 100644
--- a/Makefile
+++ b/Makefile
@@ -179,6 +179,10 @@ CC_SUPPORT_STRICT_ALIGN := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib
 # Check whether the assembler and the compiler support the Zicsr and Zifencei extensions
 CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)imafd_zicsr_zifencei -x c /dev/null -o /dev/null 2>&1 | grep "zicsr\|zifencei" > /dev/null && echo n || echo y)
 
+ifneq ($(OPENSBI_LD_PIE),y)
+$(error Your linker does not support creating PIEs, opensbi requires this.)
+endif
+
 # Build Info:
 # OPENSBI_BUILD_TIME_STAMP -- the compilation time stamp
 # OPENSBI_BUILD_COMPILER_VERSION -- the compiler version info
@@ -356,7 +360,7 @@ CFLAGS		+=	-mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
 CFLAGS		+=	$(RELAX_FLAG)
 CFLAGS		+=	$(GENFLAGS)
 CFLAGS		+=	$(platform-cflags-y)
-CFLAGS		+=	-fno-pie -no-pie
+CFLAGS		+=	-fPIE -pie
 CFLAGS		+=	$(firmware-cflags-y)
 
 CPPFLAGS	+=	$(GENFLAGS)
@@ -365,6 +369,7 @@ CPPFLAGS	+=	$(firmware-cppflags-y)
 
 ASFLAGS		=	-g -Wall -nostdlib
 ASFLAGS		+=	-fno-omit-frame-pointer -fno-optimize-sibling-calls
+ASFLAGS		+=	-fpic
 # Optionally supported flags
 ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
 ASFLAGS		+=	-mno-save-restore
@@ -391,6 +396,7 @@ ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y)
 ELFFLAGS	+=	-Wl,--exclude-libs,ALL
 endif
 ELFFLAGS	+=	-Wl,--build-id=none
+ELFFLAGS	+=	-Wl,--no-dynamic-linker -Wl,-pie
 ELFFLAGS	+=	$(platform-ldflags-y)
 ELFFLAGS	+=	$(firmware-ldflags-y)
 
diff --git a/README.md b/README.md
index 73de8ea..7a24801 100644
--- a/README.md
+++ b/README.md
@@ -274,11 +274,6 @@ make CC=riscv64-linux-gnu-gcc LLVM=1
 These variables must be passed for all the make invocations described in this
 document.
 
-NOTE: Using Clang with a `riscv*-linux-gnu` GNU binutils linker has been seen
-to produce broken binaries with missing relocations; it is therefore currently
-recommended that this combination be avoided or *FW_PIC=n* be used to disable
-building OpenSBI as a position-independent binary.
-
 Building with timestamp and compiler info
 -----------------------------------------
 
diff --git a/docs/firmware/fw.md b/docs/firmware/fw.md
index 38351c8..2f4deb5 100644
--- a/docs/firmware/fw.md
+++ b/docs/firmware/fw.md
@@ -69,12 +69,6 @@ parameters:
   argument by the prior booting stage.
 * **FW_FDT_PADDING** - Optional zero bytes padding to the embedded flattened
   device tree binary file specified by **FW_FDT_PATH** option.
-* **FW_PIC** - "FW_PIC=y" generates position independent executable firmware
-  images. OpenSBI can run at arbitrary address with appropriate alignment.
-  Therefore, the original relocation mechanism ("FW_PIC=n") will be skipped.
-  In other words, OpenSBI will directly run at the load address without any
-  code movement. This option requires a toolchain with PIE support, and it
-  is on by default.
 
 Additionally, each firmware type as a set of type specific configuration
 parameters. Detailed information for each firmware type can be found in the
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 09894e6..cd94f15 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -14,8 +14,7 @@
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_trap.h>
 
-#define BOOT_STATUS_RELOCATE_DONE	1
-#define BOOT_STATUS_BOOT_HART_DONE	2
+#define BOOT_STATUS_BOOT_HART_DONE	1
 
 .macro	MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
 	add	\__d0, \__s0, zero
@@ -31,16 +30,6 @@
 	add	\__d4, \__s4, zero
 .endm
 
-/*
- * If __start_reg <= __check_reg and __check_reg < __end_reg then
- *   jump to __pass
- */
-.macro BRANGE __start_reg, __end_reg, __check_reg, __jump_lable
-	blt	\__check_reg, \__start_reg, 999f
-	bge	\__check_reg, \__end_reg, 999f
-	j	\__jump_lable
-999:
-.endm
 
 	.section .entry, "ax", %progbits
 	.align 3
@@ -55,20 +44,19 @@ _start:
 	li	a7, -1
 	beq	a6, a7, _try_lottery
 	/* Jump to relocation wait loop if we are not boot hart */
-	bne	a0, a6, _wait_relocate_copy_done
+	bne	a0, a6, _wait_for_boot_hart
 _try_lottery:
 	/* Jump to relocation wait loop if we don't get relocation lottery */
 	lla	a6, _relocate_lottery
 	li	a7, 1
 	amoadd.w a6, a7, (a6)
-	bnez	a6, _wait_relocate_copy_done
+	bnez	a6, _wait_for_boot_hart
 
 	/* Save load address */
 	lla	t0, _load_start
 	lla	t1, _fw_start
 	REG_S	t1, 0(t0)
 
-#ifdef FW_PIC
 	/* relocate the global table content */
 	lla	t0, _link_start
 	REG_L	t0, 0(t0)
@@ -90,100 +78,8 @@ _try_lottery:
 3:
 	addi	t0, t0, (REGBYTES * 3)
 	blt	t0, t1, 2b
-	j	_relocate_done
-_wait_relocate_copy_done:
-	j	_wait_for_boot_hart
-#else
-	/* Relocate if load address != link address */
-_relocate:
-	lla	t0, _link_start
-	REG_L	t0, 0(t0)
-	lla	t1, _link_end
-	REG_L	t1, 0(t1)
-	lla	t2, _load_start
-	REG_L	t2, 0(t2)
-	beq	t0, t2, _relocate_done
-	sub	t3, t1, t0
-	add	t3, t3, t2
-	lla	t4, _relocate_done
-	sub	t4, t4, t2
-	add	t4, t4, t0
-	blt	t2, t0, _relocate_copy_to_upper
-_relocate_copy_to_lower:
-	ble	t1, t2, _relocate_copy_to_lower_loop
-	lla	t3, _relocate_lottery
-	BRANGE	t2, t1, t3, _start_hang
-	lla	t3, _boot_status
-	BRANGE	t2, t1, t3, _start_hang
-	lla	t3, _relocate
-	lla	t5, _relocate_done
-	BRANGE	t2, t1, t3, _start_hang
-	BRANGE	t2, t1, t5, _start_hang
-	BRANGE  t3, t5, t2, _start_hang
-_relocate_copy_to_lower_loop:
-	REG_L	t3, 0(t2)
-	REG_S	t3, 0(t0)
-	add	t0, t0, __SIZEOF_POINTER__
-	add	t2, t2, __SIZEOF_POINTER__
-	blt	t0, t1, _relocate_copy_to_lower_loop
-	jr	t4
-_relocate_copy_to_upper:
-	ble	t3, t0, _relocate_copy_to_upper_loop
-	lla	t2, _relocate_lottery
-	BRANGE	t0, t3, t2, _start_hang
-	lla	t2, _boot_status
-	BRANGE	t0, t3, t2, _start_hang
-	lla	t2, _relocate
-	lla	t5, _relocate_done
-	BRANGE	t0, t3, t2, _start_hang
-	BRANGE	t0, t3, t5, _start_hang
-	BRANGE	t2, t5, t0, _start_hang
-_relocate_copy_to_upper_loop:
-	add	t3, t3, -__SIZEOF_POINTER__
-	add	t1, t1, -__SIZEOF_POINTER__
-	REG_L	t2, 0(t3)
-	REG_S	t2, 0(t1)
-	blt	t0, t1, _relocate_copy_to_upper_loop
-	jr	t4
-_wait_relocate_copy_done:
-	lla	t0, _fw_start
-	lla	t1, _link_start
-	REG_L	t1, 0(t1)
-	beq	t0, t1, _wait_for_boot_hart
-	lla	t2, _boot_status
-	lla	t3, _wait_for_boot_hart
-	sub	t3, t3, t0
-	add	t3, t3, t1
-1:
-	/* waitting for relocate copy done (_boot_status == 1) */
-	li	t4, BOOT_STATUS_RELOCATE_DONE
-	REG_L	t5, 0(t2)
-	/* Reduce the bus traffic so that boot hart may proceed faster */
-	nop
-	nop
-	nop
-	bgt     t4, t5, 1b
-	jr	t3
-#endif
 _relocate_done:
 
-	/*
-	 * Mark relocate copy done
-	 * Use _boot_status copy relative to the load address
-	 */
-	lla	t0, _boot_status
-#ifndef FW_PIC
-	lla	t1, _link_start
-	REG_L	t1, 0(t1)
-	lla	t2, _load_start
-	REG_L	t2, 0(t2)
-	sub	t0, t0, t1
-	add	t0, t0, t2
-#endif
-	li	t1, BOOT_STATUS_RELOCATE_DONE
-	REG_S	t1, 0(t0)
-	fence	rw, rw
-
 	/* At this point we are running from link address */
 
 	/* Reset all registers except ra, a0, a1 and a2 for boot HART */
diff --git a/firmware/objects.mk b/firmware/objects.mk
index a1704c4..b2ace75 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -13,17 +13,6 @@ firmware-cflags-y +=
 firmware-asflags-y +=
 firmware-ldflags-y +=
 
-ifndef FW_PIC
-FW_PIC := $(OPENSBI_LD_PIE)
-endif
-
-ifeq ($(FW_PIC),y)
-firmware-genflags-y +=	-DFW_PIC
-firmware-asflags-y  +=	-fpic
-firmware-cflags-y   +=	-fPIE -pie
-firmware-ldflags-y  +=	-Wl,--no-dynamic-linker -Wl,-pie
-endif
-
 ifdef FW_TEXT_START
 firmware-genflags-y += -DFW_TEXT_START=$(FW_TEXT_START)
 endif
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:24 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:24 +0800
Subject: [PATCH v4 0/8] Improvements to fw_base.S
Message-ID: <20240211161138.2538981-1-wxjstz@126.com>

v4 changes:
- add patch2/patch6/patch7
- add patch1 according to anup suggestion
- update patch5 according to anup suggestion
- move fw_coldboot_init out of libsbi.a

Xiang W (8):
  firmware: remove copy-base relocation
  firmware: fw_base.S: Simplify address get
  firmware: fw_base: Simplified setup trap handler
  firmware: fw_dynamic.S: Remove _bad_dynamic_info
  firmware: fw_base.S: Remove _relocate_lottery
  firmware: fw_base.S: fix _reset_regs
  firmware: Improve fw_boot_hart
  firmware: Use C if possible

 Makefile                |  18 +-
 README.md               |   5 -
 docs/firmware/fw.md     |   6 -
 firmware/fw.c           | 101 +++++++++++
 firmware/fw_base.S      | 369 ++--------------------------------------
 firmware/fw_dynamic.S   |  55 +++---
 firmware/fw_jump.S      |  31 ++--
 firmware/fw_payload.S   |  31 ++--
 firmware/objects.mk     |  13 +-
 include/sbi/sbi_types.h |   1 +
 10 files changed, 182 insertions(+), 448 deletions(-)
 create mode 100644 firmware/fw.c

-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:30 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:30 +0800
Subject: [PATCH v4 6/8] firmware: fw_base.S: fix _reset_regs
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-7-wxjstz@126.com>

a3 and a4 cannot be reset because used in fw_platform_init.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 firmware/fw_base.S | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 10fee4f..30fd616 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -77,7 +77,7 @@ _relocate_done:
 
 	/* At this point we are running from link address */
 
-	/* Reset all registers except ra, a0, a1 and a2 for boot HART */
+	/* Reset all registers except ra, a0, a1, a2, a3 and a4 for boot HART */
 	li	ra, 0
 	call	_reset_regs
 
@@ -304,7 +304,7 @@ _wait_for_boot_hart:
 	bne	t0, t1, _wait_for_boot_hart
 
 _start_warm:
-	/* Reset all registers except ra, a0, a1 and a2 for non-boot HARTs */
+	/* Reset all registers except ra, a0, a1, a2, a3 and a4 for non-boot HART */
 	li	ra, 0
 	call	_reset_regs
 
@@ -655,7 +655,7 @@ _reset_regs:
 
 	/* flush the instruction cache */
 	fence.i
-	/* Reset all registers except ra, a0, a1 and a2 */
+	/* Reset all registers except ra, a0, a1, a2, a3 and a4 */
 	li sp, 0
 	li gp, 0
 	li tp, 0
@@ -664,8 +664,6 @@ _reset_regs:
 	li t2, 0
 	li s0, 0
 	li s1, 0
-	li a3, 0
-	li a4, 0
 	li a5, 0
 	li a6, 0
 	li a7, 0
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:27 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:27 +0800
Subject: [PATCH v4 3/8] firmware: fw_base: Simplified setup trap handler
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-4-wxjstz@126.com>

The same detection was done twice when setting mtvec and trap_exit.
Merging can reduce code size.

Signed-off-by: Xiang W <wxjstz at 126.com>
Reviewed-by: Anup Patel <anup at brainfault.org>
---
 firmware/fw_base.S | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index d418041..f0dd0da 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -362,22 +362,14 @@ _start_warm:
 	srli	a5, a5, ('H' - 'A')
 	andi	a5, a5, 0x1
 	beq	a5, zero, _skip_trap_handler_rv32_hyp
-	lla	a4, _trap_handler_rv32_hyp
-_skip_trap_handler_rv32_hyp:
-#endif
-	csrw	CSR_MTVEC, a4
-
-#if __riscv_xlen == 32
 	/* Override trap exit for H-extension */
-	csrr	a5, CSR_MISA
-	srli	a5, a5, ('H' - 'A')
-	andi	a5, a5, 0x1
-	beq	a5, zero, _skip_trap_exit_rv32_hyp
-	lla	a4, _trap_exit_rv32_hyp
 	csrr	a5, CSR_MSCRATCH
+	lla	a4, _trap_exit_rv32_hyp
 	REG_S	a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(a5)
-_skip_trap_exit_rv32_hyp:
+	lla	a4, _trap_handler_rv32_hyp
+_skip_trap_handler_rv32_hyp:
 #endif
+	csrw	CSR_MTVEC, a4
 
 	/* Initialize SBI runtime */
 	csrr	a0, CSR_MSCRATCH
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:26 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:26 +0800
Subject: [PATCH v4 2/8] firmware: fw_base.S: Simplify address get
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-3-wxjstz@126.com>

Simplify address get. Remove _link_start _link_end _load_start.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 firmware/fw_base.S | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index cd94f15..d418041 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -52,15 +52,9 @@ _try_lottery:
 	amoadd.w a6, a7, (a6)
 	bnez	a6, _wait_for_boot_hart
 
-	/* Save load address */
-	lla	t0, _load_start
-	lla	t1, _fw_start
-	REG_S	t1, 0(t0)
-
 	/* relocate the global table content */
-	lla	t0, _link_start
-	REG_L	t0, 0(t0)
-	/* t1 shall has the address of _fw_start */
+	li	t0, FW_TEXT_START
+	lla	t1, _fw_start
 	sub	t2, t1, t0
 	lla	t0, __rel_dyn_start
 	lla	t1, __rel_dyn_end
@@ -398,12 +392,6 @@ _relocate_lottery:
 	RISCV_PTR	0
 _boot_status:
 	RISCV_PTR	0
-_load_start:
-	RISCV_PTR	_fw_start
-_link_start:
-	RISCV_PTR	FW_TEXT_START
-_link_end:
-	RISCV_PTR	_fw_reloc_end
 
 	.section .entry, "ax", %progbits
 	.align 3
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:31 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:31 +0800
Subject: [PATCH v4 7/8] firmware: Improve fw_boot_hart
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-8-wxjstz@126.com>

Improve fw_boot_hart to reduce parameter saving and restoration.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 firmware/fw_base.S    |  7 ++-----
 firmware/fw_dynamic.S | 24 ++++++++++++------------
 firmware/fw_jump.S    |  6 +++---
 firmware/fw_payload.S |  6 +++---
 4 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 30fd616..4de053f 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -38,14 +38,11 @@
 	.globl _start_warm
 _start:
 	/* Find preferred boot HART id */
-	MOV_3R	s0, a0, s1, a1, s2, a2
 	call	fw_boot_hart
-	add	a6, a0, zero
-	MOV_3R	a0, s0, a1, s1, a2, s2
 	li	a7, -1
-	beq	a6, a7, _try_lottery
+	beq	t0, a7, _try_lottery
 	/* Jump to relocation wait loop if we are not boot hart */
-	bne	a0, a6, _wait_for_boot_hart
+	bne	a0, t0, _wait_for_boot_hart
 _try_lottery:
 	/* Jump to relocation wait loop if we don't get relocation lottery */
 	lla	a6, _boot_status
diff --git a/firmware/fw_dynamic.S b/firmware/fw_dynamic.S
index 5ee2883..52ef320 100644
--- a/firmware/fw_dynamic.S
+++ b/firmware/fw_dynamic.S
@@ -17,24 +17,24 @@
 	/*
 	 * This function is called very early even before
 	 * fw_save_info() is called.
-	 * We can only use a0, a1, and a2 registers here.
-	 * The boot HART id should be returned in 'a0'.
+	 * We can only use t0, t1, and t2 registers here.
+	 * The boot HART id should be returned in 't0'.
 	 */
 fw_boot_hart:
 	/* Sanity checks */
-	li	a1, FW_DYNAMIC_INFO_MAGIC_VALUE
-	REG_L	a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
-	bne	a0, a1, _start_hang
-	li	a1, FW_DYNAMIC_INFO_VERSION_MAX
-	REG_L	a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
-	bgt	a0, a1, _start_hang
+	li	t1, FW_DYNAMIC_INFO_MAGIC_VALUE
+	REG_L	t0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
+	bne	t0, t1, _start_hang
+	li	t1, FW_DYNAMIC_INFO_VERSION_MAX
+	REG_L	t0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
+	bgt	t0, t1, _start_hang
 
 	/* Read boot HART id */
-	li	a1, FW_DYNAMIC_INFO_VERSION_2
-	blt	a0, a1, 2f
-	REG_L	a0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
+	li	t1, FW_DYNAMIC_INFO_VERSION_2
+	blt	t0, t1, 2f
+	REG_L	t0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
 	ret
-2:	li	a0, -1
+2:	li	t0, -1
 	ret
 
 	.section .entry, "ax", %progbits
diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
index ac74dc6..1775fcd 100644
--- a/firmware/fw_jump.S
+++ b/firmware/fw_jump.S
@@ -15,11 +15,11 @@
 	/*
 	 * This function is called very early even before
 	 * fw_save_info() is called.
-	 * We can only use a0, a1, and a2 registers here.
-	 * The boot HART id should be returned in 'a0'.
+	 * We can only use t0, t1, and t2 registers here.
+	 * The boot HART id should be returned in 't0'.
 	 */
 fw_boot_hart:
-	li	a0, -1
+	li	t0, -1
 	ret
 
 	.section .entry, "ax", %progbits
diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
index c53a3bb..985f833 100644
--- a/firmware/fw_payload.S
+++ b/firmware/fw_payload.S
@@ -15,11 +15,11 @@
 	/*
 	 * This function is called very early even before
 	 * fw_save_info() is called.
-	 * We can only use a0, a1, and a2 registers here.
-	 * The boot HART id should be returned in 'a0'.
+	 * We can only use t0, t1, and t2 registers here.
+	 * The boot HART id should be returned in 't0'.
 	 */
 fw_boot_hart:
-	li	a0, -1
+	li	t0, -1
 	ret
 
 	.section .entry, "ax", %progbits
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:29 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:29 +0800
Subject: [PATCH v4 5/8] firmware: fw_base.S: Remove _relocate_lottery
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-6-wxjstz@126.com>

Remove _relocate_lottery and use _boot_status instead

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 firmware/fw_base.S | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index f0dd0da..10fee4f 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -14,7 +14,8 @@
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_trap.h>
 
-#define BOOT_STATUS_BOOT_HART_DONE	1
+#define BOOT_STATUS_LOTTERY_DONE	1
+#define BOOT_STATUS_BOOT_HART_DONE	2
 
 .macro	MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
 	add	\__d0, \__s0, zero
@@ -47,8 +48,8 @@ _start:
 	bne	a0, a6, _wait_for_boot_hart
 _try_lottery:
 	/* Jump to relocation wait loop if we don't get relocation lottery */
-	lla	a6, _relocate_lottery
-	li	a7, 1
+	lla	a6, _boot_status
+	li	a7, BOOT_STATUS_LOTTERY_DONE
 	amoadd.w a6, a7, (a6)
 	bnez	a6, _wait_for_boot_hart
 
@@ -380,8 +381,6 @@ _skip_trap_handler_rv32_hyp:
 
 	.data
 	.align 3
-_relocate_lottery:
-	RISCV_PTR	0
 _boot_status:
 	RISCV_PTR	0
 
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:28 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:28 +0800
Subject: [PATCH v4 4/8] firmware: fw_dynamic.S: Remove _bad_dynamic_info
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-5-wxjstz@126.com>

_bad_dynamic_info is same as _start_hang, so remove it.

Signed-off-by: Xiang W <wxjstz at 126.com>
Reviewed-by: Anup Patel <anup at brainfault.org>
---
 firmware/fw_dynamic.S | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/firmware/fw_dynamic.S b/firmware/fw_dynamic.S
index 7ff1c6a..5ee2883 100644
--- a/firmware/fw_dynamic.S
+++ b/firmware/fw_dynamic.S
@@ -11,12 +11,6 @@
 
 #include "fw_base.S"
 
-	.section .entry, "ax", %progbits
-	.align 3
-_bad_dynamic_info:
-	wfi
-	j	_bad_dynamic_info
-
 	.section .entry, "ax", %progbits
 	.align 3
 	.global fw_boot_hart
@@ -30,10 +24,10 @@ fw_boot_hart:
 	/* Sanity checks */
 	li	a1, FW_DYNAMIC_INFO_MAGIC_VALUE
 	REG_L	a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
-	bne	a0, a1, _bad_dynamic_info
+	bne	a0, a1, _start_hang
 	li	a1, FW_DYNAMIC_INFO_VERSION_MAX
 	REG_L	a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
-	bgt	a0, a1, _bad_dynamic_info
+	bgt	a0, a1, _start_hang
 
 	/* Read boot HART id */
 	li	a1, FW_DYNAMIC_INFO_VERSION_2
-- 
2.43.0



From wxjstz at 126.com  Sun Feb 11 08:11:32 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 12 Feb 2024 00:11:32 +0800
Subject: [PATCH v4 8/8] firmware: Use C if possible
In-Reply-To: <20240211161138.2538981-1-wxjstz@126.com>
References: <20240211161138.2538981-1-wxjstz@126.com>
Message-ID: <20240211161138.2538981-9-wxjstz@126.com>

Use C as soon as possible after setting up the stack.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 Makefile                |  10 +-
 firmware/fw.c           | 101 +++++++++++++++++++
 firmware/fw_base.S      | 209 +---------------------------------------
 firmware/fw_dynamic.S   |  25 ++---
 firmware/fw_jump.S      |  25 ++---
 firmware/fw_payload.S   |  25 ++---
 firmware/objects.mk     |   2 +
 include/sbi/sbi_types.h |   1 +
 8 files changed, 142 insertions(+), 256 deletions(-)
 create mode 100644 firmware/fw.c

diff --git a/Makefile b/Makefile
index d8cffa6..dfd2554 100644
--- a/Makefile
+++ b/Makefile
@@ -257,13 +257,14 @@ platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(platform_build_dir)/$(ob
 firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(platform_build_dir)/firmware/$(bin))
 endif
 firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf)
-firmware-objs-path-y=$(firmware-bins-path-y:.bin=.o)
+firmware-objs-path-y=$(foreach obj,$(firmware-objs-y),$(platform_build_dir)/firmware/$(obj))
 
 # Setup list of deps files for objects
 deps-y=$(platform-objs-path-y:.o=.dep)
 deps-y+=$(libsbi-objs-path-y:.o=.dep)
 deps-y+=$(libsbiutils-objs-path-y:.o=.dep)
 deps-y+=$(firmware-objs-path-y:.o=.dep)
+deps-y+=$(firmware-bins-path-y:.bin=.dep)
 deps-y+=$(firmware-elfs-path-y:=.dep)
 
 # Setup platform ABI, ISA and Code Model
@@ -510,6 +511,9 @@ $(build_dir)/lib/libsbi.a: $(libsbi-objs-path-y)
 $(platform_build_dir)/lib/libplatsbi.a: $(libsbi-objs-path-y) $(libsbiutils-objs-path-y) $(platform-objs-path-y)
 	$(call compile_ar,$@,$^)
 
+$(platform_build_dir)/firmware/libfw.a: $(firmware-objs-path-y)
+	$(call compile_ar,$@,$^)
+
 $(build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_CONFIG)
 	$(call compile_gen_dep,$@,.c,$< $(KCONFIG_CONFIG))
 	$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
@@ -572,8 +576,8 @@ $(platform_build_dir)/%.dtb: $(platform_src_dir)/%.dts
 $(platform_build_dir)/%.bin: $(platform_build_dir)/%.elf
 	$(call compile_objcopy,$@,$<)
 
-$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a
-	$(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a)
+$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a $(platform_build_dir)/firmware/libfw.a
+	$(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a) $(platform_build_dir)/firmware/libfw.a
 
 $(platform_build_dir)/%.dep: $(src_dir)/%.ldS $(KCONFIG_CONFIG)
 	$(call compile_cpp_dep,$@,.ld,$<)
diff --git a/firmware/fw.c b/firmware/fw.c
new file mode 100644
index 0000000..5f5ce30
--- /dev/null
+++ b/firmware/fw.c
@@ -0,0 +1,101 @@
+#include <libfdt.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_platform.h>
+
+extern struct sbi_platform platform;
+
+extern char _fw_start[];
+extern char _fw_end[];
+extern char _fw_rw_start[];
+extern char _start_warm[];
+extern char fw_fdt_bin[];
+extern char _hartid_to_scratch[];
+
+extern void fw_save_info(unsigned long arg0,
+			 unsigned long arg1,unsigned long arg2);
+extern unsigned long fw_next_arg1(void);
+extern unsigned long fw_next_addr(void);
+extern unsigned long fw_next_mode(void);
+extern unsigned long fw_options(void);
+
+__weak unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
+		unsigned long arg2, unsigned long arg3, unsigned long arg4)
+{
+	return arg1;
+}
+
+void fw_coldboot_init(unsigned long arg0, unsigned long arg1,
+		  unsigned long arg2, unsigned long arg3, unsigned long arg4)
+{
+	unsigned long top;
+	unsigned long fw_start;
+	unsigned long fw_rw_offset;
+	unsigned long fw_heap_size;
+	unsigned long fw_heap_offset;
+	unsigned long fw_size;
+	unsigned long warmboot_addr;
+	unsigned long platform_addr;
+	unsigned long hartid_to_scratch;
+	unsigned long next_addr;
+	unsigned long next_arg1;
+	unsigned long next_mode;
+	unsigned long options;
+
+	const void * fdt;
+	void *target_fdt;
+
+	fw_save_info(arg0, arg1, arg2);
+#ifdef FW_FDT_PATH
+	arg1 = (unsigned long)fw_fdt_bin;
+#endif
+
+	/* initialization platform */
+	arg1 = fw_platform_init(arg0, arg1, arg2, arg3, arg4);
+
+	/* relocate fdt */
+	fdt = (const void*)arg1;
+	target_fdt = (void*)fw_next_arg1();
+	fdt_move(fdt, target_fdt, fdt_totalsize(fdt));
+
+	/* initialization scratch for all harts */
+	next_addr = fw_next_addr();
+	next_arg1 = fw_next_arg1();
+	next_mode = fw_next_mode();
+#ifdef FW_OPTIONS
+	options = FW_OPTIONS
+#else
+	options = fw_options();
+#endif
+	top = (unsigned long)_fw_end
+		+ platform.hart_stack_size * platform.hart_count;
+	fw_start = (unsigned long)_fw_start;
+	fw_rw_offset = (unsigned long)_fw_rw_start - fw_start;
+	fw_heap_size = platform.heap_size;
+	fw_heap_offset = top - fw_start;
+	fw_size = top + fw_heap_size - fw_start;
+	warmboot_addr = (unsigned long)_start_warm;
+	platform_addr = (unsigned long)&platform;
+	hartid_to_scratch = (unsigned long)_hartid_to_scratch;
+
+	for (u32 i = 0; i < platform.hart_count; i++) {
+		struct sbi_scratch *scratch = (struct sbi_scratch *)(top
+			- i * platform.hart_stack_size - SBI_SCRATCH_SIZE);
+
+		scratch->fw_start = fw_start;
+		scratch->fw_size = fw_size;
+		scratch->fw_rw_offset = fw_rw_offset;
+		scratch->fw_heap_size = fw_heap_size;
+		scratch->fw_heap_offset = fw_heap_offset;
+		scratch->warmboot_addr = warmboot_addr;
+		scratch->platform_addr = platform_addr;
+		scratch->hartid_to_scratch = hartid_to_scratch;
+		scratch->next_addr = next_addr;
+		scratch->next_arg1 = next_arg1;
+		scratch->next_mode = next_mode;
+		scratch->options = options;
+		scratch->tmp0 = 0;
+	}
+}
+
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 4de053f..6ff93ea 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -17,21 +17,6 @@
 #define BOOT_STATUS_LOTTERY_DONE	1
 #define BOOT_STATUS_BOOT_HART_DONE	2
 
-.macro	MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
-	add	\__d0, \__s0, zero
-	add	\__d1, \__s1, zero
-	add	\__d2, \__s2, zero
-.endm
-
-.macro	MOV_5R __d0, __s0, __d1, __s1, __d2, __s2, __d3, __s3, __d4, __s4
-	add	\__d0, \__s0, zero
-	add	\__d1, \__s1, zero
-	add	\__d2, \__s2, zero
-	add	\__d3, \__s3, zero
-	add	\__d4, \__s4, zero
-.endm
-
-
 	.section .entry, "ax", %progbits
 	.align 3
 	.globl _start
@@ -95,192 +80,7 @@ _bss_zero:
 	li	s5, (SBI_SCRATCH_SIZE * 2)
 	add	sp, s4, s5
 
-	/* Allow main firmware to save info */
-	MOV_5R	s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
-	call	fw_save_info
-	MOV_5R	a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
-
-#ifdef FW_FDT_PATH
-	/* Override previous arg1 */
-	lla	a1, fw_fdt_bin
-#endif
-
-	/*
-	 * Initialize platform
-	 * Note: The a0 to a4 registers passed to the
-	 * firmware are parameters to this function.
-	 */
-	MOV_5R	s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
-	call	fw_platform_init
-	add	t0, a0, zero
-	MOV_5R	a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
-	add	a1, t0, zero
-
-	/* Preload HART details
-	 * s7 -> HART Count
-	 * s8 -> HART Stack Size
-	 * s9 -> Heap Size
-	 * s10 -> Heap Offset
-	 */
-	lla	a4, platform
-#if __riscv_xlen > 32
-	lwu	s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
-	lwu	s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
-	lwu	s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
-#else
-	lw	s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
-	lw	s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
-	lw	s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
-#endif
-
-	/* Setup scratch space for all the HARTs*/
-	lla	tp, _fw_end
-	mul	a5, s7, s8
-	add	tp, tp, a5
-	/* Setup heap base address */
-	lla	s10, _fw_start
-	sub	s10, tp, s10
-	add	tp, tp, s9
-	/* Keep a copy of tp */
-	add	t3, tp, zero
-	/* Counter */
-	li	t2, 1
-	/* hartid 0 is mandated by ISA */
-	li	t1, 0
-_scratch_init:
-	/*
-	 * The following registers hold values that are computed before
-	 * entering this block, and should remain unchanged.
-	 *
-	 * t3 -> the firmware end address
-	 * s7 -> HART count
-	 * s8 -> HART stack size
-	 * s9 -> Heap Size
-	 * s10 -> Heap Offset
-	 */
-	add	tp, t3, zero
-	sub	tp, tp, s9
-	mul	a5, s8, t1
-	sub	tp, tp, a5
-	li	a5, SBI_SCRATCH_SIZE
-	sub	tp, tp, a5
-
-	/* Initialize scratch space */
-	/* Store fw_start and fw_size in scratch space */
-	lla	a4, _fw_start
-	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	a5, _fw_rw_start
-	sub	a5, a5, a4
-	REG_S	a5, SBI_SCRATCH_FW_RW_OFFSET(tp)
-
-	/* Store fw_heap_offset and fw_heap_size in scratch space */
-	REG_S	s10, SBI_SCRATCH_FW_HEAP_OFFSET(tp)
-	REG_S	s9, SBI_SCRATCH_FW_HEAP_SIZE_OFFSET(tp)
-
-	/* Store next arg1 in scratch space */
-	MOV_3R	s0, a0, s1, a1, s2, a2
-	call	fw_next_arg1
-	REG_S	a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
-	MOV_3R	a0, s0, a1, s1, a2, s2
-	/* Store next address in scratch space */
-	MOV_3R	s0, a0, s1, a1, s2, a2
-	call	fw_next_addr
-	REG_S	a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
-	MOV_3R	a0, s0, a1, s1, a2, s2
-	/* Store next mode in scratch space */
-	MOV_3R	s0, a0, s1, a1, s2, a2
-	call	fw_next_mode
-	REG_S	a0, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
-	MOV_3R	a0, s0, a1, s1, a2, s2
-	/* Store warm_boot address in scratch space */
-	lla	a4, _start_warm
-	REG_S	a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
-	/* Store platform address in scratch space */
-	lla	a4, platform
-	REG_S	a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
-	/* Store hartid-to-scratch function address in scratch space */
-	lla	a4, _hartid_to_scratch
-	REG_S	a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
-	/* Store trap-exit function address in scratch space */
-	lla	a4, _trap_exit
-	REG_S	a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(tp)
-	/* Clear tmp0 in scratch space */
-	REG_S	zero, SBI_SCRATCH_TMP0_OFFSET(tp)
-	/* Store firmware options in scratch space */
-	MOV_3R	s0, a0, s1, a1, s2, a2
-#ifdef FW_OPTIONS
-	li	a0, FW_OPTIONS
-#else
-	call	fw_options
-#endif
-	REG_S	a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
-	MOV_3R	a0, s0, a1, s1, a2, s2
-	/* Move to next scratch space */
-	add	t1, t1, t2
-	blt	t1, s7, _scratch_init
-
-	/*
-	 * Relocate Flatened Device Tree (FDT)
-	 * source FDT address = previous arg1
-	 * destination FDT address = next arg1
-	 *
-	 * Note: We will preserve a0 and a1 passed by
-	 * previous booting stage.
-	 */
-	beqz	a1, _fdt_reloc_done
-	/* Mask values in a4 */
-	li	a4, 0xff
-	/* t1 = destination FDT start address */
-	MOV_3R	s0, a0, s1, a1, s2, a2
-	call	fw_next_arg1
-	add	t1, a0, zero
-	MOV_3R	a0, s0, a1, s1, a2, s2
-	beqz	t1, _fdt_reloc_done
-	beq	t1, a1, _fdt_reloc_done
-	/* t0 = source FDT start address */
-	add	t0, a1, zero
-	/* t2 = source FDT size in big-endian */
-#if __riscv_xlen > 32
-	lwu	t2, 4(t0)
-#else
-	lw	t2, 4(t0)
-#endif
-	/* t3 = bit[15:8] of FDT size */
-	add	t3, t2, zero
-	srli	t3, t3, 16
-	and	t3, t3, a4
-	slli	t3, t3, 8
-	/* t4 = bit[23:16] of FDT size */
-	add	t4, t2, zero
-	srli	t4, t4, 8
-	and	t4, t4, a4
-	slli	t4, t4, 16
-	/* t5 = bit[31:24] of FDT size */
-	add	t5, t2, zero
-	and	t5, t5, a4
-	slli	t5, t5, 24
-	/* t2 = bit[7:0] of FDT size */
-	srli	t2, t2, 24
-	and	t2, t2, a4
-	/* t2 = FDT size in little-endian */
-	or	t2, t2, t3
-	or	t2, t2, t4
-	or	t2, t2, t5
-	/* t2 = destination FDT end address */
-	add	t2, t1, t2
-	/* FDT copy loop */
-	ble	t2, t1, _fdt_reloc_done
-_fdt_reloc_again:
-	REG_L	t3, 0(t0)
-	REG_S	t3, 0(t1)
-	add	t0, t0, __SIZEOF_POINTER__
-	add	t1, t1, __SIZEOF_POINTER__
-	blt	t1, t2, _fdt_reloc_again
-_fdt_reloc_done:
+	call	fw_coldboot_init
 
 	/* mark boot hart done */
 	li	t0, BOOT_STATUS_BOOT_HART_DONE
@@ -415,13 +215,6 @@ _start_hang:
 	wfi
 	j	_start_hang
 
-	.section .entry, "ax", %progbits
-	.align 3
-	.weak fw_platform_init
-fw_platform_init:
-	add	a0, a1, zero
-	ret
-
 	/* Map implicit memcpy() added by compiler to sbi_memcpy() */
 	.section .text
 	.align 3
diff --git a/firmware/fw_dynamic.S b/firmware/fw_dynamic.S
index 52ef320..f8cb3d1 100644
--- a/firmware/fw_dynamic.S
+++ b/firmware/fw_dynamic.S
@@ -41,10 +41,8 @@ fw_boot_hart:
 	.align 3
 	.global fw_save_info
 	/*
-	 * We can only use a0, a1, a2, a3, and a4 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * Nothing to be returned here.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_save_info:
 	/* Save next arg1 in 'a1' */
@@ -76,10 +74,8 @@ fw_save_info:
 	.align 3
 	.global fw_next_arg1
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * The next arg1 should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_arg1:
 	lla	a0, _dynamic_next_arg1
@@ -90,8 +86,8 @@ fw_next_arg1:
 	.align 3
 	.global fw_next_addr
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_addr:
 	lla	a0, _dynamic_next_addr
@@ -102,8 +98,8 @@ fw_next_addr:
 	.align 3
 	.global fw_next_mode
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_mode:
 	lla	a0, _dynamic_next_mode
@@ -114,9 +110,8 @@ fw_next_mode:
 	.align 3
 	.global fw_options
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The 'a4' register will have default options.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_options:
 	lla	a0, _dynamic_options
diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
index 1775fcd..0af0cab 100644
--- a/firmware/fw_jump.S
+++ b/firmware/fw_jump.S
@@ -26,10 +26,8 @@ fw_boot_hart:
 	.align 3
 	.global fw_save_info
 	/*
-	 * We can only use a0, a1, a2, a3, and a4 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * Nothing to be returned here.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_save_info:
 	ret
@@ -38,10 +36,8 @@ fw_save_info:
 	.align 3
 	.global fw_next_arg1
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * The next arg1 should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_arg1:
 #ifdef FW_JUMP_FDT_ADDR
@@ -55,8 +51,8 @@ fw_next_arg1:
 	.align 3
 	.global fw_next_addr
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_addr:
 	lla	a0, _jump_addr
@@ -67,8 +63,8 @@ fw_next_addr:
 	.align 3
 	.global fw_next_mode
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_mode:
 	li	a0, PRV_S
@@ -78,9 +74,8 @@ fw_next_mode:
 	.align 3
 	.global fw_options
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The 'a4' register will have default options.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_options:
 	add	a0, zero, zero
diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
index 985f833..a9f4720 100644
--- a/firmware/fw_payload.S
+++ b/firmware/fw_payload.S
@@ -26,10 +26,8 @@ fw_boot_hart:
 	.align 3
 	.global fw_save_info
 	/*
-	 * We can only use a0, a1, a2, a3, and a4 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * Nothing to be returned here.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_save_info:
 	ret
@@ -38,10 +36,8 @@ fw_save_info:
 	.align 3
 	.global fw_next_arg1
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The a0, a1, and a2 registers will be same as passed by
-	 * previous booting stage.
-	 * The next arg1 should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_arg1:
 #ifdef FW_PAYLOAD_FDT_ADDR
@@ -55,8 +51,8 @@ fw_next_arg1:
 	.align 3
 	.global fw_next_addr
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_addr:
 	lla	a0, payload_bin
@@ -66,8 +62,8 @@ fw_next_addr:
 	.align 3
 	.global fw_next_mode
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_next_mode:
 	li	a0, PRV_S
@@ -77,9 +73,8 @@ fw_next_mode:
 	.align 3
 	.global fw_options
 	/*
-	 * We can only use a0, a1, and a2 registers here.
-	 * The 'a4' register will have default options.
-	 * The next address should be returned in 'a0'.
+	 * This function will be called in a C function, and the implementation
+	 * needs to meet the calling constraints of RISC-V
 	 */
 fw_options:
 	add	a0, zero, zero
diff --git a/firmware/objects.mk b/firmware/objects.mk
index b2ace75..efe44fa 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -55,3 +55,5 @@ endif
 ifdef FW_OPTIONS
 firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
 endif
+
+firmware-objs-y += fw.o
diff --git a/include/sbi/sbi_types.h b/include/sbi/sbi_types.h
index def88bb..76f86f4 100644
--- a/include/sbi/sbi_types.h
+++ b/include/sbi/sbi_types.h
@@ -66,6 +66,7 @@ typedef uint64_t		be64_t;
 
 #define NULL			((void *)0)
 
+#define __weak			__attribute__((weak))
 #define __packed		__attribute__((packed))
 #define __noreturn		__attribute__((noreturn))
 #define __aligned(x)		__attribute__((aligned(x)))
-- 
2.43.0



From minda.chen at starfivetech.com  Mon Feb 12 06:25:48 2024
From: minda.chen at starfivetech.com (Minda Chen)
Date: Mon, 12 Feb 2024 14:25:48 +0000
Subject: [PATCH v4 7/7] platform: starfive: call
 starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <f868f77b9e776c53086e9d01352c60b04fe7102f.1707122766.git.namcao@linutronix.de>
References: <cover.1707122766.git.namcao@linutronix.de>
 <f868f77b9e776c53086e9d01352c60b04fe7102f.1707122766.git.namcao@linutronix.de>
Message-ID: <SHXPR01MB08638A357E6A5964B012393AE648A@SHXPR01MB0863.CHNPR01.prod.partner.outlook.cn>



> 
> The function starfive_jh7110_inst_init() initialize some power management
> unit address and clock addresses, needed for the reset driver. It doesn't do
> anything else, and also the reset driver doesn't work without calling this
> function. Thus, it does not make much sense that this function is independent
> from pm_reset_init().
> 
> Delete the separate call to starfive_jh7110_inst_init(), and instead just call
> this function inside pm_reset_init().
> 
> Doing this also fixes another problem: if starfive_jh7110_inst_init() returns an
> error code, it gets propagated to final_init() and OpenSBI hangs. This hang is
> not necessary, because failures within
> starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
> shutdown, but the system can still function normally.
> 
> Signed-off-by: Nam Cao <namcao at linutronix.de>
> ---
>  platform/generic/starfive/jh7110.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/platform/generic/starfive/jh7110.c
> b/platform/generic/starfive/jh7110.c
> index 6990425..c25e645 100644
> --- a/platform/generic/starfive/jh7110.c
> +++ b/platform/generic/starfive/jh7110.c
> @@ -190,6 +190,8 @@ static struct sbi_system_reset_device pm_reset = {
>  	.system_reset = pm_system_reset
>  };
> 
> +static int starfive_jh7110_inst_init(void *fdt);
> +
>  static int pm_reset_init(void *fdt, int nodeoff,
>  			 const struct fdt_match *match)
>  {
> @@ -215,6 +217,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
> 
>  	pmic_inst.adapter = adapter;
> 
> +	rc = starfive_jh7110_inst_init(fdt);
> +	if (rc)
> +		return rc;
> +
>  	sbi_system_reset_add_device(&pm_reset);
> 
>  	return 0;
> @@ -278,7 +284,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
> 
>  	if (cold_boot) {
>  		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
> -		return starfive_jh7110_inst_init(fdt);
>  	}
> 
>  	return 0;
> --
> 2.39.2
Tested-by: Minda Chen <minda.chen at starfivetech.com>



From ajones at ventanamicro.com  Mon Feb 12 09:20:33 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Mon, 12 Feb 2024 18:20:33 +0100
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
Message-ID: <20240212-f61079aa6ee3990c6084ff7c@orel>

On Thu, Feb 08, 2024 at 09:50:47AM +0000, Ivan Orlov wrote:
> It is good when the code is covered with tests. Tests help us to keep
> the code clean and avoid regressions. Also, a good test is always a nice
> documentation for the code it covers.
> 
> This and the subsequent patches in this series introduce SBIUnit - the
> set of macros and functions which simplify the unit test development
> for OpenSBI and automate tests execution and evaluation. Also, this
> patch series contains two of the tests: one which covers functions from
> lib/sbi_bitmap.c, and another covering a part of functions from
> lib/sbi_console.c.

The above should be in the cover letter, which this series is missing.
Cover letters are nice since they give reviewers a place to comment on the
overall series.

> 
> This patch contains the documentation for SBIUnit. It describes:
> 
> - What is SBIUnit
> - Simple test writing scenario
> - How we can cover static functions
> - How we can "mock" structures in order to test the functions which
> operate on them
> - SBIUnit API Reference
> 
> This thing is mainly inspired by the KUnit framework from the Linux
> Kernel, where the similar unit-test development tooling have been used
> successfully for a pretty long time now. I believe it would be good to
> have such a thing in OpenSBI as well.

The above paragraph belongs in the cover letter along with elaboration
on how only certain parts of KUnit were reimplemented and why those
certain parts, and not others, were chosen.

> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
>  docs/writing_tests.md | 143 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 143 insertions(+)
>  create mode 100644 docs/writing_tests.md
> 
> diff --git a/docs/writing_tests.md b/docs/writing_tests.md
> new file mode 100644
> index 0000000..481f2ee
> --- /dev/null
> +++ b/docs/writing_tests.md
> @@ -0,0 +1,143 @@
> +Writing tests for OpenSBI
> +=========================
> +
> +SBIUnit
> +-------
> +SBIUnit is a set of macros and functions which simplify the test development and automate the

We aim for 80 char line length, especially in documentation.

> +test execution and evaluation. All of the SBIUnit definitions could be found in

s/could be found in/are in the/


> +`include/sbi/sbi_unit.h` header file, and implementations are available in `lib/sbi/sbi_unit.c`.

I think the string 'test' should be somewhere in the filenames. 'unit' is
too generic.

> +
> +Simple SBIUnit test
> +-------------------
> +
> +For instance, we would like to test the following function from `lib/sbi/sbi_string.c`:
> +
> +```c
> +size_t sbi_strlen(const char *str)
> +{
> +	unsigned long ret = 0;
> +
> +	while (*str != '\0') {
> +		ret++;
> +		str++;
> +	}
> +
> +	return ret;
> +}
> +```
> +
> +Apparently, it calculates the string length.

s/Apparently, it/which/

> +
> +Create the file `lib/sbi/sbi_string_test.c` with the following content:
> +
> +```c
> +#include <sbi/sbi_unit.h>
> +#include <sbi/sbi_string.h>
> +
> +static void strlen_test(struct sbiunit_test_case *test)
> +{
> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
> +}
> +
> +static struct sbiunit_test_case string_test_cases[] = {
> +	SBIUNIT_TEST_CASE(strlen_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
> +```
> +
> +After that, add the corresponding entry to `lib/sbi/sbi_unit.c` and update the `test_suites` array:

s/After that,/Then,/

But I think we should be able to add the test suite pointer to an elf
section with the SBIUNIT_TEST_SUITE() macro to avoid this step.

> +```c
> +...
> +extern struct sbiunit_test_suite string_test_suite;
> +...
> +static struct sbiunit_test_suite *test_suites[] = {
> +    ...
> +    &string_test_suite,
> +};
> +...
> +```
> +
> +Add the corresponding Makefile entry to `lib/sbi/objects.mk`:
> +```lang-makefile
> +...
> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
> +```
> +
> +Now recompile OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU. You will see
> +something like this:
> +```
> +# make PLATFORM=generic run
> +...
> +# Running SBIUNIT tests #
> +...
> +## Running test suite: string_test_suite
> +[OK] strlen_test
> +1 SUCCESS / 0 FAIL / 1 TOTAL
> +```
> +
> +Now let's try to change this test in the way that it will fail:
> +
> +```c
> +- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
> ++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
> +```
> +
> +Compile and run it again:
> +```
> +...
> +# Running SBIUNIT tests #
> +...
> +## Running test suite: string_test_suite
> +strlen_test: Condition "sbi_strlen("Hello") == 100" expected to be true!
> +[FAIL] strlen_test
> +0 SUCCESS / 1 FAIL / 1 TOTAL
> +```
> +Covering the static functions / using the static definitions
> +------------------------------------------------------------
> +
> +SBIUnit also allows you to test static functions. In order to do so, simply include your test source
> +in the file you would like to test. Complementing the example above, just add this to the
> +`lib/sbi/sbi_string.c` file:
> +
> +```c
> +#ifdef CONFIG_SBIUNIT
> +#include "sbi_string_test.c"
> +#endif
> +```
> +
> +In this case you should not add a new entry to `lib/sbi/objects.mk`, because the test code will be
> +included into the `sbi_string` object file.
> +
> +See example in `lib/sbi/sbi_console_test.c`, where statically declared `console_dev` variable is
> +used to mock the `sbi_console_device` structure.
> +
> +"Mocking" the structures
> +------------------------
> +See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`, where the
> +sbi_console_device structure was mocked to be used in various console-related functions in order to
> +test them.
> +
> +API Reference
> +-------------
> +All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the corresponding conditions
> +are not met, however, the execution of a particular test case will not be stopped.
> +
> +All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop immediately.

The distinction between SBIUNIT_EXPECT* and SBIUNIT_ASSERT* is good to
document, but I don't think we want to list the functions as is done
below. We should just reference the header from here, since we'll be
lucky to keep the header filename in sync, let alone each function...

> +
> +- `SBIUNIT_EXPECT(test_case, condition)` - sets an expectation that 'condition' is true
> +- `SBIUNIT_ASSERT(test_case, condition)` - sets an assertion that 'condition' is true
> +- `SBIUNIT_EXPECT_EQ(test_case, a, b)` - sets an expectation that a = b
> +- `SBIUNIT_ASSERT_EQ(test_case, a, b)` - sets an assertion that a = b
> +- `SBIUNIT_EXPECT_NE(test_case, a, b)` - sets an expectation that a != b
> +- `SBIUNIT_ASSERT_NE(test_case, a, b)` - sets an assertion that a != b
> +- `SBIUNIT_EXPECT_MEMEQ(test_case, a, b, len)` - performs sbi_memcmp on memory regions a and b with
> +a length 'len', and sets an expectation that they are equal
> +- `SBIUNIT_ASSERT_MEMEQ(test_case, a, b, len)` - performs sbi_memcmp on memory regions a and b with
> +a length 'len', and sets an assertion that they are equal
> +- `SBIUNIT_EXPECT_STREQ(test_case, a, b)` - performs sbi_strcmp on strings a and b and sets
> +an expectation that they are equal
> +- `SBIUNIT_ASSERT_STREQ(test_case, a, b)` - performs sbi_strcmp on strings a and b and sets
> +an assertion that they are equal

Thanks,
drew


From ajones at ventanamicro.com  Mon Feb 12 09:36:53 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Mon, 12 Feb 2024 18:36:53 +0100
Subject: [PATCH 2/4] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240208095050.398522-2-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-2-ivan.orlov0322@gmail.com>
Message-ID: <20240212-5d311c79e606a9d510631934@orel>

On Thu, Feb 08, 2024 at 09:50:48AM +0000, Ivan Orlov wrote:
> It is good when the code is covered with tests. Tests help us to keep
> the code clean and avoid regressions. Also, a good test is always a nice
> documentation for the code it covers.
> 
> This and the subsequent patches in this series introduce SBIUnit - the
> set of macros and functions which simplify the unit test development for
> OpenSBI and automate tests execution and evaluation.

The above paragraphs should be dropped.

> 
> This patch introduces all of the SBIUnit macros and functions which
> can be used during the test development process. Also, it defines
> the 'run_all_tests' function, which is being called during the
> 'init_coldboot' right after printing the boot hart information.
> 
> Also, add the CONFIG_SBIUNIT Kconfig entry in order to be able to
> turn the tests on and off. When the CONFIG_SBIUNIT is disabled,
> the tests and all related code should be excluded completely on the
> compilation stage (and, apparently, it works in this way).

The '(and, apparently, it works in this way)' should be dropped.

> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
>  include/sbi/sbi_unit.h | 69 ++++++++++++++++++++++++++++++++++++++++++
>  lib/sbi/Kconfig        |  4 +++
>  lib/sbi/objects.mk     |  1 +
>  lib/sbi/sbi_init.c     |  8 +++++
>  lib/sbi/sbi_unit.c     | 44 +++++++++++++++++++++++++++
>  5 files changed, 126 insertions(+)
>  create mode 100644 include/sbi/sbi_unit.h
>  create mode 100644 lib/sbi/sbi_unit.c
> 
> diff --git a/include/sbi/sbi_unit.h b/include/sbi/sbi_unit.h
> new file mode 100644
> index 0000000..685e58d
> --- /dev/null
> +++ b/include/sbi/sbi_unit.h
> @@ -0,0 +1,69 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#ifndef __SBI_UNIT_H__
> +#define __SBI_UNIT_H__
> +
> +extern struct sbiunit_test_suite *__start_sbiunit_test_suites;
> +extern struct sbiunit_test_suite *__end_sbiunit_test_suites;

These start/end pointers don't appear to be used?

> +
> +#include <sbi/sbi_types.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_string.h>
> +
> +#define _CONCAT(a, b) a ## b
> +#define CONCAT(a, b) _CONCAT(a, b)

This CONCAT macro isn't used.

> +
> +struct sbiunit_test_case {
> +	char *name;

const char *name ?

> +	bool should_run;

Rename 'should_run' to 'enabled'

> +	bool result;
> +	void (*test_func)(struct sbiunit_test_case *test);
> +	void (*onerr)(struct sbiunit_test_case *test);
> +};
> +
> +struct sbiunit_test_suite {
> +	struct sbiunit_test_case *cases;
> +	const char *name;

nit: I'd put name first.

> +};
> +
> +#define SBIUNIT_TEST_CASE(func)	\
> +	{ .name = #func, .should_run = 1, .result = 0, .test_func = &func }

nit: Should use true/false instead of 1/0.
nit: No need for the '&' in front of func.

> +
> +#define SBIUNIT_TEST_SUITE(suite_name, cases_arr) \
> +	struct sbiunit_test_suite suite_name = { .name = #suite_name, .cases = cases_arr }
> +
> +#define SBIUNIT_INFO(test, msg) sbi_printf("%s: %s", test->name, msg)

Maybe some sort of prefix like "SBIUNIT" should be on this line.

> +
> +#define SBIUNIT_EXPECT(test, cond) do {							\
> +	if (!(cond)) {									\
> +		test->result = 0;							\
> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
> +	}										\
> +} while (0)
> +
> +#define SBIUNIT_ASSERT(test, cond) do {						\
> +	if (!(cond)) {								\
> +		test->result = 0;						\
> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" must be true!\n");	\
> +		return;								\

Unnecessary 'return'. It's strange that an ASSERT macro doesn't result in
an sbi_panic().

> +	}									\
> +} while (0)
> +
> +#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, a == b)
> +#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, a == b)
> +#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, a != b)
> +#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, a != b)

These macros need () around their arguments, e.g.

#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))

> +#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) \
> +	SBIUNIT_EXPECT(test, sbi_memcmp(a, b, len) == 0)
> +#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) \
> +	SBIUNIT_ASSERT(test, sbi_memcmp(a, b, len) == 0)
> +#define SBIUNIT_EXPECT_STREQ(test, a, b) \
> +	SBIUNIT_EXPECT(test, sbi_strcmp(a, b) == 0)
> +#define SBIUNIT_ASSERT_STREQ(test, a, b) \
> +	SBIUNIT_ASSERT(test, sbi_strcmp(a, b) == 0)
> +
> +void run_all_tests(void);
> +#endif
> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> index 81dd2db..e3038ee 100644
> --- a/lib/sbi/Kconfig
> +++ b/lib/sbi/Kconfig
> @@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
>  	bool "Debug Trigger Extension"
>  	default y
>  
> +config SBIUNIT
> +	bool "Enable SBIUNIT tests"
> +	default n
> +
>  endmenu
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 0a50e95..0a2318b 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -11,6 +11,7 @@ libsbi-objs-y += riscv_asm.o
>  libsbi-objs-y += riscv_atomic.o
>  libsbi-objs-y += riscv_hardfp.o
>  libsbi-objs-y += riscv_locks.o
> +libsbi-objs-y += sbi_unit.o
>  
>  libsbi-objs-y += sbi_ecall.o
>  libsbi-objs-y += sbi_ecall_exts.o
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 804b01c..16d0a00 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -30,6 +30,10 @@
>  #include <sbi/sbi_tlb.h>
>  #include <sbi/sbi_version.h>
>  
> +#ifdef CONFIG_SBIUNIT
> +#include <sbi/sbi_unit.h>
> +#endif

We can move the '#ifdef CONFIG_SBIUNIT' into the header and then always
include it.

> +
>  #define BANNER                                              \
>  	"   ____                    _____ ____ _____\n"     \
>  	"  / __ \\                  / ____|  _ \\_   _|\n"  \
> @@ -398,6 +402,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  
>  	sbi_boot_print_hart(scratch, hartid);
>  
> +#ifdef CONFIG_SBIUNIT
> +	run_all_tests();
> +#endif

I was going to suggest that we could provide a stub for
!defined(CONFIG_SBIUNIT), but I sort like that the #ifdef annotates that
this function is only called with that config enabled. So, either way.

> +
>  	/*
>  	 * Configure PMP at last because if SMEPMP is detected,
>  	 * M-mode access to the S/U space will be rescinded.
> diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
> new file mode 100644
> index 0000000..9c7efec
> --- /dev/null
> +++ b/lib/sbi/sbi_unit.c
> @@ -0,0 +1,44 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_unit.h>
> +#include <sbi/sbi_console.h>
> +
> +static struct sbiunit_test_suite *test_suites[] = {
> +};
> +
> +static void run_test_suite(struct sbiunit_test_suite *suite)
> +{
> +	struct sbiunit_test_case *s_case;
> +	u32 count_pass, count_fail;
> +
> +	sbi_printf("## Running test suite: %s\n", suite->name);
> +	count_pass = 0;
> +	count_fail = 0;

nit: Can set these zero in the declarations above.

> +
> +	s_case = suite->cases;
> +	while (s_case->should_run) {
> +		s_case->result = 1;

Why initialize result to pass?

> +		s_case->test_func(s_case);
> +		if (s_case->result)
> +			count_pass++;
> +		else
> +			count_fail++;
> +		sbi_printf("[%s] %s\n", s_case->result ? "OK" : "FAIL", s_case->name);

Is OK/FAIL what KUnit outputs? I'd expect OK/NOK or PASS/FAIL. We'll also
probably want a SKIP sooner or later.

> +		s_case++;
> +	}
> +	sbi_printf("%u SUCCESS / %u FAIL / %u TOTAL\n", count_pass, count_fail,
> +		   count_pass + count_fail);
> +}
> +
> +void run_all_tests(void)
> +{
> +	u32 i;
> +
> +	sbi_printf("\n# Running SBIUNIT tests #\n");
> +
> +	for (i = 0; i < sizeof(test_suites) / sizeof(test_suites[0]); i++)

We have array_size() in include/sbi/sbi_types.h

> +		run_test_suite(test_suites[i]);
> +}
> -- 
> 2.34.1
> 
>

Thanks,
drew


From ajones at ventanamicro.com  Mon Feb 12 10:11:11 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Mon, 12 Feb 2024 19:11:11 +0100
Subject: [PATCH 3/4] lib: tests: Add a test for sbi_bitmap
In-Reply-To: <20240208095050.398522-3-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-3-ivan.orlov0322@gmail.com>
Message-ID: <20240212-3dd07643bfb15ca9d41694ee@orel>

On Thu, Feb 08, 2024 at 09:50:49AM +0000, Ivan Orlov wrote:
> Add test suite covering all of the functions from lib/sbi/sbi_bitmap.c:
> __bitmap_and, __bitmap_or and __bitmap_xor.
> 
> This patch depends on the previous patches in this series as it uses
> SBIUnit macros, functions and definitions

No need to state that a patch depends on a previous patch, as that's
generally the case.

> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
>  lib/sbi/objects.mk        |   2 +
>  lib/sbi/sbi_bitmap_test.c | 104 ++++++++++++++++++++++++++++++++++++++
>  lib/sbi/sbi_unit.c        |   2 +
>  3 files changed, 108 insertions(+)
>  create mode 100644 lib/sbi/sbi_bitmap_test.c
> 
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 0a2318b..b29e63f 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -56,6 +56,8 @@ libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o
>  carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_DBTR) += ecall_dbtr
>  libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
>  
> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
> +
>  libsbi-objs-y += sbi_bitmap.o
>  libsbi-objs-y += sbi_bitops.o
>  libsbi-objs-y += sbi_console.o
> diff --git a/lib/sbi/sbi_bitmap_test.c b/lib/sbi/sbi_bitmap_test.c
> new file mode 100644
> index 0000000..0fd0091
> --- /dev/null
> +++ b/lib/sbi/sbi_bitmap_test.c
> @@ -0,0 +1,104 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_bitmap.h>
> +#include <sbi/sbi_unit.h>
> +#include <sbi/sbi_console.h>
> +
> +static u64 data_a[] = { 0xDEADBEEF, 0x00BAB10C, 0x1BADB002, 0xABADBABE };
> +static u64 data_b[] = { 0xC00010FF, 0x00BAB10C, 0xBAAAAAAD, 0xBADDCAFE };
> +static u64 data_zero[] = { 0, 0, 0, 0 };
> +

nit: Remove one blank line and the below defines up above the globals.

> +
> +#define DATA_SIZE sizeof(data_zero)
> +#define DATA_BIT_SIZE (DATA_SIZE * 8)
> +
> +static void bitmap_and_test(struct sbiunit_test_case *test)
> +{
> +	u64 res[DATA_SIZE];
> +	u64 a_and_b[] = { 0xDEADBEEF & 0xC00010FF, 0x00BAB10C & 0x00BAB10C,
> +			  0x1BADB002 & 0xBAAAAAAD, 0xABADBABE & 0xBADDCAFE };

Should refer to the test data by name, e.g. data_a[0] or with a define,
'#define DATA_A0 0xDEADBEEFULL'

> +
> +	__bitmap_and(res, data_a, data_b, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, a_and_b, DATA_SIZE);
> +
> +	// a & a = a

Should use /**/ comment format.

> +	__bitmap_and(res, data_a, data_a, DATA_BIT_SIZE);
> +	SBIUNIT_ASSERT_MEMEQ(test, res, data_a, DATA_SIZE);
> +
> +	// a & 0 = 0
> +	__bitmap_and(res, data_a, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +
> +	// 0 & 0 = 0
> +	__bitmap_and(res, data_zero, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +
> +	sbi_memcpy(res, data_zero, DATA_SIZE);
> +	// Cover zero 'bits' argument
> +	__bitmap_and(res, data_a, data_b, 0);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +}
> +
> +static void bitmap_or_test(struct sbiunit_test_case *test)
> +{
> +	u64 res[DATA_SIZE];
> +	u64 a_or_b[] = { 0xDEADBEEF | 0xC00010FF, 0x00BAB10C | 0x00BAB10C,
> +		       0x1BADB002 | 0xBAAAAAAD, 0xABADBABE | 0xBADDCAFE };
> +
> +	__bitmap_or(res, data_a, data_b, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, a_or_b, DATA_SIZE);
> +
> +	// a | a = a
> +	__bitmap_or(res, data_a, data_a, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
> +
> +	// a | 0 = a
> +	__bitmap_or(res, data_a, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
> +
> +	// 0 | 0 = 0
> +	__bitmap_or(res, data_zero, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +
> +	sbi_memcpy(res, data_zero, DATA_SIZE);
> +	__bitmap_or(res, data_a, data_b, 0);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +}
> +
> +static void bitmap_xor_test(struct sbiunit_test_case *test)
> +{
> +	u64 res[DATA_SIZE];
> +	u64 a_xor_b[] = { 0xDEADBEEF ^ 0xC00010FF, 0x00BAB10C ^ 0x00BAB10C,
> +			  0x1BADB002 ^ 0xBAAAAAAD, 0xABADBABE ^ 0xBADDCAFE };
> +
> +	__bitmap_xor(res, data_a, data_b, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, a_xor_b, DATA_SIZE);
> +
> +	// a ^ 0 = a
> +	__bitmap_xor(res, data_a, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
> +
> +	// a ^ a = 0
> +	__bitmap_xor(res, data_a, data_a, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +
> +	// 0 ^ 0 = 0
> +	__bitmap_xor(res, data_zero, data_zero, DATA_BIT_SIZE);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +
> +	sbi_memcpy(res, data_zero, DATA_SIZE);
> +	__bitmap_xor(res, data_a, data_b, 0);
> +	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
> +}
> +
> +static struct sbiunit_test_case bitmap_test_cases[] = {
> +	SBIUNIT_TEST_CASE(bitmap_and_test),
> +	SBIUNIT_TEST_CASE(bitmap_or_test),
> +	SBIUNIT_TEST_CASE(bitmap_xor_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(bitmap_test_suite, bitmap_test_cases);
> diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
> index 9c7efec..2d3da7f 100644
> --- a/lib/sbi/sbi_unit.c
> +++ b/lib/sbi/sbi_unit.c
> @@ -6,7 +6,9 @@
>  #include <sbi/sbi_unit.h>
>  #include <sbi/sbi_console.h>
>  
> +extern struct sbiunit_test_suite bitmap_test_suite;
>  static struct sbiunit_test_suite *test_suites[] = {
> +	&bitmap_test_suite,
>  };
>  
>  static void run_test_suite(struct sbiunit_test_suite *suite)
> -- 
> 2.34.1
> 
>

Thanks,
drew


From ajones at ventanamicro.com  Mon Feb 12 10:24:16 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Mon, 12 Feb 2024 19:24:16 +0100
Subject: [PATCH 4/4] lib: tests: Add sbi_console test
In-Reply-To: <20240208095050.398522-4-ivan.orlov0322@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-4-ivan.orlov0322@gmail.com>
Message-ID: <20240212-cd9f3f355276b2f752006b77@orel>

On Thu, Feb 08, 2024 at 09:50:50AM +0000, Ivan Orlov wrote:
> Add the test suite covering some of the functions from
> lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
> of format specifiers for printf and different strings and characters for
> putc and puts.
> 
> In order to do that, the test "mocks" the sbi_console_device structure
> by setting the 'console_dev' variable to the virtual console.
> 
> This patch depends on the previous patches from the series as it uses
> SBIUnit macros, functions and definitions.

Again, this last sentence isn't necessary to write in a commit message.

> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
>  lib/sbi/sbi_console.c      |   4 ++
>  lib/sbi/sbi_console_test.c | 104 +++++++++++++++++++++++++++++++++++++
>  lib/sbi/sbi_unit.c         |   2 +
>  3 files changed, 110 insertions(+)
>  create mode 100644 lib/sbi/sbi_console_test.c
> 
> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
> index ab09a5c..d1229d0 100644
> --- a/lib/sbi/sbi_console.c
> +++ b/lib/sbi/sbi_console.c
> @@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
>  
>  	return rc;
>  }
> +
> +#ifdef CONFIG_SBIUNIT
> +#include "sbi_console_test.c"
> +#endif
> diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
> new file mode 100644
> index 0000000..8c3b215
> --- /dev/null
> +++ b/lib/sbi/sbi_console_test.c
> @@ -0,0 +1,104 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_unit.h>
> +#include <sbi/sbi_heap.h>
> +
> +/*
> + * Console functions are wrapped in order to mock the console object and don't affect the actual
> + * console output
> + */
> +#define CONSOLE_DO(action) ({		\
> +	old_dev = console_dev;		\
> +	console_dev = &new_dev;		\
> +	action;				\
> +	console_dev = old_dev;		\
> +})

Why not use a local variable for old_dev and pass 'new_dev' in as an
argument?

> +
> +// We are using a GCC extension here, which allows us to return a value from a block

No need for this comment.

> +#define CONSOLE_DO_RET(action) ({	\
> +	old_dev = console_dev;		\
> +	console_dev = &new_dev;		\
> +	u64 res = action;		\

Please use names like __res inside macros to avoid shadowing concerns.

> +	console_dev = old_dev;		\
> +	res;				\
> +})

We only need CONSOLE_DO_RET(). The caller can ignore the return value.
And its name should include an TEST_ prefix, because this file is
included by other files.

> +
> +#define BUF_LEN 1024

TEST_CONSOLE_BUF_LEN

> +
> +static const struct sbi_console_device *old_dev;
> +
> +static char buf[BUF_LEN];
> +static u32 pos;

All the above need a test_console_ prefix

> +static void test_console_putc(char c)
> +{
> +	buf[pos] = c;
> +	pos = (pos + 1) % BUF_LEN;
> +}
> +
> +static void clear_buf(void)
> +{
> +	pos = 0;
> +	sbi_memset(buf, 0, BUF_LEN);

I guess buf[0] = '\0' should be sufficient.

> +}
> +
> +// Mocking the console

/**/ comment style

> +static const struct sbi_console_device new_dev = {
> +	.name = "Test console device",
> +	.console_putc = test_console_putc,
> +};
> +
> +static void putc_test(struct sbiunit_test_case *test)
> +{
> +	clear_buf();
> +
> +	CONSOLE_DO(sbi_putc('a'));

I think I would replace the CONSOLE_DO macro with a _begin() / _end()
pair.

 test_console_begin();
 sbi_putc('a');
 test_console_end();

> +	SBIUNIT_ASSERT_EQ(test, buf[0], 'a');
> +}
> +
> +#define PUTS_TEST(test, expected, param) do {				\

param is the string, so it should be named 's' or 'str' or similar.

> +	clear_buf();							\
> +	CONSOLE_DO(sbi_puts(param));					\
> +	SBIUNIT_ASSERT_STREQ(test, buf, expected);			\
> +} while (0)
> +
> +static void puts_test(struct sbiunit_test_case *test)
> +{
> +	PUTS_TEST(test, "Hello, OpenSBI!", "Hello, OpenSBI!");
> +	PUTS_TEST(test, "Hello,\r\nOpenSBI!", "Hello,\nOpenSBI!");
> +	PUTS_TEST(test, "Hello,", "Hello,\0OpenSBI!");
> +}
> +
> +#define PRINTF_TEST(test, expected, format, ...) do {					\
> +	clear_buf();									\
> +	SBIUNIT_ASSERT_EQ(test, CONSOLE_DO_RET(sbi_printf(format, ##__VA_ARGS__)),	\
> +			  sbi_strlen(expected));					\
> +	SBIUNIT_ASSERT_STREQ(test, buf, expected);					\
> +} while (0)
> +
> +static void printf_test(struct sbiunit_test_case *test)
> +{
> +	PRINTF_TEST(test, "Hello", "Hello");
> +	PRINTF_TEST(test, "3 5 7", "%d %d %d", 3, 5, 7);
> +	PRINTF_TEST(test, "Hello", "%s", "Hello");
> +	PRINTF_TEST(test, "-1", "%d", -1);
> +	PRINTF_TEST(test, "FF", "%X", 255);
> +	PRINTF_TEST(test, "ff", "%x", 255);
> +	PRINTF_TEST(test, "A", "%c", 'A');
> +	PRINTF_TEST(test, "1fe", "%p", (void *)0x1fe);
> +	PRINTF_TEST(test, "4294967295", "%u", 4294967295U);
> +	PRINTF_TEST(test, "-2147483647", "%ld", -2147483647l);
> +	PRINTF_TEST(test, "-9223372036854775807", "%lld", -9223372036854775807LL);
> +	PRINTF_TEST(test, "18446744073709551615", "%llu", 18446744073709551615ULL);
> +}
> +
> +static struct sbiunit_test_case console_test_cases[] = {
> +	SBIUNIT_TEST_CASE(putc_test),
> +	SBIUNIT_TEST_CASE(puts_test),
> +	SBIUNIT_TEST_CASE(printf_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(console_test_suite, console_test_cases);
> diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
> index 2d3da7f..b2f2063 100644
> --- a/lib/sbi/sbi_unit.c
> +++ b/lib/sbi/sbi_unit.c
> @@ -7,8 +7,10 @@
>  #include <sbi/sbi_console.h>
>  
>  extern struct sbiunit_test_suite bitmap_test_suite;
> +extern struct sbiunit_test_suite console_test_suite;
>  static struct sbiunit_test_suite *test_suites[] = {
>  	&bitmap_test_suite,
> +	&console_test_suite,
>  };
>  
>  static void run_test_suite(struct sbiunit_test_suite *suite)
> -- 
> 2.34.1
> 
>

Thanks,
drew


From ivan.orlov0322 at gmail.com  Mon Feb 12 13:48:02 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Mon, 12 Feb 2024 21:48:02 +0000
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240212-f61079aa6ee3990c6084ff7c@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240212-f61079aa6ee3990c6084ff7c@orel>
Message-ID: <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>

On 2/12/24 17:20, Andrew Jones wrote:
> The above should be in the cover letter, which this series is missing.
> Cover letters are nice since they give reviewers a place to comment on the
> overall series.
> 

Alright, will be moved to the cover letter in V2.
> The above paragraph belongs in the cover letter along with elaboration
> on how only certain parts of KUnit were reimplemented and why those
> certain parts, and not others, were chosen.
> 

Makes sense, I'll extend the description.

>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>>   docs/writing_tests.md | 143 ++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 143 insertions(+)
>>   create mode 100644 docs/writing_tests.md
>>
>> diff --git a/docs/writing_tests.md b/docs/writing_tests.md
>> new file mode 100644
>> index 0000000..481f2ee
>> --- /dev/null
>> +++ b/docs/writing_tests.md
>> @@ -0,0 +1,143 @@
>> +Writing tests for OpenSBI
>> +=========================
>> +
>> +SBIUnit
>> +-------
>> +SBIUnit is a set of macros and functions which simplify the test development and automate the
> 
> We aim for 80 char line length, especially in documentation.
> 
>> +test execution and evaluation. All of the SBIUnit definitions could be found in
> 
> s/could be found in/are in the/
> 
> 
>> +`include/sbi/sbi_unit.h` header file, and implementations are available in `lib/sbi/sbi_unit.c`.
> 
> I think the string 'test' should be somewhere in the filenames. 'unit' is
> too generic.
> 
>> +
>> +Simple SBIUnit test
>> +-------------------
>> +
>> +For instance, we would like to test the following function from `lib/sbi/sbi_string.c`:
>> +
>> +```c
>> +size_t sbi_strlen(const char *str)
>> +{
>> +	unsigned long ret = 0;
>> +
>> +	while (*str != '\0') {
>> +		ret++;
>> +		str++;
>> +	}
>> +
>> +	return ret;
>> +}
>> +```
>> +
>> +Apparently, it calculates the string length.
> 
> s/Apparently, it/which/
> 
>> +
>> +Create the file `lib/sbi/sbi_string_test.c` with the following content:
>> +
>> +```c
>> +#include <sbi/sbi_unit.h>
>> +#include <sbi/sbi_string.h>
>> +
>> +static void strlen_test(struct sbiunit_test_case *test)
>> +{
>> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
>> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
>> +}
>> +
>> +static struct sbiunit_test_case string_test_cases[] = {
>> +	SBIUNIT_TEST_CASE(strlen_test),
>> +	{},
>> +};
>> +
>> +SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
>> +```
>> +
>> +After that, add the corresponding entry to `lib/sbi/sbi_unit.c` and update the `test_suites` array:
> 
> s/After that,/Then,/
> 
> But I think we should be able to add the test suite pointer to an elf
> section with the SBIUNIT_TEST_SUITE() macro to avoid this step.
> 

That was an initial idea, however I faced some obstacles during the 
implementation.

I believe we would like to cover the static functions, as well as use 
static variables in the tests. In this case, we would include the test 
in the source we are covering (for instance, include 
"sbi_console_test.c" in "sbi_console.c"). If we use OpenSBI 
(libplatsbi.a) as a library when linking firmware, and firmware refers 
to a symbol from "sbi_console.h", it will automatically link the test 
code too. This means that firmware should have the test ELF section as 
well. Manual registration of the tests in 'sbi_unit.c', on the other 
hand, would not require any effort from the firmware developers if they 
decide to enable tests for OpenSBI.

Moreover, manual test declaration will make sure that we included all of 
the tests. Otherwise, if we define the test in a separate file, it will 
be linked out unless we refer to symbols from it somewhere.

What do you think of it?

>> +```c
>> +...
>> +extern struct sbiunit_test_suite string_test_suite;
>> +...
>> +static struct sbiunit_test_suite *test_suites[] = {
>> +    ...
>> +    &string_test_suite,
>> +};
>> +...
>> +```
>> +
>> +Add the corresponding Makefile entry to `lib/sbi/objects.mk`:
>> +```lang-makefile
>> +...
>> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
>> +```
>> +
>> +Now recompile OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU. You will see
>> +something like this:
>> +```
>> +# make PLATFORM=generic run
>> +...
>> +# Running SBIUNIT tests #
>> +...
>> +## Running test suite: string_test_suite
>> +[OK] strlen_test
>> +1 SUCCESS / 0 FAIL / 1 TOTAL
>> +```
>> +
>> +Now let's try to change this test in the way that it will fail:
>> +
>> +```c
>> +- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
>> ++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
>> +```
>> +
>> +Compile and run it again:
>> +```
>> +...
>> +# Running SBIUNIT tests #
>> +...
>> +## Running test suite: string_test_suite
>> +strlen_test: Condition "sbi_strlen("Hello") == 100" expected to be true!
>> +[FAIL] strlen_test
>> +0 SUCCESS / 1 FAIL / 1 TOTAL
>> +```
>> +Covering the static functions / using the static definitions
>> +------------------------------------------------------------
>> +
>> +SBIUnit also allows you to test static functions. In order to do so, simply include your test source
>> +in the file you would like to test. Complementing the example above, just add this to the
>> +`lib/sbi/sbi_string.c` file:
>> +
>> +```c
>> +#ifdef CONFIG_SBIUNIT
>> +#include "sbi_string_test.c"
>> +#endif
>> +```
>> +
>> +In this case you should not add a new entry to `lib/sbi/objects.mk`, because the test code will be
>> +included into the `sbi_string` object file.
>> +
>> +See example in `lib/sbi/sbi_console_test.c`, where statically declared `console_dev` variable is
>> +used to mock the `sbi_console_device` structure.
>> +
>> +"Mocking" the structures
>> +------------------------
>> +See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`, where the
>> +sbi_console_device structure was mocked to be used in various console-related functions in order to
>> +test them.
>> +
>> +API Reference
>> +-------------
>> +All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the corresponding conditions
>> +are not met, however, the execution of a particular test case will not be stopped.
>> +
>> +All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop immediately.
> 
> The distinction between SBIUNIT_EXPECT* and SBIUNIT_ASSERT* is good to
> document, but I don't think we want to list the functions as is done
> below. We should just reference the header from here, since we'll be
> lucky to keep the header filename in sync, let alone each function...
> 

I agree, it is definitely redundant.

Thank you so much for the review!

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Mon Feb 12 14:03:52 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Mon, 12 Feb 2024 22:03:52 +0000
Subject: [PATCH 2/4] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240212-5d311c79e606a9d510631934@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-2-ivan.orlov0322@gmail.com>
 <20240212-5d311c79e606a9d510631934@orel>
Message-ID: <5be9d29f-08d8-40fe-adf0-7ced03303705@gmail.com>

On 2/12/24 17:36, Andrew Jones wrote:
> On Thu, Feb 08, 2024 at 09:50:48AM +0000, Ivan Orlov wrote:
>> It is good when the code is covered with tests. Tests help us to keep
>> the code clean and avoid regressions. Also, a good test is always a nice
>> documentation for the code it covers.
>>
>> This and the subsequent patches in this series introduce SBIUnit - the
>> set of macros and functions which simplify the unit test development for
>> OpenSBI and automate tests execution and evaluation.
> 
> The above paragraphs should be dropped.
> 
>>
>> This patch introduces all of the SBIUnit macros and functions which
>> can be used during the test development process. Also, it defines
>> the 'run_all_tests' function, which is being called during the
>> 'init_coldboot' right after printing the boot hart information.
>>
>> Also, add the CONFIG_SBIUNIT Kconfig entry in order to be able to
>> turn the tests on and off. When the CONFIG_SBIUNIT is disabled,
>> the tests and all related code should be excluded completely on the
>> compilation stage (and, apparently, it works in this way).
> 
> The '(and, apparently, it works in this way)' should be dropped.
> 

Thanks, I'll put this information in the cover letter of V2.
>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>>   include/sbi/sbi_unit.h | 69 ++++++++++++++++++++++++++++++++++++++++++
>>   lib/sbi/Kconfig        |  4 +++
>>   lib/sbi/objects.mk     |  1 +
>>   lib/sbi/sbi_init.c     |  8 +++++
>>   lib/sbi/sbi_unit.c     | 44 +++++++++++++++++++++++++++
>>   5 files changed, 126 insertions(+)
>>   create mode 100644 include/sbi/sbi_unit.h
>>   create mode 100644 lib/sbi/sbi_unit.c
>>
>> diff --git a/include/sbi/sbi_unit.h b/include/sbi/sbi_unit.h
>> new file mode 100644
>> index 0000000..685e58d
>> --- /dev/null
>> +++ b/include/sbi/sbi_unit.h
>> @@ -0,0 +1,69 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#ifndef __SBI_UNIT_H__
>> +#define __SBI_UNIT_H__
>> +
>> +extern struct sbiunit_test_suite *__start_sbiunit_test_suites;
>> +extern struct sbiunit_test_suite *__end_sbiunit_test_suites;
> 
> These start/end pointers don't appear to be used?
> 

Ah, I just forgot to remove them after implementing the SBIUnit version 
with a dedicated ELF section for the tests... Thanks!

>> +
>> +#include <sbi/sbi_types.h>
>> +#include <sbi/sbi_console.h>
>> +#include <sbi/sbi_string.h>
>> +
>> +#define _CONCAT(a, b) a ## b
>> +#define CONCAT(a, b) _CONCAT(a, b)
> 
> This CONCAT macro isn't used.
> 
>> +
>> +struct sbiunit_test_case {
>> +	char *name;
> 
> const char *name ?
> 
>> +	bool should_run;
> 
> Rename 'should_run' to 'enabled'
> 

Alright, will be done.

>> +	bool result;
>> +	void (*test_func)(struct sbiunit_test_case *test);
>> +	void (*onerr)(struct sbiunit_test_case *test);
>> +};
>> +
>> +struct sbiunit_test_suite {
>> +	struct sbiunit_test_case *cases;
>> +	const char *name;
> 
> nit: I'd put name first.
> 
>> +};
>> +
>> +#define SBIUNIT_TEST_CASE(func)	\
>> +	{ .name = #func, .should_run = 1, .result = 0, .test_func = &func }
> 
> nit: Should use true/false instead of 1/0.
> nit: No need for the '&' in front of func.
> 
>> +
>> +#define SBIUNIT_TEST_SUITE(suite_name, cases_arr) \
>> +	struct sbiunit_test_suite suite_name = { .name = #suite_name, .cases = cases_arr }
>> +
>> +#define SBIUNIT_INFO(test, msg) sbi_printf("%s: %s", test->name, msg)
> 
> Maybe some sort of prefix like "SBIUNIT" should be on this line.
> 
>> +
>> +#define SBIUNIT_EXPECT(test, cond) do {							\
>> +	if (!(cond)) {									\
>> +		test->result = 0;							\
>> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
>> +	}										\
>> +} while (0)
>> +
>> +#define SBIUNIT_ASSERT(test, cond) do {						\
>> +	if (!(cond)) {								\
>> +		test->result = 0;						\
>> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" must be true!\n");	\
>> +		return;								\
> 
> Unnecessary 'return'. It's strange that an ASSERT macro doesn't result in
> an sbi_panic().
> 

I thought it would be bad if test results in hang, but if it is ok I 
will rewrite it.

>> +	}									\
>> +} while (0)
>> +
>> +#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, a == b)
>> +#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, a == b)
>> +#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, a != b)
>> +#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, a != b)
> 
> These macros need () around their arguments, e.g.
> 
> #define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))
> 
>> +#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) \
>> +	SBIUNIT_EXPECT(test, sbi_memcmp(a, b, len) == 0)
>> +#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) \
>> +	SBIUNIT_ASSERT(test, sbi_memcmp(a, b, len) == 0)
>> +#define SBIUNIT_EXPECT_STREQ(test, a, b) \
>> +	SBIUNIT_EXPECT(test, sbi_strcmp(a, b) == 0)
>> +#define SBIUNIT_ASSERT_STREQ(test, a, b) \
>> +	SBIUNIT_ASSERT(test, sbi_strcmp(a, b) == 0)
>> +
>> +void run_all_tests(void);
>> +#endif
>> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
>> index 81dd2db..e3038ee 100644
>> --- a/lib/sbi/Kconfig
>> +++ b/lib/sbi/Kconfig
>> @@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
>>   	bool "Debug Trigger Extension"
>>   	default y
>>   
>> +config SBIUNIT
>> +	bool "Enable SBIUNIT tests"
>> +	default n
>> +
>>   endmenu
>> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
>> index 0a50e95..0a2318b 100644
>> --- a/lib/sbi/objects.mk
>> +++ b/lib/sbi/objects.mk
>> @@ -11,6 +11,7 @@ libsbi-objs-y += riscv_asm.o
>>   libsbi-objs-y += riscv_atomic.o
>>   libsbi-objs-y += riscv_hardfp.o
>>   libsbi-objs-y += riscv_locks.o
>> +libsbi-objs-y += sbi_unit.o
>>   
>>   libsbi-objs-y += sbi_ecall.o
>>   libsbi-objs-y += sbi_ecall_exts.o
>> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
>> index 804b01c..16d0a00 100644
>> --- a/lib/sbi/sbi_init.c
>> +++ b/lib/sbi/sbi_init.c
>> @@ -30,6 +30,10 @@
>>   #include <sbi/sbi_tlb.h>
>>   #include <sbi/sbi_version.h>
>>   
>> +#ifdef CONFIG_SBIUNIT
>> +#include <sbi/sbi_unit.h>
>> +#endif
> 
> We can move the '#ifdef CONFIG_SBIUNIT' into the header and then always
> include it.
> 

Yeah, makes sense.

>> +
>>   #define BANNER                                              \
>>   	"   ____                    _____ ____ _____\n"     \
>>   	"  / __ \\                  / ____|  _ \\_   _|\n"  \
>> @@ -398,6 +402,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>>   
>>   	sbi_boot_print_hart(scratch, hartid);
>>   
>> +#ifdef CONFIG_SBIUNIT
>> +	run_all_tests();
>> +#endif
> 
> I was going to suggest that we could provide a stub for
> !defined(CONFIG_SBIUNIT), but I sort like that the #ifdef annotates that
> this function is only called with that config enabled. So, either way.
> 

I think your suggestion is better, it will help avoiding #ifdef 
"boilerplate" and make the code cleaner.

>> +
>>   	/*
>>   	 * Configure PMP at last because if SMEPMP is detected,
>>   	 * M-mode access to the S/U space will be rescinded.
>> diff --git a/lib/sbi/sbi_unit.c b/lib/sbi/sbi_unit.c
>> new file mode 100644
>> index 0000000..9c7efec
>> --- /dev/null
>> +++ b/lib/sbi/sbi_unit.c
>> @@ -0,0 +1,44 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#include <sbi/sbi_unit.h>
>> +#include <sbi/sbi_console.h>
>> +
>> +static struct sbiunit_test_suite *test_suites[] = {
>> +};
>> +
>> +static void run_test_suite(struct sbiunit_test_suite *suite)
>> +{
>> +	struct sbiunit_test_case *s_case;
>> +	u32 count_pass, count_fail;
>> +
>> +	sbi_printf("## Running test suite: %s\n", suite->name);
>> +	count_pass = 0;
>> +	count_fail = 0;
> 
> nit: Can set these zero in the declarations above.
> 
>> +
>> +	s_case = suite->cases;
>> +	while (s_case->should_run) {
>> +		s_case->result = 1;
> 
> Why initialize result to pass?

The logic was to set the 'result' to 0 in the SBIUNIT_ASSERT or 
SBIUNIT_EXPECT, but it really seems confusing so I agree that it might 
be better to create a 'failed' field and set it to 'true' in the 
assert/expect.

> 
>> +		s_case->test_func(s_case);
>> +		if (s_case->result)
>> +			count_pass++;
>> +		else
>> +			count_fail++;
>> +		sbi_printf("[%s] %s\n", s_case->result ? "OK" : "FAIL", s_case->name);
> 
> Is OK/FAIL what KUnit outputs? I'd expect OK/NOK or PASS/FAIL. We'll also
> probably want a SKIP sooner or later.
> 

It looks like KUnit uses 'FAILED' or 'PASSED'. So I will update the 
messages correspondingly.

>> +		s_case++;
>> +	}
>> +	sbi_printf("%u SUCCESS / %u FAIL / %u TOTAL\n", count_pass, count_fail,
>> +		   count_pass + count_fail);
>> +}
>> +
>> +void run_all_tests(void)
>> +{
>> +	u32 i;
>> +
>> +	sbi_printf("\n# Running SBIUNIT tests #\n");
>> +
>> +	for (i = 0; i < sizeof(test_suites) / sizeof(test_suites[0]); i++)
> 
> We have array_size() in include/sbi/sbi_types.h
> 

Cool, I'll use it instead.

Thank you!
-- 
Kind regards,
Ivan Orlov



From ajones at ventanamicro.com  Tue Feb 13 05:51:34 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Tue, 13 Feb 2024 14:51:34 +0100
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240212-f61079aa6ee3990c6084ff7c@orel>
 <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>
Message-ID: <20240213-a2478b49c77f64f9f111e96b@orel>

On Mon, Feb 12, 2024 at 09:48:02PM +0000, Ivan Orlov wrote:
> On 2/12/24 17:20, Andrew Jones wrote:
...
> > But I think we should be able to add the test suite pointer to an elf
> > section with the SBIUNIT_TEST_SUITE() macro to avoid this step.
> > 
> 
> That was an initial idea, however I faced some obstacles during the
> implementation.
> 
> I believe we would like to cover the static functions, as well as use static
> variables in the tests. In this case, we would include the test in the
> source we are covering (for instance, include "sbi_console_test.c" in
> "sbi_console.c"). If we use OpenSBI (libplatsbi.a) as a library when linking
> firmware, and firmware refers to a symbol from "sbi_console.h", it will
> automatically link the test code too. This means that firmware should have
> the test ELF section as well. Manual registration of the tests in
> 'sbi_unit.c', on the other hand, would not require any effort from the
> firmware developers if they decide to enable tests for OpenSBI.

Hmm, I see. So maybe we can use the build system's carray?

> 
> Moreover, manual test declaration will make sure that we included all of the
> tests. Otherwise, if we define the test in a separate file, it will be
> linked out unless we refer to symbols from it somewhere.

This could possibly be worked around with the linker's --whole-archive
option.

Thanks,
drew


From ajones at ventanamicro.com  Tue Feb 13 06:00:37 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Tue, 13 Feb 2024 15:00:37 +0100
Subject: [PATCH 2/4] lib: Add SBIUnit testing macros and functions
In-Reply-To: <5be9d29f-08d8-40fe-adf0-7ced03303705@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-2-ivan.orlov0322@gmail.com>
 <20240212-5d311c79e606a9d510631934@orel>
 <5be9d29f-08d8-40fe-adf0-7ced03303705@gmail.com>
Message-ID: <20240213-c191a5bbf346ab3ca994f464@orel>

On Mon, Feb 12, 2024 at 10:03:52PM +0000, Ivan Orlov wrote:
> On 2/12/24 17:36, Andrew Jones wrote:
> > On Thu, Feb 08, 2024 at 09:50:48AM +0000, Ivan Orlov wrote:
...
> > > +#define SBIUNIT_ASSERT(test, cond) do {						\
> > > +	if (!(cond)) {								\
> > > +		test->result = 0;						\
> > > +		SBIUNIT_INFO(test, "Condition \"" #cond "\" must be true!\n");	\
> > > +		return;								\
> > 
> > Unnecessary 'return'. It's strange that an ASSERT macro doesn't result in
> > an sbi_panic().
> > 
> 
> I thought it would be bad if test results in hang, but if it is ok I will
> rewrite it.

I think an assert should output its message and then stop all execution.
Asserts should only be used in situations where failures mean the
test programmer made an improper assumption. If we don't halt the moment
we determine the assumption is wrong, then we'll potentially generate
passing test results, but the tests may not be testing what the test
programmer thought they were.

Thanks,
drew


From ivan.orlov0322 at gmail.com  Tue Feb 13 06:54:17 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Tue, 13 Feb 2024 14:54:17 +0000
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240213-a2478b49c77f64f9f111e96b@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240212-f61079aa6ee3990c6084ff7c@orel>
 <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>
 <20240213-a2478b49c77f64f9f111e96b@orel>
Message-ID: <168f8ed3-6cc1-4cb0-a3bc-a738383775a1@gmail.com>

On 2/13/24 13:51, Andrew Jones wrote:
> On Mon, Feb 12, 2024 at 09:48:02PM +0000, Ivan Orlov wrote:
>> On 2/12/24 17:20, Andrew Jones wrote:
> ...
>>> But I think we should be able to add the test suite pointer to an elf
>>> section with the SBIUNIT_TEST_SUITE() macro to avoid this step.
>>>
>>
>> That was an initial idea, however I faced some obstacles during the
>> implementation.
>>
>> I believe we would like to cover the static functions, as well as use static
>> variables in the tests. In this case, we would include the test in the
>> source we are covering (for instance, include "sbi_console_test.c" in
>> "sbi_console.c"). If we use OpenSBI (libplatsbi.a) as a library when linking
>> firmware, and firmware refers to a symbol from "sbi_console.h", it will
>> automatically link the test code too. This means that firmware should have
>> the test ELF section as well. Manual registration of the tests in
>> 'sbi_unit.c', on the other hand, would not require any effort from the
>> firmware developers if they decide to enable tests for OpenSBI.
> 
> Hmm, I see. So maybe we can use the build system's carray?
> 

Hmmm, I've never heard about this thing before, could you please point 
me to a reference or source where I could read about it?

>>
>> Moreover, manual test declaration will make sure that we included all of the
>> tests. Otherwise, if we define the test in a separate file, it will be
>> linked out unless we refer to symbols from it somewhere.
> 
> This could possibly be worked around with the linker's --whole-archive
> option.

In this case we would have to update the makefile logic, because now 
OpenSBI uses 'compile_elf' makefile procedure for the test payload and 
the firmware elf files both, and we would not like to use 
--whole-archive for the test payload. I guess it is an overcomplication...

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Tue Feb 13 06:55:21 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Tue, 13 Feb 2024 14:55:21 +0000
Subject: [PATCH 2/4] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240213-c191a5bbf346ab3ca994f464@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-2-ivan.orlov0322@gmail.com>
 <20240212-5d311c79e606a9d510631934@orel>
 <5be9d29f-08d8-40fe-adf0-7ced03303705@gmail.com>
 <20240213-c191a5bbf346ab3ca994f464@orel>
Message-ID: <43e91abd-049e-433e-a48d-0a4779232ee8@gmail.com>

On 2/13/24 14:00, Andrew Jones wrote:
> On Mon, Feb 12, 2024 at 10:03:52PM +0000, Ivan Orlov wrote:
>> On 2/12/24 17:36, Andrew Jones wrote:
>>> On Thu, Feb 08, 2024 at 09:50:48AM +0000, Ivan Orlov wrote:
> ...
>>>> +#define SBIUNIT_ASSERT(test, cond) do {						\
>>>> +	if (!(cond)) {								\
>>>> +		test->result = 0;						\
>>>> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" must be true!\n");	\
>>>> +		return;								\
>>>
>>> Unnecessary 'return'. It's strange that an ASSERT macro doesn't result in
>>> an sbi_panic().
>>>
>>
>> I thought it would be bad if test results in hang, but if it is ok I will
>> rewrite it.
> 
> I think an assert should output its message and then stop all execution.
> Asserts should only be used in situations where failures mean the
> test programmer made an improper assumption. If we don't halt the moment
> we determine the assumption is wrong, then we'll potentially generate
> passing test results, but the tests may not be testing what the test
> programmer thought they were.
> 

Makes sense, so let's add the sbi_panic in version 2.

Thanks!

-- 
Kind regards,
Ivan Orlov



From ajones at ventanamicro.com  Tue Feb 13 07:21:16 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Tue, 13 Feb 2024 16:21:16 +0100
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <168f8ed3-6cc1-4cb0-a3bc-a738383775a1@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240212-f61079aa6ee3990c6084ff7c@orel>
 <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>
 <20240213-a2478b49c77f64f9f111e96b@orel>
 <168f8ed3-6cc1-4cb0-a3bc-a738383775a1@gmail.com>
Message-ID: <20240213-1b27a0bbd79dd323daf5757e@orel>

On Tue, Feb 13, 2024 at 02:54:17PM +0000, Ivan Orlov wrote:
> On 2/13/24 13:51, Andrew Jones wrote:
> > On Mon, Feb 12, 2024 at 09:48:02PM +0000, Ivan Orlov wrote:
> > > On 2/12/24 17:20, Andrew Jones wrote:
> > ...
> > > > But I think we should be able to add the test suite pointer to an elf
> > > > section with the SBIUNIT_TEST_SUITE() macro to avoid this step.
> > > > 
> > > 
> > > That was an initial idea, however I faced some obstacles during the
> > > implementation.
> > > 
> > > I believe we would like to cover the static functions, as well as use static
> > > variables in the tests. In this case, we would include the test in the
> > > source we are covering (for instance, include "sbi_console_test.c" in
> > > "sbi_console.c"). If we use OpenSBI (libplatsbi.a) as a library when linking
> > > firmware, and firmware refers to a symbol from "sbi_console.h", it will
> > > automatically link the test code too. This means that firmware should have
> > > the test ELF section as well. Manual registration of the tests in
> > > 'sbi_unit.c', on the other hand, would not require any effort from the
> > > firmware developers if they decide to enable tests for OpenSBI.
> > 
> > Hmm, I see. So maybe we can use the build system's carray?
> > 
> 
> Hmmm, I've never heard about this thing before, could you please point me to
> a reference or source where I could read about it?

It's used in OpenSBI code for arrays such as sbi_ecall_exts. See commit
56bed1a0fe39 ("lib: sbi_ecall: Generate extensions list with carray") for
that example.

> 
> > > 
> > > Moreover, manual test declaration will make sure that we included all of the
> > > tests. Otherwise, if we define the test in a separate file, it will be
> > > linked out unless we refer to symbols from it somewhere.
> > 
> > This could possibly be worked around with the linker's --whole-archive
> > option.
> 
> In this case we would have to update the makefile logic, because now OpenSBI
> uses 'compile_elf' makefile procedure for the test payload and the firmware
> elf files both, and we would not like to use --whole-archive for the test
> payload. I guess it is an overcomplication...

Maybe, but I'm not sure how much we'd care about having bloated binaries
when building with CONFIG_SBIUNIT.

Thanks,
drew


From ivan.orlov0322 at gmail.com  Tue Feb 13 07:29:40 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Tue, 13 Feb 2024 15:29:40 +0000
Subject: [PATCH 1/4] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240213-1b27a0bbd79dd323daf5757e@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240212-f61079aa6ee3990c6084ff7c@orel>
 <12c2ecd6-0367-470f-90bf-35a805574147@gmail.com>
 <20240213-a2478b49c77f64f9f111e96b@orel>
 <168f8ed3-6cc1-4cb0-a3bc-a738383775a1@gmail.com>
 <20240213-1b27a0bbd79dd323daf5757e@orel>
Message-ID: <e9192a2b-c493-4c50-bdcb-699fd0df4454@gmail.com>

On 2/13/24 15:21, Andrew Jones wrote:
>> Hmmm, I've never heard about this thing before, could you please point me to
>> a reference or source where I could read about it?
> 
> It's used in OpenSBI code for arrays such as sbi_ecall_exts. See commit
> 56bed1a0fe39 ("lib: sbi_ecall: Generate extensions list with carray") for
> that example.
> 

Thanks, I'll take a look and use them in the V2 if it is possible!

>>
>> In this case we would have to update the makefile logic, because now OpenSBI
>> uses 'compile_elf' makefile procedure for the test payload and the firmware
>> elf files both, and we would not like to use --whole-archive for the test
>> payload. I guess it is an overcomplication...
> 
> Maybe, but I'm not sure how much we'd care about having bloated binaries
> when building with CONFIG_SBIUNIT.
>

The problem is not with the bloated payload binaries: if we use 
--whole-archive when linking the test payload, it starts giving the 
'undefined reference' errors, because some of the object files refer to 
symbols which don't exist in the test payload. Like:

```
opensbi/platform/generic/andes/sleep.S:63: undefined reference to 
`_start_warm'
```

_start_warm is defined in fw_base, but it's not accessible when building 
the test payload (firmware/payloads/).

Probably, we could just disable the test payload building when 
CONFIG_SBIUNIT is enabled, but I'm not sure if it is a correct 
approach... Another option would be optional --whole-archive use, so we 
would use it for linking the fw_* ELF files only.

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Thu Feb 15 06:44:15 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 14:44:15 +0000
Subject: [PATCH 4/4] lib: tests: Add sbi_console test
In-Reply-To: <20240212-cd9f3f355276b2f752006b77@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-4-ivan.orlov0322@gmail.com>
 <20240212-cd9f3f355276b2f752006b77@orel>
Message-ID: <d75aad80-37c7-449e-a9cf-8320bd5c0ea7@gmail.com>

On 2/12/24 18:24, Andrew Jones wrote:
> On Thu, Feb 08, 2024 at 09:50:50AM +0000, Ivan Orlov wrote:
>> Add the test suite covering some of the functions from
>> lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
>> of format specifiers for printf and different strings and characters for
>> putc and puts.
>>
>> In order to do that, the test "mocks" the sbi_console_device structure
>> by setting the 'console_dev' variable to the virtual console.
>>
>> This patch depends on the previous patches from the series as it uses
>> SBIUnit macros, functions and definitions.
> 
> Again, this last sentence isn't necessary to write in a commit message.
> 
>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>>   lib/sbi/sbi_console.c      |   4 ++
>>   lib/sbi/sbi_console_test.c | 104 +++++++++++++++++++++++++++++++++++++
>>   lib/sbi/sbi_unit.c         |   2 +
>>   3 files changed, 110 insertions(+)
>>   create mode 100644 lib/sbi/sbi_console_test.c
>>
>> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
>> index ab09a5c..d1229d0 100644
>> --- a/lib/sbi/sbi_console.c
>> +++ b/lib/sbi/sbi_console.c
>> @@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
>>   
>>   	return rc;
>>   }
>> +
>> +#ifdef CONFIG_SBIUNIT
>> +#include "sbi_console_test.c"
>> +#endif
>> diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
>> new file mode 100644
>> index 0000000..8c3b215
>> --- /dev/null
>> +++ b/lib/sbi/sbi_console_test.c
>> @@ -0,0 +1,104 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#include <sbi/sbi_unit.h>
>> +#include <sbi/sbi_heap.h>
>> +
>> +/*
>> + * Console functions are wrapped in order to mock the console object and don't affect the actual
>> + * console output
>> + */
>> +#define CONSOLE_DO(action) ({		\
>> +	old_dev = console_dev;		\
>> +	console_dev = &new_dev;		\
>> +	action;				\
>> +	console_dev = old_dev;		\
>> +})
> 
> Why not use a local variable for old_dev and pass 'new_dev' in as an
> argument?
> 
>> +
>> +// We are using a GCC extension here, which allows us to return a value from a block
> 
> No need for this comment.
> 
>> +#define CONSOLE_DO_RET(action) ({	\
>> +	old_dev = console_dev;		\
>> +	console_dev = &new_dev;		\
>> +	u64 res = action;		\
> 
> Please use names like __res inside macros to avoid shadowing concerns.
> 
>> +	console_dev = old_dev;		\
>> +	res;				\
>> +})
> 
> We only need CONSOLE_DO_RET(). The caller can ignore the return value.
> And its name should include an TEST_ prefix, because this file is
> included by other files.
> 
>> +
>> +#define BUF_LEN 1024
> 
> TEST_CONSOLE_BUF_LEN
> 
>> +
>> +static const struct sbi_console_device *old_dev;
>> +
>> +static char buf[BUF_LEN];
>> +static u32 pos;
> 
> All the above need a test_console_ prefix
> 
>> +static void test_console_putc(char c)
>> +{
>> +	buf[pos] = c;
>> +	pos = (pos + 1) % BUF_LEN;
>> +}
>> +
>> +static void clear_buf(void)
>> +{
>> +	pos = 0;
>> +	sbi_memset(buf, 0, BUF_LEN);
> 
> I guess buf[0] = '\0' should be sufficient.
> 

Sorry for the late reply, I agree on all of the points you mentioned 
except this one. The 'puts' test stops me from clearing the buffer by 
setting the first char to zero:

```
PUTS_TEST(test, "Hello,", "Hello,\0OpenSBI!");
```

This test checks if 'puts' stops printing after facing \0. 'puts' won't 
print out the \0 to the buffer after printing "Hello,", so in case of 
the 'lazy' buffer clearing there might be other characters in buffer 
after 'Hello,'. In this case, the 'sbi_strcmp' won't stop comparing the 
strings causing the test to fail (despite the behavior is correct).

I reckon that clearing the buffer completely will help avoiding such 
tricky issues by making the experiment as pure as possible :)

Thank you!
-- 
Kind regards,
Ivan Orlov



From ajones at ventanamicro.com  Thu Feb 15 07:13:26 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Thu, 15 Feb 2024 16:13:26 +0100
Subject: [PATCH 4/4] lib: tests: Add sbi_console test
In-Reply-To: <d75aad80-37c7-449e-a9cf-8320bd5c0ea7@gmail.com>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-4-ivan.orlov0322@gmail.com>
 <20240212-cd9f3f355276b2f752006b77@orel>
 <d75aad80-37c7-449e-a9cf-8320bd5c0ea7@gmail.com>
Message-ID: <20240215-62fcfc1f00c95b950e3127b3@orel>

On Thu, Feb 15, 2024 at 02:44:15PM +0000, Ivan Orlov wrote:
> On 2/12/24 18:24, Andrew Jones wrote:
> > On Thu, Feb 08, 2024 at 09:50:50AM +0000, Ivan Orlov wrote:
...
> > > +static void clear_buf(void)
> > > +{
> > > +	pos = 0;
> > > +	sbi_memset(buf, 0, BUF_LEN);
> > 
> > I guess buf[0] = '\0' should be sufficient.
> > 
> 
> Sorry for the late reply, I agree on all of the points you mentioned except
> this one. The 'puts' test stops me from clearing the buffer by setting the
> first char to zero:
> 
> ```
> PUTS_TEST(test, "Hello,", "Hello,\0OpenSBI!");
> ```
> 
> This test checks if 'puts' stops printing after facing \0. 'puts' won't
> print out the \0 to the buffer after printing "Hello,", so in case of the
> 'lazy' buffer clearing there might be other characters in buffer after
> 'Hello,'. In this case, the 'sbi_strcmp' won't stop comparing the strings
> causing the test to fail (despite the behavior is correct).
> 
> I reckon that clearing the buffer completely will help avoiding such tricky
> issues by making the experiment as pure as possible :)

Since the mock console device is a ring buffer it doesn't guarantee zeros
will follow the printed strings. I suggest writing tests which only
confirm the characters printed are in the stream and in the right order,
but not check for anything console device implementation specific.

Thanks,
drew


From ivan.orlov0322 at gmail.com  Thu Feb 15 07:45:20 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 15:45:20 +0000
Subject: [PATCH 4/4] lib: tests: Add sbi_console test
In-Reply-To: <20240215-62fcfc1f00c95b950e3127b3@orel>
References: <20240208095050.398522-1-ivan.orlov0322@gmail.com>
 <20240208095050.398522-4-ivan.orlov0322@gmail.com>
 <20240212-cd9f3f355276b2f752006b77@orel>
 <d75aad80-37c7-449e-a9cf-8320bd5c0ea7@gmail.com>
 <20240215-62fcfc1f00c95b950e3127b3@orel>
Message-ID: <290c2605-a043-4211-a6d4-65d310c2a1a9@gmail.com>

On 2/15/24 15:13, Andrew Jones wrote:
> On Thu, Feb 15, 2024 at 02:44:15PM +0000, Ivan Orlov wrote:
>> On 2/12/24 18:24, Andrew Jones wrote:
>>> On Thu, Feb 08, 2024 at 09:50:50AM +0000, Ivan Orlov wrote:
> ...
>>>> +static void clear_buf(void)
>>>> +{
>>>> +	pos = 0;
>>>> +	sbi_memset(buf, 0, BUF_LEN);
>>>
>>> I guess buf[0] = '\0' should be sufficient.
>>>
>>
>> Sorry for the late reply, I agree on all of the points you mentioned except
>> this one. The 'puts' test stops me from clearing the buffer by setting the
>> first char to zero:
>>
>> ```
>> PUTS_TEST(test, "Hello,", "Hello,\0OpenSBI!");
>> ```
>>
>> This test checks if 'puts' stops printing after facing \0. 'puts' won't
>> print out the \0 to the buffer after printing "Hello,", so in case of the
>> 'lazy' buffer clearing there might be other characters in buffer after
>> 'Hello,'. In this case, the 'sbi_strcmp' won't stop comparing the strings
>> causing the test to fail (despite the behavior is correct).
>>
>> I reckon that clearing the buffer completely will help avoiding such tricky
>> issues by making the experiment as pure as possible :)
> 
> Since the mock console device is a ring buffer it doesn't guarantee zeros
> will follow the printed strings. I suggest writing tests which only
> confirm the characters printed are in the stream and in the right order,
> but not check for anything console device implementation specific.
> 

Ah, alright, I see. Moreover, this particular test case is just useless 
since it doesn't increase the coverage. So I guess I will just use the 
"lazy" buffer clearing and remove this particular 'PUTS_TEST'. Thanks 
for the clarification!

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:20 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:20 +0000
Subject: [PATCH v2 0/5] SBIUnit: cover OpenSBI with tests
Message-ID: <20240215161625.314131-1-ivan.orlov0322@gmail.com>

It is good when the code is covered with tests. Tests help us to keep
the code clean and avoid regressions. Also, a good test is always a nice
documentation for the code it covers.

This patch series introduces SBIUnit - the set of macros and functions 
which simplify the unit test development for OpenSBI and automate tests
execution and evaluation.

This thing is mainly inspired by the KUnit framework from the Linux
Kernel, where the similar unit-test development tooling have been used
successfully for a pretty long time now. SBIUnit uses the same test
structure: multiple test cases are grouped together into the test
suites. SBIUnit also tries to reproduce the KUnit tests API while
allowing for some simplifications.

Another difference between the KUnit and SBIUnit is the location where
the tests are "stored". KUnit creates the ELF section in the kernel and
stores the pointers to all of the test suites there. SBIUnit takes
advantage of the 'carray' functionality of OpenSBI, keeping the pointers
to test suites in the auto-generated ".c" file. ELF section approach
could not be applied to SBIUnit, because OpenSBI could be used as a
static library when linking firmware. Use of a dedicated ELF section
would mean that all firmware linked with OpenSBI would need to have
this ELF section as well.

V1 -> V2:
- Add a cover letter
- Elaborate more on the differences between SBIUnit and KUnit
- Add a new patch adding a new entry to the 'clear' makefile target in
order to clear carray-generated files as well.
- (Patch-specific changes are described in the following patches)

Ivan Orlov (5):
  docs: Add documentation about tests and SBIUnit
  lib: Add SBIUnit testing macros and functions
  Makefile: clean '.c' files generated by carray
  lib: tests: Add a test for sbi_bitmap
  lib: tests: Add sbi_console test

 Makefile                      |   2 +
 docs/writing_tests.md         | 131 ++++++++++++++++++++++++++++++++++
 include/sbi/sbi_unit_test.h   |  74 +++++++++++++++++++
 lib/sbi/Kconfig               |   4 ++
 lib/sbi/objects.mk            |   6 ++
 lib/sbi/sbi_bitmap_test.c     | 103 ++++++++++++++++++++++++++
 lib/sbi/sbi_console.c         |   4 ++
 lib/sbi/sbi_console_test.c    | 102 ++++++++++++++++++++++++++
 lib/sbi/sbi_init.c            |   3 +
 lib/sbi/sbi_unit_test.c       |  43 +++++++++++
 lib/sbi/sbi_unit_tests.carray |   3 +
 11 files changed, 475 insertions(+)
 create mode 100644 docs/writing_tests.md
 create mode 100644 include/sbi/sbi_unit_test.h
 create mode 100644 lib/sbi/sbi_bitmap_test.c
 create mode 100644 lib/sbi/sbi_console_test.c
 create mode 100644 lib/sbi/sbi_unit_test.c
 create mode 100644 lib/sbi/sbi_unit_tests.carray

-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:21 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:21 +0000
Subject: [PATCH v2 1/5] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
Message-ID: <20240215161625.314131-2-ivan.orlov0322@gmail.com>

This patch contains the documentation for SBIUnit. It describes:

- What is SBIUnit
- Simple test writing scenario
- How we can cover static functions
- How we can "mock" structures in order to test the functions which
operate on them
- SBIUnit API Reference

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
V1 -> V2:
- Use more appropriate language
- Update the documentation in accordance with SBIUnit API and
structure changes
- Remove the redundant documentation for every SBIUNIT_* macro.
- Make the documentation follow the 80-characters rule.

 docs/writing_tests.md | 131 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 docs/writing_tests.md

diff --git a/docs/writing_tests.md b/docs/writing_tests.md
new file mode 100644
index 0000000..279d35b
--- /dev/null
+++ b/docs/writing_tests.md
@@ -0,0 +1,131 @@
+Writing tests for OpenSBI
+=========================
+
+SBIUnit
+-------
+SBIUnit is a set of macros and functions which simplify the test development and
+automate the test execution and evaluation. All of the SBIUnit definitions are
+in the `include/sbi/sbi_unit_test.h` header file, and implementations are
+available in `lib/sbi/sbi_unit_test.c`.
+
+Simple SBIUnit test
+-------------------
+
+For instance, we would like to test the following function from
+`lib/sbi/sbi_string.c`:
+
+```c
+size_t sbi_strlen(const char *str)
+{
+	unsigned long ret = 0;
+
+	while (*str != '\0') {
+		ret++;
+		str++;
+	}
+
+	return ret;
+}
+```
+
+Which calculates the string length.
+
+Create the file `lib/sbi/sbi_string_test.c` with the following content:
+
+```c
+#include <sbi/sbi_unit_test.h>
+#include <sbi/sbi_string.h>
+
+static void strlen_test(struct sbiunit_test_case *test)
+{
+	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
+	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
+}
+
+static struct sbiunit_test_case string_test_cases[] = {
+	SBIUNIT_TEST_CASE(strlen_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
+```
+
+Then, add the corresponding Makefile entries to `lib/sbi/objects.mk`:
+```lang-makefile
+...
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
+```
+
+Run `make clean` in order to regenerate the carray-related files, recompile
+OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU.
+You will see something like this:
+```
+# make PLATFORM=generic run
+...
+# Running SBIUNIT tests #
+...
+## Running test suite: string_test_suite
+[PASSED] strlen_test
+1 PASSED / 0 FAILED / 1 TOTAL
+```
+
+Now let's try to change this test in the way that it will fail:
+
+```c
+- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
+```
+
+`make all` and `make run` it again:
+```
+...
+# Running SBIUNIT tests #
+...
+## Running test suite: string_test_suite
+[SBIUnit] [.../opensbi/lib/sbi/sbi_string_test.c:6]: strlen_test: Condition
+"(sbi_strlen("Hello")) == (100)" expected to be true!
+[FAILED] strlen_test
+0 PASSED / 1 FAILED / 1 TOTAL
+```
+Covering the static functions / using the static definitions
+------------------------------------------------------------
+
+SBIUnit also allows you to test static functions. In order to do so, simply
+include your test source in the file you would like to test. Complementing the
+example above, just add this to the
+`lib/sbi/sbi_string.c` file:
+
+```c
+#ifdef CONFIG_SBIUNIT
+#include "sbi_string_test.c"
+#endif
+```
+
+In this case you should only add a new carray entry pointing to the test suite
+to `lib/sbi/objects.mk`:
+```lang-makefile
+...
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
+```
+
+You don't have to compile the `sbi_string_test.o` separately, because the
+test code will be included into the `sbi_string` object file.
+
+See example in `lib/sbi/sbi_console_test.c`, where statically declared
+`console_dev` variable is used to mock the `sbi_console_device` structure.
+
+"Mocking" the structures
+------------------------
+See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`,
+where the sbi_console_device structure was mocked to be used in various
+console-related functions in order to test them.
+
+API Reference
+-------------
+All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the
+corresponding conditions are not met, however, the execution of a particular
+test case will not be stopped.
+
+All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop
+immediately, triggering the panic.
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:22 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:22 +0000
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
Message-ID: <20240215161625.314131-3-ivan.orlov0322@gmail.com>

This patch introduces all of the SBIUnit macros and functions which
can be used during the test development process. Also, it defines
the 'run_all_tests' function, which is being called during the
'init_coldboot' right after printing the boot hart information.

Also, add the CONFIG_SBIUNIT Kconfig entry in order to be able to
turn the tests on and off. When the CONFIG_SBIUNIT is disabled,
the tests and all related code is excluded completely on the
compilation stage.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
V1 -> V2:
- Rename the sources to have 'test' in the names: 'sbi_unit.c' =>
'sbi_unit_test.c', 'sbi_unit.h' => 'sbi_unit_test.h'.
- Rewrite using the carray functionality instead of placing the
pointers to the test suites into the source explicitly.
- Add 'ifdef' into the sbi_unit_test header file so we could
avoid writing a lot of 'ifdef' in other files.
- Get rid of unused symbols and macros
- Change the behaviour of SBIUNIT_ASSERT_* functions: now they trigger
sbi_panic if the assertion fails.
- Add a 'SBIUnit' prefix to the SBIUNIT_INFO macro message
- Rename the sbiunit_test_case structure fields, and use true/false
instead of 1/0
- Change the logic of the test fail detection: now we have the 'failed'
sbiunit_test_case structure field instead of the 'result'. 'failed'
field gets set to 'true' if an assertion or an expectaion fails.
- Fix codestyle issues
- Add 'len' parameter to SBIUNIT_*_STREQ

 include/sbi/sbi_unit_test.h   | 74 +++++++++++++++++++++++++++++++++++
 lib/sbi/Kconfig               |  4 ++
 lib/sbi/objects.mk            |  2 +
 lib/sbi/sbi_init.c            |  3 ++
 lib/sbi/sbi_unit_test.c       | 43 ++++++++++++++++++++
 lib/sbi/sbi_unit_tests.carray |  3 ++
 6 files changed, 129 insertions(+)
 create mode 100644 include/sbi/sbi_unit_test.h
 create mode 100644 lib/sbi/sbi_unit_test.c
 create mode 100644 lib/sbi/sbi_unit_tests.carray

diff --git a/include/sbi/sbi_unit_test.h b/include/sbi/sbi_unit_test.h
new file mode 100644
index 0000000..1538332
--- /dev/null
+++ b/include/sbi/sbi_unit_test.h
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#ifdef CONFIG_SBIUNIT
+#ifndef __SBI_UNIT_H__
+#define __SBI_UNIT_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_string.h>
+
+struct sbiunit_test_case {
+	const char *name;
+	bool enabled;
+	bool failed;
+	void (*test_func)(struct sbiunit_test_case *test);
+	void (*onerr)(struct sbiunit_test_case *test);
+};
+
+struct sbiunit_test_suite {
+	const char *name;
+	struct sbiunit_test_case *cases;
+};
+
+#define SBIUNIT_TEST_CASE(func)		\
+	{				\
+		.name = #func,		\
+		.enabled = true,	\
+		.failed = false,	\
+		.test_func = (func)	\
+	}
+
+#define SBIUNIT_TEST_SUITE(suite_name, cases_arr)		\
+	struct sbiunit_test_suite suite_name = {		\
+		.name = #suite_name,				\
+		.cases = cases_arr				\
+	}
+
+#define _sbiunit_msg(test, msg) "[SBIUnit] [%s:%d]: %s: %s", __FILE__,	\
+				__LINE__, test->name, msg
+
+#define SBIUNIT_INFO(test, msg) sbi_printf(_sbiunit_msg(test, msg))
+#define SBIUNIT_PANIC(test, msg) sbi_panic(_sbiunit_msg(test, msg))
+
+#define SBIUNIT_EXPECT(test, cond) do {							\
+	if (!(cond)) {									\
+		test->failed = true;							\
+		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
+	}										\
+} while (0)
+
+#define SBIUNIT_ASSERT(test, cond) do {						\
+	if (!(cond)) {								\
+		test->failed = true;						\
+		SBIUNIT_PANIC(test, "Condition \"" #cond "\" must be true!\n");	\
+	}									\
+} while (0)
+
+#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))
+#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, (a) == (b))
+#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, (a) != (b))
+#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, (a) != (b))
+#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_memcmp(a, b, len))
+#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_memcmp(a, b, len))
+#define SBIUNIT_EXPECT_STREQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_strncmp(a, b, len))
+#define SBIUNIT_ASSERT_STREQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_strncmp(a, b, len))
+
+void run_all_tests(void);
+#endif
+#else
+#define run_all_tests()
+#endif
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index 81dd2db..e3038ee 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
 	bool "Debug Trigger Extension"
 	default y
 
+config SBIUNIT
+	bool "Enable SBIUNIT tests"
+	default n
+
 endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 0a50e95..08959f1 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -11,6 +11,8 @@ libsbi-objs-y += riscv_asm.o
 libsbi-objs-y += riscv_atomic.o
 libsbi-objs-y += riscv_hardfp.o
 libsbi-objs-y += riscv_locks.o
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_test.o
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
 
 libsbi-objs-y += sbi_ecall.o
 libsbi-objs-y += sbi_ecall_exts.o
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 804b01c..796cccc 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -29,6 +29,7 @@
 #include <sbi/sbi_timer.h>
 #include <sbi/sbi_tlb.h>
 #include <sbi/sbi_version.h>
+#include <sbi/sbi_unit_test.h>
 
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
@@ -398,6 +399,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 
 	sbi_boot_print_hart(scratch, hartid);
 
+	run_all_tests();
+
 	/*
 	 * Configure PMP at last because if SMEPMP is detected,
 	 * M-mode access to the S/U space will be rescinded.
diff --git a/lib/sbi/sbi_unit_test.c b/lib/sbi/sbi_unit_test.c
new file mode 100644
index 0000000..f4988d8
--- /dev/null
+++ b/lib/sbi/sbi_unit_test.c
@@ -0,0 +1,43 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_unit_test.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_console.h>
+
+extern struct sbiunit_test_suite *sbi_unit_tests[];
+extern unsigned long sbi_unit_tests_size;
+
+static void run_test_suite(struct sbiunit_test_suite *suite)
+{
+	struct sbiunit_test_case *s_case;
+	u32 count_pass = 0, count_fail = 0;
+
+	sbi_printf("## Running test suite: %s\n", suite->name);
+
+	s_case = suite->cases;
+	while (s_case->enabled) {
+		s_case->test_func(s_case);
+		if (s_case->failed)
+			count_fail++;
+		else
+			count_pass++;
+		sbi_printf("[%s] %s\n", s_case->failed ? "FAILED" : "PASSED",
+			   s_case->name);
+		s_case++;
+	}
+	sbi_printf("%u PASSED / %u FAILED / %u TOTAL\n", count_pass, count_fail,
+		   count_pass + count_fail);
+}
+
+void run_all_tests(void)
+{
+	u32 i;
+
+	sbi_printf("\n# Running SBIUNIT tests #\n");
+
+	for (i = 0; i < sbi_unit_tests_size; i++)
+		run_test_suite(sbi_unit_tests[i]);
+}
diff --git a/lib/sbi/sbi_unit_tests.carray b/lib/sbi/sbi_unit_tests.carray
new file mode 100644
index 0000000..8d6069b
--- /dev/null
+++ b/lib/sbi/sbi_unit_tests.carray
@@ -0,0 +1,3 @@
+HEADER: sbi/sbi_unit_test.h
+TYPE: struct sbiunit_test_suite
+NAME: sbi_unit_tests
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:23 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:23 +0000
Subject: [PATCH v2 3/5] Makefile: clean '.c' files generated by carray
In-Reply-To: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
Message-ID: <20240215161625.314131-4-ivan.orlov0322@gmail.com>

`make clean` doesn't clear the '*.c' files generated by carray.sh
in the 'build' directory. Fix it by extending the 'clean' makefile
target.

This is the only way we are able to regenerate the carray .c file in
case if we add a new test to the 'carray-sbi_unit_tests-y' Makefile
variable. However, running `make clear` every time we add a new test
is not really convenient, so the mechanics should be changed in the
future.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
 Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Makefile b/Makefile
index 680c19a..4519277 100644
--- a/Makefile
+++ b/Makefile
@@ -684,6 +684,8 @@ clean:
 	$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
 	$(if $(V), @echo " RM        $(build_dir)/*.dtb")
 	$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
+	$(if $(V), @echo " RM        $(build_dir)/*.c")
+	$(CMD_PREFIX)find $(build_dir) -type f -name "*.c" -exec rm -rf {} +
 
 # Rule for "make distclean"
 .PHONY: distclean
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:24 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:24 +0000
Subject: [PATCH v2 4/5] lib: tests: Add a test for sbi_bitmap
In-Reply-To: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
Message-ID: <20240215161625.314131-5-ivan.orlov0322@gmail.com>

Add test suite covering all of the functions from lib/sbi/sbi_bitmap.c:
__bitmap_and, __bitmap_or and __bitmap_xor.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
V1 -> V2:
- Extract the part of the commit description to the cover letter
- Update to use the carray functionality instead of placing the pointer
to the test suite directly into the sources
- Fix codestyle issues
- Use the references to the data_* arrays when defining the expected
test results, instead of repeating the same numbers again and again

 lib/sbi/objects.mk        |   3 ++
 lib/sbi/sbi_bitmap_test.c | 103 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+)
 create mode 100644 lib/sbi/sbi_bitmap_test.c

diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 08959f1..b4c273f 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -14,6 +14,9 @@ libsbi-objs-y += riscv_locks.o
 libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_test.o
 libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
 
+libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitmap_test_suite
+
 libsbi-objs-y += sbi_ecall.o
 libsbi-objs-y += sbi_ecall_exts.o
 
diff --git a/lib/sbi/sbi_bitmap_test.c b/lib/sbi/sbi_bitmap_test.c
new file mode 100644
index 0000000..918e7d9
--- /dev/null
+++ b/lib/sbi/sbi_bitmap_test.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_bitmap.h>
+#include <sbi/sbi_unit_test.h>
+#include <sbi/sbi_console.h>
+
+#define DATA_SIZE sizeof(data_zero)
+#define DATA_BIT_SIZE (DATA_SIZE * 8)
+
+static u64 data_a[] = { 0xDEADBEEF, 0x00BAB10C, 0x1BADB002, 0xABADBABE };
+static u64 data_b[] = { 0xC00010FF, 0x00BAB10C, 0xBAAAAAAD, 0xBADDCAFE };
+static u64 data_zero[] = { 0, 0, 0, 0 };
+
+static void bitmap_and_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_and_b[] = { data_a[0] & data_b[0], data_a[1] & data_b[1],
+			  data_a[2] & data_b[2], data_a[3] & data_b[3] };
+
+	__bitmap_and(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_and_b, DATA_SIZE);
+
+	/* a & a = a */
+	__bitmap_and(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_ASSERT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	/* a & 0 = 0 */
+	__bitmap_and(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	/* 0 & 0 = 0 */
+	__bitmap_and(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	/* Cover zero 'bits' argument */
+	__bitmap_and(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static void bitmap_or_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_or_b[] = { data_a[0] | data_b[0], data_a[1] | data_b[1],
+			 data_a[2] | data_b[2], data_a[3] | data_b[3] };
+
+	__bitmap_or(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_or_b, DATA_SIZE);
+
+	/* a | a = a */
+	__bitmap_or(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	/* a | 0 = a */
+	__bitmap_or(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	/* 0 | 0 = 0 */
+	__bitmap_or(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	__bitmap_or(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static void bitmap_xor_test(struct sbiunit_test_case *test)
+{
+	u64 res[DATA_SIZE];
+	u64 a_xor_b[] = { data_a[0] ^ data_b[0], data_a[1] ^ data_b[1],
+			  data_a[2] ^ data_b[2], data_a[3] ^ data_b[3] };
+
+	__bitmap_xor(res, data_a, data_b, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, a_xor_b, DATA_SIZE);
+
+	/* a ^ 0 = a */
+	__bitmap_xor(res, data_a, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_a, DATA_SIZE);
+
+	/* a ^ a = 0 */
+	__bitmap_xor(res, data_a, data_a, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	/* 0 ^ 0 = 0 */
+	__bitmap_xor(res, data_zero, data_zero, DATA_BIT_SIZE);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+
+	sbi_memcpy(res, data_zero, DATA_SIZE);
+	__bitmap_xor(res, data_a, data_b, 0);
+	SBIUNIT_EXPECT_MEMEQ(test, res, data_zero, DATA_SIZE);
+}
+
+static struct sbiunit_test_case bitmap_test_cases[] = {
+	SBIUNIT_TEST_CASE(bitmap_and_test),
+	SBIUNIT_TEST_CASE(bitmap_or_test),
+	SBIUNIT_TEST_CASE(bitmap_xor_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(bitmap_test_suite, bitmap_test_cases);
-- 
2.34.1



From ivan.orlov0322 at gmail.com  Thu Feb 15 08:16:25 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Thu, 15 Feb 2024 16:16:25 +0000
Subject: [PATCH v2 5/5] lib: tests: Add sbi_console test
In-Reply-To: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
Message-ID: <20240215161625.314131-6-ivan.orlov0322@gmail.com>

Add the test suite covering some of the functions from
lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
of format specifiers for printf and different strings and characters for
putc and puts.

In order to do that, the test "mocks" the sbi_console_device structure
by setting the 'console_dev' variable to the virtual console.

Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
---
V1 -> V2:
- Rewrite using the carray functionality
- Replace CONSOLE_DO and CONSOLE_DO_RET macros with two inline
functions: one of them "mocks" the default console device, and
the second one restores the old console device.
- Fix codestyle issues (comments, etc.)
- Remove incorrect 'puts' test
- Use updated SBIUNIT_ASSERT_STREQ API

 lib/sbi/objects.mk         |   1 +
 lib/sbi/sbi_console.c      |   4 ++
 lib/sbi/sbi_console_test.c | 102 +++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 lib/sbi/sbi_console_test.c

diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index b4c273f..9d065fa 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -16,6 +16,7 @@ libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
 
 libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
 carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitmap_test_suite
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += console_test_suite
 
 libsbi-objs-y += sbi_ecall.o
 libsbi-objs-y += sbi_ecall_exts.o
diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
index ab09a5c..d1229d0 100644
--- a/lib/sbi/sbi_console.c
+++ b/lib/sbi/sbi_console.c
@@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
 
 	return rc;
 }
+
+#ifdef CONFIG_SBIUNIT
+#include "sbi_console_test.c"
+#endif
diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
new file mode 100644
index 0000000..f24b329
--- /dev/null
+++ b/lib/sbi/sbi_console_test.c
@@ -0,0 +1,102 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
+ */
+#include <sbi/sbi_unit_test.h>
+#include <sbi/sbi_heap.h>
+
+#define TEST_CONSOLE_BUF_LEN 1024
+
+static const struct sbi_console_device *old_dev;
+static char test_console_buf[TEST_CONSOLE_BUF_LEN];
+static u32 test_console_buf_pos;
+
+static void test_console_putc(char c)
+{
+	test_console_buf[test_console_buf_pos] = c;
+	test_console_buf_pos = (test_console_buf_pos + 1) % TEST_CONSOLE_BUF_LEN;
+}
+
+static void clear_test_console_buf(void)
+{
+	test_console_buf_pos = 0;
+	test_console_buf[0] = '\0';
+}
+
+static const struct sbi_console_device new_dev = {
+	.name = "Test console device",
+	.console_putc = test_console_putc,
+};
+
+/* Mock the console device */
+static inline void test_console_begin(const struct sbi_console_device *device)
+{
+	old_dev = console_dev;
+	console_dev = device;
+}
+
+static inline void test_console_end(void)
+{
+	console_dev = old_dev;
+}
+
+static void putc_test(struct sbiunit_test_case *test)
+{
+	clear_test_console_buf();
+
+	test_console_begin(&new_dev);
+	sbi_putc('a');
+	test_console_end();
+	SBIUNIT_ASSERT_EQ(test, test_console_buf[0], 'a');
+}
+
+#define PUTS_TEST(test, expected, str) do {			\
+	clear_test_console_buf();				\
+	test_console_begin(&new_dev);				\
+	sbi_puts(str);						\
+	test_console_end();					\
+	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
+			     sbi_strlen(expected));		\
+} while (0)
+
+static void puts_test(struct sbiunit_test_case *test)
+{
+	PUTS_TEST(test, "Hello, OpenSBI!", "Hello, OpenSBI!");
+	PUTS_TEST(test, "Hello,\r\nOpenSBI!", "Hello,\nOpenSBI!");
+}
+
+#define PRINTF_TEST(test, expected, format, ...) do {		\
+	clear_test_console_buf();				\
+	test_console_begin(&new_dev);				\
+	size_t __res = sbi_printf(format, ##__VA_ARGS__);	\
+	test_console_end();					\
+	SBIUNIT_ASSERT_EQ(test, __res, sbi_strlen(expected));	\
+	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
+			     sbi_strlen(expected));		\
+} while (0)
+
+static void printf_test(struct sbiunit_test_case *test)
+{
+	PRINTF_TEST(test, "Hello", "Hello");
+	PRINTF_TEST(test, "3 5 7", "%d %d %d", 3, 5, 7);
+	PRINTF_TEST(test, "Hello", "%s", "Hello");
+	PRINTF_TEST(test, "-1", "%d", -1);
+	PRINTF_TEST(test, "FF", "%X", 255);
+	PRINTF_TEST(test, "ff", "%x", 255);
+	PRINTF_TEST(test, "A", "%c", 'A');
+	PRINTF_TEST(test, "1fe", "%p", (void *)0x1fe);
+	PRINTF_TEST(test, "4294967295", "%u", 4294967295U);
+	PRINTF_TEST(test, "-2147483647", "%ld", -2147483647l);
+	PRINTF_TEST(test, "-9223372036854775807", "%lld", -9223372036854775807LL);
+	PRINTF_TEST(test, "18446744073709551615", "%llu", 18446744073709551615ULL);
+}
+
+static struct sbiunit_test_case console_test_cases[] = {
+	SBIUNIT_TEST_CASE(putc_test),
+	SBIUNIT_TEST_CASE(puts_test),
+	SBIUNIT_TEST_CASE(printf_test),
+	{},
+};
+
+SBIUNIT_TEST_SUITE(console_test_suite, console_test_cases);
-- 
2.34.1



From atishp at rivosinc.com  Fri Feb 16 16:06:07 2024
From: atishp at rivosinc.com (Atish Patra)
Date: Fri, 16 Feb 2024 16:06:07 -0800
Subject: [PATCH v1 0/1] Add Indirect CSR and Counter delegation ISA extension support 
Message-ID: <20240217000608.3635372-1-atishp@rivosinc.com>

This patch adds indirect CSR S[m|s]csrind extension[1] and counter delegation
extensions[2] support. M-mode don't have to do a lot except setting the correct
bits in mstateen/menvcfg/mcountern.

The Qemu patches can be found here:
https://github.com/atishp04/qemu/tree/counter_delegation_rfc

The opensbi patch can be found here:
https://github.com/atishp04/opensbi/tree/counter_delegation_v1

The Linux kernel patches can be found here:
https://github.com/atishp04/linux/tree/counter_delegation_rfc


[1] https://github.com/riscv/riscv-indirect-csr-access
[2] https://github.com/riscv/riscv-smcdeleg-ssccfg

Atish Patra (1):
lib: sbi: Add support for smcsrind and smcdeleg

include/sbi/riscv_encoding.h | 25 ++++++++++++++++++++++---
include/sbi/sbi_hart.h       |  8 ++++++++
lib/sbi/sbi_hart.c           | 16 ++++++++++++----
3 files changed, 42 insertions(+), 7 deletions(-)

--
2.34.1



From atishp at rivosinc.com  Fri Feb 16 16:06:08 2024
From: atishp at rivosinc.com (Atish Patra)
Date: Fri, 16 Feb 2024 16:06:08 -0800
Subject: [PATCH v1 1/1] lib: sbi: Add support for smcsrind and smcdeleg
In-Reply-To: <20240217000608.3635372-1-atishp@rivosinc.com>
References: <20240217000608.3635372-1-atishp@rivosinc.com>
Message-ID: <20240217000608.3635372-2-atishp@rivosinc.com>

Smcsrind allows generic indirect CSR access mechanism while
Smcdeleg allows delegating hpmcounters in Supervisor mode.

Enable both extensions and set the appropriate bits in mstateen
and menvcfg.

Co-developed-by: Kaiwen Xue <kaiwenxue1 at gmail.com>
Signed-off-by: Atish Patra <atishp at rivosinc.com>
---
 include/sbi/riscv_encoding.h | 25 ++++++++++++++++++++++---
 include/sbi/sbi_hart.h       |  8 ++++++++
 lib/sbi/sbi_hart.c           | 16 ++++++++++++----
 3 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index e74cc0df1c40..57aabd665589 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -209,6 +209,7 @@
 
 #define ENVCFG_STCE			(_ULL(1) << 63)
 #define ENVCFG_PBMTE			(_ULL(1) << 62)
+#define ENVCFG_CDE			(_UL(1) << 60)
 #define ENVCFG_CBZE			(_UL(1) << 7)
 #define ENVCFG_CBCFE			(_UL(1) << 6)
 #define ENVCFG_CBIE_SHIFT		4
@@ -314,6 +315,9 @@
 /* Supervisor Configuration */
 #define CSR_SENVCFG			0x10a
 
+/* Supervisor Conter Inhibit */
+#define CSR_SCOUNTINHIBIT		0x120
+
 /* Supervisor Trap Handling */
 #define CSR_SSCRATCH			0x140
 #define CSR_SEPC			0x141
@@ -328,9 +332,14 @@
 /* Supervisor Protection and Translation */
 #define CSR_SATP			0x180
 
-/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
+/* Supervisor Indirect Register Alias */
 #define CSR_SISELECT			0x150
 #define CSR_SIREG			0x151
+#define CSR_SIREG2          		0x152
+#define CSR_SIREG3          		0x153
+#define CSR_SIREG4          		0x155
+#define CSR_SIREG5          		0x156
+#define CSR_SIREG6          		0x157
 
 /* Supervisor-Level Interrupts (AIA) */
 #define CSR_STOPEI			0x15c
@@ -391,9 +400,14 @@
 #define CSR_HVIPRIO1			0x646
 #define CSR_HVIPRIO2			0x647
 
-/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */
+/* Virtual Supervisor Indirect Alias */
 #define CSR_VSISELECT			0x250
 #define CSR_VSIREG			0x251
+#define CSR_VSIREG2         		0x252
+#define CSR_VSIREG3         		0x253
+#define CSR_VSIREG4         		0x255
+#define CSR_VSIREG5         		0x256
+#define CSR_VSIREG6         		0x257
 
 /* VS-Level Interrupts (H-extension with AIA) */
 #define CSR_VSTOPEI			0x25c
@@ -694,9 +708,14 @@
 #define CSR_DSCRATCH0			0x7b2
 #define CSR_DSCRATCH1			0x7b3
 
-/* Machine-Level Window to Indirectly Accessed Registers (AIA) */
+/* Machine Indirect Register Alias */
 #define CSR_MISELECT			0x350
 #define CSR_MIREG			0x351
+#define CSR_MIREG2          		0x352
+#define CSR_MIREG3          		0x353
+#define CSR_MIREG4          		0x355
+#define CSR_MIREG5          		0x356
+#define CSR_MIREG6          		0x357
 
 /* Machine-Level Interrupts (AIA) */
 #define CSR_MTOPEI			0x35c
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index 10dc3df5d2fc..cc78eec6f65a 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -55,6 +55,14 @@ enum sbi_hart_extensions {
 	SBI_HART_EXT_SVPBMT,
 	/** Hart has debug trigger extension */
 	SBI_HART_EXT_SDTRIG,
+	/** Hart has Smcsrind extension */
+	SBI_HART_EXT_SMCSRIND,
+	/** Hart has Smcdeleg extension */
+	SBI_HART_EXT_SMCDELEG,
+	/** Hart has Sscsrind extension */
+	SBI_HART_EXT_SSCSRIND,
+	/** Hart has Ssccfg extension */
+	SBI_HART_EXT_SSCCFG,
 
 	/** Maximum index of Hart extension */
 	SBI_HART_EXT_MAX,
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index a0ab0c640035..3d1369441c05 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -95,11 +95,16 @@ static void mstatus_init(struct sbi_scratch *scratch)
 		mstateen_val |= SMSTATEEN0_HSENVCFG;
 
 		if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMAIA))
-			mstateen_val |= (SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT |
-					SMSTATEEN0_IMSIC);
+			mstateen_val |= (SMSTATEEN0_AIA | SMSTATEEN0_IMSIC);
 		else
-			mstateen_val &= ~(SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT |
-					SMSTATEEN0_IMSIC);
+			mstateen_val &= ~(SMSTATEEN0_AIA | SMSTATEEN0_IMSIC);
+
+		if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMAIA) ||
+		    sbi_hart_has_extension(scratch, SBI_HART_EXT_SMCSRIND))
+			mstateen_val |= (SMSTATEEN0_SVSLCT);
+		else
+			mstateen_val &= ~(SMSTATEEN0_SVSLCT);
+
 		csr_write(CSR_MSTATEEN0, mstateen_val);
 #if __riscv_xlen == 32
 		csr_write(CSR_MSTATEEN0H, mstateen_val >> 32);
@@ -129,6 +134,7 @@ static void mstatus_init(struct sbi_scratch *scratch)
 		__set_menvcfg_ext(SBI_HART_EXT_SVPBMT, ENVCFG_PBMTE)
 #endif
 		__set_menvcfg_ext(SBI_HART_EXT_SSTC, ENVCFG_STCE)
+		__set_menvcfg_ext(SBI_HART_EXT_SMCDELEG, ENVCFG_CDE);
 
 #undef __set_menvcfg_ext
 
@@ -658,6 +664,8 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
 	__SBI_HART_EXT_DATA(zicbom, SBI_HART_EXT_ZICBOM),
 	__SBI_HART_EXT_DATA(svpbmt, SBI_HART_EXT_SVPBMT),
 	__SBI_HART_EXT_DATA(sdtrig, SBI_HART_EXT_SDTRIG),
+	__SBI_HART_EXT_DATA(smcsrind, SBI_HART_EXT_SMCSRIND),
+	__SBI_HART_EXT_DATA(smcdeleg, SBI_HART_EXT_SMCDELEG),
 };
 
 /**
-- 
2.34.1



From wxjstz at 126.com  Sat Feb 17 21:34:02 2024
From: wxjstz at 126.com (Xiang W)
Date: Sun, 18 Feb 2024 13:34:02 +0800
Subject: [PATCH v2 5/5] lib: tests: Add sbi_console test
In-Reply-To: <20240215161625.314131-6-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
	 <20240215161625.314131-6-ivan.orlov0322@gmail.com>
Message-ID: <b55c0465e280bbd774f21ba3937ced5bb4c66cf7.camel@126.com>

? 2024-02-15???? 16:16 +0000?Ivan Orlov???
> Add the test suite covering some of the functions from
> lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
> of format specifiers for printf and different strings and characters for
> putc and puts.
> 
> In order to do that, the test "mocks" the sbi_console_device structure
> by setting the 'console_dev' variable to the virtual console.
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
> V1 -> V2:
> - Rewrite using the carray functionality
> - Replace CONSOLE_DO and CONSOLE_DO_RET macros with two inline
> functions: one of them "mocks" the default console device, and
> the second one restores the old console device.
> - Fix codestyle issues (comments, etc.)
> - Remove incorrect 'puts' test
> - Use updated SBIUNIT_ASSERT_STREQ API
> 
> ?lib/sbi/objects.mk???????? |?? 1 +
> ?lib/sbi/sbi_console.c????? |?? 4 ++
> ?lib/sbi/sbi_console_test.c | 102 +++++++++++++++++++++++++++++++++++++
> ?3 files changed, 107 insertions(+)
> ?create mode 100644 lib/sbi/sbi_console_test.c
> 
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index b4c273f..9d065fa 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -16,6 +16,7 @@ libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
> ?
> ?libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
> ?carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitmap_test_suite
> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += console_test_suite
> ?
> ?libsbi-objs-y += sbi_ecall.o
> ?libsbi-objs-y += sbi_ecall_exts.o
> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
> index ab09a5c..d1229d0 100644
> --- a/lib/sbi/sbi_console.c
> +++ b/lib/sbi/sbi_console.c
> @@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
> ?
> ?	return rc;
> ?}
> +
> +#ifdef CONFIG_SBIUNIT
> +#include "sbi_console_test.c"
> +#endif
> diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
> new file mode 100644
> index 0000000..f24b329
> --- /dev/null
> +++ b/lib/sbi/sbi_console_test.c
> @@ -0,0 +1,102 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_unit_test.h>
> +#include <sbi/sbi_heap.h>

sbi_heap.h is not needed.

Regards,
Xiang W
> +
> +#define TEST_CONSOLE_BUF_LEN 1024
> +
> +static const struct sbi_console_device *old_dev;
> +static char test_console_buf[TEST_CONSOLE_BUF_LEN];
> +static u32 test_console_buf_pos;
> +
> +static void test_console_putc(char c)
> +{
> +	test_console_buf[test_console_buf_pos] = c;
> +	test_console_buf_pos = (test_console_buf_pos + 1) % TEST_CONSOLE_BUF_LEN;
> +}
> +
> +static void clear_test_console_buf(void)
> +{
> +	test_console_buf_pos = 0;
> +	test_console_buf[0] = '\0';
> +}
> +
> +static const struct sbi_console_device new_dev = {
> +	.name = "Test console device",
> +	.console_putc = test_console_putc,
> +};
> +
> +/* Mock the console device */
> +static inline void test_console_begin(const struct sbi_console_device *device)
> +{
> +	old_dev = console_dev;
> +	console_dev = device;
> +}
> +
> +static inline void test_console_end(void)
> +{
> +	console_dev = old_dev;
> +}
> +
> +static void putc_test(struct sbiunit_test_case *test)
> +{
> +	clear_test_console_buf();
> +
> +	test_console_begin(&new_dev);
> +	sbi_putc('a');
> +	test_console_end();
> +	SBIUNIT_ASSERT_EQ(test, test_console_buf[0], 'a');
> +}
> +
> +#define PUTS_TEST(test, expected, str) do {			\
> +	clear_test_console_buf();				\
> +	test_console_begin(&new_dev);				\
> +	sbi_puts(str);						\
> +	test_console_end();					\
> +	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
> +			???? sbi_strlen(expected));		\
> +} while (0)
> +
> +static void puts_test(struct sbiunit_test_case *test)
> +{
> +	PUTS_TEST(test, "Hello, OpenSBI!", "Hello, OpenSBI!");
> +	PUTS_TEST(test, "Hello,\r\nOpenSBI!", "Hello,\nOpenSBI!");
> +}
> +
> +#define PRINTF_TEST(test, expected, format, ...) do {		\
> +	clear_test_console_buf();				\
> +	test_console_begin(&new_dev);				\
> +	size_t __res = sbi_printf(format, ##__VA_ARGS__);	\
> +	test_console_end();					\
> +	SBIUNIT_ASSERT_EQ(test, __res, sbi_strlen(expected));	\
> +	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
> +			???? sbi_strlen(expected));		\
> +} while (0)
> +
> +static void printf_test(struct sbiunit_test_case *test)
> +{
> +	PRINTF_TEST(test, "Hello", "Hello");
> +	PRINTF_TEST(test, "3 5 7", "%d %d %d", 3, 5, 7);
> +	PRINTF_TEST(test, "Hello", "%s", "Hello");
> +	PRINTF_TEST(test, "-1", "%d", -1);
> +	PRINTF_TEST(test, "FF", "%X", 255);
> +	PRINTF_TEST(test, "ff", "%x", 255);
> +	PRINTF_TEST(test, "A", "%c", 'A');
> +	PRINTF_TEST(test, "1fe", "%p", (void *)0x1fe);
> +	PRINTF_TEST(test, "4294967295", "%u", 4294967295U);
> +	PRINTF_TEST(test, "-2147483647", "%ld", -2147483647l);
> +	PRINTF_TEST(test, "-9223372036854775807", "%lld", -9223372036854775807LL);
> +	PRINTF_TEST(test, "18446744073709551615", "%llu", 18446744073709551615ULL);
> +}
> +
> +static struct sbiunit_test_case console_test_cases[] = {
> +	SBIUNIT_TEST_CASE(putc_test),
> +	SBIUNIT_TEST_CASE(puts_test),
> +	SBIUNIT_TEST_CASE(printf_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(console_test_suite, console_test_cases);
> -- 
> 2.34.1
> 
> 



From ivan.orlov0322 at gmail.com  Sun Feb 18 12:54:28 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Sun, 18 Feb 2024 20:54:28 +0000
Subject: [PATCH v2 5/5] lib: tests: Add sbi_console test
In-Reply-To: <b55c0465e280bbd774f21ba3937ced5bb4c66cf7.camel@126.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-6-ivan.orlov0322@gmail.com>
 <b55c0465e280bbd774f21ba3937ced5bb4c66cf7.camel@126.com>
Message-ID: <f89b60f4-5cfc-45cd-acba-944543632530@gmail.com>

On 2/18/24 05:34, Xiang W wrote:
> ? 2024-02-15???? 16:16 +0000?Ivan Orlov???
>> Add the test suite covering some of the functions from
>> lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
>> of format specifiers for printf and different strings and characters for
>> putc and puts.
>>
>> In order to do that, the test "mocks" the sbi_console_device structure
>> by setting the 'console_dev' variable to the virtual console.
>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>> V1 -> V2:
>> - Rewrite using the carray functionality
>> - Replace CONSOLE_DO and CONSOLE_DO_RET macros with two inline
>> functions: one of them "mocks" the default console device, and
>> the second one restores the old console device.
>> - Fix codestyle issues (comments, etc.)
>> - Remove incorrect 'puts' test
>> - Use updated SBIUNIT_ASSERT_STREQ API
>>
>>  ?lib/sbi/objects.mk???????? |?? 1 +
>>  ?lib/sbi/sbi_console.c????? |?? 4 ++
>>  ?lib/sbi/sbi_console_test.c | 102 +++++++++++++++++++++++++++++++++++++
>>  ?3 files changed, 107 insertions(+)
>>  ?create mode 100644 lib/sbi/sbi_console_test.c
>>
>> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
>> index b4c273f..9d065fa 100644
>> --- a/lib/sbi/objects.mk
>> +++ b/lib/sbi/objects.mk
>> @@ -16,6 +16,7 @@ libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
>>   
>>  ?libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
>>  ?carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitmap_test_suite
>> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += console_test_suite
>>   
>>  ?libsbi-objs-y += sbi_ecall.o
>>  ?libsbi-objs-y += sbi_ecall_exts.o
>> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
>> index ab09a5c..d1229d0 100644
>> --- a/lib/sbi/sbi_console.c
>> +++ b/lib/sbi/sbi_console.c
>> @@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
>>   
>>  ?	return rc;
>>  ?}
>> +
>> +#ifdef CONFIG_SBIUNIT
>> +#include "sbi_console_test.c"
>> +#endif
>> diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
>> new file mode 100644
>> index 0000000..f24b329
>> --- /dev/null
>> +++ b/lib/sbi/sbi_console_test.c
>> @@ -0,0 +1,102 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#include <sbi/sbi_unit_test.h>
>> +#include <sbi/sbi_heap.h>
> 
> sbi_heap.h is not needed.
> 

Thanks, I'll fix it in V3.

-- 
Kind regards,
Ivan Orlov



From joshua.yeong at starfivetech.com  Sun Feb 18 23:14:06 2024
From: joshua.yeong at starfivetech.com (Joshua Yeong)
Date: Mon, 19 Feb 2024 15:14:06 +0800
Subject: [PATCH 1/1] lib: sbi_hsm: Restor hart state to stop when fails to start
Message-ID: <20240219071406.41703-1-joshua.yeong@starfivetech.com>

Hart state should change back to hart stop when hsm_device_hart_start()
or sbi_ipi_raw_send() fails to perform hart start.

Signed-off-by: Joshua Yeong <joshua.yeong at starfivetech.com>
---
 lib/sbi/sbi_hsm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index 3d60ceb..be48d64 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -360,6 +360,10 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
 
 	if (!rc)
 		return 0;
+
+	/* If it fails to start, change hart state back to stop */
+	__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_START_PENDING,
+				    SBI_HSM_STATE_STOPPED);
 err:
 	hsm_start_ticket_release(hdata);
 	return rc;
-- 
2.25.1



From joshua.yeong at starfivetech.com  Mon Feb 19 01:44:37 2024
From: joshua.yeong at starfivetech.com (Joshua Yeong)
Date: Mon, 19 Feb 2024 09:44:37 +0000
Subject: [PATCH 1/1] lib: sbi_hsm: Restor hart state to stop when fails to
 start
In-Reply-To: <fd9ed70b05fa883b9497b592c0ddd906dd70fdc1.camel@126.com>
References: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
 <fd9ed70b05fa883b9497b592c0ddd906dd70fdc1.camel@126.com>
Message-ID: <SH0PR01MB0841D6EDDEA711F2D14C309EF951A@SH0PR01MB0841.CHNPR01.prod.partner.outlook.cn>

On Mon, Feb 19, 2024 at 05:39:26PM +0800, Joshua Yeong <joshua.yeong at starfivetech.com> wrote:
> ? 2024-02-19???? 15:14 +0800?Joshua Yeong???
> > Hart state should change back to hart stop when
> > hsm_device_hart_start() or sbi_ipi_raw_send() fails to perform hart start.
> >
> > Signed-off-by: Joshua Yeong <joshua.yeong at starfivetech.com>
> > ---
> > ?lib/sbi/sbi_hsm.c | 4 ++++
> > ?1 file changed, 4 insertions(+)
> >
> > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c index
> > 3d60ceb..be48d64 100644
> > --- a/lib/sbi/sbi_hsm.c
> > +++ b/lib/sbi/sbi_hsm.c
> > @@ -360,6 +360,10 @@ int sbi_hsm_hart_start(struct sbi_scratch
> > *scratch,
> >
> > ?	if (!rc)
> > ?		return 0;
> > +
> > +	/* If it fails to start, change hart state back to stop */
> > +	__sbi_hsm_hart_change_state(hdata,
> SBI_HSM_STATE_START_PENDING,
> > +				??? SBI_HSM_STATE_STOPPED);
> 
> This is not needed. Because if hdata->state is not equal to
> SBI_HSM_STATE_STOPPED, SBI_HSM_STATE_START_PENDING will not be
> written.
> 
> Regards,
> Xiang W

The scenario is that the Hart is in SBI_HSM_STATE_STOPPED and then it switches to SBI_HSM_STATE_START_PENDING,
but it got stuck in SBI_HSM_STATE_START_PENDING if it fails to start. The hart's state has impact on
other process where hart's state is taken into consideration, for example system suspend.

Regards,
Joshua 

> 
> > ?err:
> > ?	hsm_start_ticket_release(hdata);
> > ?	return rc;
> > --
> > 2.25.1
> >
> >


From wxjstz at 126.com  Mon Feb 19 01:35:38 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 19 Feb 2024 17:35:38 +0800
Subject: [PATCH 1/1] lib: sbi_hsm: Restor hart state to stop when fails
 to start
In-Reply-To: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
References: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
Message-ID: <fd9ed70b05fa883b9497b592c0ddd906dd70fdc1.camel@126.com>

? 2024-02-19???? 15:14 +0800?Joshua Yeong???
> Hart state should change back to hart stop when hsm_device_hart_start()
> or sbi_ipi_raw_send() fails to perform hart start.
> 
> Signed-off-by: Joshua Yeong <joshua.yeong at starfivetech.com>
> ---
> ?lib/sbi/sbi_hsm.c | 4 ++++
> ?1 file changed, 4 insertions(+)
> 
> diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
> index 3d60ceb..be48d64 100644
> --- a/lib/sbi/sbi_hsm.c
> +++ b/lib/sbi/sbi_hsm.c
> @@ -360,6 +360,10 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
> ?
> ?	if (!rc)
> ?		return 0;
> +
> +	/* If it fails to start, change hart state back to stop */
> +	__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_START_PENDING,
> +				??? SBI_HSM_STATE_STOPPED);

This is not needed. Because if hdata->state is not equal to SBI_HSM_STATE_STOPPED,
SBI_HSM_STATE_START_PENDING will not be written.

Regards,
Xiang W

> ?err:
> ?	hsm_start_ticket_release(hdata);
> ?	return rc;
> -- 
> 2.25.1
> 
> 



From wxjstz at 126.com  Mon Feb 19 02:01:28 2024
From: wxjstz at 126.com (Xiang W)
Date: Mon, 19 Feb 2024 18:01:28 +0800
Subject: [PATCH 1/1] lib: sbi_hsm: Restor hart state to stop when fails
 to start
In-Reply-To: <SH0PR01MB0841D6EDDEA711F2D14C309EF951A@SH0PR01MB0841.CHNPR01.prod.partner.outlook.cn>
References: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
	 <fd9ed70b05fa883b9497b592c0ddd906dd70fdc1.camel@126.com>
	 <SH0PR01MB0841D6EDDEA711F2D14C309EF951A@SH0PR01MB0841.CHNPR01.prod.partner.outlook.cn>
Message-ID: <2cd3f4bb21bd2ae6e564d7edebb55bd6baa52194.camel@126.com>

? 2024-02-19???? 09:44 +0000?Joshua Yeong???
> On Mon, Feb 19, 2024 at 05:39:26PM +0800, Joshua Yeong <joshua.yeong at starfivetech.com> wrote:
> > ? 2024-02-19???? 15:14 +0800?Joshua Yeong???
> > > Hart state should change back to hart stop when
> > > hsm_device_hart_start() or sbi_ipi_raw_send() fails to perform hart start.
> > > 
> > > Signed-off-by: Joshua Yeong <joshua.yeong at starfivetech.com>
> > > ---
> > > ?lib/sbi/sbi_hsm.c | 4 ++++
> > > ?1 file changed, 4 insertions(+)
> > > 
> > > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c index
> > > 3d60ceb..be48d64 100644
> > > --- a/lib/sbi/sbi_hsm.c
> > > +++ b/lib/sbi/sbi_hsm.c
> > > @@ -360,6 +360,10 @@ int sbi_hsm_hart_start(struct sbi_scratch
> > > *scratch,
> > > 
> > > ?	if (!rc)
> > > ?		return 0;
> > > +
> > > +	/* If it fails to start, change hart state back to stop */
> > > +	__sbi_hsm_hart_change_state(hdata,
> > SBI_HSM_STATE_START_PENDING,
> > > +				??? SBI_HSM_STATE_STOPPED);
> > 
> > This is not needed. Because if hdata->state is not equal to
> > SBI_HSM_STATE_STOPPED, SBI_HSM_STATE_START_PENDING will not be
> > written.
> > 
> > Regards,
> > Xiang W
> 
> The scenario is that the Hart is in SBI_HSM_STATE_STOPPED and then it switches to SBI_HSM_STATE_START_PENDING,
> but it got stuck in SBI_HSM_STATE_START_PENDING if it fails to start. The hart's state has impact on
> other process where hart's state is taken into consideration, for example system suspend.

Sorry. I mistakenly thought that these codes were added after the err tag.

Signed-off-by: Xiang W <wxjstz at 126.com>
> 
> Regards,
> Joshua 
> 
> > 
> > > ?err:
> > > ?	hsm_start_ticket_release(hdata);
> > > ?	return rc;
> > > --
> > > 2.25.1
> > > 
> > > 
> 



From anup at brainfault.org  Tue Feb 20 02:41:28 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:11:28 +0530
Subject: [PATCH v3 1/4] lib:platform: Add support for specify coldboot
 harts in DT for generic.
In-Reply-To: <tencent_2B898B47FDD9EDB02C2B4291A06EC5C80108@qq.com>
References: <tencent_2B898B47FDD9EDB02C2B4291A06EC5C80108@qq.com>
Message-ID: <CAAhSdy1bpx8E2dQGBtfE8EYbHczrNEWwGMwNC1DvOwPPSeUK0A@mail.gmail.com>

On Thu, Feb 8, 2024 at 8:49?AM Cheng Yang <yangcheng.work at foxmail.com> wrote:
>
> Added support for the generic platform to specify the set of coldboot
> hart in DT. If not specified in DT, all harts are allowed to coldboot
> as before.
>
> The functions related to sbi_hartmask are not available before coldboot,
> so I used bitmap, and added a new bitmap_test() function to test whether
> a certain bit of the bitmap is set.
>
> Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>
> ---
> Changes v2 -> v3:
>         Add patches to expand the series.
>
>  include/sbi/sbi_bitmap.h    |  5 +++
>  lib/utils/fdt/fdt_fixup.c   | 17 ++++++++++
>  platform/generic/platform.c | 65 ++++++++++++++++++++++++++++++++++++-
>  3 files changed, 86 insertions(+), 1 deletion(-)
>
> diff --git a/include/sbi/sbi_bitmap.h b/include/sbi/sbi_bitmap.h
> index 4f0ebb6..354476c 100644
> --- a/include/sbi/sbi_bitmap.h
> +++ b/include/sbi/sbi_bitmap.h
> @@ -62,6 +62,11 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
>         }
>  }
>
> +static inline int bitmap_test(unsigned long *bmap, int bit)
> +{
> +       return __test_bit(bit, bmap);
> +}
> +
>  static inline void bitmap_zero_except(unsigned long *dst,
>                                       int exception, int nbits)
>  {
> diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
> index 5fc7673..55e6987 100644
> --- a/lib/utils/fdt/fdt_fixup.c
> +++ b/lib/utils/fdt/fdt_fixup.c
> @@ -385,6 +385,21 @@ int fdt_reserved_memory_fixup(void *fdt)
>         return 0;
>  }
>
> +void fdt_config_fixup(void *fdt) {

The brace should be on a new line.

> +       int chosen_offset, config_offset;
> +
> +       chosen_offset = fdt_path_offset(fdt, "/chosen");
> +       if (chosen_offset < 0)
> +               return;
> +
> +

Redundant new line.

> +       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
> +       if (chosen_offset < 0)
> +               return;
> +
> +       fdt_nop_node(fdt, config_offset);
> +}
> +
>  void fdt_fixups(void *fdt)
>  {
>         fdt_aplic_fixup(fdt);
> @@ -398,4 +413,6 @@ void fdt_fixups(void *fdt)
>  #ifndef CONFIG_FDT_FIXUPS_PRESERVE_PMU_NODE
>         fdt_pmu_fixup(fdt);
>  #endif
> +
> +       fdt_config_fixup(fdt);
>  }
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index bfd7d31..5f76193 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -73,6 +73,61 @@ extern struct sbi_platform platform;
>  static bool platform_has_mlevel_imsic = false;
>  static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
>
> +DECLARE_BITMAP(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);

This needs to be static.

> +
> +/*
> + * The fw_platform_coldboot_init() function is called by fw_platform_init()
> + * function to initialize the cold boot harts allowed by the generic platform
> + * according to the DT property "cold-boot-harts" in "/chosen/opensbi-config"
> + * DT node. If there is no "cold-boot-harts" in DT, all harts will be allowed.
> + */
> +static void fw_platform_coldboot_init(void *fdt)

s/fw_platform_coldboot_init/fw_platform_coldboot_harts_init/

> +{
> +       int chosen_offset, config_offset, cpu_offset, len, err;
> +       u32 val32;
> +       const u32 *val;
> +
> +       bitmap_zero(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
> +
> +       chosen_offset = fdt_path_offset(fdt, "/chosen");
> +       if (chosen_offset < 0)
> +               goto default_config;
> +
> +       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
> +       if (config_offset < 0)
> +               goto default_config;
> +
> +       val = fdt_getprop(fdt, config_offset, "cold-boot-harts", &len);
> +       len = len / sizeof(u32);
> +       if (val && len) {
> +               for (int i = 0; i < len; i++) {
> +                       cpu_offset = fdt_node_offset_by_phandle(fdt,
> +                                                       fdt32_to_cpu(val[i]));
> +                       if (cpu_offset < 0)
> +                               goto default_config;
> +
> +                       err = fdt_parse_hart_id(fdt, cpu_offset, &val32);
> +                       if (err)
> +                               goto default_config;
> +
> +                       if (!fdt_node_is_enabled(fdt, cpu_offset))
> +                               continue;
> +
> +                       for (int i = 0; i < platform.hart_count; i++) {
> +                               if (val32 == generic_hart_index2id[i])
> +                                       bitmap_set(generic_coldboot_harts, i, 1);
> +                       }
> +
> +               }
> +       }
> +
> +       return;
> +
> +default_config:
> +       bitmap_fill(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
> +       return;
> +}
> +
>  /*
>   * The fw_platform_init() function is called very early on the boot HART
>   * OpenSBI reference firmwares so that platform specific code get chance
> @@ -133,6 +188,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
>         platform.heap_size = fw_platform_calculate_heap_size(hart_count);
>         platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
>
> +       fw_platform_coldboot_init(fdt);
> +
>         /* Return original FDT pointer */
>         return arg1;
>
> @@ -146,7 +203,13 @@ static bool generic_cold_boot_allowed(u32 hartid)
>         if (generic_plat && generic_plat->cold_boot_allowed)
>                 return generic_plat->cold_boot_allowed(
>                                                 hartid, generic_plat_match);
> -       return true;
> +
> +       for (int i = 0; i < platform.hart_count; i++) {
> +               if (hartid == generic_hart_index2id[i])
> +                       return bitmap_test(generic_coldboot_harts, i);
> +       }
> +
> +       return false;
>  }
>
>  static int generic_nascent_init(void)
> --
> 2.34.1
>

I have taken care of the above at the time of merging this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


From anup at brainfault.org  Tue Feb 20 02:42:47 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:12:47 +0530
Subject: [PATCH v3 2/4] docs: Add OpenSBI DT configuration guide.
In-Reply-To: <tencent_5F0F58AA15AB481BB7126486C4FCA38FEC07@qq.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com> <tencent_5F0F58AA15AB481BB7126486C4FCA38FEC07@qq.com>
Message-ID: <CAAhSdy1jnyUaEciobDRKAVgnffGrjj+BVUyFC2U7bunshQv6XQ@mail.gmail.com>

On Thu, Feb 8, 2024 at 8:50?AM Cheng Yang <yangcheng.work at foxmail.com> wrote:
>
> This patch add docs/opensbi_config.md which describes the
> "/chosen/opensbi-config" DT node and properties
>
> Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>

The docs/opensbi_config.md needs to be added to docs/doxygen.cfg otherwise
it looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  docs/opensbi_config.md | 83 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 83 insertions(+)
>  create mode 100644 docs/opensbi_config.md
>
> diff --git a/docs/opensbi_config.md b/docs/opensbi_config.md
> new file mode 100644
> index 0000000..0c42443
> --- /dev/null
> +++ b/docs/opensbi_config.md
> @@ -0,0 +1,83 @@
> +OpenSBI Device Tree Configuration Guideline
> +==================================
> +
> +Some configurations of OpenSBI's Generic Platform can be described
> +in the **device tree (DT) blob** (or flattened device tree) passed
> +to the OpenSBI firmwares by the previous booting stage. OpenSBI will
> +parse and use these configurations during the boot phase, but delete
> +them from the device tree at the end of cold boot.
> +
> +### OpenSBI Configuration Node
> +
> +All nodes related to OpenSBI configuration should be under the OpenSBI
> +configuration DT node. The **/chosen** DT node is the preferred parent
> +of the OpenSBI configuration DT node.
> +
> +The DT properties of a domain configuration DT node are as follows:
> +
> +* **compatible** (Mandatory) - The compatible string of the OpenSBI
> +  configuration. This DT property should have value *"opensbi,config"*
> +
> +* **cold-boot-harts** (Optional) - If a platform lacks an override
> +  cold_boot_allowed() mechanism, this DT property specifies that a
> +  set of harts is permitted to perform a cold boot. Otherwise, all
> +  harts are allowed to cold boot.
> +
> +The OpenSBI Configuration Node will be deleted at the end of cold boot
> +(replace the node (subtree) with nop tags).
> +
> +### Example
> +
> +```text
> +    chosen {
> +        opensbi-config {
> +            compatible = "opensbi,config";
> +            cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
> +        };
> +    };
> +
> +    cpus {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        timebase-frequency = <10000000>;
> +
> +        cpu0: cpu at 0 {
> +            device_type = "cpu";
> +            reg = <0x00>;
> +            compatible = "riscv";
> +            ...
> +        };
> +
> +        cpu1: cpu at 1 {
> +            device_type = "cpu";
> +            reg = <0x01>;
> +            compatible = "riscv";
> +            ...
> +        };
> +
> +        cpu2: cpu at 2 {
> +            device_type = "cpu";
> +            reg = <0x02>;
> +            compatible = "riscv";
> +            ...
> +        };
> +
> +        cpu3: cpu at 3 {
> +            device_type = "cpu";
> +            reg = <0x03>;
> +            compatible = "riscv";
> +            ...
> +        };
> +
> +        cpu4: cpu at 4 {
> +            device_type = "cpu";
> +            reg = <0x04>;
> +            compatible = "riscv";
> +            ...
> +        };
> +    };
> +
> +    uart1: serial at 10011000 {
> +        ...
> +    };
> +```
> --
> 2.34.1
>


From anup at brainfault.org  Tue Feb 20 02:43:52 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:13:52 +0530
Subject: [PATCH v3 3/4] platform: generic: Parse system suspend test from
 config node.
In-Reply-To: <tencent_BAE2CFD156362A6CF8CA52A4825B12727E06@qq.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com> <tencent_BAE2CFD156362A6CF8CA52A4825B12727E06@qq.com>
Message-ID: <CAAhSdy2xmb50fUU8UL4-nuuzUCWgaeYi4U0_Eu+Hrv2yD_wykw@mail.gmail.com>

On Thu, Feb 8, 2024 at 8:50?AM Cheng Yang <yangcheng.work at foxmail.com> wrote:
>
> This patch update generic_domains_init() so that "system-suspend-test"
> is parsed from "/chosen/opensbi-config" DT node.
>
> Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  platform/generic/platform.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index 5f76193..407d5b1 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -316,7 +316,7 @@ static int generic_domains_init(void)
>
>         if (offset >= 0) {
>                 offset = fdt_node_offset_by_compatible(fdt, offset,
> -                                                      "opensbi,domain,config");
> +                                                      "opensbi,config");
>                 if (offset >= 0 &&
>                     fdt_get_property(fdt, offset, "system-suspend-test", NULL))
>                         sbi_system_suspend_test_enable();
> --
> 2.34.1
>


From anup at brainfault.org  Tue Feb 20 02:44:49 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:14:49 +0530
Subject: [PATCH v3 4/4] docs: move documentation of system suspend test.
In-Reply-To: <tencent_828AACE84732BAD1216325B61CBD668BC00A@qq.com>
References: <20240208031434.3201705-1-yangcheng.work@foxmail.com> <tencent_828AACE84732BAD1216325B61CBD668BC00A@qq.com>
Message-ID: <CAAhSdy3FcujdQJh9UqB+VvA0DuVEBY0G4A0VhdyTM53OXgbETA@mail.gmail.com>

On Thu, Feb 8, 2024 at 8:50?AM Cheng Yang <yangcheng.work at foxmail.com> wrote:
>
> This patch move documentation of "system-suspend-test" from
> docs/domain_support.md to docs/opensbi_config.md
>
> Signed-off-by: Cheng Yang <yangcheng.work at foxmail.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  docs/domain_support.md | 4 ----
>  docs/opensbi_config.md | 4 ++++
>  2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/docs/domain_support.md b/docs/domain_support.md
> index b285d65..65b6142 100644
> --- a/docs/domain_support.md
> +++ b/docs/domain_support.md
> @@ -126,9 +126,6 @@ The DT properties of a domain configuration DT node are as follows:
>  * **compatible** (Mandatory) - The compatible string of the domain
>    configuration. This DT property should have value *"opensbi,domain,config"*
>
> -* **system-suspend-test** (Optional) - When present, enable a system
> -  suspend test implementation which simply waits five seconds and issues a WFI.
> -
>  ### Domain Memory Region Node
>
>  The domain memory region DT node describes details of a memory region and
> @@ -237,7 +234,6 @@ be done:
>      chosen {
>          opensbi-domains {
>              compatible = "opensbi,domain,config";
> -            system-suspend-test;
>
>              tmem: tmem {
>                  compatible = "opensbi,domain,memregion";
> diff --git a/docs/opensbi_config.md b/docs/opensbi_config.md
> index 0c42443..1b710f1 100644
> --- a/docs/opensbi_config.md
> +++ b/docs/opensbi_config.md
> @@ -23,6 +23,9 @@ The DT properties of a domain configuration DT node are as follows:
>    set of harts is permitted to perform a cold boot. Otherwise, all
>    harts are allowed to cold boot.
>
> +* **system-suspend-test** (Optional) - When present, enable a system
> +  suspend test implementation which simply waits five seconds and issues a WFI.
> +
>  The OpenSBI Configuration Node will be deleted at the end of cold boot
>  (replace the node (subtree) with nop tags).
>
> @@ -33,6 +36,7 @@ The OpenSBI Configuration Node will be deleted at the end of cold boot
>          opensbi-config {
>              compatible = "opensbi,config";
>              cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
> +            system-suspend-test;
>          };
>      };
>
> --
> 2.34.1
>


From anup at brainfault.org  Tue Feb 20 02:59:03 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:29:03 +0530
Subject: [PATCH] lib: sbi_pmu: Before using we should ensure PMU init done
In-Reply-To: <20240201020126.23833-1-gaoshanliukou@163.com>
References: <20240201020126.23833-1-gaoshanliukou@163.com>
Message-ID: <CAAhSdy1=iL-XCOT0WDRD1bZ3cV-6KCqTJSx2Quqa6YkJAwRypA@mail.gmail.com>

On Thu, Feb 1, 2024 at 7:32?AM yang.zhang <gaoshanliukou at 163.com> wrote:
>
> From: "yang.zhang" <yang.zhang at hexintek.com>
>
> If trap earlier before sbi_pmu_init done, some path would call
> sbi_pmu_ctr_incr_fw, then it would go wrong:
> 1. if phs_ptr_offset is zero, then it get a wrong pmu state ptr
> 2. if phs_ptr_offset is ok, but we didn't call pmu_set_hart_state_ptr
> it would be NULL POINT
>
> Of course, the above situation will not occur at present, but i think
> it's reasonable that we should check it before we use it.
>
> Test:
> 1. I test it on our platform, for now we only support LR/SC not AMO.
> So when call spin_lock, would trap for amo instruction then emulate
> it with LR/SC, then it goes wrong.Of course, this case is special only
> for us, but other trap earlier cases maybe also encounter this situation.
> 2.I aslo test on qemu thead-c906, but need do some changes for simulating
> this scenario.
>   2.1 revert f067bb84cf2dd6493ff3fa49294d3ec80481ad75, the commit causes
>   we can't emulate some instructions from M mode, i think the requirement
>   may be not reasonable.
>   2.2 Then, insert a 'rdtime' instruction before pmu_get_hart_state_ptr in
>   sbi_pmu_init, then something goes wrong.

The patch description needs to be simplified because it is too verbose.

>
> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
> ---
>  lib/sbi/sbi_pmu.c | 27 +++++++++++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
> index 6209ccc..4eccb82 100644
> --- a/lib/sbi/sbi_pmu.c
> +++ b/lib/sbi/sbi_pmu.c
> @@ -74,7 +74,7 @@ struct sbi_pmu_hart_state {
>  static unsigned long phs_ptr_offset;
>
>  #define pmu_get_hart_state_ptr(__scratch)                              \
> -       sbi_scratch_read_type((__scratch), void *, phs_ptr_offset)
> +       phs_ptr_offset ? sbi_scratch_read_type((__scratch), void *, phs_ptr_offset) : NULL
>
>  #define pmu_thishart_state_ptr()                                       \
>         pmu_get_hart_state_ptr(sbi_scratch_thishart_ptr())
> @@ -207,6 +207,9 @@ int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval)
>         uint32_t event_code;
>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>
> +       if (unlikely(!phs))
> +               return SBI_EINVAL;
> +
>         event_idx_type = pmu_ctr_validate(phs, cidx, &event_code);
>         if (event_idx_type != SBI_PMU_EVENT_TYPE_FW)
>                 return SBI_EINVAL;
> @@ -432,6 +435,10 @@ int sbi_pmu_ctr_start(unsigned long cbase, unsigned long cmask,
>                       unsigned long flags, uint64_t ival)
>  {
>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
> +
> +       if (unlikely(!phs))
> +               return SBI_EINVAL;
> +
>         int event_idx_type;
>         uint32_t event_code;
>         int ret = SBI_EINVAL;
> @@ -535,6 +542,10 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask,
>                      unsigned long flag)
>  {
>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
> +
> +       if (unlikely(!phs))
> +               return SBI_EINVAL;
> +
>         int ret = SBI_EINVAL;
>         int event_idx_type;
>         uint32_t event_code;
> @@ -794,6 +805,10 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
>                           uint64_t event_data)
>  {
>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
> +
> +       if (unlikely(!phs))
> +               return SBI_EINVAL;
> +
>         int ret, event_type, ctr_idx = SBI_ENOTSUPP;
>         u32 event_code;
>
> @@ -869,6 +884,9 @@ int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id)
>         uint64_t *fcounter = NULL;
>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>
> +       if (unlikely(!phs))
> +               return 0;
> +
>         if (likely(!phs->fw_counters_started))
>                 return 0;
>
> @@ -967,7 +985,12 @@ void sbi_pmu_exit(struct sbi_scratch *scratch)
>         if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
>                 csr_write(CSR_MCOUNTEREN, -1);
>
> -       pmu_reset_event_map(pmu_get_hart_state_ptr(scratch));
> +       struct sbi_pmu_hart_state *phs = pmu_get_hart_state_ptr(scratch);

Variable declaration should be at the start of function.

> +
> +       if (unlikely(!phs))
> +               return;
> +
> +       pmu_reset_event_map(phs);
>  }
>
>  int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

I have taken care of the above comments at the time of merging
this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


From anup at brainfault.org  Tue Feb 20 03:15:35 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 20 Feb 2024 16:45:35 +0530
Subject: [PATCH] lib: sbi: Add sparse hartid support for mtimer/ipi
In-Reply-To: <20240201103020.21181-1-gaoshanliukou@163.com>
References: <20240201103020.21181-1-gaoshanliukou@163.com>
Message-ID: <CAAhSdy3MCVgJb46jeQ1-i0W4qhUUJ5_uWibnyovgXZtUC1bdAg@mail.gmail.com>

On Thu, Feb 1, 2024 at 4:00?PM yang.zhang <gaoshanliukou at 163.com> wrote:
>
> If hartid is sparse, such as 0, 7, 16..., mtimer/mswi
> can't work well.
>
> Test:
> 1.Our platform support SMT, one core contains many harts
> whoes number is configurable, so the hartids is sparse when
> enter Opensbi?
> 2.I just simply simulate a scenario on qemu, like below
> "qemu-system-riscv64 -M virt,aia=aplic -m 2g -smp 8 -dtb qemu2cpu.dtb
>  -bios fw_jump.bin ..."
> There are total 8 cpus, but the dts only suppor 2 cpu nodes, hartid are
> 0 and 7, so when enter opensbi, just hartid 0 and 7 are running, the others
> are hanged, like sparse hartid.Then the issue happened.
> Logs:
> OpenSBI v1.4-11-g0dcc2e6
>    ____                    _____ ____ _____
>   / __ \                  / ____|  _ \_   _|
>  | |  | |_ __   ___ _ __ | (___ | |_) || |
>  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
>  | |__| | |_) |  __/ | | |____) | |_) || |_
>   \____/| .__/ \___|_| |_|_____/|____/_____|
>         | |
>         |_|
>
> init_coldboot: timer init failed (error -1000)

The patch description needs to be less verbose.

>
> Signed-off-by: yang.zhang <gaoshanliukou at 163.com>
> ---

If you have additional commentary then add it here below the
"---" line.

Overall, this patch provides a half-baked solution for an
important problem. This patch will not work for the case
where we have multiple ACLINT instances.

To improve this patch, I suggest replacing "first_hartid" in
"struct aclint_mswi_data" and "struct aclint_mtimer_data"
with "first_hartindex".

Regards,
Anup

>  lib/utils/ipi/aclint_mswi.c     | 2 +-
>  lib/utils/timer/aclint_mtimer.c | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
> index 4ae6bb1..3bbab8b 100644
> --- a/lib/utils/ipi/aclint_mswi.c
> +++ b/lib/utils/ipi/aclint_mswi.c
> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
>
>         /* Update MSWI pointer in scratch space */
>         for (i = 0; i < mswi->hart_count; i++) {
> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
> +               scratch = sbi_hartindex_to_scratch(i);
>                 /*
>                  * We don't need to fail if scratch pointer is not available
>                  * because we might be dealing with hartid of a HART disabled
> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> index 271e625..77d5522 100644
> --- a/lib/utils/timer/aclint_mtimer.c
> +++ b/lib/utils/timer/aclint_mtimer.c
> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>
>         /* Update MTIMER pointer in scratch space */
>         for (i = 0; i < mt->hart_count; i++) {
> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
> +               scratch = sbi_hartindex_to_scratch(i);
>                 /*
>                  * We don't need to fail if scratch pointer is not available
>                  * because we might be dealing with hartid of a HART disabled
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From gaoshanliukou at 163.com  Tue Feb 20 18:04:06 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Wed, 21 Feb 2024 10:04:06 +0800 (CST)
Subject: [PATCH] lib: sbi_pmu: Before using we should ensure PMU init
 done
In-Reply-To: <CAAhSdy1=iL-XCOT0WDRD1bZ3cV-6KCqTJSx2Quqa6YkJAwRypA@mail.gmail.com>
References: <20240201020126.23833-1-gaoshanliukou@163.com>
 <CAAhSdy1=iL-XCOT0WDRD1bZ3cV-6KCqTJSx2Quqa6YkJAwRypA@mail.gmail.com>
Message-ID: <386d7d39.2143.18dc967e98e.Coremail.gaoshanliukou@163.com>

















At 2024-02-20 18:59:03, "Anup Patel" <anup at brainfault.org> wrote:
>On Thu, Feb 1, 2024 at 7:32?AM yang.zhang <gaoshanliukou at 163.com> wrote:
>>
>> From: "yang.zhang" <yang.zhang at hexintek.com>
>>
>> If trap earlier before sbi_pmu_init done, some path would call
>> sbi_pmu_ctr_incr_fw, then it would go wrong:
>> 1. if phs_ptr_offset is zero, then it get a wrong pmu state ptr
>> 2. if phs_ptr_offset is ok, but we didn't call pmu_set_hart_state_ptr
>> it would be NULL POINT
>>
>> Of course, the above situation will not occur at present, but i think
>> it's reasonable that we should check it before we use it.
>>
>> Test:
>> 1. I test it on our platform, for now we only support LR/SC not AMO.
>> So when call spin_lock, would trap for amo instruction then emulate
>> it with LR/SC, then it goes wrong.Of course, this case is special only
>> for us, but other trap earlier cases maybe also encounter this situation.
>> 2.I aslo test on qemu thead-c906, but need do some changes for simulating
>> this scenario.
>>   2.1 revert f067bb84cf2dd6493ff3fa49294d3ec80481ad75, the commit causes
>>   we can't emulate some instructions from M mode, i think the requirement
>>   may be not reasonable.
>>   2.2 Then, insert a 'rdtime' instruction before pmu_get_hart_state_ptr in
>>   sbi_pmu_init, then something goes wrong.
>
>The patch description needs to be simplified because it is too verbose.
>
>>
>> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
>> ---
>>  lib/sbi/sbi_pmu.c | 27 +++++++++++++++++++++++++--
>>  1 file changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
>> index 6209ccc..4eccb82 100644
>> --- a/lib/sbi/sbi_pmu.c
>> +++ b/lib/sbi/sbi_pmu.c
>> @@ -74,7 +74,7 @@ struct sbi_pmu_hart_state {
>>  static unsigned long phs_ptr_offset;
>>
>>  #define pmu_get_hart_state_ptr(__scratch)                              \
>> -       sbi_scratch_read_type((__scratch), void *, phs_ptr_offset)
>> +       phs_ptr_offset ? sbi_scratch_read_type((__scratch), void *, phs_ptr_offset) : NULL
>>
>>  #define pmu_thishart_state_ptr()                                       \
>>         pmu_get_hart_state_ptr(sbi_scratch_thishart_ptr())
>> @@ -207,6 +207,9 @@ int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval)
>>         uint32_t event_code;
>>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>>
>> +       if (unlikely(!phs))
>> +               return SBI_EINVAL;
>> +
>>         event_idx_type = pmu_ctr_validate(phs, cidx, &event_code);
>>         if (event_idx_type != SBI_PMU_EVENT_TYPE_FW)
>>                 return SBI_EINVAL;
>> @@ -432,6 +435,10 @@ int sbi_pmu_ctr_start(unsigned long cbase, unsigned long cmask,
>>                       unsigned long flags, uint64_t ival)
>>  {
>>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>> +
>> +       if (unlikely(!phs))
>> +               return SBI_EINVAL;
>> +
>>         int event_idx_type;
>>         uint32_t event_code;
>>         int ret = SBI_EINVAL;
>> @@ -535,6 +542,10 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask,
>>                      unsigned long flag)
>>  {
>>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>> +
>> +       if (unlikely(!phs))
>> +               return SBI_EINVAL;
>> +
>>         int ret = SBI_EINVAL;
>>         int event_idx_type;
>>         uint32_t event_code;
>> @@ -794,6 +805,10 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
>>                           uint64_t event_data)
>>  {
>>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>> +
>> +       if (unlikely(!phs))
>> +               return SBI_EINVAL;
>> +
>>         int ret, event_type, ctr_idx = SBI_ENOTSUPP;
>>         u32 event_code;
>>
>> @@ -869,6 +884,9 @@ int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id)
>>         uint64_t *fcounter = NULL;
>>         struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
>>
>> +       if (unlikely(!phs))
>> +               return 0;
>> +
>>         if (likely(!phs->fw_counters_started))
>>                 return 0;
>>
>> @@ -967,7 +985,12 @@ void sbi_pmu_exit(struct sbi_scratch *scratch)
>>         if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
>>                 csr_write(CSR_MCOUNTEREN, -1);
>>
>> -       pmu_reset_event_map(pmu_get_hart_state_ptr(scratch));
>> +       struct sbi_pmu_hart_state *phs = pmu_get_hart_state_ptr(scratch);
>
>Variable declaration should be at the start of function.
>
>> +
>> +       if (unlikely(!phs))
>> +               return;
>> +
>> +       pmu_reset_event_map(phs);
>>  }
>>
>>  int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
>> --
>> 2.25.1
>>
>>
>> --
>> opensbi mailing list
>> opensbi at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/opensbi
>
>I have taken care of the above comments at the time of merging
>this patch.
>
>Reviewed-by: Anup Patel <anup at brainfault.org>
>
>Applied this patch to the riscv/opensbi repo.
>
>Thanks,

>Anup


Thanks very much, i will pay attention to the comments you mentioned in the future.

From gaoshanliukou at 163.com  Wed Feb 21 02:41:46 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Wed, 21 Feb 2024 18:41:46 +0800 (CST)
Subject: [PATCH] lib: sbi: Add sparse hartid support for mtimer/ipi
In-Reply-To: <CAAhSdy3MCVgJb46jeQ1-i0W4qhUUJ5_uWibnyovgXZtUC1bdAg@mail.gmail.com>
References: <20240201103020.21181-1-gaoshanliukou@163.com>
 <CAAhSdy3MCVgJb46jeQ1-i0W4qhUUJ5_uWibnyovgXZtUC1bdAg@mail.gmail.com>
Message-ID: <165d5dbd.b537.18dcb41d9a3.Coremail.gaoshanliukou@163.com>

















At 2024-02-20 19:15:35, "Anup Patel" <anup at brainfault.org> wrote:
>On Thu, Feb 1, 2024 at 4:00?PM yang.zhang <gaoshanliukou at 163.com> wrote:
>>
>> If hartid is sparse, such as 0, 7, 16..., mtimer/mswi
>> can't work well.
>>
>> Test:
>> 1.Our platform support SMT, one core contains many harts
>> whoes number is configurable, so the hartids is sparse when
>> enter Opensbi?
>> 2.I just simply simulate a scenario on qemu, like below
>> "qemu-system-riscv64 -M virt,aia=aplic -m 2g -smp 8 -dtb qemu2cpu.dtb
>>  -bios fw_jump.bin ..."
>> There are total 8 cpus, but the dts only suppor 2 cpu nodes, hartid are
>> 0 and 7, so when enter opensbi, just hartid 0 and 7 are running, the others
>> are hanged, like sparse hartid.Then the issue happened.
>> Logs:
>> OpenSBI v1.4-11-g0dcc2e6
>>    ____                    _____ ____ _____
>>   / __ \                  / ____|  _ \_   _|
>>  | |  | |_ __   ___ _ __ | (___ | |_) || |
>>  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
>>  | |__| | |_) |  __/ | | |____) | |_) || |_
>>   \____/| .__/ \___|_| |_|_____/|____/_____|
>>         | |
>>         |_|
>>
>> init_coldboot: timer init failed (error -1000)
>
>The patch description needs to be less verbose.
>
>>
>> Signed-off-by: yang.zhang <gaoshanliukou at 163.com>
>> ---
>
>If you have additional commentary then add it here below the
>"---" line.
>
>Overall, this patch provides a half-baked solution for an
>important problem. This patch will not work for the case
>where we have multiple ACLINT instances.
>
>To improve this patch, I suggest replacing "first_hartid" in
>"struct aclint_mswi_data" and "struct aclint_mtimer_data"
>with "first_hartindex".
>
>Regards,

>Anup

Yeah? i didn't consider the case of multiple ACLINT instances, i 
would try to reproduce it in this case, thanks.

>>  lib/utils/ipi/aclint_mswi.c     | 2 +-
>>  lib/utils/timer/aclint_mtimer.c | 2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
>> index 4ae6bb1..3bbab8b 100644
>> --- a/lib/utils/ipi/aclint_mswi.c
>> +++ b/lib/utils/ipi/aclint_mswi.c
>> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
>>
>>         /* Update MSWI pointer in scratch space */
>>         for (i = 0; i < mswi->hart_count; i++) {
>> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
>> +               scratch = sbi_hartindex_to_scratch(i);
>>                 /*
>>                  * We don't need to fail if scratch pointer is not available
>>                  * because we might be dealing with hartid of a HART disabled
>> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
>> index 271e625..77d5522 100644
>> --- a/lib/utils/timer/aclint_mtimer.c
>> +++ b/lib/utils/timer/aclint_mtimer.c
>> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>>
>>         /* Update MTIMER pointer in scratch space */
>>         for (i = 0; i < mt->hart_count; i++) {
>> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
>> +               scratch = sbi_hartindex_to_scratch(i);
>>                 /*
>>                  * We don't need to fail if scratch pointer is not available
>>                  * because we might be dealing with hartid of a HART disabled
>> --
>> 2.25.1
>>
>>
>> --
>> opensbi mailing list
>> opensbi at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/opensbi

From gaoshanliukou at 163.com  Wed Feb 21 22:55:30 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Thu, 22 Feb 2024 14:55:30 +0800
Subject: [PATCH V2] lib: sbi: Add sparse hartid support for mtimer and mswi
Message-ID: <20240222065530.17673-1-gaoshanliukou@163.com>

From: "yang.zhang" <yang.zhang at hexintek.com>

Need to support sparse hartid for mtmer and mswi.

Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
---
v1 -> v2:
- Add handle in the case of multiple ACLINT instances
- Check valid hartindex not hartid when parse fdt

V1: https://lists.infradead.org/pipermail/opensbi/2024-February/006342.html

---
I add additional first_hartindex instead of replacing first_hartid with it.
Because first_hartindex maybe not the first hartid, which is the base of
mtimer/mswi, such as in the cpus node of dts:
cluster0 {cpu at 0: reg=<0x0>, cpu at 1: reg=<0x3>}
cluster1 {cpu at 2: reg=<0x7>, cpu at 3: reg=<0x4>}
---
 include/sbi_utils/fdt/fdt_helper.h      |  2 +-
 include/sbi_utils/ipi/aclint_mswi.h     |  1 +
 include/sbi_utils/timer/aclint_mtimer.h |  1 +
 lib/utils/fdt/fdt_helper.c              | 16 +++++++++++-----
 lib/utils/ipi/aclint_mswi.c             |  2 +-
 lib/utils/ipi/fdt_ipi_mswi.c            |  2 +-
 lib/utils/timer/aclint_mtimer.c         |  2 +-
 lib/utils/timer/fdt_timer_mtimer.c      |  2 +-
 platform/fpga/ariane/platform.c         |  2 ++
 platform/fpga/openpiton/platform.c      |  2 ++
 platform/kendryte/k210/platform.c       |  2 ++
 platform/nuclei/ux600/platform.c        |  2 ++
 platform/template/platform.c            |  2 ++
 13 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index ab4a80f..398700d 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -103,7 +103,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 			  bool for_timer, bool allow_regname,
 			  unsigned long *out_addr1, unsigned long *out_size1,
 			  unsigned long *out_addr2, unsigned long *out_size2,
-			  u32 *out_first_hartid, u32 *out_hart_count);
+			  u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count);
 
 int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
 			  unsigned long *plmt_size, u32 *hart_count);
diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
index e373a8c..d5708e2 100644
--- a/include/sbi_utils/ipi/aclint_mswi.h
+++ b/include/sbi_utils/ipi/aclint_mswi.h
@@ -22,6 +22,7 @@ struct aclint_mswi_data {
 	/* Public details */
 	unsigned long addr;
 	unsigned long size;
+	u32 first_hartindex;
 	u32 first_hartid;
 	u32 hart_count;
 };
diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
index 6ab8799..21a7d93 100644
--- a/include/sbi_utils/timer/aclint_mtimer.h
+++ b/include/sbi_utils/timer/aclint_mtimer.h
@@ -31,6 +31,7 @@ struct aclint_mtimer_data {
 	unsigned long mtime_size;
 	unsigned long mtimecmp_addr;
 	unsigned long mtimecmp_size;
+	u32 first_hartindex;
 	u32 first_hartid;
 	u32 hart_count;
 	bool has_64bit_mmio;
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index a0e93b9..5d9215f 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -961,16 +961,17 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 			  bool for_timer, bool allow_regname,
 			  unsigned long *out_addr1, unsigned long *out_size1,
 			  unsigned long *out_addr2, unsigned long *out_size2,
-			  u32 *out_first_hartid, u32 *out_hart_count)
+			  u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count)
 {
 	const fdt32_t *val;
 	int i, rc, count, cpu_offset, cpu_intc_offset;
-	u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
+	u32 phandle, hwirq;
+	u32 hartindex, hartid, first_hartindex, first_hartid, last_hartid, hart_count;
 	u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
 
 	if (nodeoffset < 0 || !fdt ||
 	    !out_addr1 || !out_size1 ||
-	    !out_first_hartid || !out_hart_count)
+	    !out_first_hartindex || !out_first_hartid || !out_hart_count)
 		return SBI_EINVAL;
 
 	if (for_timer && allow_regname && out_addr2 && out_size2 &&
@@ -985,6 +986,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 	if (rc)
 		return rc;
 
+	*out_first_hartindex = 0;
 	*out_first_hartid = 0;
 	*out_hart_count = 0;
 
@@ -993,7 +995,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 		return 0;
 	count = count / sizeof(fdt32_t);
 
-	first_hartid = -1U;
+	first_hartindex = first_hartid = -1U;
 	hart_count = last_hartid = 0;
 	for (i = 0; i < (count / 2); i++) {
 		phandle = fdt32_to_cpu(val[2 * i]);
@@ -1011,10 +1013,13 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 		if (rc)
 			continue;
 
-		if (SBI_HARTMASK_MAX_BITS <= hartid)
+		hartindex = sbi_hartid_to_hartindex(hartid);
+		if (SBI_HARTMASK_MAX_BITS <= hartindex)
 			continue;
 
 		if (match_hwirq == hwirq) {
+			if (hartindex < first_hartindex)
+				first_hartindex = hartindex;
 			if (hartid < first_hartid)
 				first_hartid = hartid;
 			if (hartid > last_hartid)
@@ -1024,6 +1029,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
 	}
 
 	if ((last_hartid >= first_hartid) && first_hartid != -1U) {
+		*out_first_hartindex = first_hartindex;
 		*out_first_hartid = first_hartid;
 		count = last_hartid - first_hartid + 1;
 		*out_hart_count = (hart_count < count) ? hart_count : count;
diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
index 4ae6bb1..15298eb 100644
--- a/lib/utils/ipi/aclint_mswi.c
+++ b/lib/utils/ipi/aclint_mswi.c
@@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
 
 	/* Update MSWI pointer in scratch space */
 	for (i = 0; i < mswi->hart_count; i++) {
-		scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
+		scratch = sbi_hartindex_to_scratch(mswi->first_hartindex + i);
 		/*
 		 * We don't need to fail if scratch pointer is not available
 		 * because we might be dealing with hartid of a HART disabled
diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
index a709abe..e896e5a 100644
--- a/lib/utils/ipi/fdt_ipi_mswi.c
+++ b/lib/utils/ipi/fdt_ipi_mswi.c
@@ -26,7 +26,7 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
 
 	rc = fdt_parse_aclint_node(fdt, nodeoff, false, false,
 				   &ms->addr, &ms->size, NULL, NULL,
-				   &ms->first_hartid, &ms->hart_count);
+				   &ms->first_hartindex, &ms->first_hartid, &ms->hart_count);
 	if (rc) {
 		sbi_free(ms);
 		return rc;
diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
index 271e625..706967c 100644
--- a/lib/utils/timer/aclint_mtimer.c
+++ b/lib/utils/timer/aclint_mtimer.c
@@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
 
 	/* Update MTIMER pointer in scratch space */
 	for (i = 0; i < mt->hart_count; i++) {
-		scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
+		scratch = sbi_hartindex_to_scratch(mt->first_hartindex + i);
 		/*
 		 * We don't need to fail if scratch pointer is not available
 		 * because we might be dealing with hartid of a HART disabled
diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
index 9e27e3a..aa05afe 100644
--- a/lib/utils/timer/fdt_timer_mtimer.c
+++ b/lib/utils/timer/fdt_timer_mtimer.c
@@ -47,7 +47,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
 
 	rc = fdt_parse_aclint_node(fdt, nodeoff, true, !is_clint,
 				   &addr[0], &size[0], &addr[1], &size[1],
-				   &mt->first_hartid, &mt->hart_count);
+				   &mt->first_hartindex, &mt->first_hartid, &mt->hart_count);
 	if (rc) {
 		sbi_free(mtn);
 		return rc;
diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
index 8be5e6c..d88350c 100644
--- a/platform/fpga/ariane/platform.c
+++ b/platform/fpga/ariane/platform.c
@@ -45,6 +45,7 @@ static struct plic_data plic = {
 static struct aclint_mswi_data mswi = {
 	.addr = ARIANE_ACLINT_MSWI_ADDR,
 	.size = ACLINT_MSWI_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = ARIANE_HART_COUNT,
 };
@@ -57,6 +58,7 @@ static struct aclint_mtimer_data mtimer = {
 	.mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
 			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
 	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = ARIANE_HART_COUNT,
 	.has_64bit_mmio = true,
diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
index 2317a89..c21e8ad 100644
--- a/platform/fpga/openpiton/platform.c
+++ b/platform/fpga/openpiton/platform.c
@@ -49,6 +49,7 @@ static struct plic_data plic = {
 static struct aclint_mswi_data mswi = {
 	.addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
 	.size = ACLINT_MSWI_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = OPENPITON_DEFAULT_HART_COUNT,
 };
@@ -61,6 +62,7 @@ static struct aclint_mtimer_data mtimer = {
 	.mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
 			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
 	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = OPENPITON_DEFAULT_HART_COUNT,
 	.has_64bit_mmio = true,
diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
index 27b23f7..21d34b7 100644
--- a/platform/kendryte/k210/platform.c
+++ b/platform/kendryte/k210/platform.c
@@ -39,6 +39,7 @@ static struct plic_data plic = {
 static struct aclint_mswi_data mswi = {
 	.addr = K210_ACLINT_MSWI_ADDR,
 	.size = ACLINT_MSWI_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = K210_HART_COUNT,
 };
@@ -51,6 +52,7 @@ static struct aclint_mtimer_data mtimer = {
 	.mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
 			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
 	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = K210_HART_COUNT,
 	.has_64bit_mmio = true,
diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
index f688b50..54f35f4 100644
--- a/platform/nuclei/ux600/platform.c
+++ b/platform/nuclei/ux600/platform.c
@@ -72,6 +72,7 @@ static struct plic_data plic = {
 static struct aclint_mswi_data mswi = {
 	.addr = UX600_ACLINT_MSWI_ADDR,
 	.size = ACLINT_MSWI_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = UX600_HART_COUNT,
 };
@@ -84,6 +85,7 @@ static struct aclint_mtimer_data mtimer = {
 	.mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
 			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
 	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = UX600_HART_COUNT,
 	.has_64bit_mmio = true,
diff --git a/platform/template/platform.c b/platform/template/platform.c
index 4b3f2ac..4840542 100644
--- a/platform/template/platform.c
+++ b/platform/template/platform.c
@@ -42,6 +42,7 @@ static struct plic_data plic = {
 static struct aclint_mswi_data mswi = {
 	.addr = PLATFORM_ACLINT_MSWI_ADDR,
 	.size = ACLINT_MSWI_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = PLATFORM_HART_COUNT,
 };
@@ -54,6 +55,7 @@ static struct aclint_mtimer_data mtimer = {
 	.mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
 			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
 	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
+	.first_hartindex = 0,
 	.first_hartid = 0,
 	.hart_count = PLATFORM_HART_COUNT,
 	.has_64bit_mmio = true,
-- 
2.25.1



From namcao at linutronix.de  Thu Feb 22 00:16:15 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:15 +0100
Subject: [PATCH v5 2/6] platform: starfive: get I2C offset address from clocks property
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-3-namcao@linutronix.de>

The current code gets the I2C offset address using the device tree node
name: it get the I2C device index from the 4th character in the node
name (for example, "i2c5" -> i2c device 5). However, the device tree
node's name in U-Boot is actually just "i2c" without the number, so the
current code cannot be used with the device tree from U-Boot.

Get the I2C offset address from the "clocks" property instead.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Reviewed-by: Minda Chen <minda.chen at starfivetech.com>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 4b22175..308fe39 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -29,7 +29,7 @@ struct pmic {
 struct jh7110 {
 	u64 pmu_reg_base;
 	u64 clk_reg_base;
-	u32 i2c_index;
+	u32 i2c_clk_offset;
 };
 
 static struct pmic pmic_inst;
@@ -67,7 +67,6 @@ static u32 selected_hartid = -1;
 #define AXP15060_POWER_OFF_BIT		BIT(7)
 #define AXP15060_RESET_BIT		BIT(6)
 
-#define I2C_APB_CLK_OFFSET		0x228
 #define I2C_APB_CLK_ENABLE_BIT		BIT(31)
 
 static int pm_system_reset_check(u32 type, u32 reason)
@@ -163,10 +162,7 @@ static void pmic_i2c_clk_enable(void)
 	unsigned long clock_base;
 	unsigned int val;
 
-	clock_base = jh7110_inst.clk_reg_base +
-		I2C_APB_CLK_OFFSET +
-		(jh7110_inst.i2c_index << 2);
-
+	clock_base = jh7110_inst.clk_reg_base + jh7110_inst.i2c_clk_offset;
 	val = readl((void *)clock_base);
 
 	if (!val)
@@ -241,7 +237,8 @@ static struct fdt_reset fdt_reset_pmic = {
 static int starfive_jh7110_inst_init(void *fdt)
 {
 	int noff, rc = 0;
-	const char *name;
+	const fdt32_t *val;
+	int len;
 	u64 addr;
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu");
@@ -261,9 +258,12 @@ static int starfive_jh7110_inst_init(void *fdt)
 	}
 
 	if (pmic_inst.adapter) {
-		name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
-		if (!sbi_strncmp(name, "i2c", 3))
-			jh7110_inst.i2c_index = name[3] - '0';
+		val = fdt_getprop(fdt, pmic_inst.adapter->id, "clocks", &len);
+		/* The clocks property looks like this: clocks = <&syscrg JH7110_SYSCLK_I2C5_APB>;
+		 * So check that the length is 8 bytes, and get the offset from the second value
+		 */
+		if (val && len == 8)
+			jh7110_inst.i2c_clk_offset = fdt32_to_cpu(val[1]) << 2;
 		else
 			rc = SBI_EINVAL;
 	}
-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:14 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:14 +0100
Subject: [PATCH v5 1/6] platform: starfive: correct system clock device tree node
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-2-namcao@linutronix.de>

Starfive names the system clock device tree node "starfive,jh7110-clkgen"
in all their git repositories. However, a different name is used in
upstream U-Boot (and also Linux): "starfive,jh7110-syscrg". Since
OpenSBI gets the device tree from U-Boot, this inconsistency leads the
problem that OpenSBI doesn't know the system clock device exists.

Correct this name to keep the consistency.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Acked-by: Minda Chen <minda.chen at starfivetech.com>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index dcd6306..4b22175 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -252,7 +252,7 @@ static int starfive_jh7110_inst_init(void *fdt)
 		jh7110_inst.pmu_reg_base = addr;
 	}
 
-	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen");
+	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
 	if (-1 < noff) {
 		rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
 		if (rc)
-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:13 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:13 +0100
Subject: [PATCH v5 0/6] starfive reboot cleanup & fix
Message-ID: <20240222081619.275869-1-namcao@linutronix.de>

This series:
 - Rename device tree compatible strings to match U-Boot
 - Fix code that extract I2C address from device tree
 - Cleanup

v5:
 - Collect reviewed-by and tested-by tags
 - squash 2 commits:
     platform: starfive: remove redundant compatibility check in pmic_ops
     platform: starfive: drop "compatible" from struct pmic


Nam Cao (6):
  platform: starfive: correct system clock device tree node
  platform: starfive: get I2C offset address from clocks property
  platform: starfive: remove redundant compatibility check in pmic_ops
  platform: starfive: rename "stf,axp15060-regulator" ->
    "x-powers,axp15060"
  platform: starfive: return error if needed devices are not present
  platform: starfive: call starfive_jh7110_inst_init() in
    pm_reset_init()

 platform/generic/starfive/jh7110.c | 71 ++++++++++++++++--------------
 1 file changed, 38 insertions(+), 33 deletions(-)

-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:16 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:16 +0100
Subject: [PATCH v5 3/6] platform: starfive: remove redundant compatibility check in pmic_ops
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-4-namcao@linutronix.de>

pmic_ops() is only called if a compatible device is found in device
tree. It is redundant for this function to check the compability again.
Remove this check.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 36 +++++++++++++-----------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 308fe39..3161bf1 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -23,7 +23,6 @@
 struct pmic {
 	struct i2c_adapter *adapter;
 	u32 dev_addr;
-	const char *compatible;
 };
 
 struct jh7110 {
@@ -133,28 +132,26 @@ static void pmic_ops(struct pmic *pmic, int type)
 	if (ret)
 		return;
 
-	if (!sbi_strcmp("stf,axp15060-regulator", pmic->compatible)) {
-		ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
-					   AXP15060_POWER_REG, &val);
+	ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, &val);
 
-		if (ret) {
-			sbi_printf("%s: cannot read pmic power register\n",
-				   __func__);
-			return;
-		}
+	if (ret) {
+		sbi_printf("%s: cannot read pmic power register\n",
+				__func__);
+		return;
+	}
 
+	val |= AXP15060_POWER_OFF_BIT;
+	if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
 		val |= AXP15060_POWER_OFF_BIT;
-		if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
-			val |= AXP15060_POWER_OFF_BIT;
-		else
-			val |= AXP15060_RESET_BIT;
+	else
+		val |= AXP15060_RESET_BIT;
 
-		ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
-					    AXP15060_POWER_REG, val);
-		if (ret)
-			sbi_printf("%s: cannot write pmic power register\n",
-				   __func__);
-	}
+	ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
+					AXP15060_POWER_REG, val);
+	if (ret)
+		sbi_printf("%s: cannot write pmic power register\n",
+				__func__);
 }
 
 static void pmic_i2c_clk_enable(void)
@@ -206,7 +203,6 @@ static int pm_reset_init(void *fdt, int nodeoff,
 		return rc;
 
 	pmic_inst.dev_addr = addr;
-	pmic_inst.compatible = match->compatible;
 
 	i2c_bus = fdt_parent_offset(fdt, nodeoff);
 	if (i2c_bus < 0)
-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:17 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:17 +0100
Subject: [PATCH v5 4/6] platform: starfive: rename "stf,axp15060-regulator" -> "x-powers,axp15060"
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-5-namcao@linutronix.de>

OpenSBI uses the device tree compatible string "stf,axp15060-regulator"
for the regulator node. However, the string used by U-Boot (and Linux)
is actually "x-powers,axp15060". As OpenSBI gets the device tree from
U-Boot, this causes the regulator device to be undetected, and OpenSBI
does not use this device to perform board reset/shutdown.

Rename this device tree compatible string to match U-Boot (and Linux).

Signed-off-by: Nam Cao <namcao at linutronix.de>
Acked-by: Minda Chen <minda.chen at starfivetech.com>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 3161bf1..b0b1e35 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -221,7 +221,7 @@ static int pm_reset_init(void *fdt, int nodeoff,
 }
 
 static const struct fdt_match pm_reset_match[] = {
-	{ .compatible = "stf,axp15060-regulator", .data = (void *)true },
+	{ .compatible = "x-powers,axp15060", .data = (void *)true },
 	{ },
 };
 
-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:18 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:18 +0100
Subject: [PATCH v5 5/6] platform: starfive: return error if needed devices are not present
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-6-namcao@linutronix.de>

Jh7110's reset driver needs power management device and clock controller
device to work. Currently, the driver proceed anyway without these
devices, and invalid addresses (jh7110_inst.pmu_reg_base and
jh7110_inst.clk_reg_base) are used during reboot, which causes
unpredictable broken behaviors.

If these devices are not present, return -SBI_ENODEV.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index b0b1e35..6990425 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -243,6 +243,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.pmu_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-syscrg");
@@ -251,6 +253,8 @@ static int starfive_jh7110_inst_init(void *fdt)
 		if (rc)
 			goto err;
 		jh7110_inst.clk_reg_base = addr;
+	} else {
+		return -SBI_ENODEV;
 	}
 
 	if (pmic_inst.adapter) {
-- 
2.39.2



From namcao at linutronix.de  Thu Feb 22 00:16:19 2024
From: namcao at linutronix.de (Nam Cao)
Date: Thu, 22 Feb 2024 09:16:19 +0100
Subject: [PATCH v5 6/6] platform: starfive: call starfive_jh7110_inst_init() in pm_reset_init()
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <20240222081619.275869-7-namcao@linutronix.de>

The function starfive_jh7110_inst_init() initialize some power
management unit address and clock addresses, needed for the reset
driver. It doesn't do anything else, and also the reset driver doesn't
work without calling this function. Thus, it does not make much sense
that this function is independent from pm_reset_init().

Delete the separate call to starfive_jh7110_inst_init(), and instead
just call this function inside pm_reset_init().

Doing this also fixes another problem: if starfive_jh7110_inst_init()
returns an error code, it gets propagated to final_init() and OpenSBI
hangs. This hang is not necessary, because failures within
starfive_jh7110_inst_init() only mean OpenSBI cannot perform reboot or
shutdown, but the system can still function normally.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Tested-by: Minda Chen <minda.chen at starfivetech.com>
---
 platform/generic/starfive/jh7110.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/platform/generic/starfive/jh7110.c b/platform/generic/starfive/jh7110.c
index 6990425..c25e645 100644
--- a/platform/generic/starfive/jh7110.c
+++ b/platform/generic/starfive/jh7110.c
@@ -190,6 +190,8 @@ static struct sbi_system_reset_device pm_reset = {
 	.system_reset = pm_system_reset
 };
 
+static int starfive_jh7110_inst_init(void *fdt);
+
 static int pm_reset_init(void *fdt, int nodeoff,
 			 const struct fdt_match *match)
 {
@@ -215,6 +217,10 @@ static int pm_reset_init(void *fdt, int nodeoff,
 
 	pmic_inst.adapter = adapter;
 
+	rc = starfive_jh7110_inst_init(fdt);
+	if (rc)
+		return rc;
+
 	sbi_system_reset_add_device(&pm_reset);
 
 	return 0;
@@ -278,7 +284,6 @@ static int starfive_jh7110_final_init(bool cold_boot,
 
 	if (cold_boot) {
 		fdt_reset_driver_init(fdt, &fdt_reset_pmic);
-		return starfive_jh7110_inst_init(fdt);
 	}
 
 	return 0;
-- 
2.39.2



From peterlin at andestech.com  Thu Feb 22 01:18:38 2024
From: peterlin at andestech.com (Yu Chien Peter Lin)
Date: Thu, 22 Feb 2024 17:18:38 +0800
Subject: [PATCH] platform: andes: Drop andes_pmu_setup()
Message-ID: <20240222091838.182184-1-peterlin@andestech.com>

andes_pmu_setup() [1] was intended to populate event mapping from
hardcoded arrays, however, this increases firmware size and we should
just use PMU DT node [2] instead.

Link: https://lists.infradead.org/pipermail/opensbi/2023-November/006032.html [1]
Link: https://github.com/riscv-software-src/opensbi/blob/v1.4/docs/pmu_support.md#example-3 [2]
Signed-off-by: Yu Chien Peter Lin <peterlin at andestech.com>
---
 platform/generic/andes/andes_pmu.c         | 12 ------------
 platform/generic/include/andes/andes_hpm.h | 12 ------------
 2 files changed, 24 deletions(-)
 delete mode 100644 platform/generic/include/andes/andes_hpm.h

diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
index 4b2d45b..479fb9a 100644
--- a/platform/generic/andes/andes_pmu.c
+++ b/platform/generic/andes/andes_pmu.c
@@ -6,7 +6,6 @@
  */
 
 #include <andes/andes45.h>
-#include <andes/andes_hpm.h>
 #include <andes/andes_pmu.h>
 #include <sbi/sbi_bitops.h>
 #include <sbi/sbi_error.h>
@@ -86,20 +85,9 @@ int andes_pmu_extensions_init(const struct fdt_match *match,
 int andes_pmu_init(const struct fdt_match *match)
 {
 	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
-	void *fdt = fdt_get_address();
-	int pmu_offset;
 
 	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_XANDESPMU))
 		sbi_pmu_set_device(&andes_pmu);
 
-	/*
-	 * Populate default mappings if device-tree doesn't
-	 * provide a valid pmu node.
-	 */
-	pmu_offset = fdt_node_offset_by_compatible(fdt, -1, "riscv,pmu");
-	if (pmu_offset < 0)
-		return (pmu_offset == -FDT_ERR_NOTFOUND) ? andes_pmu_setup()
-							 : SBI_EFAIL;
-
 	return 0;
 }
diff --git a/platform/generic/include/andes/andes_hpm.h b/platform/generic/include/andes/andes_hpm.h
deleted file mode 100644
index b4d71b9..0000000
--- a/platform/generic/include/andes/andes_hpm.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2023 Andes Technology Corporation
- */
-
-#ifndef _ANDES_HPM_H_
-#define _ANDES_HPM_H_
-
-static inline int andes_pmu_setup(void) { return 0; }
-
-#endif /* _ANDES_HPM_H_ */
-- 
2.34.1



From anup at brainfault.org  Thu Feb 22 04:55:37 2024
From: anup at brainfault.org (Anup Patel)
Date: Thu, 22 Feb 2024 18:25:37 +0530
Subject: [PATCH v5 0/6] starfive reboot cleanup & fix
In-Reply-To: <20240222081619.275869-1-namcao@linutronix.de>
References: <20240222081619.275869-1-namcao@linutronix.de>
Message-ID: <CAAhSdy0M_pGXptDY7RgVSuQdv=PF-ZyLpHHqe8RVnzP6NR8ddA@mail.gmail.com>

On Thu, Feb 22, 2024 at 1:46?PM Nam Cao <namcao at linutronix.de> wrote:
>
> This series:
>  - Rename device tree compatible strings to match U-Boot
>  - Fix code that extract I2C address from device tree
>  - Cleanup
>
> v5:
>  - Collect reviewed-by and tested-by tags
>  - squash 2 commits:
>      platform: starfive: remove redundant compatibility check in pmic_ops
>      platform: starfive: drop "compatible" from struct pmic
>
>
> Nam Cao (6):
>   platform: starfive: correct system clock device tree node
>   platform: starfive: get I2C offset address from clocks property
>   platform: starfive: remove redundant compatibility check in pmic_ops
>   platform: starfive: rename "stf,axp15060-regulator" ->
>     "x-powers,axp15060"
>   platform: starfive: return error if needed devices are not present
>   platform: starfive: call starfive_jh7110_inst_init() in
>     pm_reset_init()

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this series to the riscv/opensbi repo.

Thanks,
Anup

>
>  platform/generic/starfive/jh7110.c | 71 ++++++++++++++++--------------
>  1 file changed, 38 insertions(+), 33 deletions(-)
>
> --
> 2.39.2
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Thu Feb 22 20:58:49 2024
From: anup at brainfault.org (Anup Patel)
Date: Fri, 23 Feb 2024 10:28:49 +0530
Subject: [PATCH 1/4] firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
In-Reply-To: <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy3y7x5gorsW9LKpLS0ucYrOmse4-v8HwgqYnD8r9iKP5Q@mail.gmail.com>

On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> If FW_PIC=y is defined, the fw_jump.bin will be broken if
> FW_TEXT_START is wrong. This is not the desired behavior.

We should support FW_JUMP_OFFSET, irrespective of whether
FW_PIC is defined or not.

>
> Add two new variables to identify relocatable jump address:
> FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
> ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
> are defined. And these two new variables will convert to
> the old one if compiler does not support PIC.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> ---
>  firmware/fw_jump.S  | 20 ++++++++++++++++----
>  firmware/objects.mk | 15 +++++++++++++++
>  2 files changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
> index ac74dc6..0ad2398 100644
> --- a/firmware/fw_jump.S
> +++ b/firmware/fw_jump.S
> @@ -46,6 +46,10 @@ fw_save_info:
>  fw_next_arg1:
>  #ifdef FW_JUMP_FDT_ADDR
>         li      a0, FW_JUMP_FDT_ADDR
> +#elif defined(FW_JUMP_FDT_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_JUMP_FDT_OFFSET
> +       add     a0, a0, a1
>  #else
>         add     a0, a1, zero
>  #endif
> @@ -59,7 +63,13 @@ fw_next_arg1:
>          * The next address should be returned in 'a0'.
>          */
>  fw_next_addr:
> +#ifdef FW_JUMP_ADDR
>         lla     a0, _jump_addr
> +#elif defined(FW_JUMP_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_JUMP_OFFSET
> +       add     a0, a0, a1

What if both FW_JUMP_ADDR and FW_JUMP_OFFSET are not available ?

> +#endif
>         REG_L   a0, (a0)
>         ret
>
> @@ -86,11 +96,13 @@ fw_options:
>         add     a0, zero, zero
>         ret
>
> -#ifndef FW_JUMP_ADDR
> -#error "Must define FW_JUMP_ADDR"
> -#endif
> -
> +#ifdef FW_JUMP_ADDR
>         .section .rodata
>         .align 3
>  _jump_addr:
>         RISCV_PTR FW_JUMP_ADDR
> +#else
> +#ifndef FW_JUMP_OFFSET
> +#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
> +#endif
> +#endif
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index a1704c4..248706d 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -35,12 +35,27 @@ firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
>  endif
>  endif
>
> +ifeq ($(FW_PIC),n)

Let's not condition this upon FW_PIC.

Instead this should be:

ifdef FW_JUMP_OFFSET

> +  ifndef FW_JUMP_ADDR
> +    FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_OFFSET))))
> +  endif
> +  ifndef FW_JUMP_FDT_ADDR
> +    FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
> +  endif
> +endif
> +
>  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
>
>  firmware-bins-$(FW_JUMP) += fw_jump.bin
> +ifdef FW_JUMP_OFFSET
> +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
> +endif
>  ifdef FW_JUMP_ADDR
>  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
>  endif
> +ifdef FW_JUMP_FDT_OFFSET
> +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> +endif
>  ifdef FW_JUMP_FDT_ADDR
>  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
>  endif
> --
> 2.43.0
>

Regards,
Anup


From anup at brainfault.org  Thu Feb 22 21:01:32 2024
From: anup at brainfault.org (Anup Patel)
Date: Fri, 23 Feb 2024 10:31:32 +0530
Subject: [PATCH 2/4] firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
In-Reply-To: <IA1PR20MB49539A729C9350C1714D7DA4BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB49539A729C9350C1714D7DA4BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy1KuWKob_eV60RHkKXbxzxsge49n2PcfjeBbaXZJ28wFg@mail.gmail.com>

On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> The fw_payload.bin has the same issue as described in commit 80129c2.

Can't find commit 80129c2 in upstream OpenSBI. Improve commit description.

> But only FW_PAYLOAD_FDT_ADDR is affected.
>
> Add FW_PAYLOAD_FDT_OFFSET to identify relocatable payload fdt address.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> ---
>  firmware/fw_payload.S | 4 ++++
>  firmware/objects.mk   | 6 ++++++
>  2 files changed, 10 insertions(+)
>
> diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
> index c53a3bb..3c8433e 100644
> --- a/firmware/fw_payload.S
> +++ b/firmware/fw_payload.S
> @@ -46,6 +46,10 @@ fw_save_info:
>  fw_next_arg1:
>  #ifdef FW_PAYLOAD_FDT_ADDR
>         li      a0, FW_PAYLOAD_FDT_ADDR
> +#elif defined(FW_PAYLOAD_FDT_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_PAYLOAD_FDT_OFFSET
> +       add     a0, a0, a1
>  #else
>         add     a0, a1, zero
>  #endif
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index 248706d..a761b9e 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -42,6 +42,9 @@ ifeq ($(FW_PIC),n)
>    ifndef FW_JUMP_FDT_ADDR
>      FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
>    endif
> +  ifndef FW_PAYLOAD_FDT_ADDR
> +    FW_PAYLOAD_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_PAYLOAD_FDT_OFFSET))))
> +  endif
>  endif
>
>  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
> @@ -74,6 +77,9 @@ ifdef FW_PAYLOAD_ALIGN
>  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
>  endif
>
> +ifdef FW_PAYLOAD_FDT_OFFSET
> +firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
> +endif
>  ifdef FW_PAYLOAD_FDT_ADDR
>  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
>  endif
> --
> 2.43.0
>

Regards,
Anup


From anup at brainfault.org  Thu Feb 22 21:03:09 2024
From: anup at brainfault.org (Anup Patel)
Date: Fri, 23 Feb 2024 10:33:09 +0530
Subject: [PATCH 3/4] platform: Apply relocatable address
In-Reply-To: <IA1PR20MB49538AFD74ED9DA26246603CBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB49538AFD74ED9DA26246603CBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy3vt2RCUc3TNd=Fowsu_044DHaBbWej3N4a-e+88Vpzqg@mail.gmail.com>

On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> Since jump and payload firmware support relocatable address, make
> general platform use runtime relocatable address.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>

This patch should also update platform/template/objects.mk.

Regards,
Anup

> ---
>  platform/generic/objects.mk | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
> index 136853e..85aa723 100644
> --- a/platform/generic/objects.mk
> +++ b/platform/generic/objects.mk
> @@ -27,12 +27,12 @@ FW_DYNAMIC=y
>  FW_JUMP=y
>  ifeq ($(PLATFORM_RISCV_XLEN), 32)
>    # This needs to be 4MB aligned for 32-bit system
> -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000)))
> +  FW_JUMP_OFFSET=0x400000
>  else
>    # This needs to be 2MB aligned for 64-bit system
> -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000)))
> +  FW_JUMP_OFFSET=0x200000
>  endif
> -FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000)))
> +FW_JUMP_FDT_OFFSET=0x2200000
>  FW_PAYLOAD=y
>  ifeq ($(PLATFORM_RISCV_XLEN), 32)
>    # This needs to be 4MB aligned for 32-bit system
> @@ -41,4 +41,4 @@ else
>    # This needs to be 2MB aligned for 64-bit system
>    FW_PAYLOAD_OFFSET=0x200000
>  endif
> -FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> +FW_PAYLOAD_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> --
> 2.43.0
>


From anup at brainfault.org  Thu Feb 22 21:05:14 2024
From: anup at brainfault.org (Anup Patel)
Date: Fri, 23 Feb 2024 10:35:14 +0530
Subject: [PATCH 0/4] Add relocatable address support for jump and payload firmware
In-Reply-To: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy1gcFvPgp5WRSh=u3xc=zRW7kHs6T3CfK3FH5PY6DW37g@mail.gmail.com>

On Fri, Feb 2, 2024 at 9:34?AM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> If FW_PIC=y is defined, the jump and payload firmware and will
> be broken if FW_TEXT_START is wrong. This is not the desired behavior.
>
> Add some new variable to support relocatable address.
>
> build command:
> make BUILD_INFO=y DEBUG=1 FW_PIC=y PLATFORM=generic FW_TEXT_START=0x0
>
> test command:
> qemu-system-riscv64 -smp cpus=4 -M virt -m 256M \
>   -bios build/platform/generic/firmware/fw_payload.bin

Overall this patch is in the right direction but the new options should not
depend on FW_PIC.

Regards,
Anup

>
> Inochi Amaoto (4):
>   firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
>   firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
>   platform: Apply relocatable address
>   doc/firmware: add new configuration options for jump and payload
>     firmware
>
>  docs/firmware/fw_jump.md    | 17 ++++++++++++++---
>  docs/firmware/fw_payload.md |  6 ++++++
>  firmware/fw_jump.S          | 20 ++++++++++++++++----
>  firmware/fw_payload.S       |  4 ++++
>  firmware/objects.mk         | 21 +++++++++++++++++++++
>  platform/generic/objects.mk |  8 ++++----
>  6 files changed, 65 insertions(+), 11 deletions(-)
>
> --
> 2.43.0
>


From inochiama at outlook.com  Thu Feb 22 23:21:56 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 15:21:56 +0800
Subject: [PATCH 1/4] firmware: Add relocatable FW_JUMP_ADDR and
 FW_JUMP_FDT_ADDR
In-Reply-To: <CAAhSdy3y7x5gorsW9LKpLS0ucYrOmse4-v8HwgqYnD8r9iKP5Q@mail.gmail.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy3y7x5gorsW9LKpLS0ucYrOmse4-v8HwgqYnD8r9iKP5Q@mail.gmail.com>
Message-ID: <IA1PR20MB49538587A5ECDF140EDD4613BB552@IA1PR20MB4953.namprd20.prod.outlook.com>

On Fri, Feb 23, 2024 at 10:28:49AM +0530, Anup Patel wrote:
> On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
> >
> > If FW_PIC=y is defined, the fw_jump.bin will be broken if
> > FW_TEXT_START is wrong. This is not the desired behavior.
> 
> We should support FW_JUMP_OFFSET, irrespective of whether
> FW_PIC is defined or not.
> 

In fact, this patch allows to use FW_JUMP_OFFSET when FW_PIC=n.
But It will expand to FW_JUMP_ADDR to use old path.
I think your meaning is to drop this expansion and using
FW_JUMP_OFFSET directly, right?
I use this code path because of the binary size, but I am not 
sure which way is better. Is using OFFSET code path better?

> >
> > Add two new variables to identify relocatable jump address:
> > FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
> > ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
> > are defined. And these two new variables will convert to
> > the old one if compiler does not support PIC.
> >
> > Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> > ---
> >  firmware/fw_jump.S  | 20 ++++++++++++++++----
> >  firmware/objects.mk | 15 +++++++++++++++
> >  2 files changed, 31 insertions(+), 4 deletions(-)
> >
> > diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
> > index ac74dc6..0ad2398 100644
> > --- a/firmware/fw_jump.S
> > +++ b/firmware/fw_jump.S
> > @@ -46,6 +46,10 @@ fw_save_info:
> >  fw_next_arg1:
> >  #ifdef FW_JUMP_FDT_ADDR
> >         li      a0, FW_JUMP_FDT_ADDR
> > +#elif defined(FW_JUMP_FDT_OFFSET)
> > +       lla     a0, _fw_start
> > +       li      a1, FW_JUMP_FDT_OFFSET
> > +       add     a0, a0, a1
> >  #else
> >         add     a0, a1, zero
> >  #endif
> > @@ -59,7 +63,13 @@ fw_next_arg1:
> >          * The next address should be returned in 'a0'.
> >          */
> >  fw_next_addr:
> > +#ifdef FW_JUMP_ADDR
> >         lla     a0, _jump_addr
> > +#elif defined(FW_JUMP_OFFSET)
> > +       lla     a0, _fw_start
> > +       li      a1, FW_JUMP_OFFSET
> > +       add     a0, a0, a1
> 
> What if both FW_JUMP_ADDR and FW_JUMP_OFFSET are not available ?
> 

The build will failed, see the change in the below.

> > +#endif
> >         REG_L   a0, (a0)
> >         ret
> >
> > @@ -86,11 +96,13 @@ fw_options:
> >         add     a0, zero, zero
> >         ret
> >
> > -#ifndef FW_JUMP_ADDR
> > -#error "Must define FW_JUMP_ADDR"
> > -#endif
> > -
> > +#ifdef FW_JUMP_ADDR
> >         .section .rodata
> >         .align 3
> >  _jump_addr:
> >         RISCV_PTR FW_JUMP_ADDR
> > +#else
> > +#ifndef FW_JUMP_OFFSET
> > +#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
> > +#endif
> > +#endif
> > diff --git a/firmware/objects.mk b/firmware/objects.mk
> > index a1704c4..248706d 100644
> > --- a/firmware/objects.mk
> > +++ b/firmware/objects.mk
> > @@ -35,12 +35,27 @@ firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
> >  endif
> >  endif
> >
> > +ifeq ($(FW_PIC),n)
> 
> Let's not condition this upon FW_PIC.
> 
> Instead this should be:
> 
> ifdef FW_JUMP_OFFSET
> 

This is already included in the change below, If it supports
FW_PIC=n, this should be removed.

> > +  ifndef FW_JUMP_ADDR
> > +    FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_OFFSET))))
> > +  endif
> > +  ifndef FW_JUMP_FDT_ADDR
> > +    FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
> > +  endif
> > +endif
> > +
> >  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
> >
> >  firmware-bins-$(FW_JUMP) += fw_jump.bin
> > +ifdef FW_JUMP_OFFSET
> > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
> > +endif
> >  ifdef FW_JUMP_ADDR
> >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
> >  endif
> > +ifdef FW_JUMP_FDT_OFFSET
> > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> > +endif
> >  ifdef FW_JUMP_FDT_ADDR
> >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> >  endif
> > --
> > 2.43.0
> >
> 
> Regards,
> Anup


From inochiama at outlook.com  Thu Feb 22 23:23:06 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 15:23:06 +0800
Subject: [PATCH 2/4] firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
In-Reply-To: <CAAhSdy1KuWKob_eV60RHkKXbxzxsge49n2PcfjeBbaXZJ28wFg@mail.gmail.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB49539A729C9350C1714D7DA4BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy1KuWKob_eV60RHkKXbxzxsge49n2PcfjeBbaXZJ28wFg@mail.gmail.com>
Message-ID: <IA1PR20MB495313793AEC9680A540ED8ABB552@IA1PR20MB4953.namprd20.prod.outlook.com>

On Fri, Feb 23, 2024 at 10:31:32AM +0530, Anup Patel wrote:
> On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
> >
> > The fw_payload.bin has the same issue as described in commit 80129c2.
> 
> Can't find commit 80129c2 in upstream OpenSBI. Improve commit description.
> 

In fact, commit 80129c2 is patch 1. I will fix this.

> > But only FW_PAYLOAD_FDT_ADDR is affected.
> >
> > Add FW_PAYLOAD_FDT_OFFSET to identify relocatable payload fdt address.
> >
> > Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> > ---
> >  firmware/fw_payload.S | 4 ++++
> >  firmware/objects.mk   | 6 ++++++
> >  2 files changed, 10 insertions(+)
> >
> > diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
> > index c53a3bb..3c8433e 100644
> > --- a/firmware/fw_payload.S
> > +++ b/firmware/fw_payload.S
> > @@ -46,6 +46,10 @@ fw_save_info:
> >  fw_next_arg1:
> >  #ifdef FW_PAYLOAD_FDT_ADDR
> >         li      a0, FW_PAYLOAD_FDT_ADDR
> > +#elif defined(FW_PAYLOAD_FDT_OFFSET)
> > +       lla     a0, _fw_start
> > +       li      a1, FW_PAYLOAD_FDT_OFFSET
> > +       add     a0, a0, a1
> >  #else
> >         add     a0, a1, zero
> >  #endif
> > diff --git a/firmware/objects.mk b/firmware/objects.mk
> > index 248706d..a761b9e 100644
> > --- a/firmware/objects.mk
> > +++ b/firmware/objects.mk
> > @@ -42,6 +42,9 @@ ifeq ($(FW_PIC),n)
> >    ifndef FW_JUMP_FDT_ADDR
> >      FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
> >    endif
> > +  ifndef FW_PAYLOAD_FDT_ADDR
> > +    FW_PAYLOAD_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_PAYLOAD_FDT_OFFSET))))
> > +  endif
> >  endif
> >
> >  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
> > @@ -74,6 +77,9 @@ ifdef FW_PAYLOAD_ALIGN
> >  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
> >  endif
> >
> > +ifdef FW_PAYLOAD_FDT_OFFSET
> > +firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
> > +endif
> >  ifdef FW_PAYLOAD_FDT_ADDR
> >  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
> >  endif
> > --
> > 2.43.0
> >
> 
> Regards,
> Anup


From inochiama at outlook.com  Thu Feb 22 23:25:09 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 15:25:09 +0800
Subject: [PATCH 3/4] platform: Apply relocatable address
In-Reply-To: <CAAhSdy3vt2RCUc3TNd=Fowsu_044DHaBbWej3N4a-e+88Vpzqg@mail.gmail.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB49538AFD74ED9DA26246603CBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy3vt2RCUc3TNd=Fowsu_044DHaBbWej3N4a-e+88Vpzqg@mail.gmail.com>
Message-ID: <IA1PR20MB49535779A7A163C71A2FB1D4BB552@IA1PR20MB4953.namprd20.prod.outlook.com>

On Fri, Feb 23, 2024 at 10:33:09AM +0530, Anup Patel wrote:
> On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
> >
> > Since jump and payload firmware support relocatable address, make
> > general platform use runtime relocatable address.
> >
> > Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> 
> This patch should also update platform/template/objects.mk.
> 

Thanks for the reminder.

> Regards,
> Anup
> 
> > ---
> >  platform/generic/objects.mk | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
> > index 136853e..85aa723 100644
> > --- a/platform/generic/objects.mk
> > +++ b/platform/generic/objects.mk
> > @@ -27,12 +27,12 @@ FW_DYNAMIC=y
> >  FW_JUMP=y
> >  ifeq ($(PLATFORM_RISCV_XLEN), 32)
> >    # This needs to be 4MB aligned for 32-bit system
> > -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000)))
> > +  FW_JUMP_OFFSET=0x400000
> >  else
> >    # This needs to be 2MB aligned for 64-bit system
> > -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000)))
> > +  FW_JUMP_OFFSET=0x200000
> >  endif
> > -FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000)))
> > +FW_JUMP_FDT_OFFSET=0x2200000
> >  FW_PAYLOAD=y
> >  ifeq ($(PLATFORM_RISCV_XLEN), 32)
> >    # This needs to be 4MB aligned for 32-bit system
> > @@ -41,4 +41,4 @@ else
> >    # This needs to be 2MB aligned for 64-bit system
> >    FW_PAYLOAD_OFFSET=0x200000
> >  endif
> > -FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> > +FW_PAYLOAD_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> > --
> > 2.43.0
> >


From anup at brainfault.org  Thu Feb 22 23:29:30 2024
From: anup at brainfault.org (Anup Patel)
Date: Fri, 23 Feb 2024 12:59:30 +0530
Subject: [PATCH 1/4] firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
In-Reply-To: <IA1PR20MB49538587A5ECDF140EDD4613BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy3y7x5gorsW9LKpLS0ucYrOmse4-v8HwgqYnD8r9iKP5Q@mail.gmail.com> <IA1PR20MB49538587A5ECDF140EDD4613BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy0eD+gMJk6nuWy2Rs-NLYDpsKHB25jU_+pN9ZUteHc0qg@mail.gmail.com>

On Fri, Feb 23, 2024 at 12:51?PM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> On Fri, Feb 23, 2024 at 10:28:49AM +0530, Anup Patel wrote:
> > On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
> > >
> > > If FW_PIC=y is defined, the fw_jump.bin will be broken if
> > > FW_TEXT_START is wrong. This is not the desired behavior.
> >
> > We should support FW_JUMP_OFFSET, irrespective of whether
> > FW_PIC is defined or not.
> >
>
> In fact, this patch allows to use FW_JUMP_OFFSET when FW_PIC=n.
> But It will expand to FW_JUMP_ADDR to use old path.
> I think your meaning is to drop this expansion and using
> FW_JUMP_OFFSET directly, right?

Yes, FW_JUMP_ADDR should not be derived from FW_JUMP_OFFSET
so that platforms can specify any one.

> I use this code path because of the binary size, but I am not
> sure which way is better. Is using OFFSET code path better?
>
> > >
> > > Add two new variables to identify relocatable jump address:
> > > FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
> > > ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
> > > are defined. And these two new variables will convert to
> > > the old one if compiler does not support PIC.
> > >
> > > Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> > > ---
> > >  firmware/fw_jump.S  | 20 ++++++++++++++++----
> > >  firmware/objects.mk | 15 +++++++++++++++
> > >  2 files changed, 31 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
> > > index ac74dc6..0ad2398 100644
> > > --- a/firmware/fw_jump.S
> > > +++ b/firmware/fw_jump.S
> > > @@ -46,6 +46,10 @@ fw_save_info:
> > >  fw_next_arg1:
> > >  #ifdef FW_JUMP_FDT_ADDR
> > >         li      a0, FW_JUMP_FDT_ADDR
> > > +#elif defined(FW_JUMP_FDT_OFFSET)
> > > +       lla     a0, _fw_start
> > > +       li      a1, FW_JUMP_FDT_OFFSET
> > > +       add     a0, a0, a1
> > >  #else
> > >         add     a0, a1, zero
> > >  #endif
> > > @@ -59,7 +63,13 @@ fw_next_arg1:
> > >          * The next address should be returned in 'a0'.
> > >          */
> > >  fw_next_addr:
> > > +#ifdef FW_JUMP_ADDR
> > >         lla     a0, _jump_addr
> > > +#elif defined(FW_JUMP_OFFSET)
> > > +       lla     a0, _fw_start
> > > +       li      a1, FW_JUMP_OFFSET
> > > +       add     a0, a0, a1
> >
> > What if both FW_JUMP_ADDR and FW_JUMP_OFFSET are not available ?
> >
>
> The build will failed, see the change in the below.
>
> > > +#endif
> > >         REG_L   a0, (a0)
> > >         ret
> > >
> > > @@ -86,11 +96,13 @@ fw_options:
> > >         add     a0, zero, zero
> > >         ret
> > >
> > > -#ifndef FW_JUMP_ADDR
> > > -#error "Must define FW_JUMP_ADDR"
> > > -#endif
> > > -
> > > +#ifdef FW_JUMP_ADDR
> > >         .section .rodata
> > >         .align 3
> > >  _jump_addr:
> > >         RISCV_PTR FW_JUMP_ADDR
> > > +#else
> > > +#ifndef FW_JUMP_OFFSET
> > > +#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
> > > +#endif
> > > +#endif
> > > diff --git a/firmware/objects.mk b/firmware/objects.mk
> > > index a1704c4..248706d 100644
> > > --- a/firmware/objects.mk
> > > +++ b/firmware/objects.mk
> > > @@ -35,12 +35,27 @@ firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
> > >  endif
> > >  endif
> > >
> > > +ifeq ($(FW_PIC),n)
> >
> > Let's not condition this upon FW_PIC.
> >
> > Instead this should be:
> >
> > ifdef FW_JUMP_OFFSET
> >
>
> This is already included in the change below, If it supports
> FW_PIC=n, this should be removed.

Lets just remove this ifeq block so that FW_JUMP_ADDR is
totally independent of FW_JUMP_OFFSET.

>
> > > +  ifndef FW_JUMP_ADDR
> > > +    FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_OFFSET))))
> > > +  endif
> > > +  ifndef FW_JUMP_FDT_ADDR
> > > +    FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
> > > +  endif
> > > +endif
> > > +
> > >  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
> > >
> > >  firmware-bins-$(FW_JUMP) += fw_jump.bin
> > > +ifdef FW_JUMP_OFFSET
> > > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
> > > +endif
> > >  ifdef FW_JUMP_ADDR
> > >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
> > >  endif
> > > +ifdef FW_JUMP_FDT_OFFSET
> > > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> > > +endif
> > >  ifdef FW_JUMP_FDT_ADDR
> > >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> > >  endif
> > > --
> > > 2.43.0
> > >
> >
> > Regards,
> > Anup

Regards,
Anup


From inochiama at outlook.com  Thu Feb 22 23:37:34 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 15:37:34 +0800
Subject: [PATCH 1/4] firmware: Add relocatable FW_JUMP_ADDR and
 FW_JUMP_FDT_ADDR
In-Reply-To: <CAAhSdy0eD+gMJk6nuWy2Rs-NLYDpsKHB25jU_+pN9ZUteHc0qg@mail.gmail.com>
References: <IA1PR20MB495352218C0BF2CE8D86B3B9BB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB4953C326B2BADDFFAB32987BBB422@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy3y7x5gorsW9LKpLS0ucYrOmse4-v8HwgqYnD8r9iKP5Q@mail.gmail.com>
 <IA1PR20MB49538587A5ECDF140EDD4613BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
 <CAAhSdy0eD+gMJk6nuWy2Rs-NLYDpsKHB25jU_+pN9ZUteHc0qg@mail.gmail.com>
Message-ID: <IA1PR20MB4953E1883A2CE65DFE459F0CBB552@IA1PR20MB4953.namprd20.prod.outlook.com>

On Fri, Feb 23, 2024 at 12:59:30PM +0530, Anup Patel wrote:
> On Fri, Feb 23, 2024 at 12:51?PM Inochi Amaoto <inochiama at outlook.com> wrote:
> >
> > On Fri, Feb 23, 2024 at 10:28:49AM +0530, Anup Patel wrote:
> > > On Fri, Feb 2, 2024 at 9:35?AM Inochi Amaoto <inochiama at outlook.com> wrote:
> > > >
> > > > If FW_PIC=y is defined, the fw_jump.bin will be broken if
> > > > FW_TEXT_START is wrong. This is not the desired behavior.
> > >
> > > We should support FW_JUMP_OFFSET, irrespective of whether
> > > FW_PIC is defined or not.
> > >
> >
> > In fact, this patch allows to use FW_JUMP_OFFSET when FW_PIC=n.
> > But It will expand to FW_JUMP_ADDR to use old path.
> > I think your meaning is to drop this expansion and using
> > FW_JUMP_OFFSET directly, right?
> 
> Yes, FW_JUMP_ADDR should not be derived from FW_JUMP_OFFSET
> so that platforms can specify any one.
> 

Thanks. I will support this.

> > I use this code path because of the binary size, but I am not
> > sure which way is better. Is using OFFSET code path better?
> >
> > > >
> > > > Add two new variables to identify relocatable jump address:
> > > > FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
> > > > ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
> > > > are defined. And these two new variables will convert to
> > > > the old one if compiler does not support PIC.
> > > >
> > > > Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
> > > > ---
> > > >  firmware/fw_jump.S  | 20 ++++++++++++++++----
> > > >  firmware/objects.mk | 15 +++++++++++++++
> > > >  2 files changed, 31 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
> > > > index ac74dc6..0ad2398 100644
> > > > --- a/firmware/fw_jump.S
> > > > +++ b/firmware/fw_jump.S
> > > > @@ -46,6 +46,10 @@ fw_save_info:
> > > >  fw_next_arg1:
> > > >  #ifdef FW_JUMP_FDT_ADDR
> > > >         li      a0, FW_JUMP_FDT_ADDR
> > > > +#elif defined(FW_JUMP_FDT_OFFSET)
> > > > +       lla     a0, _fw_start
> > > > +       li      a1, FW_JUMP_FDT_OFFSET
> > > > +       add     a0, a0, a1
> > > >  #else
> > > >         add     a0, a1, zero
> > > >  #endif
> > > > @@ -59,7 +63,13 @@ fw_next_arg1:
> > > >          * The next address should be returned in 'a0'.
> > > >          */
> > > >  fw_next_addr:
> > > > +#ifdef FW_JUMP_ADDR
> > > >         lla     a0, _jump_addr
> > > > +#elif defined(FW_JUMP_OFFSET)
> > > > +       lla     a0, _fw_start
> > > > +       li      a1, FW_JUMP_OFFSET
> > > > +       add     a0, a0, a1
> > >
> > > What if both FW_JUMP_ADDR and FW_JUMP_OFFSET are not available ?
> > >
> >
> > The build will failed, see the change in the below.
> >
> > > > +#endif
> > > >         REG_L   a0, (a0)
> > > >         ret
> > > >
> > > > @@ -86,11 +96,13 @@ fw_options:
> > > >         add     a0, zero, zero
> > > >         ret
> > > >
> > > > -#ifndef FW_JUMP_ADDR
> > > > -#error "Must define FW_JUMP_ADDR"
> > > > -#endif
> > > > -
> > > > +#ifdef FW_JUMP_ADDR
> > > >         .section .rodata
> > > >         .align 3
> > > >  _jump_addr:
> > > >         RISCV_PTR FW_JUMP_ADDR
> > > > +#else
> > > > +#ifndef FW_JUMP_OFFSET
> > > > +#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
> > > > +#endif
> > > > +#endif
> > > > diff --git a/firmware/objects.mk b/firmware/objects.mk
> > > > index a1704c4..248706d 100644
> > > > --- a/firmware/objects.mk
> > > > +++ b/firmware/objects.mk
> > > > @@ -35,12 +35,27 @@ firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
> > > >  endif
> > > >  endif
> > > >
> > > > +ifeq ($(FW_PIC),n)
> > >
> > > Let's not condition this upon FW_PIC.
> > >
> > > Instead this should be:
> > >
> > > ifdef FW_JUMP_OFFSET
> > >
> >
> > This is already included in the change below, If it supports
> > FW_PIC=n, this should be removed.
> 
> Lets just remove this ifeq block so that FW_JUMP_ADDR is
> totally independent of FW_JUMP_OFFSET.
> 
> >
> > > > +  ifndef FW_JUMP_ADDR
> > > > +    FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_OFFSET))))
> > > > +  endif
> > > > +  ifndef FW_JUMP_FDT_ADDR
> > > > +    FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + $(FW_JUMP_FDT_OFFSET))))
> > > > +  endif
> > > > +endif
> > > > +
> > > >  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
> > > >
> > > >  firmware-bins-$(FW_JUMP) += fw_jump.bin
> > > > +ifdef FW_JUMP_OFFSET
> > > > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
> > > > +endif
> > > >  ifdef FW_JUMP_ADDR
> > > >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
> > > >  endif
> > > > +ifdef FW_JUMP_FDT_OFFSET
> > > > +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> > > > +endif
> > > >  ifdef FW_JUMP_FDT_ADDR
> > > >  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> > > >  endif
> > > > --
> > > > 2.43.0
> > > >
> > >
> > > Regards,
> > > Anup
> 
> Regards,
> Anup


From inochiama at outlook.com  Fri Feb 23 00:17:20 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 16:17:20 +0800
Subject: [PATCH v2 0/4] Add relocatable address support for jump and payload firmware
Message-ID: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>

If FW_PIC=y is defined, the jump and payload firmware and will
be broken if FW_TEXT_START is wrong. This is not the desired behavior.

Add some new variable to support relocatable address.

build command:
make BUILD_INFO=y DEBUG=1 FW_PIC=y PLATFORM=generic FW_TEXT_START=0x0

test command:
qemu-system-riscv64 -smp cpus=4 -M virt -m 256M \
  -bios build/platform/generic/firmware/fw_payload.bin

Changed from v1:
1. allow to use <X>_OFFSET when FW_PIC=n
2. fix wrong fw_next_address when using offset address.

Inochi Amaoto (4):
  firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
  firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
  platform: Apply relocatable address
  doc/firmware: add new configuration options for jump and payload
    firmware

 docs/firmware/fw_jump.md     | 17 ++++++++++++++---
 docs/firmware/fw_payload.md  |  6 ++++++
 firmware/fw_jump.S           | 18 ++++++++++++++----
 firmware/fw_payload.S        |  4 ++++
 firmware/objects.mk          |  9 +++++++++
 platform/generic/objects.mk  |  8 ++++----
 platform/template/objects.mk | 17 +++++++++++++++++
 7 files changed, 68 insertions(+), 11 deletions(-)

--
2.43.2



From inochiama at outlook.com  Fri Feb 23 00:18:12 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 16:18:12 +0800
Subject: [PATCH v2 1/4] firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
In-Reply-To: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB495382D3F9CEEBAACA5F5E68BB552@IA1PR20MB4953.namprd20.prod.outlook.com>

If FW_PIC=y is defined, the fw_jump.bin will be broken if
FW_TEXT_START is wrong. This is not the desired behavior.

Add two new variables to identify relocatable jump address:
FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
are defined.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 firmware/fw_jump.S  | 18 ++++++++++++++----
 firmware/objects.mk |  6 ++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
index ac74dc6..ebf297f 100644
--- a/firmware/fw_jump.S
+++ b/firmware/fw_jump.S
@@ -46,6 +46,10 @@ fw_save_info:
 fw_next_arg1:
 #ifdef FW_JUMP_FDT_ADDR
 	li	a0, FW_JUMP_FDT_ADDR
+#elif defined(FW_JUMP_FDT_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_JUMP_FDT_OFFSET
+	add	a0, a0, a1
 #else
 	add	a0, a1, zero
 #endif
@@ -59,8 +63,16 @@ fw_next_arg1:
 	 * The next address should be returned in 'a0'.
 	 */
 fw_next_addr:
+#ifdef FW_JUMP_ADDR
 	lla	a0, _jump_addr
 	REG_L	a0, (a0)
+#elif defined(FW_JUMP_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_JUMP_OFFSET
+	add	a0, a0, a1
+#else
+#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
+#endif
 	ret
 
 	.section .entry, "ax", %progbits
@@ -86,11 +98,9 @@ fw_options:
 	add	a0, zero, zero
 	ret
 
-#ifndef FW_JUMP_ADDR
-#error "Must define FW_JUMP_ADDR"
-#endif
-
+#ifdef FW_JUMP_ADDR
 	.section .rodata
 	.align 3
 _jump_addr:
 	RISCV_PTR FW_JUMP_ADDR
+#endif
diff --git a/firmware/objects.mk b/firmware/objects.mk
index a1704c4..fef090a 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -38,9 +38,15 @@ endif
 firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
 
 firmware-bins-$(FW_JUMP) += fw_jump.bin
+ifdef FW_JUMP_OFFSET
+firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
+endif
 ifdef FW_JUMP_ADDR
 firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
 endif
+ifdef FW_JUMP_FDT_OFFSET
+firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
+endif
 ifdef FW_JUMP_FDT_ADDR
 firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
 endif
-- 
2.43.2



From inochiama at outlook.com  Fri Feb 23 00:18:13 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 16:18:13 +0800
Subject: [PATCH v2 2/4] firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
In-Reply-To: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB4953A6803AB85AB9EF9447BEBB552@IA1PR20MB4953.namprd20.prod.outlook.com>

The fw_payload.bin has the same issue as described in previous patch.
But only FW_PAYLOAD_FDT_ADDR is affected.

Add FW_PAYLOAD_FDT_OFFSET to identify relocatable payload fdt address.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 firmware/fw_payload.S | 4 ++++
 firmware/objects.mk   | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
index c53a3bb..3c8433e 100644
--- a/firmware/fw_payload.S
+++ b/firmware/fw_payload.S
@@ -46,6 +46,10 @@ fw_save_info:
 fw_next_arg1:
 #ifdef FW_PAYLOAD_FDT_ADDR
 	li	a0, FW_PAYLOAD_FDT_ADDR
+#elif defined(FW_PAYLOAD_FDT_OFFSET)
+	lla	a0, _fw_start
+	li	a1, FW_PAYLOAD_FDT_OFFSET
+	add	a0, a0, a1
 #else
 	add	a0, a1, zero
 #endif
diff --git a/firmware/objects.mk b/firmware/objects.mk
index fef090a..3ae0a28 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -65,6 +65,9 @@ ifdef FW_PAYLOAD_ALIGN
 firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
 endif
 
+ifdef FW_PAYLOAD_FDT_OFFSET
+firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
+endif
 ifdef FW_PAYLOAD_FDT_ADDR
 firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
 endif
-- 
2.43.2



From inochiama at outlook.com  Fri Feb 23 00:18:14 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 16:18:14 +0800
Subject: [PATCH v2 3/4] platform: Apply relocatable address
In-Reply-To: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB495323C838505F085A4E402CBB552@IA1PR20MB4953.namprd20.prod.outlook.com>

Since jump and payload firmware support relocatable address, make
general platform use runtime relocatable address.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 platform/generic/objects.mk  |  8 ++++----
 platform/template/objects.mk | 17 +++++++++++++++++
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
index 136853e..85aa723 100644
--- a/platform/generic/objects.mk
+++ b/platform/generic/objects.mk
@@ -27,12 +27,12 @@ FW_DYNAMIC=y
 FW_JUMP=y
 ifeq ($(PLATFORM_RISCV_XLEN), 32)
   # This needs to be 4MB aligned for 32-bit system
-  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000)))
+  FW_JUMP_OFFSET=0x400000
 else
   # This needs to be 2MB aligned for 64-bit system
-  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000)))
+  FW_JUMP_OFFSET=0x200000
 endif
-FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000)))
+FW_JUMP_FDT_OFFSET=0x2200000
 FW_PAYLOAD=y
 ifeq ($(PLATFORM_RISCV_XLEN), 32)
   # This needs to be 4MB aligned for 32-bit system
@@ -41,4 +41,4 @@ else
   # This needs to be 2MB aligned for 64-bit system
   FW_PAYLOAD_OFFSET=0x200000
 endif
-FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
+FW_PAYLOAD_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
diff --git a/platform/template/objects.mk b/platform/template/objects.mk
index 0025928..b143cbc 100644
--- a/platform/template/objects.mk
+++ b/platform/template/objects.mk
@@ -63,6 +63,17 @@ FW_JUMP=<y|n>
 # This needs to be 4MB aligned for 32-bit support
 # This needs to be 2MB aligned for 64-bit support
 # ifeq ($(PLATFORM_RISCV_XLEN), 32)
+# FW_JUMP_OFFSET=0x400000
+# else
+# FW_JUMP_OFFSET=0x200000
+# endif
+# FW_JUMP_FDT_OFFSET=0x2200000
+#
+# You can use fixed address for jump firmware as an alternative option,
+# but this may fail when setting wrong FW_TEXT_START. Use with caution.
+# SBI will prefer "<X>_ADDR" if both "<X>_ADDR" and "<X>_OFFSET" are
+# defined
+# ifeq ($(PLATFORM_RISCV_XLEN), 32)
 # FW_JUMP_ADDR=0x80400000
 # else
 # FW_JUMP_ADDR=0x80200000
@@ -84,4 +95,10 @@ FW_PAYLOAD_OFFSET=0x200000
 endif
 # FW_PAYLOAD_ALIGN=0x1000
 # FW_PAYLOAD_PATH="path to next boot stage binary image file"
+# FW_PAYLOAD_FDT_OFFSET=0x2200000
+#
+# You can use fixed address for payload firmware as an alternative option,
+# but this may fail when setting wrong FW_TEXT_START. Use with caution.
+# SBI will prefer "FW_PAYLOAD_FDT_ADDR" if both "FW_PAYLOAD_FDT_OFFSET"
+# and "FW_PAYLOAD_FDT_ADDR" are defined.
 # FW_PAYLOAD_FDT_ADDR=0x82200000
-- 
2.43.2



From inochiama at outlook.com  Fri Feb 23 00:18:15 2024
From: inochiama at outlook.com (Inochi Amaoto)
Date: Fri, 23 Feb 2024 16:18:15 +0800
Subject: [PATCH v2 4/4] doc/firmware: add new configuration options for jump and payload firmware
In-Reply-To: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <IA1PR20MB49538E5FEEB091B8DFBBBCFFBB552@IA1PR20MB4953.namprd20.prod.outlook.com>

Adding relocatable address brings new configuration options.
Add these new options in doc.

Signed-off-by: Inochi Amaoto <inochiama at outlook.com>
---
 docs/firmware/fw_jump.md    | 17 ++++++++++++++---
 docs/firmware/fw_payload.md |  6 ++++++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/docs/firmware/fw_jump.md b/docs/firmware/fw_jump.md
index 3e883fa..4484393 100644
--- a/docs/firmware/fw_jump.md
+++ b/docs/firmware/fw_jump.md
@@ -31,9 +31,15 @@ follows:
 
 * **FW_JUMP_ADDR** - Address of the entry point of the booting stage to be
   executed following OpenSBI firmware. This address generally corresponds
-  exactly to the address where this next booting stage was loaded. This is a
-  mandatory parameter. Compilation errors will result from not defining this
-  address.
+  exactly to the address where this next booting stage was loaded.
+  At least one of *FW_JUMP_ADDR* and *FW_JUMP_OFFSET* (see below) should be
+  defined. Compilation errors will result from not defining one of them.
+
+* **FW_JUMP_OFFSET** - Address offset from the *FW_TEXT_START* of *FW_JUMP_ADDR*.
+  This offset is used as relocatable *FW_JUMP_ADDR* when "FW_PIC=y".
+  If *FW_JUMP_ADDR* is also defined, the firmware will prefer *FW_JUMP_ADDR*.
+  This offset will convert to *FW_JUMP_ADDR* at build time if "FW_PIC=n"
+  and *FW_JUMP_ADDR* is not defined.
 
 * **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
   passed by the prior booting stage will be placed in memory before executing
@@ -56,6 +62,11 @@ follows:
   (( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) &&
   echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR
   ```
+* **FW_JUMP_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
+  *FW_JUMP_FDT_ADDR*. This offset is used as relocatable *FW_JUMP_FDT_ADDR*
+  when "FW_PIC=y". If *FW_JUMP_FDT_ADDR* is also defined, the firmware will
+  prefer *FW_JUMP_FDT_ADDR*. This offset will convert to *FW_JUMP_FDT_ADDR*
+  at build time if "FW_PIC=n" and *FW_JUMP_FDT_ADDR* is not defined.
 
 *FW_JUMP* Example
 -----------------
diff --git a/docs/firmware/fw_payload.md b/docs/firmware/fw_payload.md
index 113604a..3a5ffe8 100644
--- a/docs/firmware/fw_payload.md
+++ b/docs/firmware/fw_payload.md
@@ -62,6 +62,12 @@ file. The parameters currently defined are as follows:
   firmware will pass the FDT address passed by the previous booting stage
   to the next booting stage.
 
+* **FW_PAYLOAD_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
+  *FW_PAYLOAD_FDT_ADDR*. This offset is used as relocatable *FW_PAYLOAD_FDT_ADDR*
+  when "FW_PIC=y". If *FW_PAYLOAD_FDT_ADDR* is also defined, the firmware will
+  prefer *FW_PAYLOAD_FDT_ADDR*. This offset will convert to *FW_PAYLOAD_FDT_ADDR*
+  at build time if "FW_PIC=n" and *FW_PAYLOAD_FDT_ADDR* is not defined.
+
 *FW_PAYLOAD* Example
 --------------------
 
-- 
2.43.2



From anup at brainfault.org  Sat Feb 24 02:59:29 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 16:29:29 +0530
Subject: [PATCH v2 1/4] firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
In-Reply-To: <IA1PR20MB495382D3F9CEEBAACA5F5E68BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB495382D3F9CEEBAACA5F5E68BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy3XCg0iS=q-2YSo1EGfxUFU0KLivWNTq3JO=E-108LiTw@mail.gmail.com>

On Fri, Feb 23, 2024 at 1:48?PM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> If FW_PIC=y is defined, the fw_jump.bin will be broken if
> FW_TEXT_START is wrong. This is not the desired behavior.
>
> Add two new variables to identify relocatable jump address:
> FW_JUMP_OFFSET and FW_JUMP_FDT_ADDR. To keep the existing
> ABI, FW_JUMP_ADDR and FW_JUMP_FDT_ADDR is prefered if they
> are defined.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_jump.S  | 18 ++++++++++++++----
>  firmware/objects.mk |  6 ++++++
>  2 files changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S
> index ac74dc6..ebf297f 100644
> --- a/firmware/fw_jump.S
> +++ b/firmware/fw_jump.S
> @@ -46,6 +46,10 @@ fw_save_info:
>  fw_next_arg1:
>  #ifdef FW_JUMP_FDT_ADDR
>         li      a0, FW_JUMP_FDT_ADDR
> +#elif defined(FW_JUMP_FDT_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_JUMP_FDT_OFFSET
> +       add     a0, a0, a1
>  #else
>         add     a0, a1, zero
>  #endif
> @@ -59,8 +63,16 @@ fw_next_arg1:
>          * The next address should be returned in 'a0'.
>          */
>  fw_next_addr:
> +#ifdef FW_JUMP_ADDR
>         lla     a0, _jump_addr
>         REG_L   a0, (a0)
> +#elif defined(FW_JUMP_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_JUMP_OFFSET
> +       add     a0, a0, a1
> +#else
> +#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
> +#endif
>         ret
>
>         .section .entry, "ax", %progbits
> @@ -86,11 +98,9 @@ fw_options:
>         add     a0, zero, zero
>         ret
>
> -#ifndef FW_JUMP_ADDR
> -#error "Must define FW_JUMP_ADDR"
> -#endif
> -
> +#ifdef FW_JUMP_ADDR
>         .section .rodata
>         .align 3
>  _jump_addr:
>         RISCV_PTR FW_JUMP_ADDR
> +#endif
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index a1704c4..fef090a 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -38,9 +38,15 @@ endif
>  firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
>
>  firmware-bins-$(FW_JUMP) += fw_jump.bin
> +ifdef FW_JUMP_OFFSET
> +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
> +endif
>  ifdef FW_JUMP_ADDR
>  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
>  endif
> +ifdef FW_JUMP_FDT_OFFSET
> +firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> +endif
>  ifdef FW_JUMP_FDT_ADDR
>  firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
>  endif
> --
> 2.43.2
>


From anup at brainfault.org  Sat Feb 24 02:59:44 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 16:29:44 +0530
Subject: [PATCH v2 2/4] firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
In-Reply-To: <IA1PR20MB4953A6803AB85AB9EF9447BEBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB4953A6803AB85AB9EF9447BEBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy2pm_NU+G_MB_0yX3DcYk_Li4jxOfMQ-HB2UNAHBBOz5w@mail.gmail.com>

On Fri, Feb 23, 2024 at 1:48?PM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> The fw_payload.bin has the same issue as described in previous patch.
> But only FW_PAYLOAD_FDT_ADDR is affected.
>
> Add FW_PAYLOAD_FDT_OFFSET to identify relocatable payload fdt address.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_payload.S | 4 ++++
>  firmware/objects.mk   | 3 +++
>  2 files changed, 7 insertions(+)
>
> diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S
> index c53a3bb..3c8433e 100644
> --- a/firmware/fw_payload.S
> +++ b/firmware/fw_payload.S
> @@ -46,6 +46,10 @@ fw_save_info:
>  fw_next_arg1:
>  #ifdef FW_PAYLOAD_FDT_ADDR
>         li      a0, FW_PAYLOAD_FDT_ADDR
> +#elif defined(FW_PAYLOAD_FDT_OFFSET)
> +       lla     a0, _fw_start
> +       li      a1, FW_PAYLOAD_FDT_OFFSET
> +       add     a0, a0, a1
>  #else
>         add     a0, a1, zero
>  #endif
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index fef090a..3ae0a28 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -65,6 +65,9 @@ ifdef FW_PAYLOAD_ALIGN
>  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
>  endif
>
> +ifdef FW_PAYLOAD_FDT_OFFSET
> +firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
> +endif
>  ifdef FW_PAYLOAD_FDT_ADDR
>  firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
>  endif
> --
> 2.43.2
>


From anup at brainfault.org  Sat Feb 24 02:59:59 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 16:29:59 +0530
Subject: [PATCH v2 3/4] platform: Apply relocatable address
In-Reply-To: <IA1PR20MB495323C838505F085A4E402CBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB495323C838505F085A4E402CBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy2QRQhNbhiYewoKhDMjuDeWbPFbuQ9fYWTVxFLvv0vK0w@mail.gmail.com>

On Fri, Feb 23, 2024 at 1:48?PM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> Since jump and payload firmware support relocatable address, make
> general platform use runtime relocatable address.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  platform/generic/objects.mk  |  8 ++++----
>  platform/template/objects.mk | 17 +++++++++++++++++
>  2 files changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
> index 136853e..85aa723 100644
> --- a/platform/generic/objects.mk
> +++ b/platform/generic/objects.mk
> @@ -27,12 +27,12 @@ FW_DYNAMIC=y
>  FW_JUMP=y
>  ifeq ($(PLATFORM_RISCV_XLEN), 32)
>    # This needs to be 4MB aligned for 32-bit system
> -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000)))
> +  FW_JUMP_OFFSET=0x400000
>  else
>    # This needs to be 2MB aligned for 64-bit system
> -  FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000)))
> +  FW_JUMP_OFFSET=0x200000
>  endif
> -FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000)))
> +FW_JUMP_FDT_OFFSET=0x2200000
>  FW_PAYLOAD=y
>  ifeq ($(PLATFORM_RISCV_XLEN), 32)
>    # This needs to be 4MB aligned for 32-bit system
> @@ -41,4 +41,4 @@ else
>    # This needs to be 2MB aligned for 64-bit system
>    FW_PAYLOAD_OFFSET=0x200000
>  endif
> -FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
> +FW_PAYLOAD_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
> diff --git a/platform/template/objects.mk b/platform/template/objects.mk
> index 0025928..b143cbc 100644
> --- a/platform/template/objects.mk
> +++ b/platform/template/objects.mk
> @@ -63,6 +63,17 @@ FW_JUMP=<y|n>
>  # This needs to be 4MB aligned for 32-bit support
>  # This needs to be 2MB aligned for 64-bit support
>  # ifeq ($(PLATFORM_RISCV_XLEN), 32)
> +# FW_JUMP_OFFSET=0x400000
> +# else
> +# FW_JUMP_OFFSET=0x200000
> +# endif
> +# FW_JUMP_FDT_OFFSET=0x2200000
> +#
> +# You can use fixed address for jump firmware as an alternative option,
> +# but this may fail when setting wrong FW_TEXT_START. Use with caution.
> +# SBI will prefer "<X>_ADDR" if both "<X>_ADDR" and "<X>_OFFSET" are
> +# defined
> +# ifeq ($(PLATFORM_RISCV_XLEN), 32)
>  # FW_JUMP_ADDR=0x80400000
>  # else
>  # FW_JUMP_ADDR=0x80200000
> @@ -84,4 +95,10 @@ FW_PAYLOAD_OFFSET=0x200000
>  endif
>  # FW_PAYLOAD_ALIGN=0x1000
>  # FW_PAYLOAD_PATH="path to next boot stage binary image file"
> +# FW_PAYLOAD_FDT_OFFSET=0x2200000
> +#
> +# You can use fixed address for payload firmware as an alternative option,
> +# but this may fail when setting wrong FW_TEXT_START. Use with caution.
> +# SBI will prefer "FW_PAYLOAD_FDT_ADDR" if both "FW_PAYLOAD_FDT_OFFSET"
> +# and "FW_PAYLOAD_FDT_ADDR" are defined.
>  # FW_PAYLOAD_FDT_ADDR=0x82200000
> --
> 2.43.2
>


From anup at brainfault.org  Sat Feb 24 03:00:56 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 16:30:56 +0530
Subject: [PATCH v2 4/4] doc/firmware: add new configuration options for
 jump and payload firmware
In-Reply-To: <IA1PR20MB49538E5FEEB091B8DFBBBCFFBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
References: <IA1PR20MB495379ECC11096AEEBC4C691BB552@IA1PR20MB4953.namprd20.prod.outlook.com>
 <IA1PR20MB49538E5FEEB091B8DFBBBCFFBB552@IA1PR20MB4953.namprd20.prod.outlook.com>
Message-ID: <CAAhSdy0sV2b62tjPW2wzJnGVyWomv_+kNBDeNukc6721jjbZRA@mail.gmail.com>

On Fri, Feb 23, 2024 at 1:49?PM Inochi Amaoto <inochiama at outlook.com> wrote:
>
> Adding relocatable address brings new configuration options.
> Add these new options in doc.
>
> Signed-off-by: Inochi Amaoto <inochiama at outlook.com>

This patch needs to be improved because the new options don't
depend on FW_PIC. I have take care of this at the time of merging
this patch.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  docs/firmware/fw_jump.md    | 17 ++++++++++++++---
>  docs/firmware/fw_payload.md |  6 ++++++
>  2 files changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/docs/firmware/fw_jump.md b/docs/firmware/fw_jump.md
> index 3e883fa..4484393 100644
> --- a/docs/firmware/fw_jump.md
> +++ b/docs/firmware/fw_jump.md
> @@ -31,9 +31,15 @@ follows:
>
>  * **FW_JUMP_ADDR** - Address of the entry point of the booting stage to be
>    executed following OpenSBI firmware. This address generally corresponds
> -  exactly to the address where this next booting stage was loaded. This is a
> -  mandatory parameter. Compilation errors will result from not defining this
> -  address.
> +  exactly to the address where this next booting stage was loaded.
> +  At least one of *FW_JUMP_ADDR* and *FW_JUMP_OFFSET* (see below) should be
> +  defined. Compilation errors will result from not defining one of them.
> +
> +* **FW_JUMP_OFFSET** - Address offset from the *FW_TEXT_START* of *FW_JUMP_ADDR*.
> +  This offset is used as relocatable *FW_JUMP_ADDR* when "FW_PIC=y".
> +  If *FW_JUMP_ADDR* is also defined, the firmware will prefer *FW_JUMP_ADDR*.
> +  This offset will convert to *FW_JUMP_ADDR* at build time if "FW_PIC=n"
> +  and *FW_JUMP_ADDR* is not defined.
>
>  * **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
>    passed by the prior booting stage will be placed in memory before executing
> @@ -56,6 +62,11 @@ follows:
>    (( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) &&
>    echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR
>    ```
> +* **FW_JUMP_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
> +  *FW_JUMP_FDT_ADDR*. This offset is used as relocatable *FW_JUMP_FDT_ADDR*
> +  when "FW_PIC=y". If *FW_JUMP_FDT_ADDR* is also defined, the firmware will
> +  prefer *FW_JUMP_FDT_ADDR*. This offset will convert to *FW_JUMP_FDT_ADDR*
> +  at build time if "FW_PIC=n" and *FW_JUMP_FDT_ADDR* is not defined.
>
>  *FW_JUMP* Example
>  -----------------
> diff --git a/docs/firmware/fw_payload.md b/docs/firmware/fw_payload.md
> index 113604a..3a5ffe8 100644
> --- a/docs/firmware/fw_payload.md
> +++ b/docs/firmware/fw_payload.md
> @@ -62,6 +62,12 @@ file. The parameters currently defined are as follows:
>    firmware will pass the FDT address passed by the previous booting stage
>    to the next booting stage.
>
> +* **FW_PAYLOAD_FDT_OFFSET** - Address offset from the *FW_TEXT_START* of
> +  *FW_PAYLOAD_FDT_ADDR*. This offset is used as relocatable *FW_PAYLOAD_FDT_ADDR*
> +  when "FW_PIC=y". If *FW_PAYLOAD_FDT_ADDR* is also defined, the firmware will
> +  prefer *FW_PAYLOAD_FDT_ADDR*. This offset will convert to *FW_PAYLOAD_FDT_ADDR*
> +  at build time if "FW_PIC=n" and *FW_PAYLOAD_FDT_ADDR* is not defined.
> +
>  *FW_PAYLOAD* Example
>  --------------------
>
> --
> 2.43.2
>


From anup at brainfault.org  Sat Feb 24 04:55:58 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 18:25:58 +0530
Subject: [PATCH V2] lib: sbi: Add sparse hartid support for mtimer and mswi
In-Reply-To: <20240222065530.17673-1-gaoshanliukou@163.com>
References: <20240222065530.17673-1-gaoshanliukou@163.com>
Message-ID: <CAAhSdy1nEgZa+T1VzWL-Soam5PU6ztqRXCsJc9yrpyCu4n8HkA@mail.gmail.com>

On Thu, Feb 22, 2024 at 12:25?PM yang.zhang <gaoshanliukou at 163.com> wrote:
>
> From: "yang.zhang" <yang.zhang at hexintek.com>
>
> Need to support sparse hartid for mtmer and mswi.
>
> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>

hartid can always be derived from hartindex using sbi_hartindex_to_hartid()
so this patch can be simplified

> ---
> v1 -> v2:
> - Add handle in the case of multiple ACLINT instances
> - Check valid hartindex not hartid when parse fdt
>
> V1: https://lists.infradead.org/pipermail/opensbi/2024-February/006342.html
>
> ---
> I add additional first_hartindex instead of replacing first_hartid with it.
> Because first_hartindex maybe not the first hartid, which is the base of
> mtimer/mswi, such as in the cpus node of dts:
> cluster0 {cpu at 0: reg=<0x0>, cpu at 1: reg=<0x3>}
> cluster1 {cpu at 2: reg=<0x7>, cpu at 3: reg=<0x4>}
> ---
>  include/sbi_utils/fdt/fdt_helper.h      |  2 +-
>  include/sbi_utils/ipi/aclint_mswi.h     |  1 +
>  include/sbi_utils/timer/aclint_mtimer.h |  1 +
>  lib/utils/fdt/fdt_helper.c              | 16 +++++++++++-----
>  lib/utils/ipi/aclint_mswi.c             |  2 +-
>  lib/utils/ipi/fdt_ipi_mswi.c            |  2 +-
>  lib/utils/timer/aclint_mtimer.c         |  2 +-
>  lib/utils/timer/fdt_timer_mtimer.c      |  2 +-
>  platform/fpga/ariane/platform.c         |  2 ++
>  platform/fpga/openpiton/platform.c      |  2 ++
>  platform/kendryte/k210/platform.c       |  2 ++
>  platform/nuclei/ux600/platform.c        |  2 ++
>  platform/template/platform.c            |  2 ++
>  13 files changed, 28 insertions(+), 10 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index ab4a80f..398700d 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -103,7 +103,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>                           bool for_timer, bool allow_regname,
>                           unsigned long *out_addr1, unsigned long *out_size1,
>                           unsigned long *out_addr2, unsigned long *out_size2,
> -                         u32 *out_first_hartid, u32 *out_hart_count);
> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count);

Drop out_first_hartid

>
>  int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
>                           unsigned long *plmt_size, u32 *hart_count);
> diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
> index e373a8c..d5708e2 100644
> --- a/include/sbi_utils/ipi/aclint_mswi.h
> +++ b/include/sbi_utils/ipi/aclint_mswi.h
> @@ -22,6 +22,7 @@ struct aclint_mswi_data {
>         /* Public details */
>         unsigned long addr;
>         unsigned long size;
> +       u32 first_hartindex;
>         u32 first_hartid;

Remove first_hartid

>         u32 hart_count;
>  };
> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> index 6ab8799..21a7d93 100644
> --- a/include/sbi_utils/timer/aclint_mtimer.h
> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> @@ -31,6 +31,7 @@ struct aclint_mtimer_data {
>         unsigned long mtime_size;
>         unsigned long mtimecmp_addr;
>         unsigned long mtimecmp_size;
> +       u32 first_hartindex;
>         u32 first_hartid;

Remove first_hartid

>         u32 hart_count;
>         bool has_64bit_mmio;
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index a0e93b9..5d9215f 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -961,16 +961,17 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>                           bool for_timer, bool allow_regname,
>                           unsigned long *out_addr1, unsigned long *out_size1,
>                           unsigned long *out_addr2, unsigned long *out_size2,
> -                         u32 *out_first_hartid, u32 *out_hart_count)
> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count)

Same as above.

>  {
>         const fdt32_t *val;
>         int i, rc, count, cpu_offset, cpu_intc_offset;
> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
> +       u32 phandle, hwirq;
> +       u32 hartindex, hartid, first_hartindex, first_hartid, last_hartid, hart_count;
>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
>
>         if (nodeoffset < 0 || !fdt ||
>             !out_addr1 || !out_size1 ||
> -           !out_first_hartid || !out_hart_count)
> +           !out_first_hartindex || !out_first_hartid || !out_hart_count)
>                 return SBI_EINVAL;
>
>         if (for_timer && allow_regname && out_addr2 && out_size2 &&
> @@ -985,6 +986,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>         if (rc)
>                 return rc;
>
> +       *out_first_hartindex = 0;
>         *out_first_hartid = 0;
>         *out_hart_count = 0;
>
> @@ -993,7 +995,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>                 return 0;
>         count = count / sizeof(fdt32_t);
>
> -       first_hartid = -1U;
> +       first_hartindex = first_hartid = -1U;
>         hart_count = last_hartid = 0;
>         for (i = 0; i < (count / 2); i++) {
>                 phandle = fdt32_to_cpu(val[2 * i]);
> @@ -1011,10 +1013,13 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>                 if (rc)
>                         continue;
>
> -               if (SBI_HARTMASK_MAX_BITS <= hartid)
> +               hartindex = sbi_hartid_to_hartindex(hartid);
> +               if (SBI_HARTMASK_MAX_BITS <= hartindex)
>                         continue;
>
>                 if (match_hwirq == hwirq) {
> +                       if (hartindex < first_hartindex)
> +                               first_hartindex = hartindex;
>                         if (hartid < first_hartid)
>                                 first_hartid = hartid;
>                         if (hartid > last_hartid)
> @@ -1024,6 +1029,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>         }
>
>         if ((last_hartid >= first_hartid) && first_hartid != -1U) {
> +               *out_first_hartindex = first_hartindex;
>                 *out_first_hartid = first_hartid;
>                 count = last_hartid - first_hartid + 1;
>                 *out_hart_count = (hart_count < count) ? hart_count : count;
> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
> index 4ae6bb1..15298eb 100644
> --- a/lib/utils/ipi/aclint_mswi.c
> +++ b/lib/utils/ipi/aclint_mswi.c
> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
>
>         /* Update MSWI pointer in scratch space */
>         for (i = 0; i < mswi->hart_count; i++) {
> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
> +               scratch = sbi_hartindex_to_scratch(mswi->first_hartindex + i);
>                 /*
>                  * We don't need to fail if scratch pointer is not available
>                  * because we might be dealing with hartid of a HART disabled
> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
> index a709abe..e896e5a 100644
> --- a/lib/utils/ipi/fdt_ipi_mswi.c
> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
> @@ -26,7 +26,7 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
>
>         rc = fdt_parse_aclint_node(fdt, nodeoff, false, false,
>                                    &ms->addr, &ms->size, NULL, NULL,
> -                                  &ms->first_hartid, &ms->hart_count);
> +                                  &ms->first_hartindex, &ms->first_hartid, &ms->hart_count);
>         if (rc) {
>                 sbi_free(ms);
>                 return rc;
> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> index 271e625..706967c 100644
> --- a/lib/utils/timer/aclint_mtimer.c
> +++ b/lib/utils/timer/aclint_mtimer.c
> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>
>         /* Update MTIMER pointer in scratch space */
>         for (i = 0; i < mt->hart_count; i++) {
> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
> +               scratch = sbi_hartindex_to_scratch(mt->first_hartindex + i);
>                 /*
>                  * We don't need to fail if scratch pointer is not available
>                  * because we might be dealing with hartid of a HART disabled
> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> index 9e27e3a..aa05afe 100644
> --- a/lib/utils/timer/fdt_timer_mtimer.c
> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> @@ -47,7 +47,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>
>         rc = fdt_parse_aclint_node(fdt, nodeoff, true, !is_clint,
>                                    &addr[0], &size[0], &addr[1], &size[1],
> -                                  &mt->first_hartid, &mt->hart_count);
> +                                  &mt->first_hartindex, &mt->first_hartid, &mt->hart_count);
>         if (rc) {
>                 sbi_free(mtn);
>                 return rc;
> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
> index 8be5e6c..d88350c 100644
> --- a/platform/fpga/ariane/platform.c
> +++ b/platform/fpga/ariane/platform.c
> @@ -45,6 +45,7 @@ static struct plic_data plic = {
>  static struct aclint_mswi_data mswi = {
>         .addr = ARIANE_ACLINT_MSWI_ADDR,
>         .size = ACLINT_MSWI_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = ARIANE_HART_COUNT,
>  };
> @@ -57,6 +58,7 @@ static struct aclint_mtimer_data mtimer = {
>         .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = ARIANE_HART_COUNT,
>         .has_64bit_mmio = true,
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index 2317a89..c21e8ad 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -49,6 +49,7 @@ static struct plic_data plic = {
>  static struct aclint_mswi_data mswi = {
>         .addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
>         .size = ACLINT_MSWI_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>  };
> @@ -61,6 +62,7 @@ static struct aclint_mtimer_data mtimer = {
>         .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>         .has_64bit_mmio = true,
> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
> index 27b23f7..21d34b7 100644
> --- a/platform/kendryte/k210/platform.c
> +++ b/platform/kendryte/k210/platform.c
> @@ -39,6 +39,7 @@ static struct plic_data plic = {
>  static struct aclint_mswi_data mswi = {
>         .addr = K210_ACLINT_MSWI_ADDR,
>         .size = ACLINT_MSWI_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = K210_HART_COUNT,
>  };
> @@ -51,6 +52,7 @@ static struct aclint_mtimer_data mtimer = {
>         .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = K210_HART_COUNT,
>         .has_64bit_mmio = true,
> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
> index f688b50..54f35f4 100644
> --- a/platform/nuclei/ux600/platform.c
> +++ b/platform/nuclei/ux600/platform.c
> @@ -72,6 +72,7 @@ static struct plic_data plic = {
>  static struct aclint_mswi_data mswi = {
>         .addr = UX600_ACLINT_MSWI_ADDR,
>         .size = ACLINT_MSWI_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = UX600_HART_COUNT,
>  };
> @@ -84,6 +85,7 @@ static struct aclint_mtimer_data mtimer = {
>         .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = UX600_HART_COUNT,
>         .has_64bit_mmio = true,
> diff --git a/platform/template/platform.c b/platform/template/platform.c
> index 4b3f2ac..4840542 100644
> --- a/platform/template/platform.c
> +++ b/platform/template/platform.c
> @@ -42,6 +42,7 @@ static struct plic_data plic = {
>  static struct aclint_mswi_data mswi = {
>         .addr = PLATFORM_ACLINT_MSWI_ADDR,
>         .size = ACLINT_MSWI_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = PLATFORM_HART_COUNT,
>  };
> @@ -54,6 +55,7 @@ static struct aclint_mtimer_data mtimer = {
>         .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> +       .first_hartindex = 0,
>         .first_hartid = 0,
>         .hart_count = PLATFORM_HART_COUNT,
>         .has_64bit_mmio = true,
> --
> 2.25.1
>

Regards,
Anup


From anup at brainfault.org  Sat Feb 24 07:20:37 2024
From: anup at brainfault.org (Anup Patel)
Date: Sat, 24 Feb 2024 20:50:37 +0530
Subject: [PATCH 1/1] lib: sbi_hsm: Restor hart state to stop when fails to start
In-Reply-To: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
References: <20240219071406.41703-1-joshua.yeong@starfivetech.com>
Message-ID: <CAAhSdy1zL015JgM=TqeVK-nnird_mTgW=TmZttPk5WiGFhnSug@mail.gmail.com>

On Mon, Feb 19, 2024 at 12:44?PM Joshua Yeong
<joshua.yeong at starfivetech.com> wrote:
>
> Hart state should change back to hart stop when hsm_device_hart_start()
> or sbi_ipi_raw_send() fails to perform hart start.
>
> Signed-off-by: Joshua Yeong <joshua.yeong at starfivetech.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  lib/sbi/sbi_hsm.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
> index 3d60ceb..be48d64 100644
> --- a/lib/sbi/sbi_hsm.c
> +++ b/lib/sbi/sbi_hsm.c
> @@ -360,6 +360,10 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
>
>         if (!rc)
>                 return 0;
> +
> +       /* If it fails to start, change hart state back to stop */
> +       __sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_START_PENDING,
> +                                   SBI_HSM_STATE_STOPPED);
>  err:
>         hsm_start_ticket_release(hdata);
>         return rc;
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From gaoshanliukou at 163.com  Sun Feb 25 17:46:09 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Mon, 26 Feb 2024 09:46:09 +0800 (CST)
Subject: [PATCH V2] lib: sbi: Add sparse hartid support for mtimer
 and mswi
In-Reply-To: <CAAhSdy1nEgZa+T1VzWL-Soam5PU6ztqRXCsJc9yrpyCu4n8HkA@mail.gmail.com>
References: <20240222065530.17673-1-gaoshanliukou@163.com>
 <CAAhSdy1nEgZa+T1VzWL-Soam5PU6ztqRXCsJc9yrpyCu4n8HkA@mail.gmail.com>
Message-ID: <6cf968eb.2609.18de31745ff.Coremail.gaoshanliukou@163.com>

At 2024-02-24 20:55:58, "Anup Patel" <anup at brainfault.org> wrote:
>On Thu, Feb 22, 2024 at 12:25?PM yang.zhang <gaoshanliukou at 163.com> wrote:
>>
>> From: "yang.zhang" <yang.zhang at hexintek.com>
>>
>> Need to support sparse hartid for mtmer and mswi.
>>
>> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
>
>hartid can always be derived from hartindex using sbi_hartindex_to_hartid()
>so this patch can be simplified

I considered this replacement, but the first_hartindex is not always  first_hartid.
Such as mswi_ipi_send, when set IPI, it needs to know the offset between current hart_id
and first_hartid. If i drop first_hartid, maybe i would calculate the first_hartid by all of the
hartindex?
Thanks.

>> ---
>> v1 -> v2:
>> - Add handle in the case of multiple ACLINT instances
>> - Check valid hartindex not hartid when parse fdt
>>
>> V1: https://lists.infradead.org/pipermail/opensbi/2024-February/006342.html
>>
>> ---
>> I add additional first_hartindex instead of replacing first_hartid with it.
>> Because first_hartindex maybe not the first hartid, which is the base of
>> mtimer/mswi, such as in the cpus node of dts:
>> cluster0 {cpu at 0: reg=<0x0>, cpu at 1: reg=<0x3>}
>> cluster1 {cpu at 2: reg=<0x7>, cpu at 3: reg=<0x4>}
>> ---
>>  include/sbi_utils/fdt/fdt_helper.h      |  2 +-
>>  include/sbi_utils/ipi/aclint_mswi.h     |  1 +
>>  include/sbi_utils/timer/aclint_mtimer.h |  1 +
>>  lib/utils/fdt/fdt_helper.c              | 16 +++++++++++-----
>>  lib/utils/ipi/aclint_mswi.c             |  2 +-
>>  lib/utils/ipi/fdt_ipi_mswi.c            |  2 +-
>>  lib/utils/timer/aclint_mtimer.c         |  2 +-
>>  lib/utils/timer/fdt_timer_mtimer.c      |  2 +-
>>  platform/fpga/ariane/platform.c         |  2 ++
>>  platform/fpga/openpiton/platform.c      |  2 ++
>>  platform/kendryte/k210/platform.c       |  2 ++
>>  platform/nuclei/ux600/platform.c        |  2 ++
>>  platform/template/platform.c            |  2 ++
>>  13 files changed, 28 insertions(+), 10 deletions(-)
>>
>> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
>> index ab4a80f..398700d 100644
>> --- a/include/sbi_utils/fdt/fdt_helper.h
>> +++ b/include/sbi_utils/fdt/fdt_helper.h
>> @@ -103,7 +103,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>                           bool for_timer, bool allow_regname,
>>                           unsigned long *out_addr1, unsigned long *out_size1,
>>                           unsigned long *out_addr2, unsigned long *out_size2,
>> -                         u32 *out_first_hartid, u32 *out_hart_count);
>> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count);
>
>Drop out_first_hartid
>
>>
>>  int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
>>                           unsigned long *plmt_size, u32 *hart_count);
>> diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
>> index e373a8c..d5708e2 100644
>> --- a/include/sbi_utils/ipi/aclint_mswi.h
>> +++ b/include/sbi_utils/ipi/aclint_mswi.h
>> @@ -22,6 +22,7 @@ struct aclint_mswi_data {
>>         /* Public details */
>>         unsigned long addr;
>>         unsigned long size;
>> +       u32 first_hartindex;
>>         u32 first_hartid;
>
>Remove first_hartid
>
>>         u32 hart_count;
>>  };
>> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
>> index 6ab8799..21a7d93 100644
>> --- a/include/sbi_utils/timer/aclint_mtimer.h
>> +++ b/include/sbi_utils/timer/aclint_mtimer.h
>> @@ -31,6 +31,7 @@ struct aclint_mtimer_data {
>>         unsigned long mtime_size;
>>         unsigned long mtimecmp_addr;
>>         unsigned long mtimecmp_size;
>> +       u32 first_hartindex;
>>         u32 first_hartid;
>
>Remove first_hartid
>
>>         u32 hart_count;
>>         bool has_64bit_mmio;
>> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
>> index a0e93b9..5d9215f 100644
>> --- a/lib/utils/fdt/fdt_helper.c
>> +++ b/lib/utils/fdt/fdt_helper.c
>> @@ -961,16 +961,17 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>                           bool for_timer, bool allow_regname,
>>                           unsigned long *out_addr1, unsigned long *out_size1,
>>                           unsigned long *out_addr2, unsigned long *out_size2,
>> -                         u32 *out_first_hartid, u32 *out_hart_count)
>> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count)
>
>Same as above.
>
>>  {
>>         const fdt32_t *val;
>>         int i, rc, count, cpu_offset, cpu_intc_offset;
>> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
>> +       u32 phandle, hwirq;
>> +       u32 hartindex, hartid, first_hartindex, first_hartid, last_hartid, hart_count;
>>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
>>
>>         if (nodeoffset < 0 || !fdt ||
>>             !out_addr1 || !out_size1 ||
>> -           !out_first_hartid || !out_hart_count)
>> +           !out_first_hartindex || !out_first_hartid || !out_hart_count)
>>                 return SBI_EINVAL;
>>
>>         if (for_timer && allow_regname && out_addr2 && out_size2 &&
>> @@ -985,6 +986,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>         if (rc)
>>                 return rc;
>>
>> +       *out_first_hartindex = 0;
>>         *out_first_hartid = 0;
>>         *out_hart_count = 0;
>>
>> @@ -993,7 +995,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>                 return 0;
>>         count = count / sizeof(fdt32_t);
>>
>> -       first_hartid = -1U;
>> +       first_hartindex = first_hartid = -1U;
>>         hart_count = last_hartid = 0;
>>         for (i = 0; i < (count / 2); i++) {
>>                 phandle = fdt32_to_cpu(val[2 * i]);
>> @@ -1011,10 +1013,13 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>                 if (rc)
>>                         continue;
>>
>> -               if (SBI_HARTMASK_MAX_BITS <= hartid)
>> +               hartindex = sbi_hartid_to_hartindex(hartid);
>> +               if (SBI_HARTMASK_MAX_BITS <= hartindex)
>>                         continue;
>>
>>                 if (match_hwirq == hwirq) {
>> +                       if (hartindex < first_hartindex)
>> +                               first_hartindex = hartindex;
>>                         if (hartid < first_hartid)
>>                                 first_hartid = hartid;
>>                         if (hartid > last_hartid)
>> @@ -1024,6 +1029,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>>         }
>>
>>         if ((last_hartid >= first_hartid) && first_hartid != -1U) {
>> +               *out_first_hartindex = first_hartindex;
>>                 *out_first_hartid = first_hartid;
>>                 count = last_hartid - first_hartid + 1;
>>                 *out_hart_count = (hart_count < count) ? hart_count : count;
>> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
>> index 4ae6bb1..15298eb 100644
>> --- a/lib/utils/ipi/aclint_mswi.c
>> +++ b/lib/utils/ipi/aclint_mswi.c
>> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
>>
>>         /* Update MSWI pointer in scratch space */
>>         for (i = 0; i < mswi->hart_count; i++) {
>> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
>> +               scratch = sbi_hartindex_to_scratch(mswi->first_hartindex + i);
>>                 /*
>>                  * We don't need to fail if scratch pointer is not available
>>                  * because we might be dealing with hartid of a HART disabled
>> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
>> index a709abe..e896e5a 100644
>> --- a/lib/utils/ipi/fdt_ipi_mswi.c
>> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
>> @@ -26,7 +26,7 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
>>
>>         rc = fdt_parse_aclint_node(fdt, nodeoff, false, false,
>>                                    &ms->addr, &ms->size, NULL, NULL,
>> -                                  &ms->first_hartid, &ms->hart_count);
>> +                                  &ms->first_hartindex, &ms->first_hartid, &ms->hart_count);
>>         if (rc) {
>>                 sbi_free(ms);
>>                 return rc;
>> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
>> index 271e625..706967c 100644
>> --- a/lib/utils/timer/aclint_mtimer.c
>> +++ b/lib/utils/timer/aclint_mtimer.c
>> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>>
>>         /* Update MTIMER pointer in scratch space */
>>         for (i = 0; i < mt->hart_count; i++) {
>> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
>> +               scratch = sbi_hartindex_to_scratch(mt->first_hartindex + i);
>>                 /*
>>                  * We don't need to fail if scratch pointer is not available
>>                  * because we might be dealing with hartid of a HART disabled
>> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
>> index 9e27e3a..aa05afe 100644
>> --- a/lib/utils/timer/fdt_timer_mtimer.c
>> +++ b/lib/utils/timer/fdt_timer_mtimer.c
>> @@ -47,7 +47,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>>
>>         rc = fdt_parse_aclint_node(fdt, nodeoff, true, !is_clint,
>>                                    &addr[0], &size[0], &addr[1], &size[1],
>> -                                  &mt->first_hartid, &mt->hart_count);
>> +                                  &mt->first_hartindex, &mt->first_hartid, &mt->hart_count);
>>         if (rc) {
>>                 sbi_free(mtn);
>>                 return rc;
>> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
>> index 8be5e6c..d88350c 100644
>> --- a/platform/fpga/ariane/platform.c
>> +++ b/platform/fpga/ariane/platform.c
>> @@ -45,6 +45,7 @@ static struct plic_data plic = {
>>  static struct aclint_mswi_data mswi = {
>>         .addr = ARIANE_ACLINT_MSWI_ADDR,
>>         .size = ACLINT_MSWI_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = ARIANE_HART_COUNT,
>>  };
>> @@ -57,6 +58,7 @@ static struct aclint_mtimer_data mtimer = {
>>         .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
>>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = ARIANE_HART_COUNT,
>>         .has_64bit_mmio = true,
>> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
>> index 2317a89..c21e8ad 100644
>> --- a/platform/fpga/openpiton/platform.c
>> +++ b/platform/fpga/openpiton/platform.c
>> @@ -49,6 +49,7 @@ static struct plic_data plic = {
>>  static struct aclint_mswi_data mswi = {
>>         .addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
>>         .size = ACLINT_MSWI_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>>  };
>> @@ -61,6 +62,7 @@ static struct aclint_mtimer_data mtimer = {
>>         .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
>>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>>         .has_64bit_mmio = true,
>> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
>> index 27b23f7..21d34b7 100644
>> --- a/platform/kendryte/k210/platform.c
>> +++ b/platform/kendryte/k210/platform.c
>> @@ -39,6 +39,7 @@ static struct plic_data plic = {
>>  static struct aclint_mswi_data mswi = {
>>         .addr = K210_ACLINT_MSWI_ADDR,
>>         .size = ACLINT_MSWI_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = K210_HART_COUNT,
>>  };
>> @@ -51,6 +52,7 @@ static struct aclint_mtimer_data mtimer = {
>>         .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
>>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = K210_HART_COUNT,
>>         .has_64bit_mmio = true,
>> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
>> index f688b50..54f35f4 100644
>> --- a/platform/nuclei/ux600/platform.c
>> +++ b/platform/nuclei/ux600/platform.c
>> @@ -72,6 +72,7 @@ static struct plic_data plic = {
>>  static struct aclint_mswi_data mswi = {
>>         .addr = UX600_ACLINT_MSWI_ADDR,
>>         .size = ACLINT_MSWI_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = UX600_HART_COUNT,
>>  };
>> @@ -84,6 +85,7 @@ static struct aclint_mtimer_data mtimer = {
>>         .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
>>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = UX600_HART_COUNT,
>>         .has_64bit_mmio = true,
>> diff --git a/platform/template/platform.c b/platform/template/platform.c
>> index 4b3f2ac..4840542 100644
>> --- a/platform/template/platform.c
>> +++ b/platform/template/platform.c
>> @@ -42,6 +42,7 @@ static struct plic_data plic = {
>>  static struct aclint_mswi_data mswi = {
>>         .addr = PLATFORM_ACLINT_MSWI_ADDR,
>>         .size = ACLINT_MSWI_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = PLATFORM_HART_COUNT,
>>  };
>> @@ -54,6 +55,7 @@ static struct aclint_mtimer_data mtimer = {
>>         .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
>>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> +       .first_hartindex = 0,
>>         .first_hartid = 0,
>>         .hart_count = PLATFORM_HART_COUNT,
>>         .has_64bit_mmio = true,
>> --
>> 2.25.1
>>
>
>Regards,
>Anup

From apatel at ventanamicro.com  Sun Feb 25 19:17:07 2024
From: apatel at ventanamicro.com (Anup Patel)
Date: Mon, 26 Feb 2024 08:47:07 +0530
Subject: [PATCH V2] lib: sbi: Add sparse hartid support for mtimer and mswi
In-Reply-To: <6cf968eb.2609.18de31745ff.Coremail.gaoshanliukou@163.com>
References: <20240222065530.17673-1-gaoshanliukou@163.com> <CAAhSdy1nEgZa+T1VzWL-Soam5PU6ztqRXCsJc9yrpyCu4n8HkA@mail.gmail.com>
 <6cf968eb.2609.18de31745ff.Coremail.gaoshanliukou@163.com>
Message-ID: <CAK9=C2WH1JM6j8iT6JYYb5v+v0gc1_Kv7_6BzqLyd1BkoY40Sw@mail.gmail.com>

On Mon, Feb 26, 2024 at 7:16?AM yang.zhang <gaoshanliukou at 163.com> wrote:
>
> At 2024-02-24 20:55:58, "Anup Patel" <anup at brainfault.org> wrote:
> >On Thu, Feb 22, 2024 at 12:25?PM yang.zhang <gaoshanliukou at 163.com> wrote:
> >>
> >> From: "yang.zhang" <yang.zhang at hexintek.com>
> >>
> >> Need to support sparse hartid for mtmer and mswi.
> >>
> >> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
> >
> >hartid can always be derived from hartindex using sbi_hartindex_to_hartid()
> >so this patch can be simplified
>
> I considered this replacement, but the first_hartindex is not always  first_hartid.
> Such as mswi_ipi_send, when set IPI, it needs to know the offset between current hart_id
> and first_hartid. If i drop first_hartid, maybe i would calculate the first_hartid by all of the
> hartindex?

You can simply translate current hart_id to current hartindex using
sbi_hartid_to_hartindex().

Regards,
Anup

> Thanks.
>
> >> ---
> >> v1 -> v2:
> >> - Add handle in the case of multiple ACLINT instances
> >> - Check valid hartindex not hartid when parse fdt
> >>
> >> V1: https://lists.infradead.org/pipermail/opensbi/2024-February/006342.html
> >>
> >> ---
> >> I add additional first_hartindex instead of replacing first_hartid with it.
> >> Because first_hartindex maybe not the first hartid, which is the base of
> >> mtimer/mswi, such as in the cpus node of dts:
> >> cluster0 {cpu at 0: reg=<0x0>, cpu at 1: reg=<0x3>}
> >> cluster1 {cpu at 2: reg=<0x7>, cpu at 3: reg=<0x4>}
> >> ---
> >>  include/sbi_utils/fdt/fdt_helper.h      |  2 +-
> >>  include/sbi_utils/ipi/aclint_mswi.h     |  1 +
> >>  include/sbi_utils/timer/aclint_mtimer.h |  1 +
> >>  lib/utils/fdt/fdt_helper.c              | 16 +++++++++++-----
> >>  lib/utils/ipi/aclint_mswi.c             |  2 +-
> >>  lib/utils/ipi/fdt_ipi_mswi.c            |  2 +-
> >>  lib/utils/timer/aclint_mtimer.c         |  2 +-
> >>  lib/utils/timer/fdt_timer_mtimer.c      |  2 +-
> >>  platform/fpga/ariane/platform.c         |  2 ++
> >>  platform/fpga/openpiton/platform.c      |  2 ++
> >>  platform/kendryte/k210/platform.c       |  2 ++
> >>  platform/nuclei/ux600/platform.c        |  2 ++
> >>  platform/template/platform.c            |  2 ++
> >>  13 files changed, 28 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> >> index ab4a80f..398700d 100644
> >> --- a/include/sbi_utils/fdt/fdt_helper.h
> >> +++ b/include/sbi_utils/fdt/fdt_helper.h
> >> @@ -103,7 +103,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>                           bool for_timer, bool allow_regname,
> >>                           unsigned long *out_addr1, unsigned long *out_size1,
> >>                           unsigned long *out_addr2, unsigned long *out_size2,
> >> -                         u32 *out_first_hartid, u32 *out_hart_count);
> >> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count);
> >
> >Drop out_first_hartid
> >
> >>
> >>  int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
> >>                           unsigned long *plmt_size, u32 *hart_count);
> >> diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
> >> index e373a8c..d5708e2 100644
> >> --- a/include/sbi_utils/ipi/aclint_mswi.h
> >> +++ b/include/sbi_utils/ipi/aclint_mswi.h
> >> @@ -22,6 +22,7 @@ struct aclint_mswi_data {
> >>         /* Public details */
> >>         unsigned long addr;
> >>         unsigned long size;
> >> +       u32 first_hartindex;
> >>         u32 first_hartid;
> >
> >Remove first_hartid
> >
> >>         u32 hart_count;
> >>  };
> >> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
> >> index 6ab8799..21a7d93 100644
> >> --- a/include/sbi_utils/timer/aclint_mtimer.h
> >> +++ b/include/sbi_utils/timer/aclint_mtimer.h
> >> @@ -31,6 +31,7 @@ struct aclint_mtimer_data {
> >>         unsigned long mtime_size;
> >>         unsigned long mtimecmp_addr;
> >>         unsigned long mtimecmp_size;
> >> +       u32 first_hartindex;
> >>         u32 first_hartid;
> >
> >Remove first_hartid
> >
> >>         u32 hart_count;
> >>         bool has_64bit_mmio;
> >> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> >> index a0e93b9..5d9215f 100644
> >> --- a/lib/utils/fdt/fdt_helper.c
> >> +++ b/lib/utils/fdt/fdt_helper.c
> >> @@ -961,16 +961,17 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>                           bool for_timer, bool allow_regname,
> >>                           unsigned long *out_addr1, unsigned long *out_size1,
> >>                           unsigned long *out_addr2, unsigned long *out_size2,
> >> -                         u32 *out_first_hartid, u32 *out_hart_count)
> >> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count)
> >
> >Same as above.
> >
> >>  {
> >>         const fdt32_t *val;
> >>         int i, rc, count, cpu_offset, cpu_intc_offset;
> >> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
> >> +       u32 phandle, hwirq;
> >> +       u32 hartindex, hartid, first_hartindex, first_hartid, last_hartid, hart_count;
> >>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
> >>
> >>         if (nodeoffset < 0 || !fdt ||
> >>             !out_addr1 || !out_size1 ||
> >> -           !out_first_hartid || !out_hart_count)
> >> +           !out_first_hartindex || !out_first_hartid || !out_hart_count)
> >>                 return SBI_EINVAL;
> >>
> >>         if (for_timer && allow_regname && out_addr2 && out_size2 &&
> >> @@ -985,6 +986,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>         if (rc)
> >>                 return rc;
> >>
> >> +       *out_first_hartindex = 0;
> >>         *out_first_hartid = 0;
> >>         *out_hart_count = 0;
> >>
> >> @@ -993,7 +995,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>                 return 0;
> >>         count = count / sizeof(fdt32_t);
> >>
> >> -       first_hartid = -1U;
> >> +       first_hartindex = first_hartid = -1U;
> >>         hart_count = last_hartid = 0;
> >>         for (i = 0; i < (count / 2); i++) {
> >>                 phandle = fdt32_to_cpu(val[2 * i]);
> >> @@ -1011,10 +1013,13 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>                 if (rc)
> >>                         continue;
> >>
> >> -               if (SBI_HARTMASK_MAX_BITS <= hartid)
> >> +               hartindex = sbi_hartid_to_hartindex(hartid);
> >> +               if (SBI_HARTMASK_MAX_BITS <= hartindex)
> >>                         continue;
> >>
> >>                 if (match_hwirq == hwirq) {
> >> +                       if (hartindex < first_hartindex)
> >> +                               first_hartindex = hartindex;
> >>                         if (hartid < first_hartid)
> >>                                 first_hartid = hartid;
> >>                         if (hartid > last_hartid)
> >> @@ -1024,6 +1029,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
> >>         }
> >>
> >>         if ((last_hartid >= first_hartid) && first_hartid != -1U) {
> >> +               *out_first_hartindex = first_hartindex;
> >>                 *out_first_hartid = first_hartid;
> >>                 count = last_hartid - first_hartid + 1;
> >>                 *out_hart_count = (hart_count < count) ? hart_count : count;
> >> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
> >> index 4ae6bb1..15298eb 100644
> >> --- a/lib/utils/ipi/aclint_mswi.c
> >> +++ b/lib/utils/ipi/aclint_mswi.c
> >> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
> >>
> >>         /* Update MSWI pointer in scratch space */
> >>         for (i = 0; i < mswi->hart_count; i++) {
> >> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
> >> +               scratch = sbi_hartindex_to_scratch(mswi->first_hartindex + i);
> >>                 /*
> >>                  * We don't need to fail if scratch pointer is not available
> >>                  * because we might be dealing with hartid of a HART disabled
> >> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
> >> index a709abe..e896e5a 100644
> >> --- a/lib/utils/ipi/fdt_ipi_mswi.c
> >> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
> >> @@ -26,7 +26,7 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
> >>
> >>         rc = fdt_parse_aclint_node(fdt, nodeoff, false, false,
> >>                                    &ms->addr, &ms->size, NULL, NULL,
> >> -                                  &ms->first_hartid, &ms->hart_count);
> >> +                                  &ms->first_hartindex, &ms->first_hartid, &ms->hart_count);
> >>         if (rc) {
> >>                 sbi_free(ms);
> >>                 return rc;
> >> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
> >> index 271e625..706967c 100644
> >> --- a/lib/utils/timer/aclint_mtimer.c
> >> +++ b/lib/utils/timer/aclint_mtimer.c
> >> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
> >>
> >>         /* Update MTIMER pointer in scratch space */
> >>         for (i = 0; i < mt->hart_count; i++) {
> >> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
> >> +               scratch = sbi_hartindex_to_scratch(mt->first_hartindex + i);
> >>                 /*
> >>                  * We don't need to fail if scratch pointer is not available
> >>                  * because we might be dealing with hartid of a HART disabled
> >> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
> >> index 9e27e3a..aa05afe 100644
> >> --- a/lib/utils/timer/fdt_timer_mtimer.c
> >> +++ b/lib/utils/timer/fdt_timer_mtimer.c
> >> @@ -47,7 +47,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
> >>
> >>         rc = fdt_parse_aclint_node(fdt, nodeoff, true, !is_clint,
> >>                                    &addr[0], &size[0], &addr[1], &size[1],
> >> -                                  &mt->first_hartid, &mt->hart_count);
> >> +                                  &mt->first_hartindex, &mt->first_hartid, &mt->hart_count);
> >>         if (rc) {
> >>                 sbi_free(mtn);
> >>                 return rc;
> >> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
> >> index 8be5e6c..d88350c 100644
> >> --- a/platform/fpga/ariane/platform.c
> >> +++ b/platform/fpga/ariane/platform.c
> >> @@ -45,6 +45,7 @@ static struct plic_data plic = {
> >>  static struct aclint_mswi_data mswi = {
> >>         .addr = ARIANE_ACLINT_MSWI_ADDR,
> >>         .size = ACLINT_MSWI_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = ARIANE_HART_COUNT,
> >>  };
> >> @@ -57,6 +58,7 @@ static struct aclint_mtimer_data mtimer = {
> >>         .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = ARIANE_HART_COUNT,
> >>         .has_64bit_mmio = true,
> >> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> >> index 2317a89..c21e8ad 100644
> >> --- a/platform/fpga/openpiton/platform.c
> >> +++ b/platform/fpga/openpiton/platform.c
> >> @@ -49,6 +49,7 @@ static struct plic_data plic = {
> >>  static struct aclint_mswi_data mswi = {
> >>         .addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
> >>         .size = ACLINT_MSWI_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
> >>  };
> >> @@ -61,6 +62,7 @@ static struct aclint_mtimer_data mtimer = {
> >>         .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
> >>         .has_64bit_mmio = true,
> >> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
> >> index 27b23f7..21d34b7 100644
> >> --- a/platform/kendryte/k210/platform.c
> >> +++ b/platform/kendryte/k210/platform.c
> >> @@ -39,6 +39,7 @@ static struct plic_data plic = {
> >>  static struct aclint_mswi_data mswi = {
> >>         .addr = K210_ACLINT_MSWI_ADDR,
> >>         .size = ACLINT_MSWI_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = K210_HART_COUNT,
> >>  };
> >> @@ -51,6 +52,7 @@ static struct aclint_mtimer_data mtimer = {
> >>         .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = K210_HART_COUNT,
> >>         .has_64bit_mmio = true,
> >> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
> >> index f688b50..54f35f4 100644
> >> --- a/platform/nuclei/ux600/platform.c
> >> +++ b/platform/nuclei/ux600/platform.c
> >> @@ -72,6 +72,7 @@ static struct plic_data plic = {
> >>  static struct aclint_mswi_data mswi = {
> >>         .addr = UX600_ACLINT_MSWI_ADDR,
> >>         .size = ACLINT_MSWI_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = UX600_HART_COUNT,
> >>  };
> >> @@ -84,6 +85,7 @@ static struct aclint_mtimer_data mtimer = {
> >>         .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = UX600_HART_COUNT,
> >>         .has_64bit_mmio = true,
> >> diff --git a/platform/template/platform.c b/platform/template/platform.c
> >> index 4b3f2ac..4840542 100644
> >> --- a/platform/template/platform.c
> >> +++ b/platform/template/platform.c
> >> @@ -42,6 +42,7 @@ static struct plic_data plic = {
> >>  static struct aclint_mswi_data mswi = {
> >>         .addr = PLATFORM_ACLINT_MSWI_ADDR,
> >>         .size = ACLINT_MSWI_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = PLATFORM_HART_COUNT,
> >>  };
> >> @@ -54,6 +55,7 @@ static struct aclint_mtimer_data mtimer = {
> >>         .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
> >> +       .first_hartindex = 0,
> >>         .first_hartid = 0,
> >>         .hart_count = PLATFORM_HART_COUNT,
> >>         .has_64bit_mmio = true,
> >> --
> >> 2.25.1
> >>
> >
> >Regards,
> >Anup


From nylon.chen at sifive.com  Sun Feb 25 21:56:44 2024
From: nylon.chen at sifive.com (Nylon Chen)
Date: Mon, 26 Feb 2024 13:56:44 +0800
Subject: [PATCH] lib: sbi_misaligned_ldst: Add handling of C.LHU/C.LH and C.SH
Message-ID: <20240226055644.881161-1-nylon.chen@sifive.com>

From: "Nylon Chen" <nylon.chen at sifive.com>

Added exception handling for compressed instructions C.LHU, C.LH, and
C.SH from the zcb extension to the sbi_misaligned_ldst library.

Signed-off-by: Nylon Chen <nylon.chen at sifive.com>
---
 include/sbi/riscv_encoding.h  |  7 +++++++
 lib/sbi/sbi_misaligned_ldst.c | 10 ++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index e74cc0d..3d77e26 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -837,6 +837,13 @@
 #define INSN_MATCH_C_FSWSP		0xe002
 #define INSN_MASK_C_FSWSP		0xe003
 
+#define INSN_MATCH_C_LHU		0x8400
+#define INSN_MASK_C_LHU		0xfc43
+#define INSN_MATCH_C_LH		0x8440
+#define INSN_MASK_C_LH			0xfc43
+#define INSN_MATCH_C_SH		0x8c00
+#define INSN_MASK_C_SH			0xfc43
+
 #define INSN_MASK_WFI			0xffffff00
 #define INSN_MATCH_WFI			0x10500000
 
diff --git a/lib/sbi/sbi_misaligned_ldst.c b/lib/sbi/sbi_misaligned_ldst.c
index aa512de..9ca225a 100644
--- a/lib/sbi/sbi_misaligned_ldst.c
+++ b/lib/sbi/sbi_misaligned_ldst.c
@@ -123,6 +123,13 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
 		len = 4;
 #endif
 #endif
+	} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {
+		len = 2;
+		insn = RVC_RS2S(insn) << SH_RD;
+	} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {
+		len = 2;
+		shift = 8 * (sizeof(ulong) - len);
+		insn = RVC_RS2S(insn) << SH_RD;
 	} else {
 		uptrap.epc = regs->mepc;
 		uptrap.cause = CAUSE_MISALIGNED_LOAD;
@@ -237,6 +244,9 @@ int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
 		val.data_ulong = GET_F32_RS2C(insn, regs);
 #endif
 #endif
+	} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {
+		len		= 2;
+		val.data_ulong = GET_RS2S(insn, regs);
 	} else {
 		uptrap.epc = regs->mepc;
 		uptrap.cause = CAUSE_MISALIGNED_STORE;
-- 
2.34.1



From gaoshanliukou at 163.com  Sun Feb 25 22:26:57 2024
From: gaoshanliukou at 163.com (yang.zhang)
Date: Mon, 26 Feb 2024 14:26:57 +0800 (CST)
Subject: [PATCH V2] lib: sbi: Add sparse hartid support for
 mtimer and mswi
In-Reply-To: <CAK9=C2WH1JM6j8iT6JYYb5v+v0gc1_Kv7_6BzqLyd1BkoY40Sw@mail.gmail.com>
References: <20240222065530.17673-1-gaoshanliukou@163.com>
 <CAAhSdy1nEgZa+T1VzWL-Soam5PU6ztqRXCsJc9yrpyCu4n8HkA@mail.gmail.com>
 <6cf968eb.2609.18de31745ff.Coremail.gaoshanliukou@163.com>
 <CAK9=C2WH1JM6j8iT6JYYb5v+v0gc1_Kv7_6BzqLyd1BkoY40Sw@mail.gmail.com>
Message-ID: <474e5b2a.8c52.18de418592d.Coremail.gaoshanliukou@163.com>

At 2024-02-26 11:17:07, "Anup Patel" <apatel at ventanamicro.com> wrote:
>On Mon, Feb 26, 2024 at 7:16?AM yang.zhang <gaoshanliukou at 163.com> wrote:
>>
>> At 2024-02-24 20:55:58, "Anup Patel" <anup at brainfault.org> wrote:
>> >On Thu, Feb 22, 2024 at 12:25?PM yang.zhang <gaoshanliukou at 163.com> wrote:
>> >>
>> >> From: "yang.zhang" <yang.zhang at hexintek.com>
>> >>
>> >> Need to support sparse hartid for mtmer and mswi.
>> >>
>> >> Signed-off-by: yang.zhang <yang.zhang at hexintek.com>
>> >
>> >hartid can always be derived from hartindex using sbi_hartindex_to_hartid()
>> >so this patch can be simplified
>>
>> I considered this replacement, but the first_hartindex is not always  first_hartid.
>> Such as mswi_ipi_send, when set IPI, it needs to know the offset between current hart_id
>> and first_hartid. If i drop first_hartid, maybe i would calculate the first_hartid by all of the
>> hartindex?
>
>You can simply translate current hart_id to current hartindex using
>sbi_hartid_to_hartindex().
>
=========================
Uh, i'm not sure...
lib/utils/ipi/aclint_mswi.c
static void mswi_ipi_send(u32 hart_index)
{
	u32 *msip;
	struct sbi_scratch *scratch;
	struct aclint_mswi_data *mswi;

	scratch = sbi_hartindex_to_scratch(hart_index);
	if (!scratch)
		return;

	mswi = mswi_get_hart_data_ptr(scratch);
	if (!mswi)
		return;

	/* Set ACLINT IPI */
	msip = (void *)mswi->addr;
>>	writel_relaxed(1, &msip[sbi_hartindex_to_hartid(hart_index) -
			mswi->first_hartid]);
}
Maybe I misunderstood, as above, if i replace first_hartid with first_hartindex,  
i have two aclints, one contains hartid0 and hartid3, another contains hartid4
and hartid7, but generic_hart_index2id is below
(gdb) p generic_hart_index2id
$1 = {0, 3, 7, 4, 0 <repeats 124 times>}
then the second aclint's first_hartindex is 0x2, correspondingly hartid is 7, but
first_hartid should be 4,  correspondingly hartindex is 0x3
(gdb) p/x *(struct aclint_mswi_data *)(0x80055440)
$6 = {addr = 0x2010000, size = 0x4000, first_hartindex = 0x2, hart_count = 0x2}
Why the generic_hart_index2id is the order of 0,3,7,4 not 0,3,4,7, i intentionally
construct a unorder dts as below:
                cpu at 0 {
                        phandle = <0x07>;
                        numa-node-id = <0x00>;
                        device_type = "cpu";
                        reg = <0x00>;

                cpu at 1 {
                        phandle = <0x05>;
                        numa-node-id = <0x00>;
                        device_type = "cpu";
                        reg = <0x03>;


                cpu at 2 {
                        phandle = <0x03>;
                        numa-node-id = <0x01>;
                        device_type = "cpu";
                        reg = <0x07>;


                cpu at 3 {
                        phandle = <0x01>;
                        numa-node-id = <0x01>;
                        device_type = "cpu";
                        reg = <0x04>;


                cpu-map {

                        cluster0 {

                                core0 {
                                        cpu = <0x07>;
                                };

                                core1 {
                                        cpu = <0x05>;
                                };
                        };

                        cluster1 {

                                core0 {
                                        cpu = <0x03>;
                                };

                                core1 {
                                        cpu = <0x01>;
                                };
                        };
                };

So, i'm not sure how to deal with mswi_ipi_send simplily.
=========================
>Regards,
>Anup
>
>> Thanks.
>>
>> >> ---
>> >> v1 -> v2:
>> >> - Add handle in the case of multiple ACLINT instances
>> >> - Check valid hartindex not hartid when parse fdt
>> >>
>> >> V1: https://lists.infradead.org/pipermail/opensbi/2024-February/006342.html
>> >>
>> >> ---
>> >> I add additional first_hartindex instead of replacing first_hartid with it.
>> >> Because first_hartindex maybe not the first hartid, which is the base of
>> >> mtimer/mswi, such as in the cpus node of dts:
>> >> cluster0 {cpu at 0: reg=<0x0>, cpu at 1: reg=<0x3>}
>> >> cluster1 {cpu at 2: reg=<0x7>, cpu at 3: reg=<0x4>}
>> >> ---
>> >>  include/sbi_utils/fdt/fdt_helper.h      |  2 +-
>> >>  include/sbi_utils/ipi/aclint_mswi.h     |  1 +
>> >>  include/sbi_utils/timer/aclint_mtimer.h |  1 +
>> >>  lib/utils/fdt/fdt_helper.c              | 16 +++++++++++-----
>> >>  lib/utils/ipi/aclint_mswi.c             |  2 +-
>> >>  lib/utils/ipi/fdt_ipi_mswi.c            |  2 +-
>> >>  lib/utils/timer/aclint_mtimer.c         |  2 +-
>> >>  lib/utils/timer/fdt_timer_mtimer.c      |  2 +-
>> >>  platform/fpga/ariane/platform.c         |  2 ++
>> >>  platform/fpga/openpiton/platform.c      |  2 ++
>> >>  platform/kendryte/k210/platform.c       |  2 ++
>> >>  platform/nuclei/ux600/platform.c        |  2 ++
>> >>  platform/template/platform.c            |  2 ++
>> >>  13 files changed, 28 insertions(+), 10 deletions(-)
>> >>
>> >> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
>> >> index ab4a80f..398700d 100644
>> >> --- a/include/sbi_utils/fdt/fdt_helper.h
>> >> +++ b/include/sbi_utils/fdt/fdt_helper.h
>> >> @@ -103,7 +103,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>                           bool for_timer, bool allow_regname,
>> >>                           unsigned long *out_addr1, unsigned long *out_size1,
>> >>                           unsigned long *out_addr2, unsigned long *out_size2,
>> >> -                         u32 *out_first_hartid, u32 *out_hart_count);
>> >> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count);
>> >
>> >Drop out_first_hartid
>> >
>> >>
>> >>  int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
>> >>                           unsigned long *plmt_size, u32 *hart_count);
>> >> diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
>> >> index e373a8c..d5708e2 100644
>> >> --- a/include/sbi_utils/ipi/aclint_mswi.h
>> >> +++ b/include/sbi_utils/ipi/aclint_mswi.h
>> >> @@ -22,6 +22,7 @@ struct aclint_mswi_data {
>> >>         /* Public details */
>> >>         unsigned long addr;
>> >>         unsigned long size;
>> >> +       u32 first_hartindex;
>> >>         u32 first_hartid;
>> >
>> >Remove first_hartid
>> >
>> >>         u32 hart_count;
>> >>  };
>> >> diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
>> >> index 6ab8799..21a7d93 100644
>> >> --- a/include/sbi_utils/timer/aclint_mtimer.h
>> >> +++ b/include/sbi_utils/timer/aclint_mtimer.h
>> >> @@ -31,6 +31,7 @@ struct aclint_mtimer_data {
>> >>         unsigned long mtime_size;
>> >>         unsigned long mtimecmp_addr;
>> >>         unsigned long mtimecmp_size;
>> >> +       u32 first_hartindex;
>> >>         u32 first_hartid;
>> >
>> >Remove first_hartid
>> >
>> >>         u32 hart_count;
>> >>         bool has_64bit_mmio;
>> >> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
>> >> index a0e93b9..5d9215f 100644
>> >> --- a/lib/utils/fdt/fdt_helper.c
>> >> +++ b/lib/utils/fdt/fdt_helper.c
>> >> @@ -961,16 +961,17 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>                           bool for_timer, bool allow_regname,
>> >>                           unsigned long *out_addr1, unsigned long *out_size1,
>> >>                           unsigned long *out_addr2, unsigned long *out_size2,
>> >> -                         u32 *out_first_hartid, u32 *out_hart_count)
>> >> +                         u32 *out_first_hartindex, u32 *out_first_hartid, u32 *out_hart_count)
>> >
>> >Same as above.
>> >
>> >>  {
>> >>         const fdt32_t *val;
>> >>         int i, rc, count, cpu_offset, cpu_intc_offset;
>> >> -       u32 phandle, hwirq, hartid, first_hartid, last_hartid, hart_count;
>> >> +       u32 phandle, hwirq;
>> >> +       u32 hartindex, hartid, first_hartindex, first_hartid, last_hartid, hart_count;
>> >>         u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;
>> >>
>> >>         if (nodeoffset < 0 || !fdt ||
>> >>             !out_addr1 || !out_size1 ||
>> >> -           !out_first_hartid || !out_hart_count)
>> >> +           !out_first_hartindex || !out_first_hartid || !out_hart_count)
>> >>                 return SBI_EINVAL;
>> >>
>> >>         if (for_timer && allow_regname && out_addr2 && out_size2 &&
>> >> @@ -985,6 +986,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>         if (rc)
>> >>                 return rc;
>> >>
>> >> +       *out_first_hartindex = 0;
>> >>         *out_first_hartid = 0;
>> >>         *out_hart_count = 0;
>> >>
>> >> @@ -993,7 +995,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>                 return 0;
>> >>         count = count / sizeof(fdt32_t);
>> >>
>> >> -       first_hartid = -1U;
>> >> +       first_hartindex = first_hartid = -1U;
>> >>         hart_count = last_hartid = 0;
>> >>         for (i = 0; i < (count / 2); i++) {
>> >>                 phandle = fdt32_to_cpu(val[2 * i]);
>> >> @@ -1011,10 +1013,13 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>                 if (rc)
>> >>                         continue;
>> >>
>> >> -               if (SBI_HARTMASK_MAX_BITS <= hartid)
>> >> +               hartindex = sbi_hartid_to_hartindex(hartid);
>> >> +               if (SBI_HARTMASK_MAX_BITS <= hartindex)
>> >>                         continue;
>> >>
>> >>                 if (match_hwirq == hwirq) {
>> >> +                       if (hartindex < first_hartindex)
>> >> +                               first_hartindex = hartindex;
>> >>                         if (hartid < first_hartid)
>> >>                                 first_hartid = hartid;
>> >>                         if (hartid > last_hartid)
>> >> @@ -1024,6 +1029,7 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset,
>> >>         }
>> >>
>> >>         if ((last_hartid >= first_hartid) && first_hartid != -1U) {
>> >> +               *out_first_hartindex = first_hartindex;
>> >>                 *out_first_hartid = first_hartid;
>> >>                 count = last_hartid - first_hartid + 1;
>> >>                 *out_hart_count = (hart_count < count) ? hart_count : count;
>> >> diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
>> >> index 4ae6bb1..15298eb 100644
>> >> --- a/lib/utils/ipi/aclint_mswi.c
>> >> +++ b/lib/utils/ipi/aclint_mswi.c
>> >> @@ -102,7 +102,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
>> >>
>> >>         /* Update MSWI pointer in scratch space */
>> >>         for (i = 0; i < mswi->hart_count; i++) {
>> >> -               scratch = sbi_hartid_to_scratch(mswi->first_hartid + i);
>> >> +               scratch = sbi_hartindex_to_scratch(mswi->first_hartindex + i);
>> >>                 /*
>> >>                  * We don't need to fail if scratch pointer is not available
>> >>                  * because we might be dealing with hartid of a HART disabled
>> >> diff --git a/lib/utils/ipi/fdt_ipi_mswi.c b/lib/utils/ipi/fdt_ipi_mswi.c
>> >> index a709abe..e896e5a 100644
>> >> --- a/lib/utils/ipi/fdt_ipi_mswi.c
>> >> +++ b/lib/utils/ipi/fdt_ipi_mswi.c
>> >> @@ -26,7 +26,7 @@ static int ipi_mswi_cold_init(void *fdt, int nodeoff,
>> >>
>> >>         rc = fdt_parse_aclint_node(fdt, nodeoff, false, false,
>> >>                                    &ms->addr, &ms->size, NULL, NULL,
>> >> -                                  &ms->first_hartid, &ms->hart_count);
>> >> +                                  &ms->first_hartindex, &ms->first_hartid, &ms->hart_count);
>> >>         if (rc) {
>> >>                 sbi_free(ms);
>> >>                 return rc;
>> >> diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
>> >> index 271e625..706967c 100644
>> >> --- a/lib/utils/timer/aclint_mtimer.c
>> >> +++ b/lib/utils/timer/aclint_mtimer.c
>> >> @@ -218,7 +218,7 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
>> >>
>> >>         /* Update MTIMER pointer in scratch space */
>> >>         for (i = 0; i < mt->hart_count; i++) {
>> >> -               scratch = sbi_hartid_to_scratch(mt->first_hartid + i);
>> >> +               scratch = sbi_hartindex_to_scratch(mt->first_hartindex + i);
>> >>                 /*
>> >>                  * We don't need to fail if scratch pointer is not available
>> >>                  * because we might be dealing with hartid of a HART disabled
>> >> diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
>> >> index 9e27e3a..aa05afe 100644
>> >> --- a/lib/utils/timer/fdt_timer_mtimer.c
>> >> +++ b/lib/utils/timer/fdt_timer_mtimer.c
>> >> @@ -47,7 +47,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
>> >>
>> >>         rc = fdt_parse_aclint_node(fdt, nodeoff, true, !is_clint,
>> >>                                    &addr[0], &size[0], &addr[1], &size[1],
>> >> -                                  &mt->first_hartid, &mt->hart_count);
>> >> +                                  &mt->first_hartindex, &mt->first_hartid, &mt->hart_count);
>> >>         if (rc) {
>> >>                 sbi_free(mtn);
>> >>                 return rc;
>> >> diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c
>> >> index 8be5e6c..d88350c 100644
>> >> --- a/platform/fpga/ariane/platform.c
>> >> +++ b/platform/fpga/ariane/platform.c
>> >> @@ -45,6 +45,7 @@ static struct plic_data plic = {
>> >>  static struct aclint_mswi_data mswi = {
>> >>         .addr = ARIANE_ACLINT_MSWI_ADDR,
>> >>         .size = ACLINT_MSWI_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = ARIANE_HART_COUNT,
>> >>  };
>> >> @@ -57,6 +58,7 @@ static struct aclint_mtimer_data mtimer = {
>> >>         .mtimecmp_addr = ARIANE_ACLINT_MTIMER_ADDR +
>> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = ARIANE_HART_COUNT,
>> >>         .has_64bit_mmio = true,
>> >> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
>> >> index 2317a89..c21e8ad 100644
>> >> --- a/platform/fpga/openpiton/platform.c
>> >> +++ b/platform/fpga/openpiton/platform.c
>> >> @@ -49,6 +49,7 @@ static struct plic_data plic = {
>> >>  static struct aclint_mswi_data mswi = {
>> >>         .addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
>> >>         .size = ACLINT_MSWI_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>> >>  };
>> >> @@ -61,6 +62,7 @@ static struct aclint_mtimer_data mtimer = {
>> >>         .mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
>> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = OPENPITON_DEFAULT_HART_COUNT,
>> >>         .has_64bit_mmio = true,
>> >> diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c
>> >> index 27b23f7..21d34b7 100644
>> >> --- a/platform/kendryte/k210/platform.c
>> >> +++ b/platform/kendryte/k210/platform.c
>> >> @@ -39,6 +39,7 @@ static struct plic_data plic = {
>> >>  static struct aclint_mswi_data mswi = {
>> >>         .addr = K210_ACLINT_MSWI_ADDR,
>> >>         .size = ACLINT_MSWI_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = K210_HART_COUNT,
>> >>  };
>> >> @@ -51,6 +52,7 @@ static struct aclint_mtimer_data mtimer = {
>> >>         .mtimecmp_addr = K210_ACLINT_MTIMER_ADDR +
>> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = K210_HART_COUNT,
>> >>         .has_64bit_mmio = true,
>> >> diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c
>> >> index f688b50..54f35f4 100644
>> >> --- a/platform/nuclei/ux600/platform.c
>> >> +++ b/platform/nuclei/ux600/platform.c
>> >> @@ -72,6 +72,7 @@ static struct plic_data plic = {
>> >>  static struct aclint_mswi_data mswi = {
>> >>         .addr = UX600_ACLINT_MSWI_ADDR,
>> >>         .size = ACLINT_MSWI_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = UX600_HART_COUNT,
>> >>  };
>> >> @@ -84,6 +85,7 @@ static struct aclint_mtimer_data mtimer = {
>> >>         .mtimecmp_addr = UX600_ACLINT_MTIMER_ADDR +
>> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = UX600_HART_COUNT,
>> >>         .has_64bit_mmio = true,
>> >> diff --git a/platform/template/platform.c b/platform/template/platform.c
>> >> index 4b3f2ac..4840542 100644
>> >> --- a/platform/template/platform.c
>> >> +++ b/platform/template/platform.c
>> >> @@ -42,6 +42,7 @@ static struct plic_data plic = {
>> >>  static struct aclint_mswi_data mswi = {
>> >>         .addr = PLATFORM_ACLINT_MSWI_ADDR,
>> >>         .size = ACLINT_MSWI_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = PLATFORM_HART_COUNT,
>> >>  };
>> >> @@ -54,6 +55,7 @@ static struct aclint_mtimer_data mtimer = {
>> >>         .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR +
>> >>                          ACLINT_DEFAULT_MTIMECMP_OFFSET,
>> >>         .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
>> >> +       .first_hartindex = 0,
>> >>         .first_hartid = 0,
>> >>         .hart_count = PLATFORM_HART_COUNT,
>> >>         .has_64bit_mmio = true,
>> >> --
>> >> 2.25.1
>> >>
>> >
>> >Regards,
>> >Anup

From anup at brainfault.org  Mon Feb 26 22:31:24 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 27 Feb 2024 12:01:24 +0530
Subject: [PATCH v2 3/3] lib: sbi: Allow platform to fixup load/store faults
In-Reply-To: <1707130200-559404-4-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com> <1707130200-559404-4-git-send-email-ganboing@gmail.com>
Message-ID: <CAAhSdy1__yDWDAoDOJe=6i=6a_i1HveQ9Ox_Hg-TQwoLBbzZsQ@mail.gmail.com>

On Mon, Feb 5, 2024 at 4:20?PM Bo Gan <ganboing at gmail.com> wrote:
>
> This patch allows platforms to define load/store emulators to handle
> load/store faults. Each platform can then use it to trap-and-emulate
> special devices, or filter access to physical devices.
>
> Two more functions are added to `sbi_platform_operations`.
> emulate_load: called when trap.mcause == CAUSE_LOAD_ACCESS
> emulate_store: called when trap.mcause == CAUSE_STORE_ACCESS
> If not defined, sbi_trap_handler redirects the fault, same as before.
>
> The code to decode load/store instruction is reused from
> sbi_misaligned_load/store_handler, with additional lb/lbu/sb decoding.
>
> Signed-off-by: Bo Gan <ganboing at gmail.com>
> ---
>  include/sbi/sbi_platform.h  |  13 +++
>  include/sbi/sbi_trap.h      |   2 +-
>  include/sbi/sbi_trap_ldst.h |  28 +++++-
>  lib/sbi/sbi_trap.c          |  36 +++++---
>  lib/sbi/sbi_trap_ldst.c     | 208 +++++++++++++++++++++++++++++---------------
>  5 files changed, 196 insertions(+), 91 deletions(-)

This patch needs to be broken down into small patches.

The changes to sbi_trap_redirect() prototype needs to be a separate patch.

The addition of emulate_load() and emulate_store() callbacks in sbi_platform.h
needs to be a separate patch. Also, add sbi_platform_emulate_load() and
sbi_platform_emulate_store().

>
> diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
> index 2fb33e1..f8e4514 100644
> --- a/include/sbi/sbi_platform.h
> +++ b/include/sbi/sbi_platform.h
> @@ -48,6 +48,7 @@
>  #include <sbi/sbi_error.h>
>  #include <sbi/sbi_scratch.h>
>  #include <sbi/sbi_version.h>
> +#include <sbi/sbi_trap_ldst.h>
>
>  struct sbi_domain_memregion;
>  struct sbi_ecall_return;
> @@ -139,6 +140,18 @@ struct sbi_platform_operations {
>         int (*vendor_ext_provider)(long funcid,
>                                    struct sbi_trap_regs *regs,
>                                    struct sbi_ecall_return *out);
> +
> +       /**
> +        * platform specific handler to "fixup" load fault
> +        * If NULL, `sbi_trap_handler` will redirect the load fault
> +        */
> +       sbi_trap_ld_emulator emulate_load;
> +
> +       /**
> +        * platform specific handler to "fixup" store fault
> +        * If NULL, `sbi_trap_handler` will redirect the store fault
> +        */
> +       sbi_trap_st_emulator emulate_store;

No need for this typedef and drop the "#include <sbi/sbi_trap_ldst.h>"

>  };
>
>  /** Platform default per-HART stack size for exception/interrupt handling */
> diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
> index a562b95..2727bdb 100644
> --- a/include/sbi/sbi_trap.h
> +++ b/include/sbi/sbi_trap.h
> @@ -225,7 +225,7 @@ static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
>  }
>
>  int sbi_trap_redirect(struct sbi_trap_regs *regs,
> -                     struct sbi_trap_info *trap);
> +                     const struct sbi_trap_info *trap);
>
>  struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs);
>
> diff --git a/include/sbi/sbi_trap_ldst.h b/include/sbi/sbi_trap_ldst.h
> index ab27eb4..54df16e 100644
> --- a/include/sbi/sbi_trap_ldst.h
> +++ b/include/sbi/sbi_trap_ldst.h
> @@ -13,11 +13,31 @@
>  #include <sbi/sbi_types.h>
>
>  struct sbi_trap_regs;
> +struct sbi_trap_info;
>
> -int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
> -                               struct sbi_trap_regs *regs);
> +union reg_data {
> +       u64 data_u64;
> +       u32 data_u32;
> +       u8 data_bytes[8];
> +       ulong data_ulong;
> +};
>
> -int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
> -                                struct sbi_trap_regs *regs);
> +typedef int (*sbi_trap_ld_emulator)(ulong addr, int len, union reg_data *out_val,
> +               struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap);
> +
> +typedef int (*sbi_trap_st_emulator)(ulong addr, int len, union reg_data in_val,
> +               struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap);
> +
> +int sbi_misaligned_load_handler(struct sbi_trap_regs *regs,
> +                               const struct sbi_trap_info *orig_trap);
> +
> +int sbi_misaligned_store_handler(struct sbi_trap_regs *regs,
> +                               const struct sbi_trap_info *orig_trap);
> +
> +int sbi_load_fault_handler(struct sbi_trap_regs *regs,
> +                       const struct sbi_trap_info *orig_trap);
> +
> +int sbi_store_fault_handler(struct sbi_trap_regs *regs,
> +                       const struct sbi_trap_info *orig_trap);
>
>  #endif
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index 145db4b..eb4cc0f 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -84,7 +84,7 @@ static void __noreturn sbi_trap_error(const char *msg, int rc,
>   * @return 0 on success and negative error code on failure
>   */
>  int sbi_trap_redirect(struct sbi_trap_regs *regs,
> -                     struct sbi_trap_info *trap)
> +                     const struct sbi_trap_info *trap)
>  {
>         ulong hstatus, vsstatus, prev_mode;
>  #if __riscv_xlen == 32
> @@ -285,6 +285,13 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
>                 }
>                 return regs;
>         }
> +       /* Original trap_info */
> +       trap.epc   = regs->mepc;
> +       trap.cause = mcause;
> +       trap.tval  = mtval;
> +       trap.tval2 = mtval2;
> +       trap.tinst = mtinst;
> +       trap.gva   = sbi_regs_gva(regs);
>
>         switch (mcause) {
>         case CAUSE_ILLEGAL_INSTRUCTION:
> @@ -292,11 +299,13 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
>                 msg = "illegal instruction handler failed";
>                 break;
>         case CAUSE_MISALIGNED_LOAD:
> -               rc = sbi_misaligned_load_handler(mtval, mtval2, mtinst, regs);
> +               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD);
> +               rc  = sbi_misaligned_load_handler(regs, &trap);
>                 msg = "misaligned load handler failed";
>                 break;
>         case CAUSE_MISALIGNED_STORE:
> -               rc  = sbi_misaligned_store_handler(mtval, mtval2, mtinst, regs);
> +               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE);
> +               rc  = sbi_misaligned_store_handler(regs, &trap);
>                 msg = "misaligned store handler failed";
>                 break;
>         case CAUSE_SUPERVISOR_ECALL:
> @@ -305,20 +314,19 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
>                 msg = "ecall handler failed";
>                 break;
>         case CAUSE_LOAD_ACCESS:
> +               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD);
> +               rc  = sbi_load_fault_handler(regs, &trap);
> +               msg = "load fault handler failed";
> +               break;
>         case CAUSE_STORE_ACCESS:
> -               sbi_pmu_ctr_incr_fw(mcause == CAUSE_LOAD_ACCESS ?
> -                       SBI_PMU_FW_ACCESS_LOAD : SBI_PMU_FW_ACCESS_STORE);
> -               /* fallthrough */
> +               sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE);
> +               rc  = sbi_store_fault_handler(regs, &trap);
> +               msg = "store fault handler failed";
> +               break;
>         default:
>                 /* If the trap came from S or U mode, redirect it there */
> -               trap.epc = regs->mepc;
> -               trap.cause = mcause;
> -               trap.tval = mtval;
> -               trap.tval2 = mtval2;
> -               trap.tinst = mtinst;
> -               trap.gva   = sbi_regs_gva(regs);
> -
> -               rc = sbi_trap_redirect(regs, &trap);
> +               msg = "trap redirect failed";
> +               rc  = sbi_trap_redirect(regs, &trap);
>                 break;
>         }
>
> diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c
> index be9a394..93d4ce9 100644
> --- a/lib/sbi/sbi_trap_ldst.c
> +++ b/lib/sbi/sbi_trap_ldst.c
> @@ -15,42 +15,24 @@
>  #include <sbi/sbi_pmu.h>
>  #include <sbi/sbi_trap.h>
>  #include <sbi/sbi_unpriv.h>
> +#include <sbi/sbi_platform.h>
>
> -union reg_data {
> -       u8 data_bytes[8];
> -       ulong data_ulong;
> -       u64 data_u64;
> -};
> -
> -static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,
> -                                       ulong addr_offset)
> -{
> -       if (new_tinst == INSN_PSEUDO_VS_LOAD ||
> -           new_tinst == INSN_PSEUDO_VS_STORE)
> -               return new_tinst;
> -       else if (orig_tinst == 0)
> -               return 0UL;
> -       else
> -               return orig_tinst | (addr_offset << SH_RS1);
> -}
> -
> -int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
> -                               struct sbi_trap_regs *regs)
> +static int sbi_trap_emulate_load(struct sbi_trap_regs *regs,
> +                                const struct sbi_trap_info *orig_trap,
> +                                sbi_trap_ld_emulator emu)
>  {
>         ulong insn, insn_len;
> -       union reg_data val;
> +       union reg_data val = { 0 };
>         struct sbi_trap_info uptrap;
> -       int i, fp = 0, shift = 0, len = 0;
> +       int rc, fp = 0, shift = 0, len = 0;
>
> -       sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD);
> -
> -       if (tinst & 0x1) {
> +       if (orig_trap->tinst & 0x1) {
>                 /*
>                  * Bit[0] == 1 implies trapped instruction value is
>                  * transformed instruction or custom instruction.
>                  */
> -               insn = tinst | INSN_16BIT_MASK;
> -               insn_len = (tinst & 0x2) ? INSN_LEN(insn) : 2;
> +               insn     = orig_trap->tinst | INSN_16BIT_MASK;
> +               insn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;
>         } else {
>                 /*
>                  * Bit[0] == 0 implies trapped instruction value is
> @@ -64,7 +46,12 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
>                 insn_len = INSN_LEN(insn);
>         }
>
> -       if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
> +       if ((insn & INSN_MASK_LB) == INSN_MATCH_LB) {
> +               len   = 1;
> +               shift = 8 * (sizeof(ulong) - len);
> +       } else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) {
> +               len = 1;
> +       } else if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
>                 len   = 4;
>                 shift = 8 * (sizeof(ulong) - len);
>  #if __riscv_xlen == 64
> @@ -124,26 +111,12 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
>  #endif
>  #endif
>         } else {
> -               uptrap.epc = regs->mepc;
> -               uptrap.cause = CAUSE_MISALIGNED_LOAD;
> -               uptrap.tval = addr;
> -               uptrap.tval2 = tval2;
> -               uptrap.tinst = tinst;
> -               uptrap.gva   = sbi_regs_gva(regs);
> -               return sbi_trap_redirect(regs, &uptrap);
> +               return sbi_trap_redirect(regs, orig_trap);
>         }
>
> -       val.data_u64 = 0;
> -       for (i = 0; i < len; i++) {
> -               val.data_bytes[i] = sbi_load_u8((void *)(addr + i),
> -                                               &uptrap);
> -               if (uptrap.cause) {
> -                       uptrap.epc = regs->mepc;
> -                       uptrap.tinst = sbi_misaligned_tinst_fixup(
> -                               tinst, uptrap.tinst, i);
> -                       return sbi_trap_redirect(regs, &uptrap);
> -               }
> -       }
> +       rc = emu(orig_trap->tval, len, &val, regs, orig_trap);
> +       if (rc)
> +               return rc;
>
>         if (!fp)
>                 SET_RD(insn, regs, ((long)(val.data_ulong << shift)) >> shift);
> @@ -159,23 +132,22 @@ int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
>         return 0;
>  }
>
> -int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
> -                                struct sbi_trap_regs *regs)
> +static int sbi_trap_emulate_store(struct sbi_trap_regs *regs,
> +                                 const struct sbi_trap_info *orig_trap,
> +                                 sbi_trap_st_emulator emu)
>  {
>         ulong insn, insn_len;
>         union reg_data val;
>         struct sbi_trap_info uptrap;
> -       int i, len = 0;
> +       int rc, len = 0;
>
> -       sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE);
> -
> -       if (tinst & 0x1) {
> +       if (orig_trap->tinst & 0x1) {
>                 /*
>                  * Bit[0] == 1 implies trapped instruction value is
>                  * transformed instruction or custom instruction.
>                  */
> -               insn = tinst | INSN_16BIT_MASK;
> -               insn_len = (tinst & 0x2) ? INSN_LEN(insn) : 2;
> +               insn     = orig_trap->tinst | INSN_16BIT_MASK;
> +               insn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;
>         } else {
>                 /*
>                  * Bit[0] == 0 implies trapped instruction value is
> @@ -191,7 +163,9 @@ int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
>
>         val.data_ulong = GET_RS2(insn, regs);
>
> -       if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {
> +       if ((insn & INSN_MASK_SB) == INSN_MATCH_SB) {
> +               len = 1;
> +       } else if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {
>                 len = 4;
>  #if __riscv_xlen == 64
>         } else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) {
> @@ -238,27 +212,117 @@ int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
>  #endif
>  #endif
>         } else {
> -               uptrap.epc = regs->mepc;
> -               uptrap.cause = CAUSE_MISALIGNED_STORE;
> -               uptrap.tval = addr;
> -               uptrap.tval2 = tval2;
> -               uptrap.tinst = tinst;
> -               uptrap.gva   = sbi_regs_gva(regs);
> -               return sbi_trap_redirect(regs, &uptrap);
> +               return sbi_trap_redirect(regs, orig_trap);
>         }
>
> -       for (i = 0; i < len; i++) {
> -               sbi_store_u8((void *)(addr + i), val.data_bytes[i],
> -                            &uptrap);
> -               if (uptrap.cause) {
> -                       uptrap.epc = regs->mepc;
> -                       uptrap.tinst = sbi_misaligned_tinst_fixup(
> -                               tinst, uptrap.tinst, i);
> -                       return sbi_trap_redirect(regs, &uptrap);
> -               }
> -       }
> +       rc = emu(orig_trap->tval, len, val, regs, orig_trap);
> +       if (rc)
> +               return rc;
>
>         regs->mepc += insn_len;
>
>         return 0;
>  }
> +
> +static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,
> +                                       ulong addr_offset)
> +{
> +       if (new_tinst == INSN_PSEUDO_VS_LOAD ||
> +           new_tinst == INSN_PSEUDO_VS_STORE)
> +               return new_tinst;
> +       else if (orig_tinst == 0)
> +               return 0UL;
> +       else
> +               return orig_tinst | (addr_offset << SH_RS1);
> +}
> +
> +static int sbi_misaligned_ld_emulator(ulong addr, int len,
> +                                     union reg_data *out_val,
> +                                     struct sbi_trap_regs *regs,
> +                                     const struct sbi_trap_info *orig_trap)
> +{
> +       struct sbi_trap_info uptrap;
> +       int i;
> +
> +       for (i = 0; i < len; i++) {
> +               out_val->data_bytes[i] =
> +                       sbi_load_u8((void *)(addr + i), &uptrap);
> +               if (uptrap.cause) {
> +                       uptrap.epc   = regs->mepc;
> +                       uptrap.tinst = sbi_misaligned_tinst_fixup(
> +                               orig_trap->tinst, uptrap.tinst, i);
> +                       return sbi_trap_redirect(regs, &uptrap);
> +               }
> +       }
> +       return 0;
> +}
> +
> +static int sbi_misaligned_st_emulator(ulong addr, int len,
> +                                     union reg_data in_val,
> +                                     struct sbi_trap_regs *regs,
> +                                     const struct sbi_trap_info *orig_trap)
> +{
> +       struct sbi_trap_info uptrap;
> +       int i;
> +
> +       for (i = 0; i < len; i++) {
> +               sbi_store_u8((void *)(addr + i), in_val.data_bytes[i], &uptrap);
> +               if (uptrap.cause) {
> +                       uptrap.epc   = regs->mepc;
> +                       uptrap.tinst = sbi_misaligned_tinst_fixup(
> +                               orig_trap->tinst, uptrap.tinst, i);
> +                       return sbi_trap_redirect(regs, &uptrap);
> +               }
> +       }
> +       return 0;
> +}
> +
> +int sbi_misaligned_load_handler(struct sbi_trap_regs *regs,
> +                               const struct sbi_trap_info *orig_trap)
> +{
> +       return sbi_trap_emulate_load(regs, orig_trap,
> +                                    sbi_misaligned_ld_emulator);
> +}
> +
> +int sbi_misaligned_store_handler(struct sbi_trap_regs *regs,
> +                                const struct sbi_trap_info *orig_trap)
> +{
> +       return sbi_trap_emulate_store(regs, orig_trap,
> +                                     sbi_misaligned_st_emulator);
> +}
> +
> +int sbi_load_fault_handler(struct sbi_trap_regs *regs,
> +                          const struct sbi_trap_info *orig_trap)
> +{
> +       const struct sbi_platform *plat;
> +
> +       /* If fault came from M mode, just fail */
> +       if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) {
> +               return SBI_EINVAL;
> +       }
> +
> +       plat = sbi_platform_ptr(sbi_scratch_thishart_ptr());
> +       if (sbi_platform_ops(plat)->emulate_load) {
> +               return sbi_trap_emulate_load(
> +                       regs, orig_trap, sbi_platform_ops(plat)->emulate_load);
> +       }
> +       return sbi_trap_redirect(regs, orig_trap);
> +}
> +
> +int sbi_store_fault_handler(struct sbi_trap_regs *regs,
> +                           const struct sbi_trap_info *orig_trap)
> +{
> +       const struct sbi_platform *plat;
> +
> +       /* If fault came from M mode, just fail */
> +       if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) {
> +               return SBI_EINVAL;
> +       }
> +
> +       plat = sbi_platform_ptr(sbi_scratch_thishart_ptr());
> +       if (sbi_platform_ops(plat)->emulate_store) {
> +               return sbi_trap_emulate_store(
> +                       regs, orig_trap, sbi_platform_ops(plat)->emulate_store);
> +       }
> +       return sbi_trap_redirect(regs, orig_trap);
> +}
> --
> 2.7.4
>

Regards,
Anup


From anup at brainfault.org  Mon Feb 26 22:31:29 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 27 Feb 2024 12:01:29 +0530
Subject: [PATCH v2 1/3] lib: sbi: rename sbi_misaligned_ldst.c to sbi_trap_ldst.c
In-Reply-To: <1707130200-559404-2-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com> <1707130200-559404-2-git-send-email-ganboing@gmail.com>
Message-ID: <CAAhSdy1Bnx7ZQB_NCdKAmi5ervuukg8k9=gkCvn77drNS0o2rA@mail.gmail.com>

On Mon, Feb 5, 2024 at 4:20?PM Bo Gan <ganboing at gmail.com> wrote:
>
> Signed-off-by: Bo Gan <ganboing at gmail.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup


> ---
>  lib/sbi/objects.mk                                 | 2 +-
>  lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} | 0
>  2 files changed, 1 insertion(+), 1 deletion(-)
>  rename lib/sbi/{sbi_misaligned_ldst.c => sbi_trap_ldst.c} (100%)
>
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 0a50e95..204dd6b 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -70,7 +70,6 @@ libsbi-objs-y += sbi_illegal_insn.o
>  libsbi-objs-y += sbi_init.o
>  libsbi-objs-y += sbi_ipi.o
>  libsbi-objs-y += sbi_irqchip.o
> -libsbi-objs-y += sbi_misaligned_ldst.o
>  libsbi-objs-y += sbi_platform.o
>  libsbi-objs-y += sbi_pmu.o
>  libsbi-objs-y += sbi_dbtr.o
> @@ -80,6 +79,7 @@ libsbi-objs-y += sbi_system.o
>  libsbi-objs-y += sbi_timer.o
>  libsbi-objs-y += sbi_tlb.o
>  libsbi-objs-y += sbi_trap.o
> +libsbi-objs-y += sbi_trap_ldst.o
>  libsbi-objs-y += sbi_unpriv.o
>  libsbi-objs-y += sbi_expected_trap.o
>  libsbi-objs-y += sbi_cppc.o
> diff --git a/lib/sbi/sbi_misaligned_ldst.c b/lib/sbi/sbi_trap_ldst.c
> similarity index 100%
> rename from lib/sbi/sbi_misaligned_ldst.c
> rename to lib/sbi/sbi_trap_ldst.c
> --
> 2.7.4
>


From anup at brainfault.org  Mon Feb 26 22:31:35 2024
From: anup at brainfault.org (Anup Patel)
Date: Tue, 27 Feb 2024 12:01:35 +0530
Subject: [PATCH v2 2/3] include: sbi: rename sbi_misaligned_ldst.h to sbi_trap_ldst.h
In-Reply-To: <1707130200-559404-3-git-send-email-ganboing@gmail.com>
References: <1707130200-559404-1-git-send-email-ganboing@gmail.com> <1707130200-559404-3-git-send-email-ganboing@gmail.com>
Message-ID: <CAAhSdy32+Pyig7q=szmJ-8G1-=mAtuEy=TSnrWSYM6DM8SO__Q@mail.gmail.com>

On Mon, Feb 5, 2024 at 4:20?PM Bo Gan <ganboing at gmail.com> wrote:
>
> Signed-off-by: Bo Gan <ganboing at gmail.com>
> ---
>  include/sbi/{sbi_misaligned_ldst.h => sbi_trap_ldst.h} | 0
>  lib/sbi/sbi_trap.c                                     | 2 +-
>  lib/sbi/sbi_trap_ldst.c                                | 2 +-
>  3 files changed, 2 insertions(+), 2 deletions(-)
>  rename include/sbi/{sbi_misaligned_ldst.h => sbi_trap_ldst.h} (100%)

You need to rename __SBI_MISALIGNED_LDST_H__ in sbi_misaligned_ldst.h
to __SBI_TRAP_LDST_H__

Otherwise, it looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup


>
> diff --git a/include/sbi/sbi_misaligned_ldst.h b/include/sbi/sbi_trap_ldst.h
> similarity index 100%
> rename from include/sbi/sbi_misaligned_ldst.h
> rename to include/sbi/sbi_trap_ldst.h
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index dbf307c..145db4b 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -17,7 +17,7 @@
>  #include <sbi/sbi_illegal_insn.h>
>  #include <sbi/sbi_ipi.h>
>  #include <sbi/sbi_irqchip.h>
> -#include <sbi/sbi_misaligned_ldst.h>
> +#include <sbi/sbi_trap_ldst.h>
>  #include <sbi/sbi_pmu.h>
>  #include <sbi/sbi_scratch.h>
>  #include <sbi/sbi_timer.h>
> diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c
> index aa512de..be9a394 100644
> --- a/lib/sbi/sbi_trap_ldst.c
> +++ b/lib/sbi/sbi_trap_ldst.c
> @@ -11,7 +11,7 @@
>  #include <sbi/riscv_encoding.h>
>  #include <sbi/riscv_fp.h>
>  #include <sbi/sbi_error.h>
> -#include <sbi/sbi_misaligned_ldst.h>
> +#include <sbi/sbi_trap_ldst.h>
>  #include <sbi/sbi_pmu.h>
>  #include <sbi/sbi_trap.h>
>  #include <sbi/sbi_unpriv.h>
> --
> 2.7.4
>


From cmax at mailbox.org  Tue Feb 27 12:07:43 2024
From: cmax at mailbox.org (cmax at mailbox.org)
Date: Tue, 27 Feb 2024 21:07:43 +0100
Subject: [PATCH] lib: sbi_domain: Fix PMP condition for addresses
Message-ID: <20240227200743.22661-1-cmax@mailbox.org>

From: max <cmax at mailbox.org>

In order to put an address/size into an NAPOT PMP region, the address
needs to be aligned to the size shifted two to the right.

Example:
fw_start: 0x80040000
fw_size:  0x00040000
PMP address: 0x80040000 | (0x00040000 >> 2)
fw_size is valid, but not in the current implementation

Signed-off-by: max <cmax at mailbox.org>
---
 lib/sbi/sbi_domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index 4e9f742..94ee717 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -749,7 +749,7 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 		return SBI_EINVAL;
 	}
 
-	if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+	if ((scratch->fw_start & ((scratch->fw_rw_offset >> 2) - 1)) != 0) {
 		sbi_printf("%s: fw_start and fw_rw_offset not aligned\n",
 			   __func__);
 		return SBI_EINVAL;
-- 
2.43.0



From ajones at ventanamicro.com  Wed Feb 28 05:47:19 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 14:47:19 +0100
Subject: [PATCH v2 1/5] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240215161625.314131-2-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-2-ivan.orlov0322@gmail.com>
Message-ID: <20240228-82fb0c4b75bdfb2507c80100@orel>

On Thu, Feb 15, 2024 at 04:16:21PM +0000, Ivan Orlov wrote:
> This patch contains the documentation for SBIUnit. It describes:
> 
> - What is SBIUnit
> - Simple test writing scenario
> - How we can cover static functions
> - How we can "mock" structures in order to test the functions which
> operate on them
> - SBIUnit API Reference
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
> V1 -> V2:
> - Use more appropriate language
> - Update the documentation in accordance with SBIUnit API and
> structure changes
> - Remove the redundant documentation for every SBIUNIT_* macro.
> - Make the documentation follow the 80-characters rule.
> 
>  docs/writing_tests.md | 131 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 131 insertions(+)
>  create mode 100644 docs/writing_tests.md
> 
> diff --git a/docs/writing_tests.md b/docs/writing_tests.md
> new file mode 100644
> index 0000000..279d35b
> --- /dev/null
> +++ b/docs/writing_tests.md
> @@ -0,0 +1,131 @@
> +Writing tests for OpenSBI
> +=========================
> +
> +SBIUnit
> +-------
> +SBIUnit is a set of macros and functions which simplify the test development and
> +automate the test execution and evaluation. All of the SBIUnit definitions are
> +in the `include/sbi/sbi_unit_test.h` header file, and implementations are
> +available in `lib/sbi/sbi_unit_test.c`.
> +
> +Simple SBIUnit test
> +-------------------
> +
> +For instance, we would like to test the following function from
> +`lib/sbi/sbi_string.c`:
> +
> +```c
> +size_t sbi_strlen(const char *str)
> +{
> +	unsigned long ret = 0;
> +
> +	while (*str != '\0') {
> +		ret++;
> +		str++;
> +	}
> +
> +	return ret;
> +}
> +```
> +
> +Which calculates the string length.

Lowercase 'w' in which, since this line is a continuation of the sentence
started above.

> +
> +Create the file `lib/sbi/sbi_string_test.c` with the following content:
> +
> +```c
> +#include <sbi/sbi_unit_test.h>
> +#include <sbi/sbi_string.h>
> +
> +static void strlen_test(struct sbiunit_test_case *test)
> +{
> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
> +}
> +
> +static struct sbiunit_test_case string_test_cases[] = {
> +	SBIUNIT_TEST_CASE(strlen_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
> +```
> +
> +Then, add the corresponding Makefile entries to `lib/sbi/objects.mk`:
> +```lang-makefile
> +...
> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
> +```
> +
> +Run `make clean` in order to regenerate the carray-related files, recompile
> +OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU.
> +You will see something like this:
> +```
> +# make PLATFORM=generic run
> +...
> +# Running SBIUNIT tests #
> +...
> +## Running test suite: string_test_suite
> +[PASSED] strlen_test
> +1 PASSED / 0 FAILED / 1 TOTAL
> +```
> +
> +Now let's try to change this test in the way that it will fail:
> +
> +```c
> +- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
> ++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
> +```
> +
> +`make all` and `make run` it again:
> +```
> +...
> +# Running SBIUNIT tests #
> +...
> +## Running test suite: string_test_suite
> +[SBIUnit] [.../opensbi/lib/sbi/sbi_string_test.c:6]: strlen_test: Condition
> +"(sbi_strlen("Hello")) == (100)" expected to be true!

If the test will output the above all on one line, then the document
should also use a single line even though it will exceed 80 chars.

> +[FAILED] strlen_test
> +0 PASSED / 1 FAILED / 1 TOTAL
> +```
> +Covering the static functions / using the static definitions
> +------------------------------------------------------------
> +
> +SBIUnit also allows you to test static functions. In order to do so, simply
> +include your test source in the file you would like to test. Complementing the
> +example above, just add this to the
> +`lib/sbi/sbi_string.c` file:
> +
> +```c
> +#ifdef CONFIG_SBIUNIT
> +#include "sbi_string_test.c"
> +#endif
> +```
> +
> +In this case you should only add a new carray entry pointing to the test suite
> +to `lib/sbi/objects.mk`:
> +```lang-makefile
> +...
> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
> +```
> +
> +You don't have to compile the `sbi_string_test.o` separately, because the
> +test code will be included into the `sbi_string` object file.
> +
> +See example in `lib/sbi/sbi_console_test.c`, where statically declared
> +`console_dev` variable is used to mock the `sbi_console_device` structure.
> +
> +"Mocking" the structures
> +------------------------
> +See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`,
> +where the sbi_console_device structure was mocked to be used in various
> +console-related functions in order to test them.
> +
> +API Reference
> +-------------
> +All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the
> +corresponding conditions are not met, however, the execution of a particular
> +test case will not be stopped.
> +
> +All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop
> +immediately, triggering the panic.

s/the panic/a panic/

> -- 
> 2.34.1
>

Other than the nits,

Reviewed-by: Andrew Jones <ajones at ventanamicro.com>

Thanks,
drew


From ajones at ventanamicro.com  Wed Feb 28 06:19:20 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 15:19:20 +0100
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240215161625.314131-3-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
Message-ID: <20240228-3b952164f9b56135e30a6282@orel>

On Thu, Feb 15, 2024 at 04:16:22PM +0000, Ivan Orlov wrote:
> This patch introduces all of the SBIUnit macros and functions which
> can be used during the test development process. Also, it defines
> the 'run_all_tests' function, which is being called during the
> 'init_coldboot' right after printing the boot hart information.
> 
> Also, add the CONFIG_SBIUNIT Kconfig entry in order to be able to
> turn the tests on and off. When the CONFIG_SBIUNIT is disabled,
> the tests and all related code is excluded completely on the
> compilation stage.
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
> V1 -> V2:
> - Rename the sources to have 'test' in the names: 'sbi_unit.c' =>
> 'sbi_unit_test.c', 'sbi_unit.h' => 'sbi_unit_test.h'.
> - Rewrite using the carray functionality instead of placing the
> pointers to the test suites into the source explicitly.
> - Add 'ifdef' into the sbi_unit_test header file so we could
> avoid writing a lot of 'ifdef' in other files.
> - Get rid of unused symbols and macros
> - Change the behaviour of SBIUNIT_ASSERT_* functions: now they trigger
> sbi_panic if the assertion fails.
> - Add a 'SBIUnit' prefix to the SBIUNIT_INFO macro message
> - Rename the sbiunit_test_case structure fields, and use true/false
> instead of 1/0
> - Change the logic of the test fail detection: now we have the 'failed'
> sbiunit_test_case structure field instead of the 'result'. 'failed'
> field gets set to 'true' if an assertion or an expectaion fails.
> - Fix codestyle issues
> - Add 'len' parameter to SBIUNIT_*_STREQ
> 
>  include/sbi/sbi_unit_test.h   | 74 +++++++++++++++++++++++++++++++++++
>  lib/sbi/Kconfig               |  4 ++
>  lib/sbi/objects.mk            |  2 +
>  lib/sbi/sbi_init.c            |  3 ++
>  lib/sbi/sbi_unit_test.c       | 43 ++++++++++++++++++++
>  lib/sbi/sbi_unit_tests.carray |  3 ++
>  6 files changed, 129 insertions(+)
>  create mode 100644 include/sbi/sbi_unit_test.h
>  create mode 100644 lib/sbi/sbi_unit_test.c
>  create mode 100644 lib/sbi/sbi_unit_tests.carray
> 
> diff --git a/include/sbi/sbi_unit_test.h b/include/sbi/sbi_unit_test.h
> new file mode 100644
> index 0000000..1538332
> --- /dev/null
> +++ b/include/sbi/sbi_unit_test.h
> @@ -0,0 +1,74 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#ifdef CONFIG_SBIUNIT
> +#ifndef __SBI_UNIT_H__
> +#define __SBI_UNIT_H__
> +
> +#include <sbi/sbi_types.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_string.h>
> +
> +struct sbiunit_test_case {
> +	const char *name;
> +	bool enabled;
> +	bool failed;
> +	void (*test_func)(struct sbiunit_test_case *test);
> +	void (*onerr)(struct sbiunit_test_case *test);

Please rename to on_error()

> +};
> +
> +struct sbiunit_test_suite {
> +	const char *name;
> +	struct sbiunit_test_case *cases;
> +};
> +
> +#define SBIUNIT_TEST_CASE(func)		\
> +	{				\
> +		.name = #func,		\
> +		.enabled = true,	\
> +		.failed = false,	\
> +		.test_func = (func)	\
> +	}
> +
> +#define SBIUNIT_TEST_SUITE(suite_name, cases_arr)		\
> +	struct sbiunit_test_suite suite_name = {		\
> +		.name = #suite_name,				\
> +		.cases = cases_arr				\
> +	}
> +
> +#define _sbiunit_msg(test, msg) "[SBIUnit] [%s:%d]: %s: %s", __FILE__,	\
> +				__LINE__, test->name, msg
> +
> +#define SBIUNIT_INFO(test, msg) sbi_printf(_sbiunit_msg(test, msg))
> +#define SBIUNIT_PANIC(test, msg) sbi_panic(_sbiunit_msg(test, msg))
> +
> +#define SBIUNIT_EXPECT(test, cond) do {							\
> +	if (!(cond)) {									\
> +		test->failed = true;							\
> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
> +	}										\
> +} while (0)
> +
> +#define SBIUNIT_ASSERT(test, cond) do {						\
> +	if (!(cond)) {								\
> +		test->failed = true;						\

No need to set failed since the next line calls panic.

> +		SBIUNIT_PANIC(test, "Condition \"" #cond "\" must be true!\n");	\
> +	}									\
> +} while (0)
> +
> +#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))
> +#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, (a) == (b))
> +#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, (a) != (b))
> +#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, (a) != (b))
> +#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_memcmp(a, b, len))
> +#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_memcmp(a, b, len))
> +#define SBIUNIT_EXPECT_STREQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_strncmp(a, b, len))
> +#define SBIUNIT_ASSERT_STREQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_strncmp(a, b, len))
> +
> +void run_all_tests(void);
> +#endif
> +#else
> +#define run_all_tests()
> +#endif
> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> index 81dd2db..e3038ee 100644
> --- a/lib/sbi/Kconfig
> +++ b/lib/sbi/Kconfig
> @@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
>  	bool "Debug Trigger Extension"
>  	default y
>  
> +config SBIUNIT
> +	bool "Enable SBIUNIT tests"
> +	default n
> +
>  endmenu
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 0a50e95..08959f1 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -11,6 +11,8 @@ libsbi-objs-y += riscv_asm.o
>  libsbi-objs-y += riscv_atomic.o
>  libsbi-objs-y += riscv_hardfp.o
>  libsbi-objs-y += riscv_locks.o
> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_test.o
> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
>  
>  libsbi-objs-y += sbi_ecall.o
>  libsbi-objs-y += sbi_ecall_exts.o
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 804b01c..796cccc 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -29,6 +29,7 @@
>  #include <sbi/sbi_timer.h>
>  #include <sbi/sbi_tlb.h>
>  #include <sbi/sbi_version.h>
> +#include <sbi/sbi_unit_test.h>
>  
>  #define BANNER                                              \
>  	"   ____                    _____ ____ _____\n"     \
> @@ -398,6 +399,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  
>  	sbi_boot_print_hart(scratch, hartid);
>  
> +	run_all_tests();
> +
>  	/*
>  	 * Configure PMP at last because if SMEPMP is detected,
>  	 * M-mode access to the S/U space will be rescinded.
> diff --git a/lib/sbi/sbi_unit_test.c b/lib/sbi/sbi_unit_test.c
> new file mode 100644
> index 0000000..f4988d8
> --- /dev/null
> +++ b/lib/sbi/sbi_unit_test.c
> @@ -0,0 +1,43 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_unit_test.h>
> +#include <sbi/sbi_types.h>
> +#include <sbi/sbi_console.h>
> +
> +extern struct sbiunit_test_suite *sbi_unit_tests[];
> +extern unsigned long sbi_unit_tests_size;
> +
> +static void run_test_suite(struct sbiunit_test_suite *suite)
> +{
> +	struct sbiunit_test_case *s_case;
> +	u32 count_pass = 0, count_fail = 0;
> +
> +	sbi_printf("## Running test suite: %s\n", suite->name);
> +
> +	s_case = suite->cases;
> +	while (s_case->enabled) {

Can't test cases be enabled/disabled sparsely? Shouldn't we instead
loop while s_case->name is not NULL? And we need to ensure the cases
array always has an empty case at the end.

> +		s_case->test_func(s_case);
> +		if (s_case->failed)
> +			count_fail++;
> +		else
> +			count_pass++;
> +		sbi_printf("[%s] %s\n", s_case->failed ? "FAILED" : "PASSED",
> +			   s_case->name);
> +		s_case++;
> +	}
> +	sbi_printf("%u PASSED / %u FAILED / %u TOTAL\n", count_pass, count_fail,
> +		   count_pass + count_fail);
> +}
> +
> +void run_all_tests(void)
> +{
> +	u32 i;
> +
> +	sbi_printf("\n# Running SBIUNIT tests #\n");
> +
> +	for (i = 0; i < sbi_unit_tests_size; i++)
> +		run_test_suite(sbi_unit_tests[i]);
> +}
> diff --git a/lib/sbi/sbi_unit_tests.carray b/lib/sbi/sbi_unit_tests.carray
> new file mode 100644
> index 0000000..8d6069b
> --- /dev/null
> +++ b/lib/sbi/sbi_unit_tests.carray
> @@ -0,0 +1,3 @@
> +HEADER: sbi/sbi_unit_test.h
> +TYPE: struct sbiunit_test_suite
> +NAME: sbi_unit_tests
> -- 
> 2.34.1
>

Thanks,
drew


From ajones at ventanamicro.com  Wed Feb 28 06:23:40 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 15:23:40 +0100
Subject: [PATCH v2 3/5] Makefile: clean '.c' files generated by carray
In-Reply-To: <20240215161625.314131-4-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-4-ivan.orlov0322@gmail.com>
Message-ID: <20240228-0575feceddadf1436bb41adb@orel>

On Thu, Feb 15, 2024 at 04:16:23PM +0000, Ivan Orlov wrote:
> `make clean` doesn't clear the '*.c' files generated by carray.sh
> in the 'build' directory. Fix it by extending the 'clean' makefile
> target.
> 
> This is the only way we are able to regenerate the carray .c file in
> case if we add a new test to the 'carray-sbi_unit_tests-y' Makefile
> variable. However, running `make clear` every time we add a new test
> is not really convenient, so the mechanics should be changed in the
> future.
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
>  Makefile | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Makefile b/Makefile
> index 680c19a..4519277 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -684,6 +684,8 @@ clean:
>  	$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
>  	$(if $(V), @echo " RM        $(build_dir)/*.dtb")
>  	$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
> +	$(if $(V), @echo " RM        $(build_dir)/*.c")
> +	$(CMD_PREFIX)find $(build_dir) -type f -name "*.c" -exec rm -rf {} +

I realize these *.c files are in $build_dir, so they're supposed to be
generated files, but it still looks scary to remove source files. I
think we should try to be more specific. Maybe we should put all generated
source files in directories named 'generated' or something and then only
remove files in those directories.

Thanks,
drew

>  
>  # Rule for "make distclean"
>  .PHONY: distclean
> -- 
> 2.34.1
> 


From ajones at ventanamicro.com  Wed Feb 28 06:28:42 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 15:28:42 +0100
Subject: [PATCH v2 4/5] lib: tests: Add a test for sbi_bitmap
In-Reply-To: <20240215161625.314131-5-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-5-ivan.orlov0322@gmail.com>
Message-ID: <20240228-171d01c049bbf1e5f64b3174@orel>

On Thu, Feb 15, 2024 at 04:16:24PM +0000, Ivan Orlov wrote:
> Add test suite covering all of the functions from lib/sbi/sbi_bitmap.c:
> __bitmap_and, __bitmap_or and __bitmap_xor.
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
> V1 -> V2:
> - Extract the part of the commit description to the cover letter
> - Update to use the carray functionality instead of placing the pointer
> to the test suite directly into the sources
> - Fix codestyle issues
> - Use the references to the data_* arrays when defining the expected
> test results, instead of repeating the same numbers again and again
> 
>  lib/sbi/objects.mk        |   3 ++
>  lib/sbi/sbi_bitmap_test.c | 103 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 106 insertions(+)
>  create mode 100644 lib/sbi/sbi_bitmap_test.c
>

Reviewed-by: Andrew Jones <ajones at ventanamicro.com>


From ajones at ventanamicro.com  Wed Feb 28 06:33:51 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 15:33:51 +0100
Subject: [PATCH v2 5/5] lib: tests: Add sbi_console test
In-Reply-To: <20240215161625.314131-6-ivan.orlov0322@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-6-ivan.orlov0322@gmail.com>
Message-ID: <20240228-7ceaaf4e09d16694c1dd2f05@orel>

On Thu, Feb 15, 2024 at 04:16:25PM +0000, Ivan Orlov wrote:
> Add the test suite covering some of the functions from
> lib/sbi/sbi_console.c: putc, puts and printf. The test covers a variety
> of format specifiers for printf and different strings and characters for
> putc and puts.
> 
> In order to do that, the test "mocks" the sbi_console_device structure
> by setting the 'console_dev' variable to the virtual console.
> 
> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> ---
> V1 -> V2:
> - Rewrite using the carray functionality
> - Replace CONSOLE_DO and CONSOLE_DO_RET macros with two inline
> functions: one of them "mocks" the default console device, and
> the second one restores the old console device.
> - Fix codestyle issues (comments, etc.)
> - Remove incorrect 'puts' test
> - Use updated SBIUNIT_ASSERT_STREQ API
> 
>  lib/sbi/objects.mk         |   1 +
>  lib/sbi/sbi_console.c      |   4 ++
>  lib/sbi/sbi_console_test.c | 102 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 107 insertions(+)
>  create mode 100644 lib/sbi/sbi_console_test.c
> 
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index b4c273f..9d065fa 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -16,6 +16,7 @@ libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
>  
>  libsbi-objs-$(CONFIG_SBIUNIT) += sbi_bitmap_test.o
>  carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitmap_test_suite
> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += console_test_suite
>  
>  libsbi-objs-y += sbi_ecall.o
>  libsbi-objs-y += sbi_ecall_exts.o
> diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c
> index ab09a5c..d1229d0 100644
> --- a/lib/sbi/sbi_console.c
> +++ b/lib/sbi/sbi_console.c
> @@ -488,3 +488,7 @@ int sbi_console_init(struct sbi_scratch *scratch)
>  
>  	return rc;
>  }
> +
> +#ifdef CONFIG_SBIUNIT
> +#include "sbi_console_test.c"
> +#endif
> diff --git a/lib/sbi/sbi_console_test.c b/lib/sbi/sbi_console_test.c
> new file mode 100644
> index 0000000..f24b329
> --- /dev/null
> +++ b/lib/sbi/sbi_console_test.c
> @@ -0,0 +1,102 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> + */
> +#include <sbi/sbi_unit_test.h>
> +#include <sbi/sbi_heap.h>
> +
> +#define TEST_CONSOLE_BUF_LEN 1024
> +
> +static const struct sbi_console_device *old_dev;
> +static char test_console_buf[TEST_CONSOLE_BUF_LEN];
> +static u32 test_console_buf_pos;
> +
> +static void test_console_putc(char c)
> +{
> +	test_console_buf[test_console_buf_pos] = c;
> +	test_console_buf_pos = (test_console_buf_pos + 1) % TEST_CONSOLE_BUF_LEN;
> +}
> +
> +static void clear_test_console_buf(void)
> +{
> +	test_console_buf_pos = 0;
> +	test_console_buf[0] = '\0';
> +}
> +
> +static const struct sbi_console_device new_dev = {

Please rename 'new_dev' to 'test_console_dev'

> +	.name = "Test console device",
> +	.console_putc = test_console_putc,
> +};
> +
> +/* Mock the console device */
> +static inline void test_console_begin(const struct sbi_console_device *device)
> +{
> +	old_dev = console_dev;
> +	console_dev = device;
> +}
> +
> +static inline void test_console_end(void)
> +{
> +	console_dev = old_dev;
> +}
> +
> +static void putc_test(struct sbiunit_test_case *test)
> +{
> +	clear_test_console_buf();
> +
> +	test_console_begin(&new_dev);
> +	sbi_putc('a');
> +	test_console_end();
> +	SBIUNIT_ASSERT_EQ(test, test_console_buf[0], 'a');
> +}
> +
> +#define PUTS_TEST(test, expected, str) do {			\
> +	clear_test_console_buf();				\
> +	test_console_begin(&new_dev);				\
> +	sbi_puts(str);						\
> +	test_console_end();					\
> +	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
> +			     sbi_strlen(expected));		\
> +} while (0)
> +
> +static void puts_test(struct sbiunit_test_case *test)
> +{
> +	PUTS_TEST(test, "Hello, OpenSBI!", "Hello, OpenSBI!");
> +	PUTS_TEST(test, "Hello,\r\nOpenSBI!", "Hello,\nOpenSBI!");
> +}
> +
> +#define PRINTF_TEST(test, expected, format, ...) do {		\
> +	clear_test_console_buf();				\
> +	test_console_begin(&new_dev);				\
> +	size_t __res = sbi_printf(format, ##__VA_ARGS__);	\
> +	test_console_end();					\
> +	SBIUNIT_ASSERT_EQ(test, __res, sbi_strlen(expected));	\
> +	SBIUNIT_ASSERT_STREQ(test, test_console_buf, expected,	\
> +			     sbi_strlen(expected));		\
> +} while (0)
> +
> +static void printf_test(struct sbiunit_test_case *test)
> +{
> +	PRINTF_TEST(test, "Hello", "Hello");
> +	PRINTF_TEST(test, "3 5 7", "%d %d %d", 3, 5, 7);
> +	PRINTF_TEST(test, "Hello", "%s", "Hello");
> +	PRINTF_TEST(test, "-1", "%d", -1);
> +	PRINTF_TEST(test, "FF", "%X", 255);
> +	PRINTF_TEST(test, "ff", "%x", 255);
> +	PRINTF_TEST(test, "A", "%c", 'A');
> +	PRINTF_TEST(test, "1fe", "%p", (void *)0x1fe);
> +	PRINTF_TEST(test, "4294967295", "%u", 4294967295U);
> +	PRINTF_TEST(test, "-2147483647", "%ld", -2147483647l);
> +	PRINTF_TEST(test, "-9223372036854775807", "%lld", -9223372036854775807LL);
> +	PRINTF_TEST(test, "18446744073709551615", "%llu", 18446744073709551615ULL);
> +}
> +
> +static struct sbiunit_test_case console_test_cases[] = {
> +	SBIUNIT_TEST_CASE(putc_test),
> +	SBIUNIT_TEST_CASE(puts_test),
> +	SBIUNIT_TEST_CASE(printf_test),
> +	{},
> +};
> +
> +SBIUNIT_TEST_SUITE(console_test_suite, console_test_cases);
> -- 
> 2.34.1
>

Other than the rename

Reviewed-by: Andrew Jones <ajones at ventanamicro.com>


From ivan.orlov0322 at gmail.com  Wed Feb 28 08:01:41 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 16:01:41 +0000
Subject: [PATCH v2 1/5] docs: Add documentation about tests and SBIUnit
In-Reply-To: <20240228-82fb0c4b75bdfb2507c80100@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-2-ivan.orlov0322@gmail.com>
 <20240228-82fb0c4b75bdfb2507c80100@orel>
Message-ID: <89312def-69e0-4b9a-9969-19cd9971930f@gmail.com>

On 2/28/24 13:47, Andrew Jones wrote:
> On Thu, Feb 15, 2024 at 04:16:21PM +0000, Ivan Orlov wrote:
>> This patch contains the documentation for SBIUnit. It describes:
>>
>> - What is SBIUnit
>> - Simple test writing scenario
>> - How we can cover static functions
>> - How we can "mock" structures in order to test the functions which
>> operate on them
>> - SBIUnit API Reference
>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>> V1 -> V2:
>> - Use more appropriate language
>> - Update the documentation in accordance with SBIUnit API and
>> structure changes
>> - Remove the redundant documentation for every SBIUNIT_* macro.
>> - Make the documentation follow the 80-characters rule.
>>
>>   docs/writing_tests.md | 131 ++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 131 insertions(+)
>>   create mode 100644 docs/writing_tests.md
>>
>> diff --git a/docs/writing_tests.md b/docs/writing_tests.md
>> new file mode 100644
>> index 0000000..279d35b
>> --- /dev/null
>> +++ b/docs/writing_tests.md
>> @@ -0,0 +1,131 @@
>> +Writing tests for OpenSBI
>> +=========================
>> +
>> +SBIUnit
>> +-------
>> +SBIUnit is a set of macros and functions which simplify the test development and
>> +automate the test execution and evaluation. All of the SBIUnit definitions are
>> +in the `include/sbi/sbi_unit_test.h` header file, and implementations are
>> +available in `lib/sbi/sbi_unit_test.c`.
>> +
>> +Simple SBIUnit test
>> +-------------------
>> +
>> +For instance, we would like to test the following function from
>> +`lib/sbi/sbi_string.c`:
>> +
>> +```c
>> +size_t sbi_strlen(const char *str)
>> +{
>> +	unsigned long ret = 0;
>> +
>> +	while (*str != '\0') {
>> +		ret++;
>> +		str++;
>> +	}
>> +
>> +	return ret;
>> +}
>> +```
>> +
>> +Which calculates the string length.
> 
> Lowercase 'w' in which, since this line is a continuation of the sentence
> started above.
> 
>> +
>> +Create the file `lib/sbi/sbi_string_test.c` with the following content:
>> +
>> +```c
>> +#include <sbi/sbi_unit_test.h>
>> +#include <sbi/sbi_string.h>
>> +
>> +static void strlen_test(struct sbiunit_test_case *test)
>> +{
>> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
>> +	SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
>> +}
>> +
>> +static struct sbiunit_test_case string_test_cases[] = {
>> +	SBIUNIT_TEST_CASE(strlen_test),
>> +	{},
>> +};
>> +
>> +SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
>> +```
>> +
>> +Then, add the corresponding Makefile entries to `lib/sbi/objects.mk`:
>> +```lang-makefile
>> +...
>> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_string_test.o
>> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
>> +```
>> +
>> +Run `make clean` in order to regenerate the carray-related files, recompile
>> +OpenSBI with CONFIG_SBIUNIT option enabled and run it in the QEMU.
>> +You will see something like this:
>> +```
>> +# make PLATFORM=generic run
>> +...
>> +# Running SBIUNIT tests #
>> +...
>> +## Running test suite: string_test_suite
>> +[PASSED] strlen_test
>> +1 PASSED / 0 FAILED / 1 TOTAL
>> +```
>> +
>> +Now let's try to change this test in the way that it will fail:
>> +
>> +```c
>> +- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
>> ++ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
>> +```
>> +
>> +`make all` and `make run` it again:
>> +```
>> +...
>> +# Running SBIUNIT tests #
>> +...
>> +## Running test suite: string_test_suite
>> +[SBIUnit] [.../opensbi/lib/sbi/sbi_string_test.c:6]: strlen_test: Condition
>> +"(sbi_strlen("Hello")) == (100)" expected to be true!
> 
> If the test will output the above all on one line, then the document
> should also use a single line even though it will exceed 80 chars.
> 
>> +[FAILED] strlen_test
>> +0 PASSED / 1 FAILED / 1 TOTAL
>> +```
>> +Covering the static functions / using the static definitions
>> +------------------------------------------------------------
>> +
>> +SBIUnit also allows you to test static functions. In order to do so, simply
>> +include your test source in the file you would like to test. Complementing the
>> +example above, just add this to the
>> +`lib/sbi/sbi_string.c` file:
>> +
>> +```c
>> +#ifdef CONFIG_SBIUNIT
>> +#include "sbi_string_test.c"
>> +#endif
>> +```
>> +
>> +In this case you should only add a new carray entry pointing to the test suite
>> +to `lib/sbi/objects.mk`:
>> +```lang-makefile
>> +...
>> +carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
>> +```
>> +
>> +You don't have to compile the `sbi_string_test.o` separately, because the
>> +test code will be included into the `sbi_string` object file.
>> +
>> +See example in `lib/sbi/sbi_console_test.c`, where statically declared
>> +`console_dev` variable is used to mock the `sbi_console_device` structure.
>> +
>> +"Mocking" the structures
>> +------------------------
>> +See the example of structure "mocking" in the `lib/sbi/sbi_console_test.c`,
>> +where the sbi_console_device structure was mocked to be used in various
>> +console-related functions in order to test them.
>> +
>> +API Reference
>> +-------------
>> +All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the
>> +corresponding conditions are not met, however, the execution of a particular
>> +test case will not be stopped.
>> +
>> +All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop
>> +immediately, triggering the panic.
> 
> s/the panic/a panic/
> 
>> -- 
>> 2.34.1
>>
> 
> Other than the nits,
> 

Hi Andrew,

Thank you so much for the review. I'll make the suggested changes and 
send the V3.

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Wed Feb 28 08:12:13 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 16:12:13 +0000
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240228-3b952164f9b56135e30a6282@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
 <20240228-3b952164f9b56135e30a6282@orel>
Message-ID: <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>

On 2/28/24 14:19, Andrew Jones wrote:

>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#ifdef CONFIG_SBIUNIT
>> +#ifndef __SBI_UNIT_H__
>> +#define __SBI_UNIT_H__
>> +
>> +#include <sbi/sbi_types.h>
>> +#include <sbi/sbi_console.h>
>> +#include <sbi/sbi_string.h>
>> +
>> +struct sbiunit_test_case {
>> +	const char *name;
>> +	bool enabled;
>> +	bool failed;
>> +	void (*test_func)(struct sbiunit_test_case *test);
>> +	void (*onerr)(struct sbiunit_test_case *test);
> 
> Please rename to on_error()
> 

Hmm, it looks like this 'onerr' is not used anywhere, so I'll just get 
rid of it in the V3.

>> +};
>> +
>> +struct sbiunit_test_suite {
>> +	const char *name;
>> +	struct sbiunit_test_case *cases;
>> +};
>> +
>> +#define SBIUNIT_TEST_CASE(func)		\
>> +	{				\
>> +		.name = #func,		\
>> +		.enabled = true,	\
>> +		.failed = false,	\
>> +		.test_func = (func)	\
>> +	}
>> +
>> +#define SBIUNIT_TEST_SUITE(suite_name, cases_arr)		\
>> +	struct sbiunit_test_suite suite_name = {		\
>> +		.name = #suite_name,				\
>> +		.cases = cases_arr				\
>> +	}
>> +
>> +#define _sbiunit_msg(test, msg) "[SBIUnit] [%s:%d]: %s: %s", __FILE__,	\
>> +				__LINE__, test->name, msg
>> +
>> +#define SBIUNIT_INFO(test, msg) sbi_printf(_sbiunit_msg(test, msg))
>> +#define SBIUNIT_PANIC(test, msg) sbi_panic(_sbiunit_msg(test, msg))
>> +
>> +#define SBIUNIT_EXPECT(test, cond) do {							\
>> +	if (!(cond)) {									\
>> +		test->failed = true;							\
>> +		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
>> +	}										\
>> +} while (0)
>> +
>> +#define SBIUNIT_ASSERT(test, cond) do {						\
>> +	if (!(cond)) {								\
>> +		test->failed = true;						\
> 
> No need to set failed since the next line calls panic.
> 

Yeah, I agree.

>> +		SBIUNIT_PANIC(test, "Condition \"" #cond "\" must be true!\n");	\
>> +	}									\
>> +} while (0)
>> +
>> +#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))
>> +#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, (a) == (b))
>> +#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, (a) != (b))
>> +#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, (a) != (b))
>> +#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_memcmp(a, b, len))
>> +#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_memcmp(a, b, len))
>> +#define SBIUNIT_EXPECT_STREQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_strncmp(a, b, len))
>> +#define SBIUNIT_ASSERT_STREQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_strncmp(a, b, len))
>> +
>> +void run_all_tests(void);
>> +#endif
>> +#else
>> +#define run_all_tests()
>> +#endif
>> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
>> index 81dd2db..e3038ee 100644
>> --- a/lib/sbi/Kconfig
>> +++ b/lib/sbi/Kconfig
>> @@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
>>   	bool "Debug Trigger Extension"
>>   	default y
>>   
>> +config SBIUNIT
>> +	bool "Enable SBIUNIT tests"
>> +	default n
>> +
>>   endmenu
>> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
>> index 0a50e95..08959f1 100644
>> --- a/lib/sbi/objects.mk
>> +++ b/lib/sbi/objects.mk
>> @@ -11,6 +11,8 @@ libsbi-objs-y += riscv_asm.o
>>   libsbi-objs-y += riscv_atomic.o
>>   libsbi-objs-y += riscv_hardfp.o
>>   libsbi-objs-y += riscv_locks.o
>> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_test.o
>> +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
>>   
>>   libsbi-objs-y += sbi_ecall.o
>>   libsbi-objs-y += sbi_ecall_exts.o
>> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
>> index 804b01c..796cccc 100644
>> --- a/lib/sbi/sbi_init.c
>> +++ b/lib/sbi/sbi_init.c
>> @@ -29,6 +29,7 @@
>>   #include <sbi/sbi_timer.h>
>>   #include <sbi/sbi_tlb.h>
>>   #include <sbi/sbi_version.h>
>> +#include <sbi/sbi_unit_test.h>
>>   
>>   #define BANNER                                              \
>>   	"   ____                    _____ ____ _____\n"     \
>> @@ -398,6 +399,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>>   
>>   	sbi_boot_print_hart(scratch, hartid);
>>   
>> +	run_all_tests();
>> +
>>   	/*
>>   	 * Configure PMP at last because if SMEPMP is detected,
>>   	 * M-mode access to the S/U space will be rescinded.
>> diff --git a/lib/sbi/sbi_unit_test.c b/lib/sbi/sbi_unit_test.c
>> new file mode 100644
>> index 0000000..f4988d8
>> --- /dev/null
>> +++ b/lib/sbi/sbi_unit_test.c
>> @@ -0,0 +1,43 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> + */
>> +#include <sbi/sbi_unit_test.h>
>> +#include <sbi/sbi_types.h>
>> +#include <sbi/sbi_console.h>
>> +
>> +extern struct sbiunit_test_suite *sbi_unit_tests[];
>> +extern unsigned long sbi_unit_tests_size;
>> +
>> +static void run_test_suite(struct sbiunit_test_suite *suite)
>> +{
>> +	struct sbiunit_test_case *s_case;
>> +	u32 count_pass = 0, count_fail = 0;
>> +
>> +	sbi_printf("## Running test suite: %s\n", suite->name);
>> +
>> +	s_case = suite->cases;
>> +	while (s_case->enabled) {
> 
> Can't test cases be enabled/disabled sparsely? Shouldn't we instead
> loop while s_case->name is not NULL? And we need to ensure the cases
> array always has an empty case at the end.
> 

They can't be enabled/disabled separately at the moment, but I believe 
it would be good to have such a functionality in the future, when we 
have more tests. Also, I reckon we should be able to iterate and execute 
the test even if it has no name: technically it doesn't mean that the 
test is invalid, and breaking the tests execution completely in this 
case would be pretty implicit and non-obvious for the test developer...

Thank you for the review!

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Wed Feb 28 08:18:28 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 16:18:28 +0000
Subject: [PATCH v2 3/5] Makefile: clean '.c' files generated by carray
In-Reply-To: <20240228-0575feceddadf1436bb41adb@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-4-ivan.orlov0322@gmail.com>
 <20240228-0575feceddadf1436bb41adb@orel>
Message-ID: <bc2028de-64ee-44cc-a85e-b13c5c6a607c@gmail.com>

On 2/28/24 14:23, Andrew Jones wrote:
> On Thu, Feb 15, 2024 at 04:16:23PM +0000, Ivan Orlov wrote:
>> `make clean` doesn't clear the '*.c' files generated by carray.sh
>> in the 'build' directory. Fix it by extending the 'clean' makefile
>> target.
>>
>> This is the only way we are able to regenerate the carray .c file in
>> case if we add a new test to the 'carray-sbi_unit_tests-y' Makefile
>> variable. However, running `make clear` every time we add a new test
>> is not really convenient, so the mechanics should be changed in the
>> future.
>>
>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>> ---
>>   Makefile | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/Makefile b/Makefile
>> index 680c19a..4519277 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -684,6 +684,8 @@ clean:
>>   	$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
>>   	$(if $(V), @echo " RM        $(build_dir)/*.dtb")
>>   	$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
>> +	$(if $(V), @echo " RM        $(build_dir)/*.c")
>> +	$(CMD_PREFIX)find $(build_dir) -type f -name "*.c" -exec rm -rf {} +
> 
> I realize these *.c files are in $build_dir, so they're supposed to be
> generated files, but it still looks scary to remove source files. I
> think we should try to be more specific. Maybe we should put all generated
> source files in directories named 'generated' or something and then only
> remove files in those directories.
> 

Hmm, maybe it would be better to do this in the separate patch series? I 
was thinking about upgrading carrays in general: now the generated .c 
files don't get updated when we change the corresponding Makefile 
variable. It produces inconvenience and these variables should be 
tracked somehow.

For instance, we could possibly move the carray entries to the separate 
files instead of keeping them in the Makefile variables: this way they 
will be tracked by 'make'.

-- 
Kind regards,
Ivan Orlov



From ajones at ventanamicro.com  Wed Feb 28 08:30:45 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 17:30:45 +0100
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
 <20240228-3b952164f9b56135e30a6282@orel>
 <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>
Message-ID: <20240228-15428229b0969d4d57210313@orel>

On Wed, Feb 28, 2024 at 04:12:13PM +0000, Ivan Orlov wrote:
> On 2/28/24 14:19, Andrew Jones wrote:
> 
> > > + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> > > + */
> > > +#ifdef CONFIG_SBIUNIT
> > > +#ifndef __SBI_UNIT_H__
> > > +#define __SBI_UNIT_H__
> > > +
> > > +#include <sbi/sbi_types.h>
> > > +#include <sbi/sbi_console.h>
> > > +#include <sbi/sbi_string.h>
> > > +
> > > +struct sbiunit_test_case {
> > > +	const char *name;
> > > +	bool enabled;
> > > +	bool failed;
> > > +	void (*test_func)(struct sbiunit_test_case *test);
> > > +	void (*onerr)(struct sbiunit_test_case *test);
> > 
> > Please rename to on_error()
> > 
> 
> Hmm, it looks like this 'onerr' is not used anywhere, so I'll just get rid
> of it in the V3.
> 
> > > +};
> > > +
> > > +struct sbiunit_test_suite {
> > > +	const char *name;
> > > +	struct sbiunit_test_case *cases;
> > > +};
> > > +
> > > +#define SBIUNIT_TEST_CASE(func)		\
> > > +	{				\
> > > +		.name = #func,		\
> > > +		.enabled = true,	\
> > > +		.failed = false,	\
> > > +		.test_func = (func)	\
> > > +	}
> > > +
> > > +#define SBIUNIT_TEST_SUITE(suite_name, cases_arr)		\
> > > +	struct sbiunit_test_suite suite_name = {		\
> > > +		.name = #suite_name,				\
> > > +		.cases = cases_arr				\
> > > +	}
> > > +
> > > +#define _sbiunit_msg(test, msg) "[SBIUnit] [%s:%d]: %s: %s", __FILE__,	\
> > > +				__LINE__, test->name, msg
> > > +
> > > +#define SBIUNIT_INFO(test, msg) sbi_printf(_sbiunit_msg(test, msg))
> > > +#define SBIUNIT_PANIC(test, msg) sbi_panic(_sbiunit_msg(test, msg))
> > > +
> > > +#define SBIUNIT_EXPECT(test, cond) do {							\
> > > +	if (!(cond)) {									\
> > > +		test->failed = true;							\
> > > +		SBIUNIT_INFO(test, "Condition \"" #cond "\" expected to be true!\n");	\
> > > +	}										\
> > > +} while (0)
> > > +
> > > +#define SBIUNIT_ASSERT(test, cond) do {						\
> > > +	if (!(cond)) {								\
> > > +		test->failed = true;						\
> > 
> > No need to set failed since the next line calls panic.
> > 
> 
> Yeah, I agree.
> 
> > > +		SBIUNIT_PANIC(test, "Condition \"" #cond "\" must be true!\n");	\
> > > +	}									\
> > > +} while (0)
> > > +
> > > +#define SBIUNIT_EXPECT_EQ(test, a, b) SBIUNIT_EXPECT(test, (a) == (b))
> > > +#define SBIUNIT_ASSERT_EQ(test, a, b) SBIUNIT_ASSERT(test, (a) == (b))
> > > +#define SBIUNIT_EXPECT_NE(test, a, b) SBIUNIT_EXPECT(test, (a) != (b))
> > > +#define SBIUNIT_ASSERT_NE(test, a, b) SBIUNIT_ASSERT(test, (a) != (b))
> > > +#define SBIUNIT_EXPECT_MEMEQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_memcmp(a, b, len))
> > > +#define SBIUNIT_ASSERT_MEMEQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_memcmp(a, b, len))
> > > +#define SBIUNIT_EXPECT_STREQ(test, a, b, len) SBIUNIT_EXPECT(test, !sbi_strncmp(a, b, len))
> > > +#define SBIUNIT_ASSERT_STREQ(test, a, b, len) SBIUNIT_ASSERT(test, !sbi_strncmp(a, b, len))
> > > +
> > > +void run_all_tests(void);
> > > +#endif
> > > +#else
> > > +#define run_all_tests()
> > > +#endif
> > > diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> > > index 81dd2db..e3038ee 100644
> > > --- a/lib/sbi/Kconfig
> > > +++ b/lib/sbi/Kconfig
> > > @@ -50,4 +50,8 @@ config SBI_ECALL_DBTR
> > >   	bool "Debug Trigger Extension"
> > >   	default y
> > > +config SBIUNIT
> > > +	bool "Enable SBIUNIT tests"
> > > +	default n
> > > +
> > >   endmenu
> > > diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> > > index 0a50e95..08959f1 100644
> > > --- a/lib/sbi/objects.mk
> > > +++ b/lib/sbi/objects.mk
> > > @@ -11,6 +11,8 @@ libsbi-objs-y += riscv_asm.o
> > >   libsbi-objs-y += riscv_atomic.o
> > >   libsbi-objs-y += riscv_hardfp.o
> > >   libsbi-objs-y += riscv_locks.o
> > > +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_test.o
> > > +libsbi-objs-$(CONFIG_SBIUNIT) += sbi_unit_tests.o
> > >   libsbi-objs-y += sbi_ecall.o
> > >   libsbi-objs-y += sbi_ecall_exts.o
> > > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> > > index 804b01c..796cccc 100644
> > > --- a/lib/sbi/sbi_init.c
> > > +++ b/lib/sbi/sbi_init.c
> > > @@ -29,6 +29,7 @@
> > >   #include <sbi/sbi_timer.h>
> > >   #include <sbi/sbi_tlb.h>
> > >   #include <sbi/sbi_version.h>
> > > +#include <sbi/sbi_unit_test.h>
> > >   #define BANNER                                              \
> > >   	"   ____                    _____ ____ _____\n"     \
> > > @@ -398,6 +399,8 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
> > >   	sbi_boot_print_hart(scratch, hartid);
> > > +	run_all_tests();
> > > +
> > >   	/*
> > >   	 * Configure PMP at last because if SMEPMP is detected,
> > >   	 * M-mode access to the S/U space will be rescinded.
> > > diff --git a/lib/sbi/sbi_unit_test.c b/lib/sbi/sbi_unit_test.c
> > > new file mode 100644
> > > index 0000000..f4988d8
> > > --- /dev/null
> > > +++ b/lib/sbi/sbi_unit_test.c
> > > @@ -0,0 +1,43 @@
> > > +/*
> > > + * SPDX-License-Identifier: BSD-2-Clause
> > > + *
> > > + * Author: Ivan Orlov <ivan.orlov0322 at gmail.com>
> > > + */
> > > +#include <sbi/sbi_unit_test.h>
> > > +#include <sbi/sbi_types.h>
> > > +#include <sbi/sbi_console.h>
> > > +
> > > +extern struct sbiunit_test_suite *sbi_unit_tests[];
> > > +extern unsigned long sbi_unit_tests_size;
> > > +
> > > +static void run_test_suite(struct sbiunit_test_suite *suite)
> > > +{
> > > +	struct sbiunit_test_case *s_case;
> > > +	u32 count_pass = 0, count_fail = 0;
> > > +
> > > +	sbi_printf("## Running test suite: %s\n", suite->name);
> > > +
> > > +	s_case = suite->cases;
> > > +	while (s_case->enabled) {
> > 
> > Can't test cases be enabled/disabled sparsely? Shouldn't we instead
> > loop while s_case->name is not NULL? And we need to ensure the cases
> > array always has an empty case at the end.
> > 
> 
> They can't be enabled/disabled separately at the moment, but I believe it
> would be good to have such a functionality in the future, when we have more
> tests. Also, I reckon we should be able to iterate and execute the test even
> if it has no name: technically it doesn't mean that the test is invalid, and
> breaking the tests execution completely in this case would be pretty
> implicit and non-obvious for the test developer...

If a no-name test is OK, then the stop condition should be
s_case->test_func being NULL.

Thanks,
drew

> 
> Thank you for the review!
> 
> -- 
> Kind regards,
> Ivan Orlov
> 


From ajones at ventanamicro.com  Wed Feb 28 08:32:52 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 17:32:52 +0100
Subject: [PATCH v2 3/5] Makefile: clean '.c' files generated by carray
In-Reply-To: <bc2028de-64ee-44cc-a85e-b13c5c6a607c@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-4-ivan.orlov0322@gmail.com>
 <20240228-0575feceddadf1436bb41adb@orel>
 <bc2028de-64ee-44cc-a85e-b13c5c6a607c@gmail.com>
Message-ID: <20240228-c0c64e4ec284507123a5aada@orel>

On Wed, Feb 28, 2024 at 04:18:28PM +0000, Ivan Orlov wrote:
> On 2/28/24 14:23, Andrew Jones wrote:
> > On Thu, Feb 15, 2024 at 04:16:23PM +0000, Ivan Orlov wrote:
> > > `make clean` doesn't clear the '*.c' files generated by carray.sh
> > > in the 'build' directory. Fix it by extending the 'clean' makefile
> > > target.
> > > 
> > > This is the only way we are able to regenerate the carray .c file in
> > > case if we add a new test to the 'carray-sbi_unit_tests-y' Makefile
> > > variable. However, running `make clear` every time we add a new test
> > > is not really convenient, so the mechanics should be changed in the
> > > future.
> > > 
> > > Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
> > > ---
> > >   Makefile | 2 ++
> > >   1 file changed, 2 insertions(+)
> > > 
> > > diff --git a/Makefile b/Makefile
> > > index 680c19a..4519277 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -684,6 +684,8 @@ clean:
> > >   	$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
> > >   	$(if $(V), @echo " RM        $(build_dir)/*.dtb")
> > >   	$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
> > > +	$(if $(V), @echo " RM        $(build_dir)/*.c")
> > > +	$(CMD_PREFIX)find $(build_dir) -type f -name "*.c" -exec rm -rf {} +
> > 
> > I realize these *.c files are in $build_dir, so they're supposed to be
> > generated files, but it still looks scary to remove source files. I
> > think we should try to be more specific. Maybe we should put all generated
> > source files in directories named 'generated' or something and then only
> > remove files in those directories.
> > 
> 
> Hmm, maybe it would be better to do this in the separate patch series? I was
> thinking about upgrading carrays in general: now the generated .c files
> don't get updated when we change the corresponding Makefile variable. It
> produces inconvenience and these variables should be tracked somehow.

Yes, a separate series is a good idea. For this series, I'd just make the
new carrays behave like the rest, even if that behavior isn't ideal.

Thanks,
drew

> 
> For instance, we could possibly move the carray entries to the separate
> files instead of keeping them in the Makefile variables: this way they will
> be tracked by 'make'.
> 
> -- 
> Kind regards,
> Ivan Orlov
> 


From ivan.orlov0322 at gmail.com  Wed Feb 28 08:43:59 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 16:43:59 +0000
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240228-15428229b0969d4d57210313@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
 <20240228-3b952164f9b56135e30a6282@orel>
 <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>
 <20240228-15428229b0969d4d57210313@orel>
Message-ID: <5169c824-531c-4520-b211-466fda16b529@gmail.com>

On 2/28/24 16:30, Andrew Jones wrote:

> If a no-name test is OK, then the stop condition should be
> s_case->test_func being NULL.
> 

Yeah, I guess we can check the test_func. Thanks!

Also, I believe it would be good to mention that we need the last test 
cases array entry to be empty in the documentation, so it will be more 
explicit for a developer. I'll do that in the V3 if it is OK with you.

-- 
Kind regards,
Ivan Orlov



From ivan.orlov0322 at gmail.com  Wed Feb 28 08:52:06 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 16:52:06 +0000
Subject: [PATCH v2 3/5] Makefile: clean '.c' files generated by carray
In-Reply-To: <20240228-c0c64e4ec284507123a5aada@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-4-ivan.orlov0322@gmail.com>
 <20240228-0575feceddadf1436bb41adb@orel>
 <bc2028de-64ee-44cc-a85e-b13c5c6a607c@gmail.com>
 <20240228-c0c64e4ec284507123a5aada@orel>
Message-ID: <bccf0f66-41e1-4439-b44c-7bff669e0d60@gmail.com>

On 2/28/24 16:32, Andrew Jones wrote:
> On Wed, Feb 28, 2024 at 04:18:28PM +0000, Ivan Orlov wrote:
>> On 2/28/24 14:23, Andrew Jones wrote:
>>> On Thu, Feb 15, 2024 at 04:16:23PM +0000, Ivan Orlov wrote:
>>>> `make clean` doesn't clear the '*.c' files generated by carray.sh
>>>> in the 'build' directory. Fix it by extending the 'clean' makefile
>>>> target.
>>>>
>>>> This is the only way we are able to regenerate the carray .c file in
>>>> case if we add a new test to the 'carray-sbi_unit_tests-y' Makefile
>>>> variable. However, running `make clear` every time we add a new test
>>>> is not really convenient, so the mechanics should be changed in the
>>>> future.
>>>>
>>>> Signed-off-by: Ivan Orlov <ivan.orlov0322 at gmail.com>
>>>> ---
>>>>    Makefile | 2 ++
>>>>    1 file changed, 2 insertions(+)
>>>>
>>>> diff --git a/Makefile b/Makefile
>>>> index 680c19a..4519277 100644
>>>> --- a/Makefile
>>>> +++ b/Makefile
>>>> @@ -684,6 +684,8 @@ clean:
>>>>    	$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
>>>>    	$(if $(V), @echo " RM        $(build_dir)/*.dtb")
>>>>    	$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
>>>> +	$(if $(V), @echo " RM        $(build_dir)/*.c")
>>>> +	$(CMD_PREFIX)find $(build_dir) -type f -name "*.c" -exec rm -rf {} +
>>>
>>> I realize these *.c files are in $build_dir, so they're supposed to be
>>> generated files, but it still looks scary to remove source files. I
>>> think we should try to be more specific. Maybe we should put all generated
>>> source files in directories named 'generated' or something and then only
>>> remove files in those directories.
>>>
>>
>> Hmm, maybe it would be better to do this in the separate patch series? I was
>> thinking about upgrading carrays in general: now the generated .c files
>> don't get updated when we change the corresponding Makefile variable. It
>> produces inconvenience and these variables should be tracked somehow.
> 
> Yes, a separate series is a good idea. For this series, I'd just make the
> new carrays behave like the rest, even if that behavior isn't ideal.
> 

Alright, then I'll drop this patch by now and mention in the docs that 
you may need to manually remove autogenerated .c files in order to make 
the new test work.

Thanks!

-- 
Kind regards,
Ivan Orlov



From ajones at ventanamicro.com  Wed Feb 28 09:00:15 2024
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 28 Feb 2024 18:00:15 +0100
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <5169c824-531c-4520-b211-466fda16b529@gmail.com>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
 <20240228-3b952164f9b56135e30a6282@orel>
 <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>
 <20240228-15428229b0969d4d57210313@orel>
 <5169c824-531c-4520-b211-466fda16b529@gmail.com>
Message-ID: <20240228-b8e4253e844b44a4d90e92d5@orel>

On Wed, Feb 28, 2024 at 04:43:59PM +0000, Ivan Orlov wrote:
> On 2/28/24 16:30, Andrew Jones wrote:
> 
> > If a no-name test is OK, then the stop condition should be
> > s_case->test_func being NULL.
> > 
> 
> Yeah, I guess we can check the test_func. Thanks!
> 
> Also, I believe it would be good to mention that we need the last test cases
> array entry to be empty in the documentation, so it will be more explicit
> for a developer. I'll do that in the V3 if it is OK with you.
>

Sure. You can define an 'END_CASE = { }' type of macro and put it in the
document's code examples. That'd probably be enough, but you could also
add a sentence to explicitly state it's required too.

Thanks,
drew


From ivan.orlov0322 at gmail.com  Wed Feb 28 09:10:11 2024
From: ivan.orlov0322 at gmail.com (Ivan Orlov)
Date: Wed, 28 Feb 2024 17:10:11 +0000
Subject: [PATCH v2 2/5] lib: Add SBIUnit testing macros and functions
In-Reply-To: <20240228-b8e4253e844b44a4d90e92d5@orel>
References: <20240215161625.314131-1-ivan.orlov0322@gmail.com>
 <20240215161625.314131-3-ivan.orlov0322@gmail.com>
 <20240228-3b952164f9b56135e30a6282@orel>
 <2e16bf64-ea2b-4063-91f1-fc08b827559b@gmail.com>
 <20240228-15428229b0969d4d57210313@orel>
 <5169c824-531c-4520-b211-466fda16b529@gmail.com>
 <20240228-b8e4253e844b44a4d90e92d5@orel>
Message-ID: <c94a2fa5-f1c5-4002-8176-dac9bc194023@gmail.com>

On 2/28/24 17:00, Andrew Jones wrote:
> On Wed, Feb 28, 2024 at 04:43:59PM +0000, Ivan Orlov wrote:
>> On 2/28/24 16:30, Andrew Jones wrote:
>>
>>> If a no-name test is OK, then the stop condition should be
>>> s_case->test_func being NULL.
>>>
>>
>> Yeah, I guess we can check the test_func. Thanks!
>>
>> Also, I believe it would be good to mention that we need the last test cases
>> array entry to be empty in the documentation, so it will be more explicit
>> for a developer. I'll do that in the V3 if it is OK with you.
>>
> 
> Sure. You can define an 'END_CASE = { }' type of macro and put it in the
> document's code examples. That'd probably be enough, but you could also
> add a sentence to explicitly state it's required too.
> 

Great, thanks! Perhaps I could define it as SBIUNIT_END_CASE macro and 
use in other tests as well.
-- 
Kind regards,
Ivan Orlov



From wxjstz at 126.com  Wed Feb 28 18:36:47 2024
From: wxjstz at 126.com (Xiang W)
Date: Thu, 29 Feb 2024 10:36:47 +0800
Subject: [PATCH] lib: sbi_domain: Fix PMP condition for addresses
In-Reply-To: <20240227200743.22661-1-cmax@mailbox.org>
References: <20240227200743.22661-1-cmax@mailbox.org>
Message-ID: <272de5922603af4a3080eba37b2368bb8b3ead64.camel@126.com>

? 2024-02-27???? 21:07 +0100?cmax at mailbox.org???
> From: max <cmax at mailbox.org>
> 
> In order to put an address/size into an NAPOT PMP region, the address
> needs to be aligned to the size shifted two to the right.
The address that needs to be aligned is
scratch->fw_start
scratch->fw_start + scratch->fw_rw_offset

Regards,
Xiang W

> 
> Example:
> fw_start: 0x80040000
> fw_size:? 0x00040000
> PMP address: 0x80040000 | (0x00040000 >> 2)
> fw_size is valid, but not in the current implementation
> 
> Signed-off-by: max <cmax at mailbox.org>
> ---
> ?lib/sbi/sbi_domain.c | 2 +-
> ?1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
> index 4e9f742..94ee717 100644
> --- a/lib/sbi/sbi_domain.c
> +++ b/lib/sbi/sbi_domain.c
> @@ -749,7 +749,7 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
> ?		return SBI_EINVAL;
> ?	}
> ?
> -	if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
> +	if ((scratch->fw_start & ((scratch->fw_rw_offset >> 2) - 1)) != 0) {
> ?		sbi_printf("%s: fw_start and fw_rw_offset not aligned\n",
> ?			?? __func__);
> ?		return SBI_EINVAL;
> -- 
> 2.43.0
> 
> 



From cmax at mailbox.org  Thu Feb 29 08:02:17 2024
From: cmax at mailbox.org (cmax at mailbox.org)
Date: Thu, 29 Feb 2024 17:02:17 +0100
Subject: [PATCH v2] lib: sbi_domain: Fix PMP condition for addresses
In-Reply-To: <272de5922603af4a3080eba37b2368bb8b3ead64.camel@126.com>
References: <272de5922603af4a3080eba37b2368bb8b3ead64.camel@126.com>
Message-ID: <20240229160432.6230-1-cmax@mailbox.org>

From: max <cmax at mailbox.org>

In order to put an address/size into an NAPOT PMP region, the fw_start
address needs to be aligned to the fw_rw_offset. Since the PMP address
is already aligned to 4 byte by design, we have two more bits available.

Example:
fw_start: 0x80040000
fw_rw_offset:  0x00040000
PMP address: 0x80040000 | (0x00040000 >> 2)
fw_rw_offset is valid, but not in the current implementation

Signed-off-by: max <cmax at mailbox.org>
---
I updated to commit-msg to be more clear. I hope that clears it up.
This is my first email patch, so I probably made some mistakes.

kind regards,
Max

 lib/sbi/sbi_domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index 4e9f742..94ee717 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -749,7 +749,7 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
 		return SBI_EINVAL;
 	}
 
-	if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) {
+	if ((scratch->fw_start & ((scratch->fw_rw_offset >> 2) - 1)) != 0) {
 		sbi_printf("%s: fw_start and fw_rw_offset not aligned\n",
 			   __func__);
 		return SBI_EINVAL;
-- 
2.44.0



