From alvinga at andestech.com  Thu Jul  3 08:19:56 2025
From: alvinga at andestech.com (Alvin Chang)
Date: Thu, 3 Jul 2025 23:19:56 +0800
Subject: [PATCH v3 1/2] lib: sbi: Remove redundant call to sbi_hart_expected_trap_addr()
In-Reply-To: <20250703151957.2545958-1-alvinga@andestech.com>
References: <20250703151957.2545958-1-alvinga@andestech.com>
Message-ID: <20250703151957.2545958-2-alvinga@andestech.com>

The variable "sbi_hart_expected_trap" has already been extern variable.
Therefore, the program can directly refer to it instead of calling
sbi_hart_expected_trap_addr().

Signed-off-by: Alvin Chang <alvinga at andestech.com>
---
 include/sbi/sbi_csr_detect.h | 4 ++--
 include/sbi/sbi_hart.h       | 4 ----
 lib/sbi/sbi_illegal_atomic.c | 4 ++--
 lib/sbi/sbi_unpriv.c         | 6 +++---
 4 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/include/sbi/sbi_csr_detect.h b/include/sbi/sbi_csr_detect.h
index 89ba294..097c31c 100644
--- a/include/sbi/sbi_csr_detect.h
+++ b/include/sbi/sbi_csr_detect.h
@@ -18,7 +18,7 @@
 	({								\
 	register ulong tinfo asm("a3") = (ulong)trap;			\
 	register ulong ttmp asm("a4");					\
-	register ulong mtvec = sbi_hart_expected_trap_addr();		\
+	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 	register ulong ret = 0;						\
 	((struct sbi_trap_info *)(trap))->cause = 0;			\
 	asm volatile(							\
@@ -37,7 +37,7 @@
 	({								\
 	register ulong tinfo asm("a3") = (ulong)trap;			\
 	register ulong ttmp asm("a4");					\
-	register ulong mtvec = sbi_hart_expected_trap_addr();		\
+	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 	((struct sbi_trap_info *)(trap))->cause = 0;			\
 	asm volatile(							\
 		"add %[ttmp], %[tinfo], zero\n"				\
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index dfbe8e4..82b19dc 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -134,10 +134,6 @@ int sbi_hart_reinit(struct sbi_scratch *scratch);
 int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
 
 extern void (*sbi_hart_expected_trap)(void);
-static inline ulong sbi_hart_expected_trap_addr(void)
-{
-	return (ulong)sbi_hart_expected_trap;
-}
 
 unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
 void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
diff --git a/lib/sbi/sbi_illegal_atomic.c b/lib/sbi/sbi_illegal_atomic.c
index 2161b23..8fd6c55 100644
--- a/lib/sbi/sbi_illegal_atomic.c
+++ b/lib/sbi/sbi_illegal_atomic.c
@@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
 	{									\
 		register ulong tinfo asm("a3");					\
 		register ulong mstatus = 0;					\
-		register ulong mtvec = sbi_hart_expected_trap_addr();		\
+		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 		type ret = 0;							\
 		trap->cause = 0;						\
 		asm volatile(							\
@@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
 	{									\
 		register ulong tinfo asm("a3");					\
 		register ulong mstatus = 0;					\
-		register ulong mtvec = sbi_hart_expected_trap_addr();		\
+		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 		type ret = 0;							\
 		trap->cause = 0;						\
 		asm volatile(							\
diff --git a/lib/sbi/sbi_unpriv.c b/lib/sbi/sbi_unpriv.c
index 2a55d9d..f9bbec5 100644
--- a/lib/sbi/sbi_unpriv.c
+++ b/lib/sbi/sbi_unpriv.c
@@ -24,7 +24,7 @@
 	{                                                                     \
 		register ulong tinfo asm("a3");                               \
 		register ulong mstatus = 0;                                   \
-		register ulong mtvec = sbi_hart_expected_trap_addr();         \
+		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
 		type ret = 0;                                                 \
 		trap->cause = 0;                                              \
 		asm volatile(                                                 \
@@ -51,7 +51,7 @@
 	{                                                                     \
 		register ulong tinfo asm("a3") = (ulong)trap;                 \
 		register ulong mstatus = 0;                                   \
-		register ulong mtvec = sbi_hart_expected_trap_addr();         \
+		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
 		trap->cause = 0;                                              \
 		asm volatile(                                                 \
 			"add %[tinfo], %[taddr], zero\n"                      \
@@ -121,7 +121,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
 	register ulong tinfo asm("a3");
 	register ulong ttmp asm("a4");
 	register ulong mstatus = 0;
-	register ulong mtvec = sbi_hart_expected_trap_addr();
+	register ulong mtvec = (ulong)sbi_hart_expected_trap;
 	ulong insn = 0;
 
 	trap->cause = 0;
-- 
2.43.0



From alvinga at andestech.com  Thu Jul  3 08:19:55 2025
From: alvinga at andestech.com (Alvin Chang)
Date: Thu, 3 Jul 2025 23:19:55 +0800
Subject: [PATCH v3 0/2] firmware: Initial compiler built-in stack protector support
Message-ID: <20250703151957.2545958-1-alvinga@andestech.com>

This series add initial compiler built-in stack protector support into OpenSBI
firmware. The __stack_chk_fail() and __stack_chk_guard variable are added into
firmware assembly files accordingly.

Introduce three Kconfig configurations to enable the stack protector:
1. CONFIG_STACK_PROTECTOR to enable the stack protector feature by
   providing "-fstack-protector" compiler flag
2. CONFIG_STACK_PROTECTOR_STRONG to provide "-fstack-protector-strong"
3. CONFIG_STACK_PROTECTOR_ALL to provide "-fstack-protector-all"

---
Changes from v2
- Adopt Xiang's suggestion on __stack_chk_fail in fw_payload.bin
- Adopt Peter's suggestion to print error message

Changes from v1
- Fix boot hang when compiling with DEBUG=1 and -fstack-protector-all
- Move implementation to firmware

Alvin Chang (2):
  lib: sbi: Remove redundant call to sbi_hart_expected_trap_addr()
  firmware: Initial compiler built-in stack protector support

 firmware/Kconfig              | 27 +++++++++++++++++++++++++++
 firmware/fw_base.S            | 21 +++++++++++++++++++++
 firmware/objects.mk           |  9 +++++++++
 firmware/payloads/test_head.S | 15 +++++++++++++++
 include/sbi/sbi_csr_detect.h  |  4 ++--
 include/sbi/sbi_hart.h        |  4 ----
 lib/sbi/sbi_illegal_atomic.c  |  4 ++--
 lib/sbi/sbi_unpriv.c          |  6 +++---
 8 files changed, 79 insertions(+), 11 deletions(-)

-- 
2.43.0



From alvinga at andestech.com  Thu Jul  3 08:19:57 2025
From: alvinga at andestech.com (Alvin Chang)
Date: Thu, 3 Jul 2025 23:19:57 +0800
Subject: [PATCH v3 2/2] firmware: Initial compiler built-in stack protector support
In-Reply-To: <20250703151957.2545958-1-alvinga@andestech.com>
References: <20250703151957.2545958-1-alvinga@andestech.com>
Message-ID: <20250703151957.2545958-3-alvinga@andestech.com>

Add __stack_chk_fail() and __stack_chk_guard variable which are used by
compiler built-in stack protector.

This patch just try to support stack-protector so the value of the stack
guard variable is simply fixed for now. It could be improved by
deriving from a random number generator, such as Zkr extension or any
platform-specific random number sources.

Introduce three configurations for the stack protector:
1. CONFIG_STACK_PROTECTOR to enable the stack protector feature by
   providing "-fstack-protector" compiler flag
2. CONFIG_STACK_PROTECTOR_STRONG to provide "-fstack-protector-strong"
3. CONFIG_STACK_PROTECTOR_ALL to provide "-fstack-protector-all"

Instead of fixing the compiler flag of stack-protector feature as
"-fstack-protector", we derive it from the introduced Kconfig
configurations. The compiler flag "stack-protector-cflags-y" is defined
as Makefile "immediately expanded variables" with ":=". Thus, the
stronger configuration of the stack protector can overwrite the
preceding one.

Signed-off-by: Alvin Chang <alvinga at andestech.com>
---
 firmware/Kconfig              | 27 +++++++++++++++++++++++++++
 firmware/fw_base.S            | 21 +++++++++++++++++++++
 firmware/objects.mk           |  9 +++++++++
 firmware/payloads/test_head.S | 15 +++++++++++++++
 4 files changed, 72 insertions(+)

diff --git a/firmware/Kconfig b/firmware/Kconfig
index d6e0506..c1fee19 100644
--- a/firmware/Kconfig
+++ b/firmware/Kconfig
@@ -1 +1,28 @@
 # SPDX-License-Identifier: BSD-2-Clause
+
+menu "Stack Protector Support"
+
+config STACK_PROTECTOR
+	bool "Stack Protector buffer overflow detection"
+	default n
+	help
+	  This option turns on the "stack-protector" compiler feature.
+
+config STACK_PROTECTOR_STRONG
+	bool "Strong Stack Protector"
+	depends on STACK_PROTECTOR
+	default n
+	help
+	  Turn on the "stack-protector" with "-fstack-protector-strong" option.
+	  Like -fstack-protector but includes additional functions to be
+	  protected.
+
+config STACK_PROTECTOR_ALL
+	bool "Almighty Stack Protector"
+	depends on STACK_PROTECTOR
+	default n
+	help
+	  Turn on the "stack-protector" with "-fstack-protector-all" option.
+	  Like -fstack-protector except that all functions are protected.
+
+endmenu
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 2498797..a008fa7 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -736,6 +736,27 @@ _reset_regs:
 
 	ret
 
+	.section .rodata
+.Lstack_corrupt_msg:
+	.string "stack smashing detected\n"
+
+	/* This will be called when the stack corruption is detected */
+	.section .text
+	.align 3
+	.globl __stack_chk_fail
+	.type __stack_chk_fail, %function
+__stack_chk_fail:
+	la	a0, .Lstack_corrupt_msg
+	call	sbi_panic
+
+	/* Initial value of the stack guard variable */
+	.section .data
+	.align 3
+	.globl __stack_chk_guard
+	.type __stack_chk_guard, %object
+__stack_chk_guard:
+	RISCV_PTR	0x95B5FF5A
+
 #ifdef FW_FDT_PATH
 	.section .rodata
 	.align 4
diff --git a/firmware/objects.mk b/firmware/objects.mk
index a90485d..bfec467 100644
--- a/firmware/objects.mk
+++ b/firmware/objects.mk
@@ -66,3 +66,12 @@ endif
 ifdef FW_OPTIONS
 firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
 endif
+
+ifeq ($(CONFIG_STACK_PROTECTOR),y)
+stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
+stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
+stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
+else
+stack-protector-cflags-y := -fno-stack-protector
+endif
+firmware-cflags-y += $(stack-protector-cflags-y)
diff --git a/firmware/payloads/test_head.S b/firmware/payloads/test_head.S
index 7d25e07..070ce8a 100644
--- a/firmware/payloads/test_head.S
+++ b/firmware/payloads/test_head.S
@@ -97,3 +97,18 @@ _boot_a0:
 	RISCV_PTR	0
 _boot_a1:
 	RISCV_PTR	0
+
+	/* This will be called when the stack corruption is detected */
+	.section .text
+	.align 3
+	.globl __stack_chk_fail
+	.type __stack_chk_fail, %function
+	.equ  __stack_chk_fail, _start_hang
+
+	/* Initial value of the stack guard variable */
+	.section .data
+	.align 3
+	.globl __stack_chk_guard
+	.type __stack_chk_guard, %object
+__stack_chk_guard:
+	RISCV_PTR	0x95B5FF5A
-- 
2.43.0



From peter.lin at sifive.com  Fri Jul  4 03:58:17 2025
From: peter.lin at sifive.com (Peter Lin)
Date: Fri, 4 Jul 2025 18:58:17 +0800
Subject: [PATCH v3 2/2] firmware: Initial compiler built-in stack
 protector support
In-Reply-To: <20250703151957.2545958-3-alvinga@andestech.com>
References: <20250703151957.2545958-1-alvinga@andestech.com> <20250703151957.2545958-3-alvinga@andestech.com>
Message-ID: <CAHZsQ-PXKJLUv-y40OHa+1iVGJXtodJn-y4d9WcL+pSGLSfy3A@mail.gmail.com>

On Thu, Jul 3, 2025 at 11:20?PM Alvin Chang <alvinga at andestech.com> wrote:
>
> Add __stack_chk_fail() and __stack_chk_guard variable which are used by
> compiler built-in stack protector.
>
> This patch just try to support stack-protector so the value of the stack
> guard variable is simply fixed for now. It could be improved by
> deriving from a random number generator, such as Zkr extension or any
> platform-specific random number sources.
>
> Introduce three configurations for the stack protector:
> 1. CONFIG_STACK_PROTECTOR to enable the stack protector feature by
>    providing "-fstack-protector" compiler flag
> 2. CONFIG_STACK_PROTECTOR_STRONG to provide "-fstack-protector-strong"
> 3. CONFIG_STACK_PROTECTOR_ALL to provide "-fstack-protector-all"
>
> Instead of fixing the compiler flag of stack-protector feature as
> "-fstack-protector", we derive it from the introduced Kconfig
> configurations. The compiler flag "stack-protector-cflags-y" is defined
> as Makefile "immediately expanded variables" with ":=". Thus, the
> stronger configuration of the stack protector can overwrite the
> preceding one.
>
> Signed-off-by: Alvin Chang <alvinga at andestech.com>

Reviewed-by: Yu-Chien Peter Lin <peter.lin at sifive.com>

> ---
>  firmware/Kconfig              | 27 +++++++++++++++++++++++++++
>  firmware/fw_base.S            | 21 +++++++++++++++++++++
>  firmware/objects.mk           |  9 +++++++++
>  firmware/payloads/test_head.S | 15 +++++++++++++++
>  4 files changed, 72 insertions(+)
>
> diff --git a/firmware/Kconfig b/firmware/Kconfig
> index d6e0506..c1fee19 100644
> --- a/firmware/Kconfig
> +++ b/firmware/Kconfig
> @@ -1 +1,28 @@
>  # SPDX-License-Identifier: BSD-2-Clause
> +
> +menu "Stack Protector Support"
> +
> +config STACK_PROTECTOR
> +       bool "Stack Protector buffer overflow detection"
> +       default n
> +       help
> +         This option turns on the "stack-protector" compiler feature.
> +
> +config STACK_PROTECTOR_STRONG
> +       bool "Strong Stack Protector"
> +       depends on STACK_PROTECTOR
> +       default n
> +       help
> +         Turn on the "stack-protector" with "-fstack-protector-strong" option.
> +         Like -fstack-protector but includes additional functions to be
> +         protected.
> +
> +config STACK_PROTECTOR_ALL
> +       bool "Almighty Stack Protector"
> +       depends on STACK_PROTECTOR
> +       default n
> +       help
> +         Turn on the "stack-protector" with "-fstack-protector-all" option.
> +         Like -fstack-protector except that all functions are protected.
> +
> +endmenu
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 2498797..a008fa7 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -736,6 +736,27 @@ _reset_regs:
>
>         ret
>
> +       .section .rodata
> +.Lstack_corrupt_msg:
> +       .string "stack smashing detected\n"
> +
> +       /* This will be called when the stack corruption is detected */
> +       .section .text
> +       .align 3
> +       .globl __stack_chk_fail
> +       .type __stack_chk_fail, %function
> +__stack_chk_fail:
> +       la      a0, .Lstack_corrupt_msg
> +       call    sbi_panic
> +
> +       /* Initial value of the stack guard variable */
> +       .section .data
> +       .align 3
> +       .globl __stack_chk_guard
> +       .type __stack_chk_guard, %object
> +__stack_chk_guard:
> +       RISCV_PTR       0x95B5FF5A
> +
>  #ifdef FW_FDT_PATH
>         .section .rodata
>         .align 4
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index a90485d..bfec467 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -66,3 +66,12 @@ endif
>  ifdef FW_OPTIONS
>  firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
>  endif
> +
> +ifeq ($(CONFIG_STACK_PROTECTOR),y)
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
> +else
> +stack-protector-cflags-y := -fno-stack-protector
> +endif
> +firmware-cflags-y += $(stack-protector-cflags-y)
> diff --git a/firmware/payloads/test_head.S b/firmware/payloads/test_head.S
> index 7d25e07..070ce8a 100644
> --- a/firmware/payloads/test_head.S
> +++ b/firmware/payloads/test_head.S
> @@ -97,3 +97,18 @@ _boot_a0:
>         RISCV_PTR       0
>  _boot_a1:
>         RISCV_PTR       0
> +
> +       /* This will be called when the stack corruption is detected */
> +       .section .text
> +       .align 3
> +       .globl __stack_chk_fail
> +       .type __stack_chk_fail, %function
> +       .equ  __stack_chk_fail, _start_hang
> +
> +       /* Initial value of the stack guard variable */
> +       .section .data
> +       .align 3
> +       .globl __stack_chk_guard
> +       .type __stack_chk_guard, %object
> +__stack_chk_guard:
> +       RISCV_PTR       0x95B5FF5A
> --
> 2.43.0
>


From ben.dooks at codethink.co.uk  Fri Jul  4 05:29:38 2025
From: ben.dooks at codethink.co.uk (Ben Dooks)
Date: Fri,  4 Jul 2025 13:29:38 +0100
Subject: [PATCH] include: sbi: fix swap errors with newer gcc -Werror=sequence-point
Message-ID: <20250704122938.897832-1-ben.dooks@codethink.co.uk>

The BSWAPxx() macros are now throwing the following warnings with
newer gcc versions. This is due to throwing an argument in that may
be evaluated more than one (I think) and therefore things like the
example below should be avoided.

Fix by making a set of BSWAPxx() wrappers which specifically onlt
evaluate 'x' once.

In file included lib/sbi/sbi_mpxy.c:21:
lib/sbi/sbi_mpxy.c: In function ?sbi_mpxy_write_attrs?:
ib/sbi/sbi_mpxy.c:632:63: error: operation on ?mem_idx? may be undefined [-Werror=sequence-point]
  632 |                         attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
      |                                                        ~~~~~~~^~

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
 include/sbi/sbi_byteorder.h | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/sbi/sbi_byteorder.h b/include/sbi/sbi_byteorder.h
index 2b4981e..ed7cad1 100644
--- a/include/sbi/sbi_byteorder.h
+++ b/include/sbi/sbi_byteorder.h
@@ -14,13 +14,13 @@
 # define _conv_cast(type, val) ((type)(val))
 #endif
 
-#define BSWAP16(x)	((((x) & 0x00ff) << 8) | \
+#define __BSWAP16(x)	((((x) & 0x00ff) << 8) | \
 			 (((x) & 0xff00) >> 8))
-#define BSWAP32(x)	((((x) & 0x000000ff) << 24) | \
+#define __BSWAP32(x)	((((x) & 0x000000ff) << 24) | \
 			 (((x) & 0x0000ff00) << 8) | \
 			 (((x) & 0x00ff0000) >> 8) | \
 			 (((x) & 0xff000000) >> 24))
-#define BSWAP64(x)	((((x) & 0x00000000000000ffULL) << 56) | \
+#define __BSWAP64(x)	((((x) & 0x00000000000000ffULL) << 56) | \
 			 (((x) & 0x000000000000ff00ULL) << 40) | \
 			 (((x) & 0x0000000000ff0000ULL) << 24) | \
 			 (((x) & 0x00000000ff000000ULL) << 8) | \
@@ -29,6 +29,10 @@
 			 (((x) & 0x00ff000000000000ULL) >> 40) | \
 			 (((x) & 0xff00000000000000ULL) >> 56))
 
+#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
+#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
+#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
+
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* CPU(little-endian) */
 #define cpu_to_be16(x)		_conv_cast(uint16_t, BSWAP16(x))
 #define cpu_to_be32(x)		_conv_cast(uint32_t, BSWAP32(x))
-- 
2.37.2.352.g3c44437643



From wxjstz at 126.com  Mon Jul  7 08:42:29 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 07 Jul 2025 23:42:29 +0800
Subject: [PATCH] include: sbi: fix swap errors with newer gcc
 -Werror=sequence-point
In-Reply-To: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
References: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
Message-ID: <de389e7561ea7ecabfadc0949916fde5763f8afe.camel@126.com>

? 2025-07-04?? 13:29 +0100?Ben Dooks???
> The BSWAPxx() macros are now throwing the following warnings with
> newer gcc versions. This is due to throwing an argument in that may
> be evaluated more than one (I think) and therefore things like the
> example below should be avoided.
> 
> Fix by making a set of BSWAPxx() wrappers which specifically onlt
> evaluate 'x' once.
> 
> In file included lib/sbi/sbi_mpxy.c:21:
> lib/sbi/sbi_mpxy.c: In function ?sbi_mpxy_write_attrs?:
> ib/sbi/sbi_mpxy.c:632:63: error: operation on ?mem_idx? may be undefined [-Werror=sequence-point]
> ? 632 |???????????????????????? attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
> ????? |??????????????????????????????????????????????????????? ~~~~~~~^~
> 
> Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
Look good to me.

Reviewed-by: Xiang W <wxjstz at 126.com>
> ---
> ?include/sbi/sbi_byteorder.h | 10 +++++++---
> ?1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/include/sbi/sbi_byteorder.h b/include/sbi/sbi_byteorder.h
> index 2b4981e..ed7cad1 100644
> --- a/include/sbi/sbi_byteorder.h
> +++ b/include/sbi/sbi_byteorder.h
> @@ -14,13 +14,13 @@
> ?# define _conv_cast(type, val) ((type)(val))
> ?#endif
> ?
> -#define BSWAP16(x)	((((x) & 0x00ff) << 8) | \
> +#define __BSWAP16(x)	((((x) & 0x00ff) << 8) | \
> ?			 (((x) & 0xff00) >> 8))
> -#define BSWAP32(x)	((((x) & 0x000000ff) << 24) | \
> +#define __BSWAP32(x)	((((x) & 0x000000ff) << 24) | \
> ?			 (((x) & 0x0000ff00) << 8) | \
> ?			 (((x) & 0x00ff0000) >> 8) | \
> ?			 (((x) & 0xff000000) >> 24))
> -#define BSWAP64(x)	((((x) & 0x00000000000000ffULL) << 56) | \
> +#define __BSWAP64(x)	((((x) & 0x00000000000000ffULL) << 56) | \
> ?			 (((x) & 0x000000000000ff00ULL) << 40) | \
> ?			 (((x) & 0x0000000000ff0000ULL) << 24) | \
> ?			 (((x) & 0x00000000ff000000ULL) << 8) | \
> @@ -29,6 +29,10 @@
> ?			 (((x) & 0x00ff000000000000ULL) >> 40) | \
> ?			 (((x) & 0xff00000000000000ULL) >> 56))
> ?
> +#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
> +#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
> +#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
> +
> ?#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__? /* CPU(little-endian) */
> ?#define cpu_to_be16(x)		_conv_cast(uint16_t, BSWAP16(x))
> ?#define cpu_to_be32(x)		_conv_cast(uint32_t, BSWAP32(x))
> -- 
> 2.37.2.352.g3c44437643
> 



From nick.hu at sifive.com  Tue Jul  8 00:49:28 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:28 +0800
Subject: [PATCH v3 00/12] Add SiFive TMC0 and SMC0 driver
Message-ID: <20250708074940.10904-1-nick.hu@sifive.com>

The previous version can be found in [1].

SiFive TMC0 and SMC0 are the power controllers that controls the Tile and
CoreComplex power domain. Add the drivers to support the power
management features such as HSM STOP and System Suspend.

Some features, such as power management, may require flushing the entire
cache before entering a non-retention power state. To support this, a
simple cache framework is introduced to allow the external CMO to
perform a full cache flush.

Changes in v3:
- Add the SiFive TMC and SMC driver

Changes in v2:
- Since the platform override hooks was deprecated, use the fdt_driver
for initializing the sifive_dev_platform.

Links:
- [1] https://lore.kernel.org/opensbi/20250424034003.28522-1-nick.hu at sifive.com/

Nick Hu (10):
  lib: utils: Add cache flush library
  lib: utils: Add FDT cache library
  lib: utils/cache: Add fdt cmo helpers
  lib: sbi: Add SiFive proprietary xsfcflushdlone
  lib: sbi: Add SiFive proprietary xsfcease
  lib: utils/ipi: Exposing the ACLINT IPI device
  lib: utils/irqchip: Add APLIC restore function
  platform: sifive: Add SiFive TMC0 driver
  lib: utils/timer: Expose timer update function
  platform: sifive: Add SiFive SMC0 driver

Vincent Chen (2):
  utils: cache: Add SiFive ccache controller
  platform: generic: Add SiFive development platform

 include/sbi/sbi_hart.h                        |   4 +
 include/sbi_utils/cache/cache.h               |  69 +++
 include/sbi_utils/cache/fdt_cache.h           |  34 ++
 include/sbi_utils/cache/fdt_cmo_helper.h      |  34 ++
 include/sbi_utils/ipi/aclint_mswi.h           |   1 +
 include/sbi_utils/irqchip/aplic.h             |   3 +
 include/sbi_utils/timer/aclint_mtimer.h       |   5 +
 lib/sbi/sbi_hart.c                            |   2 +
 lib/utils/Kconfig                             |   2 +
 lib/utils/cache/Kconfig                       |  23 +
 lib/utils/cache/cache.c                       |  46 ++
 lib/utils/cache/fdt_cache.c                   |  87 ++++
 lib/utils/cache/fdt_cache_drivers.carray      |   3 +
 lib/utils/cache/fdt_cmo_helper.c              | 112 +++++
 lib/utils/cache/fdt_sifive_ccache.c           | 175 +++++++
 lib/utils/cache/objects.mk                    |  14 +
 lib/utils/ipi/aclint_mswi.c                   |   5 +
 lib/utils/irqchip/aplic.c                     | 160 +++---
 lib/utils/timer/aclint_mtimer.c               |  28 +-
 platform/generic/Kconfig                      |   8 +
 platform/generic/configs/defconfig            |   3 +
 platform/generic/include/sifive/sifive_inst.h |  20 +
 platform/generic/include/sifive/sifive_smc0.h |  13 +
 platform/generic/include/sifive/sifive_tmc0.h |  15 +
 platform/generic/sifive/Kconfig               |  10 +
 platform/generic/sifive/objects.mk            |   7 +
 .../pmdomain/fdt_pmdomain_sifive_smc0.c       | 322 ++++++++++++
 .../pmdomain/fdt_pmdomain_sifive_tmc0.c       | 459 ++++++++++++++++++
 platform/generic/sifive/sifive_dev_platform.c |  62 +++
 29 files changed, 1652 insertions(+), 74 deletions(-)
 create mode 100644 include/sbi_utils/cache/cache.h
 create mode 100644 include/sbi_utils/cache/fdt_cache.h
 create mode 100644 include/sbi_utils/cache/fdt_cmo_helper.h
 create mode 100644 lib/utils/cache/Kconfig
 create mode 100644 lib/utils/cache/cache.c
 create mode 100644 lib/utils/cache/fdt_cache.c
 create mode 100644 lib/utils/cache/fdt_cache_drivers.carray
 create mode 100644 lib/utils/cache/fdt_cmo_helper.c
 create mode 100644 lib/utils/cache/fdt_sifive_ccache.c
 create mode 100644 lib/utils/cache/objects.mk
 create mode 100644 platform/generic/include/sifive/sifive_inst.h
 create mode 100644 platform/generic/include/sifive/sifive_smc0.h
 create mode 100644 platform/generic/include/sifive/sifive_tmc0.h
 create mode 100644 platform/generic/sifive/Kconfig
 create mode 100644 platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_smc0.c
 create mode 100644 platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
 create mode 100644 platform/generic/sifive/sifive_dev_platform.c

-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:29 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:29 +0800
Subject: [PATCH v3 01/12] lib: utils: Add cache flush library
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-2-nick.hu@sifive.com>

The current RISC-V CMO only defines how to flush a cache block. However,
certain use cases, such as power management, may require flushing the
entire cache. Therefore, a framework is being introduced to allow vendors
to flush the entire cache using their own methods.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
---
 include/sbi_utils/cache/cache.h | 69 +++++++++++++++++++++++++++++++++
 lib/utils/Kconfig               |  2 +
 lib/utils/cache/Kconfig         |  9 +++++
 lib/utils/cache/cache.c         | 46 ++++++++++++++++++++++
 lib/utils/cache/objects.mk      |  7 ++++
 5 files changed, 133 insertions(+)
 create mode 100644 include/sbi_utils/cache/cache.h
 create mode 100644 lib/utils/cache/Kconfig
 create mode 100644 lib/utils/cache/cache.c
 create mode 100644 lib/utils/cache/objects.mk

diff --git a/include/sbi_utils/cache/cache.h b/include/sbi_utils/cache/cache.h
new file mode 100644
index 00000000..70d9286f
--- /dev/null
+++ b/include/sbi_utils/cache/cache.h
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __CACHE_H__
+#define __CACHE_H__
+
+#include <sbi/sbi_list.h>
+#include <sbi/sbi_types.h>
+
+#define CACHE_NAME_LEN	32
+
+struct cache_device;
+
+struct cache_ops {
+	/** Warm init **/
+	int (*warm_init)(struct cache_device *dev);
+	/** Flush entire cache **/
+	int (*cache_flush_all)(struct cache_device *dev);
+};
+
+struct cache_device {
+	/** Name of the device **/
+	char name[CACHE_NAME_LEN];
+	/** List node for search **/
+	struct sbi_dlist node;
+	/** Point to the next level cache **/
+	struct cache_device *next;
+	/** Cache Management Operations **/
+	struct cache_ops *ops;
+	/** CPU private cache **/
+	bool cpu_private;
+	/** The unique id of this cache device **/
+	u32 id;
+};
+
+/**
+ * Find a registered cache device
+ *
+ * @param id unique ID of the cache device
+ *
+ * @return the cache device or NULL
+ */
+struct cache_device *cache_find(u32 id);
+
+/**
+ * Register a cache device
+ *
+ * cache_device->id must be initialized already and must not change during the life
+ * of the cache_device object.
+ *
+ * @param dev the cache device to register
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int cache_add(struct cache_device *dev);
+
+/**
+ * Flush the entire cache
+ *
+ * @param dev the cache to flush
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int cache_flush_all(struct cache_device *dev);
+
+#endif
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index 901ba564..5a5b3b1e 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -2,6 +2,8 @@
 
 menu "Utils and Drivers Support"
 
+source "$(OPENSBI_SRC_DIR)/lib/utils/cache/Kconfig"
+
 source "$(OPENSBI_SRC_DIR)/lib/utils/cppc/Kconfig"
 
 source "$(OPENSBI_SRC_DIR)/lib/utils/fdt/Kconfig"
diff --git a/lib/utils/cache/Kconfig b/lib/utils/cache/Kconfig
new file mode 100644
index 00000000..24aa41bc
--- /dev/null
+++ b/lib/utils/cache/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+menu "Cache Support"
+
+config CACHE
+	bool "Cache support"
+	default n
+
+endmenu
diff --git a/lib/utils/cache/cache.c b/lib/utils/cache/cache.c
new file mode 100644
index 00000000..6bc3d10e
--- /dev/null
+++ b/lib/utils/cache/cache.c
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <sbi/sbi_error.h>
+#include <sbi_utils/cache/cache.h>
+
+static SBI_LIST_HEAD(cache_list);
+
+struct cache_device *cache_find(u32 id)
+{
+	struct cache_device *dev;
+
+	sbi_list_for_each_entry(dev, &cache_list, node) {
+		if (dev->id == id)
+			return dev;
+	}
+
+	return NULL;
+}
+
+int cache_add(struct cache_device *dev)
+{
+	if (!dev)
+		return SBI_ENODEV;
+
+	if (cache_find(dev->id))
+		return SBI_EALREADY;
+
+	sbi_list_add(&dev->node, &cache_list);
+
+	return SBI_OK;
+}
+
+int cache_flush_all(struct cache_device *dev)
+{
+	if (!dev)
+		return SBI_ENODEV;
+
+	if (!dev->ops || !dev->ops->cache_flush_all)
+		return SBI_ENOTSUPP;
+
+	return dev->ops->cache_flush_all(dev);
+}
diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk
new file mode 100644
index 00000000..21d30ce8
--- /dev/null
+++ b/lib/utils/cache/objects.mk
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2025 SiFive
+#
+
+libsbiutils-objs-$(CONFIG_CACHE) += cache/cache.o
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:30 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:30 +0800
Subject: [PATCH v3 02/12] lib: utils: Add FDT cache library
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-3-nick.hu@sifive.com>

Add the FDT cache library so we can build up the cache topology via the
'next-level-cache' DT property.

Co-developed-by: Vincent Chen <vincent.chen at sifive.com>
Signed-off-by: Vincent Chen <vincent.chen at sifive.com>
Co-developed-by: Andy Chiu <andy.chiu at sifive.com>
Signed-off-by: Andy Chiu <andy.chiu at sifive.com>
Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
---
 include/sbi_utils/cache/fdt_cache.h      | 34 +++++++++
 lib/utils/cache/Kconfig                  |  6 ++
 lib/utils/cache/fdt_cache.c              | 87 ++++++++++++++++++++++++
 lib/utils/cache/fdt_cache_drivers.carray |  3 +
 lib/utils/cache/objects.mk               |  3 +
 platform/generic/configs/defconfig       |  1 +
 6 files changed, 134 insertions(+)
 create mode 100644 include/sbi_utils/cache/fdt_cache.h
 create mode 100644 lib/utils/cache/fdt_cache.c
 create mode 100644 lib/utils/cache/fdt_cache_drivers.carray

diff --git a/include/sbi_utils/cache/fdt_cache.h b/include/sbi_utils/cache/fdt_cache.h
new file mode 100644
index 00000000..b377d6f5
--- /dev/null
+++ b/include/sbi_utils/cache/fdt_cache.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __FDT_CACHE_H__
+#define __FDT_CACHE_H__
+
+#include <sbi_utils/cache/cache.h>
+
+/**
+ * Register a cache device using information from the DT
+ *
+ * @param fdt devicetree blob
+ * @param noff offset of a node in the devicetree blob
+ * @param dev cache device to register for this devicetree node
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cache_add(const void *fdt, int noff, struct cache_device *dev);
+
+/**
+ * Get the cache device referencd by the "next-level-cache" property of a DT node
+ *
+ * @param fdt devicetree blob
+ * @param noff offset of a node in the devicetree blob
+ * @param out_dev location to return the cache device
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_next_cache_get(const void *fdt, int noff, struct cache_device **out_dev);
+
+#endif
diff --git a/lib/utils/cache/Kconfig b/lib/utils/cache/Kconfig
index 24aa41bc..10602176 100644
--- a/lib/utils/cache/Kconfig
+++ b/lib/utils/cache/Kconfig
@@ -2,6 +2,12 @@
 
 menu "Cache Support"
 
+config FDT_CACHE
+	bool "FDT based cache drivers"
+	depends on FDT
+	select CACHE
+	default n
+
 config CACHE
 	bool "Cache support"
 	default n
diff --git a/lib/utils/cache/fdt_cache.c b/lib/utils/cache/fdt_cache.c
new file mode 100644
index 00000000..e1c6f67c
--- /dev/null
+++ b/lib/utils/cache/fdt_cache.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi_utils/cache/fdt_cache.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+/* List of FDT cache drivers generated at compile time */
+extern const struct fdt_driver *const fdt_cache_drivers[];
+
+int fdt_cache_add(const void *fdt, int noff, struct cache_device *dev)
+{
+	int rc;
+
+	dev->id = noff;
+	sbi_strncpy(dev->name, fdt_get_name(fdt, noff, NULL), sizeof(dev->name) - 1);
+	sbi_dprintf("%s: %s\n", __func__, dev->name);
+
+	rc = fdt_next_cache_get(fdt, noff, &dev->next);
+	if (rc)
+		return rc;
+
+	return cache_add(dev);
+}
+
+static int fdt_cache_add_generic(const void *fdt, int noff)
+{
+	struct cache_device *dev;
+	int rc;
+
+	dev = sbi_zalloc(sizeof(*dev));
+	if (!dev)
+		return SBI_ENOMEM;
+
+	rc = fdt_cache_add(fdt, noff, dev);
+	if (rc) {
+		sbi_free(dev);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int fdt_cache_find(const void *fdt, int noff, struct cache_device **out_dev)
+{
+	struct cache_device *dev = cache_find(noff);
+	int rc;
+
+	if (!dev) {
+		rc = fdt_driver_init_by_offset(fdt, noff, fdt_cache_drivers);
+		if (rc == SBI_ENODEV)
+			rc = fdt_cache_add_generic(fdt, noff);
+		if (rc)
+			return rc;
+
+		dev = cache_find(noff);
+		if (!dev)
+			return SBI_EFAIL;
+	}
+
+	if (out_dev)
+		*out_dev = dev;
+
+	return SBI_OK;
+}
+
+int fdt_next_cache_get(const void *fdt, int noff, struct cache_device **out_dev)
+{
+	const fdt32_t *val;
+	int len;
+
+	val = fdt_getprop(fdt, noff, "next-level-cache", &len);
+	if (!val || len < sizeof(*val))
+		return SBI_OK;
+
+	noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(val[0]));
+	if (noff < 0)
+		return noff;
+
+	return fdt_cache_find(fdt, noff, out_dev);
+}
diff --git a/lib/utils/cache/fdt_cache_drivers.carray b/lib/utils/cache/fdt_cache_drivers.carray
new file mode 100644
index 00000000..c1b1791c
--- /dev/null
+++ b/lib/utils/cache/fdt_cache_drivers.carray
@@ -0,0 +1,3 @@
+HEADER: sbi_utils/cache/fdt_cache.h
+TYPE: const struct fdt_driver
+NAME: fdt_cache_drivers
diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk
index 21d30ce8..2fcf9666 100644
--- a/lib/utils/cache/objects.mk
+++ b/lib/utils/cache/objects.mk
@@ -4,4 +4,7 @@
 # Copyright (c) 2025 SiFive
 #
 
+libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache.o
+libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache_drivers.carray.o
+
 libsbiutils-objs-$(CONFIG_CACHE) += cache/cache.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index c7a6531e..b5a7993d 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -7,6 +7,7 @@ CONFIG_PLATFORM_SOPHGO_SG2042=y
 CONFIG_PLATFORM_STARFIVE_JH7110=y
 CONFIG_PLATFORM_THEAD=y
 CONFIG_PLATFORM_MIPS_P8700=y
+CONFIG_FDT_CACHE=y
 CONFIG_FDT_CPPC=y
 CONFIG_FDT_CPPC_RPMI=y
 CONFIG_FDT_GPIO=y
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:31 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:31 +0800
Subject: [PATCH v3 03/12] utils: cache: Add SiFive ccache controller
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-4-nick.hu@sifive.com>

From: Vincent Chen <vincent.chen at sifive.com>

SiFive Composable cache is a L3 share cache of the core complex. Add this
driver to support the share cache maintenance operations via the MMIO
registers.

Co-developed-by: Samuel Holland <samuel.holland at sifive.com>
Signed-off-by: Samuel Holland <samuel.holland at sifive.com>
Signed-off-by: Vincent Chen <vincent.chen at sifive.com>
Co-developed-by: Nick Hu <nick.hu at sifive.com>
Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
---
 lib/utils/cache/Kconfig             |   8 ++
 lib/utils/cache/fdt_sifive_ccache.c | 175 ++++++++++++++++++++++++++++
 lib/utils/cache/objects.mk          |   3 +
 platform/generic/configs/defconfig  |   1 +
 4 files changed, 187 insertions(+)
 create mode 100644 lib/utils/cache/fdt_sifive_ccache.c

diff --git a/lib/utils/cache/Kconfig b/lib/utils/cache/Kconfig
index 10602176..1c7abdc9 100644
--- a/lib/utils/cache/Kconfig
+++ b/lib/utils/cache/Kconfig
@@ -8,6 +8,14 @@ config FDT_CACHE
 	select CACHE
 	default n
 
+if FDT_CACHE
+
+config FDT_CACHE_SIFIVE_CCACHE
+	bool "SiFive CCACHE FDT cache driver"
+	default n
+
+endif
+
 config CACHE
 	bool "Cache support"
 	default n
diff --git a/lib/utils/cache/fdt_sifive_ccache.c b/lib/utils/cache/fdt_sifive_ccache.c
new file mode 100644
index 00000000..ad7511b5
--- /dev/null
+++ b/lib/utils/cache/fdt_sifive_ccache.c
@@ -0,0 +1,175 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_barrier.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi_utils/cache/fdt_cache.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#define CCACHE_CFG_CSR			0
+#define CCACHE_CMD_CSR			0x280
+#define CCACHE_STATUS_CSR		0x288
+
+#define CFG_CSR_BANK_MASK		0xff
+#define CFG_CSR_WAY_MASK		0xff00
+#define CFG_CSR_WAY_OFFSET		8
+#define CFG_CSR_SET_MASK		0xff0000
+#define CFG_CSR_SET_OFFSET		16
+
+#define CMD_CSR_CMD_OFFSET	56
+#define CMD_CSR_BANK_OFFSET	6
+
+#define CMD_OPCODE_SETWAY	0x1ULL
+#define CMD_OPCODE_OFFSET	0x2ULL
+
+#define CFLUSH_SETWAY_CLEANINV  ((CMD_OPCODE_SETWAY << CMD_OPCODE_OFFSET) | 0x3)
+
+#define CCACHE_CMD_QLEN	0xff
+
+#define ccache_mb_b()		RISCV_FENCE(rw, o)
+#define ccache_mb_a()		RISCV_FENCE(o, rw)
+
+#define CCACHE_ALL_OP_REQ_BATCH_NUM	0x10
+#define CCACHE_ALL_OP_REQ_BATCH_MASK (CCACHE_CMD_QLEN + 1 - CCACHE_ALL_OP_REQ_BATCH_NUM)
+
+struct sifive_ccache {
+	struct cache_device dev;
+	void *addr;
+	u64 total_lines;
+};
+
+#define to_ccache(_dev) container_of(_dev, struct sifive_ccache, dev)
+
+static inline unsigned int sifive_ccache_read_status(void *status_addr)
+{
+	return readl_relaxed(status_addr);
+}
+
+static inline void sifive_ccache_write_cmd(u64 cmd, void *cmd_csr_addr)
+{
+#if __riscv_xlen != 32
+	writeq_relaxed(cmd, cmd_csr_addr);
+#else
+	/*
+	 * The cache maintenance request is only generated when the "command"
+	 * field (part of the high word) is written.
+	 */
+	writel_relaxed(cmd, cmd_csr_addr);
+	writel(cmd >> 32, cmd_csr_addr + 4);
+#endif
+}
+
+static int sifive_ccache_flush_all(struct cache_device *dev)
+{
+	struct sifive_ccache *ccache = to_ccache(dev);
+	void *status_addr = (char *)ccache->addr + CCACHE_STATUS_CSR;
+	void *cmd_csr_addr = (char *)ccache->addr + CCACHE_CMD_CSR;
+	u64 total_cnt = ccache->total_lines;
+	u64 cmd = CFLUSH_SETWAY_CLEANINV << CMD_CSR_CMD_OFFSET;
+	int loop_cnt = CCACHE_CMD_QLEN & CCACHE_ALL_OP_REQ_BATCH_MASK;
+
+	ccache_mb_b();
+send_cmd:
+	total_cnt -= loop_cnt;
+	while (loop_cnt > 0) {
+		sifive_ccache_write_cmd(cmd + (0 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (1 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (2 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (3 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (4 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (5 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (6 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (7 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (8 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (9 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (10 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (11 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (12 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (13 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (14 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		sifive_ccache_write_cmd(cmd + (15 << CMD_CSR_BANK_OFFSET), cmd_csr_addr);
+		cmd += CCACHE_ALL_OP_REQ_BATCH_NUM << CMD_CSR_BANK_OFFSET;
+		loop_cnt -= CCACHE_ALL_OP_REQ_BATCH_NUM;
+	}
+	if (!total_cnt)
+		goto done;
+
+	/* Ensure the ccache is able receive more than 16 requests */
+	do {
+		loop_cnt = (CCACHE_CMD_QLEN - sifive_ccache_read_status(status_addr));
+	} while (loop_cnt < CCACHE_ALL_OP_REQ_BATCH_NUM);
+	loop_cnt &= CCACHE_ALL_OP_REQ_BATCH_MASK;
+
+	if (total_cnt < loop_cnt) {
+		loop_cnt = (total_cnt + CCACHE_ALL_OP_REQ_BATCH_NUM) & CCACHE_ALL_OP_REQ_BATCH_MASK;
+		cmd -= ((loop_cnt - total_cnt) << CMD_CSR_BANK_OFFSET);
+		total_cnt = loop_cnt;
+	}
+	goto send_cmd;
+done:
+	do {} while (sifive_ccache_read_status(status_addr));
+	ccache_mb_a();
+
+	return 0;
+}
+
+static struct cache_ops sifive_ccache_ops = {
+	.cache_flush_all = sifive_ccache_flush_all,
+};
+
+static int sifive_ccache_cold_init(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+	struct sifive_ccache *ccache;
+	struct cache_device *dev;
+	u64 reg_addr = 0;
+	u32 config_csr, banks, sets, ways;
+	int rc;
+
+	/** find the ccache base control address **/
+	rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &reg_addr, NULL);
+	if (rc < 0 && reg_addr)
+		return SBI_ENODEV;
+
+	ccache = sbi_zalloc(sizeof(*ccache));
+	if (!ccache)
+		return SBI_ENOMEM;
+
+	dev = &ccache->dev;
+	dev->ops = &sifive_ccache_ops;
+	rc = fdt_cache_add(fdt, nodeoff, dev);
+	if (rc) {
+		sbi_free(ccache);
+		return rc;
+	}
+
+	ccache->addr = (void *)(uintptr_t)reg_addr;
+
+	/** get the info of ccache from config CSR **/
+	config_csr = readl((char *)reg_addr + CCACHE_CFG_CSR);
+	banks = config_csr & CFG_CSR_BANK_MASK;
+
+	sets = (config_csr & CFG_CSR_SET_MASK) >> CFG_CSR_SET_OFFSET;
+	sets = (1 << sets);
+
+	ways = (config_csr & CFG_CSR_WAY_MASK) >> CFG_CSR_WAY_OFFSET;
+
+	ccache->total_lines = sets * ways * banks;
+
+	return SBI_OK;
+}
+
+static const struct fdt_match sifive_ccache_match[] = {
+	{ .compatible = "sifive,ccache2" },
+	{},
+};
+
+const struct fdt_driver fdt_sifive_ccache = {
+	.match_table = sifive_ccache_match,
+	.init = sifive_ccache_cold_init,
+};
diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk
index 2fcf9666..a343eb8c 100644
--- a/lib/utils/cache/objects.mk
+++ b/lib/utils/cache/objects.mk
@@ -7,4 +7,7 @@
 libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache.o
 libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache_drivers.carray.o
 
+carray-fdt_cache_drivers-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += fdt_sifive_ccache
+libsbiutils-objs-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += cache/fdt_sifive_ccache.o
+
 libsbiutils-objs-$(CONFIG_CACHE) += cache/cache.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index b5a7993d..6b219cfb 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -8,6 +8,7 @@ CONFIG_PLATFORM_STARFIVE_JH7110=y
 CONFIG_PLATFORM_THEAD=y
 CONFIG_PLATFORM_MIPS_P8700=y
 CONFIG_FDT_CACHE=y
+CONFIG_FDT_CACHE_SIFIVE_CCACHE=y
 CONFIG_FDT_CPPC=y
 CONFIG_FDT_CPPC_RPMI=y
 CONFIG_FDT_GPIO=y
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:32 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:32 +0800
Subject: [PATCH v3 04/12] lib: utils/cache: Add fdt cmo helpers
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-5-nick.hu@sifive.com>

Add the helpers to build up the cache hierarchy via FDT and provide some
cmo functions for the user who want to flush the entire cache.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
---
 include/sbi_utils/cache/fdt_cmo_helper.h |  34 +++++++
 lib/utils/cache/fdt_cmo_helper.c         | 112 +++++++++++++++++++++++
 lib/utils/cache/objects.mk               |   1 +
 3 files changed, 147 insertions(+)
 create mode 100644 include/sbi_utils/cache/fdt_cmo_helper.h
 create mode 100644 lib/utils/cache/fdt_cmo_helper.c

diff --git a/include/sbi_utils/cache/fdt_cmo_helper.h b/include/sbi_utils/cache/fdt_cmo_helper.h
new file mode 100644
index 00000000..4275725e
--- /dev/null
+++ b/include/sbi_utils/cache/fdt_cmo_helper.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __FDT_CMO_HELPER_H__
+#define __FDT_CMO_HELPER_H__
+
+/**
+ * Flush the private first level cache of the current hart
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_private_flc_flush_all(void);
+
+/**
+ * Flush the last level cache of the current hart
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_llc_flush_all(void);
+
+/**
+ * Initialize the cache devices for each hart
+ *
+ * @param fdt devicetree blob
+ * @param cold_boot cold init or warm init
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_init(bool cold_boot);
+
+#endif
diff --git a/lib/utils/cache/fdt_cmo_helper.c b/lib/utils/cache/fdt_cmo_helper.c
new file mode 100644
index 00000000..6d2e853d
--- /dev/null
+++ b/lib/utils/cache/fdt_cmo_helper.c
@@ -0,0 +1,112 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi_utils/cache/fdt_cache.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+
+static unsigned long flc_offset;
+
+#define get_hart_flc(_s) \
+	sbi_scratch_read_type(_s, struct cache_device *, flc_offset)
+#define set_hart_flc(_s, _p) \
+	sbi_scratch_write_type(_s, struct cache_device *, flc_offset, _p)
+
+int fdt_cmo_private_flc_flush_all(void)
+{
+	struct cache_device *flc = get_hart_flc(sbi_scratch_thishart_ptr());
+
+	if (!flc || !flc->cpu_private)
+		return SBI_ENODEV;
+
+	return cache_flush_all(flc);
+}
+
+int fdt_cmo_llc_flush_all(void)
+{
+	struct cache_device *llc = get_hart_flc(sbi_scratch_thishart_ptr());
+
+	if (!llc)
+		return SBI_ENODEV;
+
+	while (llc->next)
+		llc = llc->next;
+
+	return cache_flush_all(llc);
+}
+
+static int fdt_cmo_cold_init(const void *fdt)
+{
+	struct sbi_scratch *scratch;
+	struct cache_device *dev;
+	int cpu_offset, cpus_offset, rc;
+	u32 hartid;
+
+	cpus_offset = fdt_path_offset(fdt, "/cpus");
+	if (cpus_offset < 0)
+		return SBI_EINVAL;
+
+	fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
+		rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
+		if (rc)
+			continue;
+
+		scratch = sbi_hartid_to_scratch(hartid);
+		if (!scratch)
+			continue;
+
+		rc = fdt_next_cache_get(fdt, cpu_offset, &dev);
+		if (rc)
+			return rc;
+
+		set_hart_flc(scratch, dev);
+	}
+
+	return SBI_OK;
+}
+
+static int fdt_cmo_warm_init(void)
+{
+	struct cache_device *cur = get_hart_flc(sbi_scratch_thishart_ptr());
+	int rc;
+
+	while (cur) {
+		if (cur->ops && cur->ops->warm_init) {
+			rc = cur->ops->warm_init(cur);
+			if (rc)
+				return rc;
+		}
+
+		cur = cur->next;
+	}
+
+	return SBI_OK;
+}
+
+int fdt_cmo_init(bool cold_boot)
+{
+	const void *fdt = fdt_get_address();
+	int rc;
+
+	if (cold_boot) {
+		flc_offset = sbi_scratch_alloc_type_offset(struct cache_device *);
+		if (!flc_offset)
+			return SBI_ENOMEM;
+
+		rc = fdt_cmo_cold_init(fdt);
+		if (rc)
+			return rc;
+	}
+
+	rc = fdt_cmo_warm_init();
+	if (rc)
+		return rc;
+
+	return SBI_OK;
+}
diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk
index a343eb8c..6829a966 100644
--- a/lib/utils/cache/objects.mk
+++ b/lib/utils/cache/objects.mk
@@ -6,6 +6,7 @@
 
 libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache.o
 libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache_drivers.carray.o
+libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cmo_helper.o
 
 carray-fdt_cache_drivers-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += fdt_sifive_ccache
 libsbiutils-objs-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += cache/fdt_sifive_ccache.o
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:33 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:33 +0800
Subject: [PATCH v3 05/12] platform: generic: Add SiFive development platform
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-6-nick.hu@sifive.com>

From: Vincent Chen <vincent.chen at sifive.com>

The sifive_dev_platform is a new platform which is compatible to the
generic platform to place some features which are only for the SiFive
development machine.

Signed-off-by: Vincent Chen <vincent.chen at sifive.com>
Co-developed-by: Nick Hu <nick.hu at sifive.com>
Signed-off-by: Nick Hu <nick.hu at sifive.com>
---
 platform/generic/Kconfig                      |  5 +++
 platform/generic/configs/defconfig            |  1 +
 platform/generic/sifive/objects.mk            |  3 ++
 platform/generic/sifive/sifive_dev_platform.c | 41 +++++++++++++++++++
 4 files changed, 50 insertions(+)
 create mode 100644 platform/generic/sifive/sifive_dev_platform.c

diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index a24d6ab2..20c25a83 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -43,6 +43,11 @@ config PLATFORM_RENESAS_RZFIVE
 	select ANDES_PMU
 	default n
 
+config PLATFORM_SIFIVE_DEV
+	bool "SiFive development platform support"
+	depends on FDT_CACHE
+	default n
+
 config PLATFORM_SIFIVE_FU540
 	bool "SiFive FU540 support"
 	default n
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 6b219cfb..42e7ef75 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -1,6 +1,7 @@
 CONFIG_PLATFORM_ALLWINNER_D1=y
 CONFIG_PLATFORM_ANDES_AE350=y
 CONFIG_PLATFORM_RENESAS_RZFIVE=y
+CONFIG_PLATFORM_SIFIVE_DEV=y
 CONFIG_PLATFORM_SIFIVE_FU540=y
 CONFIG_PLATFORM_SIFIVE_FU740=y
 CONFIG_PLATFORM_SOPHGO_SG2042=y
diff --git a/platform/generic/sifive/objects.mk b/platform/generic/sifive/objects.mk
index d75e444a..d32e1273 100644
--- a/platform/generic/sifive/objects.mk
+++ b/platform/generic/sifive/objects.mk
@@ -2,6 +2,9 @@
 # SPDX-License-Identifier: BSD-2-Clause
 #
 
+carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_DEV) += sifive_dev_platform
+platform-objs-$(CONFIG_PLATFORM_SIFIVE_DEV) += sifive/sifive_dev_platform.o
+
 carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive_fu540
 platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive/fu540.o
 
diff --git a/platform/generic/sifive/sifive_dev_platform.c b/platform/generic/sifive/sifive_dev_platform.c
new file mode 100644
index 00000000..ac659868
--- /dev/null
+++ b/platform/generic/sifive/sifive_dev_platform.c
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <platform_override.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
+
+static int sifive_early_init(bool cold_boot)
+{
+	int rc;
+
+	rc = generic_early_init(cold_boot);
+	if (rc)
+		return rc;
+
+	rc = fdt_cmo_init(cold_boot);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int sifive_platform_init(const void *fdt, int nodeoff,
+				const struct fdt_match *match)
+{
+	generic_platform_ops.early_init = sifive_early_init;
+
+	return 0;
+}
+
+static const struct fdt_match sifive_dev_platform_match[] = {
+	{ .compatible = "sifive-dev" },
+	{ },
+};
+
+const struct fdt_driver sifive_dev_platform = {
+	.match_table = sifive_dev_platform_match,
+	.init = sifive_platform_init,
+};
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:34 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:34 +0800
Subject: [PATCH v3 06/12] lib: sbi: Add SiFive proprietary xsfcflushdlone
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-7-nick.hu@sifive.com>

Using ISA string "xsfcflushdlone" to detect the support of the
SiFive L1D cache flush custom instruction.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 include/sbi/sbi_hart.h | 2 ++
 lib/sbi/sbi_hart.c     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index dfbe8e4c..567e0130 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -81,6 +81,8 @@ enum sbi_hart_extensions {
 	SBI_HART_EXT_SSCTR,
 	/** HART has Ssstateen extension **/
 	SBI_HART_EXT_SSSTATEEN,
+	/** Hart has Xsfcflushdlone extension */
+	SBI_HART_EXT_XSF_CFLUSH_D_L1,
 
 	/** Maximum index of Hart extension */
 	SBI_HART_EXT_MAX,
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 054a405c..e91e1123 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -715,6 +715,7 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
 	__SBI_HART_EXT_DATA(smctr, SBI_HART_EXT_SMCTR),
 	__SBI_HART_EXT_DATA(ssctr, SBI_HART_EXT_SSCTR),
 	__SBI_HART_EXT_DATA(ssstateen, SBI_HART_EXT_SSSTATEEN),
+	__SBI_HART_EXT_DATA(xsfcflushdlone, SBI_HART_EXT_XSF_CFLUSH_D_L1),
 };
 
 _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:35 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:35 +0800
Subject: [PATCH v3 07/12] lib: sbi: Add SiFive proprietary xsfcease
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-8-nick.hu@sifive.com>

Using ISA string "xsfcease" to detect the support of the custom
instruction "CEASE".

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 include/sbi/sbi_hart.h | 2 ++
 lib/sbi/sbi_hart.c     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index 567e0130..db6f4adb 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -83,6 +83,8 @@ enum sbi_hart_extensions {
 	SBI_HART_EXT_SSSTATEEN,
 	/** Hart has Xsfcflushdlone extension */
 	SBI_HART_EXT_XSF_CFLUSH_D_L1,
+	/** Hart has Xsfcease extension */
+	SBI_HART_EXT_XSF_CEASE,
 
 	/** Maximum index of Hart extension */
 	SBI_HART_EXT_MAX,
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index e91e1123..c9036084 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -716,6 +716,7 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
 	__SBI_HART_EXT_DATA(ssctr, SBI_HART_EXT_SSCTR),
 	__SBI_HART_EXT_DATA(ssstateen, SBI_HART_EXT_SSSTATEEN),
 	__SBI_HART_EXT_DATA(xsfcflushdlone, SBI_HART_EXT_XSF_CFLUSH_D_L1),
+	__SBI_HART_EXT_DATA(xsfcease, SBI_HART_EXT_XSF_CEASE),
 };
 
 _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:36 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:36 +0800
Subject: [PATCH v3 08/12] lib: utils/ipi: Exposing the ACLINT IPI device
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-9-nick.hu@sifive.com>

Exposing the ACLINT IPI device so the other driver can send the CLINT
IPI on the platform with IMSIC.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 include/sbi_utils/ipi/aclint_mswi.h | 1 +
 lib/utils/ipi/aclint_mswi.c         | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/include/sbi_utils/ipi/aclint_mswi.h b/include/sbi_utils/ipi/aclint_mswi.h
index 4b8249f2..311228eb 100644
--- a/include/sbi_utils/ipi/aclint_mswi.h
+++ b/include/sbi_utils/ipi/aclint_mswi.h
@@ -26,6 +26,7 @@ struct aclint_mswi_data {
 	u32 hart_count;
 };
 
+struct sbi_ipi_device *aclint_mswi_get(void);
 int aclint_mswi_cold_init(struct aclint_mswi_data *mswi);
 
 #endif
diff --git a/lib/utils/ipi/aclint_mswi.c b/lib/utils/ipi/aclint_mswi.c
index 9e55078a..a4173b7c 100644
--- a/lib/utils/ipi/aclint_mswi.c
+++ b/lib/utils/ipi/aclint_mswi.c
@@ -66,6 +66,11 @@ static struct sbi_ipi_device aclint_mswi = {
 	.ipi_clear = mswi_ipi_clear
 };
 
+struct sbi_ipi_device *aclint_mswi_get(void)
+{
+	return &aclint_mswi;
+}
+
 int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
 {
 	u32 i;
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:37 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:37 +0800
Subject: [PATCH v3 09/12] lib: utils/irqchip: Add APLIC restore function
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-10-nick.hu@sifive.com>

Since the APLIC may enter a reset state upon system wake-up from a
platform low power state, adding a restore function to reinitialize
the APLIC.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Yong-Xuan Wang <yongxuan.wang at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 include/sbi_utils/irqchip/aplic.h |   3 +
 lib/utils/irqchip/aplic.c         | 160 +++++++++++++++++-------------
 2 files changed, 96 insertions(+), 67 deletions(-)

diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
index e31f48a4..ca606d06 100644
--- a/include/sbi_utils/irqchip/aplic.h
+++ b/include/sbi_utils/irqchip/aplic.h
@@ -33,6 +33,7 @@ struct aplic_delegate_data {
 struct aplic_data {
 	/* Private members */
 	struct sbi_irqchip_device irqchip;
+	struct sbi_dlist node;
 	/* Public members */
 	unsigned long addr;
 	unsigned long size;
@@ -48,4 +49,6 @@ struct aplic_data {
 
 int aplic_cold_irqchip_init(struct aplic_data *aplic);
 
+void aplic_restore(void);
+
 #endif
diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c
index 72906d5d..68f5d107 100644
--- a/lib/utils/irqchip/aplic.c
+++ b/lib/utils/irqchip/aplic.c
@@ -115,6 +115,88 @@
 #define APLIC_DISABLE_ITHRESHOLD	1
 #define APLIC_ENABLE_ITHRESHOLD		0
 
+static SBI_LIST_HEAD(aplic_list);
+static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg,
+				void *msicfgaddr, void *msicfgaddrH);
+
+static void aplic_init(struct aplic_data *aplic)
+{
+	u32 i, j, tmp;
+	struct aplic_delegate_data *deleg;
+
+	/* Set domain configuration to 0 */
+	writel(0, (void *)(aplic->addr + APLIC_DOMAINCFG));
+
+	/* Disable all interrupts */
+	for (i = 0; i <= aplic->num_source; i += 32)
+		writel(-1U, (void *)(aplic->addr + APLIC_CLRIE_BASE +
+				     (i / 32) * sizeof(u32)));
+
+	/* Set interrupt type and priority for all interrupts */
+	for (i = 1; i <= aplic->num_source; i++) {
+		/* Set IRQ source configuration to 0 */
+		writel(0, (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
+			  (i - 1) * sizeof(u32)));
+		/* Set IRQ target hart index and priority to 1 */
+		writel(APLIC_DEFAULT_PRIORITY, (void *)(aplic->addr +
+						APLIC_TARGET_BASE +
+						(i - 1) * sizeof(u32)));
+	}
+
+	/* Configure IRQ delegation */
+	for (i = 0; i < APLIC_MAX_DELEGATE; i++) {
+		deleg = &aplic->delegate[i];
+		if (!deleg->first_irq || !deleg->last_irq)
+			continue;
+		if (aplic->num_source < deleg->first_irq ||
+		    aplic->num_source < deleg->last_irq)
+			continue;
+		if (deleg->child_index > APLIC_SOURCECFG_CHILDIDX_MASK)
+			continue;
+		if (deleg->first_irq > deleg->last_irq) {
+			tmp = deleg->first_irq;
+			deleg->first_irq = deleg->last_irq;
+			deleg->last_irq = tmp;
+		}
+		for (j = deleg->first_irq; j <= deleg->last_irq; j++)
+			writel(APLIC_SOURCECFG_D | deleg->child_index,
+			       (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
+			       (j - 1) * sizeof(u32)));
+	}
+
+	/* Default initialization of IDC structures */
+	for (i = 0; i < aplic->num_idc; i++) {
+		writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
+				   i * APLIC_IDC_SIZE + APLIC_IDC_IDELIVERY));
+		writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
+				   i * APLIC_IDC_SIZE + APLIC_IDC_IFORCE));
+		writel(APLIC_DISABLE_ITHRESHOLD, (void *)(aplic->addr +
+						  APLIC_IDC_BASE +
+						  (i * APLIC_IDC_SIZE) +
+						  APLIC_IDC_ITHRESHOLD));
+	}
+
+	/* MSI configuration */
+	if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
+		aplic_writel_msicfg(&aplic->msicfg_mmode,
+				    (void *)(aplic->addr + APLIC_MMSICFGADDR),
+				    (void *)(aplic->addr + APLIC_MMSICFGADDRH));
+	}
+	if (aplic->targets_mmode && aplic->has_msicfg_smode) {
+		aplic_writel_msicfg(&aplic->msicfg_smode,
+				    (void *)(aplic->addr + APLIC_SMSICFGADDR),
+				    (void *)(aplic->addr + APLIC_SMSICFGADDRH));
+	}
+}
+
+void aplic_restore(void)
+{
+	struct aplic_data *aplic;
+
+	sbi_list_for_each_entry(aplic, &aplic_list, node)
+		aplic_init(aplic);
+}
+
 static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg,
 				void *msicfgaddr, void *msicfgaddrH)
 {
@@ -168,9 +250,8 @@ static int aplic_check_msicfg(struct aplic_msicfg_data *msicfg)
 int aplic_cold_irqchip_init(struct aplic_data *aplic)
 {
 	int rc;
-	u32 i, j, tmp;
 	struct aplic_delegate_data *deleg;
-	u32 first_deleg_irq, last_deleg_irq;
+	u32 first_deleg_irq, last_deleg_irq, i;
 
 	/* Sanity checks */
 	if (!aplic ||
@@ -188,81 +269,23 @@ int aplic_cold_irqchip_init(struct aplic_data *aplic)
 			return rc;
 	}
 
-	/* Set domain configuration to 0 */
-	writel(0, (void *)(aplic->addr + APLIC_DOMAINCFG));
-
-	/* Disable all interrupts */
-	for (i = 0; i <= aplic->num_source; i += 32)
-		writel(-1U, (void *)(aplic->addr + APLIC_CLRIE_BASE +
-				     (i / 32) * sizeof(u32)));
-
-	/* Set interrupt type and priority for all interrupts */
-	for (i = 1; i <= aplic->num_source; i++) {
-		/* Set IRQ source configuration to 0 */
-		writel(0, (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
-			  (i - 1) * sizeof(u32)));
-		/* Set IRQ target hart index and priority to 1 */
-		writel(APLIC_DEFAULT_PRIORITY, (void *)(aplic->addr +
-						APLIC_TARGET_BASE +
-						(i - 1) * sizeof(u32)));
-	}
+	/* Init the APLIC registers */
+	aplic_init(aplic);
 
-	/* Configure IRQ delegation */
+	/*
+	 * Add APLIC region to the root domain if:
+	 * 1) It targets M-mode of any HART directly or via MSIs
+	 * 2) All interrupts are delegated to some child APLIC
+	 */
 	first_deleg_irq = -1U;
 	last_deleg_irq = 0;
 	for (i = 0; i < APLIC_MAX_DELEGATE; i++) {
 		deleg = &aplic->delegate[i];
-		if (!deleg->first_irq || !deleg->last_irq)
-			continue;
-		if (aplic->num_source < deleg->first_irq ||
-		    aplic->num_source < deleg->last_irq)
-			continue;
-		if (APLIC_SOURCECFG_CHILDIDX_MASK < deleg->child_index)
-			continue;
-		if (deleg->first_irq > deleg->last_irq) {
-			tmp = deleg->first_irq;
-			deleg->first_irq = deleg->last_irq;
-			deleg->last_irq = tmp;
-		}
 		if (deleg->first_irq < first_deleg_irq)
 			first_deleg_irq = deleg->first_irq;
 		if (last_deleg_irq < deleg->last_irq)
 			last_deleg_irq = deleg->last_irq;
-		for (j = deleg->first_irq; j <= deleg->last_irq; j++)
-			writel(APLIC_SOURCECFG_D | deleg->child_index,
-				(void *)(aplic->addr + APLIC_SOURCECFG_BASE +
-				(j - 1) * sizeof(u32)));
-	}
-
-	/* Default initialization of IDC structures */
-	for (i = 0; i < aplic->num_idc; i++) {
-		writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
-			  i * APLIC_IDC_SIZE + APLIC_IDC_IDELIVERY));
-		writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
-			  i * APLIC_IDC_SIZE + APLIC_IDC_IFORCE));
-		writel(APLIC_DISABLE_ITHRESHOLD, (void *)(aplic->addr +
-						  APLIC_IDC_BASE +
-						  (i * APLIC_IDC_SIZE) +
-						  APLIC_IDC_ITHRESHOLD));
-	}
-
-	/* MSI configuration */
-	if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
-		aplic_writel_msicfg(&aplic->msicfg_mmode,
-				(void *)(aplic->addr + APLIC_MMSICFGADDR),
-				(void *)(aplic->addr + APLIC_MMSICFGADDRH));
-	}
-	if (aplic->targets_mmode && aplic->has_msicfg_smode) {
-		aplic_writel_msicfg(&aplic->msicfg_smode,
-				(void *)(aplic->addr + APLIC_SMSICFGADDR),
-				(void *)(aplic->addr + APLIC_SMSICFGADDRH));
 	}
-
-	/*
-	 * Add APLIC region to the root domain if:
-	 * 1) It targets M-mode of any HART directly or via MSIs
-	 * 2) All interrupts are delegated to some child APLIC
-	 */
 	if (aplic->targets_mmode ||
 	    ((first_deleg_irq < last_deleg_irq) &&
 	    (last_deleg_irq == aplic->num_source) &&
@@ -278,5 +301,8 @@ int aplic_cold_irqchip_init(struct aplic_data *aplic)
 	/* Register irqchip device */
 	sbi_irqchip_add_device(&aplic->irqchip);
 
+	/* Attach to the aplic list */
+	sbi_list_add_tail(&aplic->node, &aplic_list);
+
 	return 0;
 }
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:38 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:38 +0800
Subject: [PATCH v3 10/12] platform: sifive: Add SiFive TMC0 driver
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-11-nick.hu@sifive.com>

The SiFive TMC0 controls the tile power domains on SiFive platform. The
CPU enters the low power state via the `CEASE` instruction after
configuring the TMC0. Any devices that inside the tile power domain will
be power gated, including the private cache. Therefore flushing the
private cache before entering the low power state.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 platform/generic/Kconfig                      |   2 +
 platform/generic/include/sifive/sifive_inst.h |  20 +
 platform/generic/include/sifive/sifive_tmc0.h |  12 +
 platform/generic/sifive/Kconfig               |   5 +
 platform/generic/sifive/objects.mk            |   2 +
 .../pmdomain/fdt_pmdomain_sifive_tmc0.c       | 371 ++++++++++++++++++
 platform/generic/sifive/sifive_dev_platform.c |  21 +
 7 files changed, 433 insertions(+)
 create mode 100644 platform/generic/include/sifive/sifive_inst.h
 create mode 100644 platform/generic/include/sifive/sifive_tmc0.h
 create mode 100644 platform/generic/sifive/Kconfig
 create mode 100644 platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c

diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 20c25a83..1d6ea3f4 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -46,6 +46,7 @@ config PLATFORM_RENESAS_RZFIVE
 config PLATFORM_SIFIVE_DEV
 	bool "SiFive development platform support"
 	depends on FDT_CACHE
+	select SIFIVE_TMC0
 	default n
 
 config PLATFORM_SIFIVE_FU540
@@ -78,6 +79,7 @@ config PLATFORM_MIPS_P8700
 	default n
 
 source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
+source "$(OPENSBI_SRC_DIR)/platform/generic/sifive/Kconfig"
 source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
 
 endif
diff --git a/platform/generic/include/sifive/sifive_inst.h b/platform/generic/include/sifive/sifive_inst.h
new file mode 100644
index 00000000..36dddf68
--- /dev/null
+++ b/platform/generic/include/sifive/sifive_inst.h
@@ -0,0 +1,20 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __SIFIVE_INST_H__
+#define __SIFIVE_INST_H__
+
+static inline void sifive_cease(void)
+{
+	__asm__ __volatile__(".word 0x30500073" ::: "memory");
+}
+
+static inline void sifive_cflush(void)
+{
+	__asm__ __volatile__(".word 0xfc000073" ::: "memory");
+}
+
+#endif
diff --git a/platform/generic/include/sifive/sifive_tmc0.h b/platform/generic/include/sifive/sifive_tmc0.h
new file mode 100644
index 00000000..6100e0dc
--- /dev/null
+++ b/platform/generic/include/sifive/sifive_tmc0.h
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __SIFIVE_TMC0_H__
+#define __SIFIVE_TMC0_H__
+
+int sifive_tmc0_cold_init(void);
+
+#endif
diff --git a/platform/generic/sifive/Kconfig b/platform/generic/sifive/Kconfig
new file mode 100644
index 00000000..2cbcea08
--- /dev/null
+++ b/platform/generic/sifive/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+config SIFIVE_TMC0
+	bool "SiFive TMC v0 driver support"
+	default n
diff --git a/platform/generic/sifive/objects.mk b/platform/generic/sifive/objects.mk
index d32e1273..f8938713 100644
--- a/platform/generic/sifive/objects.mk
+++ b/platform/generic/sifive/objects.mk
@@ -10,3 +10,5 @@ platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive/fu540.o
 
 carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive_fu740
 platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive/fu740.o
+
+platform-objs-$(CONFIG_SIFIVE_TMC0) += sifive/pmdomain/fdt_pmdomain_sifive_tmc0.o
diff --git a/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
new file mode 100644
index 00000000..70d02b33
--- /dev/null
+++ b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
@@ -0,0 +1,371 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_bitops.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_ipi.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/ipi/aclint_mswi.h>
+#include <sifive/sifive_inst.h>
+#include <sifive/sifive_tmc0.h>
+
+struct sifive_tmc0 {
+	unsigned long reg;
+	struct sbi_dlist node;
+	u32 id;
+};
+
+static SBI_LIST_HEAD(tmc0_list);
+static unsigned long tmc0_offset;
+
+#define tmc0_ptr_get(__scratch)				\
+	sbi_scratch_read_type((__scratch), struct sifive_tmc0 *, tmc0_offset)
+
+#define tmc0_ptr_set(__scratch, __tmc0)			\
+	sbi_scratch_write_type((__scratch), struct sifive_tmc0 *, tmc0_offset, (__tmc0))
+
+/* TMC.PGPREP */
+#define SIFIVE_TMC_PGPREP_OFF			0x0
+#define SIFIVE_TMC_PGPREP_ENA_REQ		BIT(31)
+#define SIFIVE_TMC_PGPREP_ENA_ACK		BIT(30)
+#define SIFIVE_TMC_PGPREP_DIS_REQ		BIT(29)
+#define SIFIVE_TMC_PGPREP_DIS_ACK		BIT(28)
+#define SIFIVE_TMC_PGPREP_CLFPNOTQ		BIT(18)
+#define SIFIVE_TMC_PGPREP_PMCENAERR		BIT(17)
+#define SIFIVE_TMC_PGPREP_PMCDENY		BIT(16)
+#define SIFIVE_TMC_PGPREP_BUSERR		BIT(15)
+#define SIFIVE_TMC_PGPREP_WAKE_DETECT		BIT(12)
+#define SIFIVE_TMC_PGPREP_INTERNAL_ABORT	BIT(2)
+#define SIFIVE_TMC_PGPREP_ENARSP		(SIFIVE_TMC_PGPREP_CLFPNOTQ | \
+						 SIFIVE_TMC_PGPREP_PMCENAERR | \
+						 SIFIVE_TMC_PGPREP_PMCDENY | \
+						 SIFIVE_TMC_PGPREP_BUSERR | \
+						 SIFIVE_TMC_PGPREP_WAKE_DETECT)
+
+/* TMC.PG */
+#define SIFIVE_TMC_PG_OFF			0x4
+#define SIFIVE_TMC_PG_ENA_REQ			BIT(31)
+#define SIFIVE_TMC_PG_ENA_ACK			BIT(30)
+#define SIFIVE_TMC_PG_DIS_REQ			BIT(29)
+#define SIFIVE_TMC_PG_DIS_ACK			BIT(28)
+#define SIFIVE_TMC_PG_PMC_ENA_ERR		BIT(17)
+#define SIFIVE_TMC_PG_PMC_DENY			BIT(16)
+#define SIFIVE_TMC_PG_BUS_ERR			BIT(15)
+#define SIFIVE_TMC_PG_MASTNOTQ			BIT(14)
+#define SIFIVE_TMC_PG_WARM_RESET		BIT(1)
+#define SIFIVE_TMC_PG_ENARSP			(SIFIVE_TMC_PG_PMC_ENA_ERR | \
+						 SIFIVE_TMC_PG_PMC_DENY | \
+						 SIFIVE_TMC_PG_BUS_ERR | \
+						 SIFIVE_TMC_PG_MASTNOTQ)
+
+/* TMC.RESUMEPC */
+#define SIFIVE_TMC_RESUMEPC_LO			0x10
+#define SIFIVE_TMC_RESUMEPC_HI			0x14
+
+/* TMC.WAKEMASK */
+#define SIFIVE_TMC_WAKE_MASK_OFF		0x20
+#define SIFIVE_TMC_WAKE_MASK_WREQ		BIT(31)
+#define SIFIVE_TMC_WAKE_MASK_ACK		BIT(30)
+
+static void sifive_tmc0_set_resumepc(physical_addr_t addr)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+
+	writel((u32)addr, (void *)(tmc0->reg + SIFIVE_TMC_RESUMEPC_LO));
+	writel((u32)(addr >> 32), (void *)(tmc0->reg + SIFIVE_TMC_RESUMEPC_HI));
+}
+
+static u32 sifive_tmc0_set_pgprep_enareq(void)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+	unsigned long reg = tmc0->reg + SIFIVE_TMC_PGPREP_OFF;
+	u32 v = readl((void *)reg);
+
+	writel(v | SIFIVE_TMC_PGPREP_ENA_REQ, (void *)reg);
+	while (!(readl((void *)reg) & SIFIVE_TMC_PGPREP_ENA_ACK));
+
+	v = readl((void *)reg);
+	return v & SIFIVE_TMC_PGPREP_INTERNAL_ABORT;
+}
+
+static void sifive_tmc0_set_pgprep_disreq(void)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+	unsigned long reg = tmc0->reg + SIFIVE_TMC_PGPREP_OFF;
+	u32 v = readl((void *)reg);
+
+	writel(v | SIFIVE_TMC_PGPREP_DIS_REQ, (void *)reg);
+	while (!(readl((void *)reg) & SIFIVE_TMC_PGPREP_DIS_ACK));
+}
+
+static u32 sifive_tmc0_get_pgprep_enarsp(void)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+	unsigned long reg = tmc0->reg + SIFIVE_TMC_PGPREP_OFF;
+	u32 v = readl((void *)reg);
+
+	return v & SIFIVE_TMC_PGPREP_ENARSP;
+}
+
+static void sifive_tmc0_set_pg_enareq(void)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+	unsigned long reg = tmc0->reg + SIFIVE_TMC_PG_OFF;
+	u32 v = readl((void *)reg);
+
+	writel(v | SIFIVE_TMC_PG_ENA_REQ, (void *)reg);
+}
+
+static int sifive_tmc0_prep(void)
+{
+	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+	u32 rc;
+
+	if (!tmc0_ptr_get(scratch))
+		return SBI_ENODEV;
+
+	rc = sifive_tmc0_set_pgprep_enareq();
+	if (rc) {
+		sbi_printf("TMC0 error: Internal Abort (Wake detect)\n");
+		goto fail;
+	}
+
+	rc = sifive_tmc0_get_pgprep_enarsp();
+	if (rc) {
+		sifive_tmc0_set_pgprep_disreq();
+		sbi_printf("TMC0 error: error response code: 0x%x\n", rc);
+		goto fail;
+	}
+
+	sifive_tmc0_set_resumepc(scratch->warmboot_addr);
+
+	return SBI_OK;
+
+fail:
+	return SBI_EFAIL;
+}
+
+static int sifive_tmc0_enter(void)
+{
+	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+	u32 rc;
+
+	/* Flush cache and check if there is wake detect or bus error */
+	if (fdt_cmo_private_flc_flush_all() &&
+	    sbi_hart_has_extension(scratch, SBI_HART_EXT_XSF_CFLUSH_D_L1))
+		sifive_cflush();
+
+	rc = sifive_tmc0_get_pgprep_enarsp();
+	if (rc) {
+		sbi_printf("TMC0 error: error response code: 0x%x\n", rc);
+		goto fail;
+	}
+
+	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_XSF_CEASE)) {
+		sifive_tmc0_set_pg_enareq();
+		while (1)
+			sifive_cease();
+	}
+
+	rc = SBI_ENOTSUPP;
+fail:
+	sifive_tmc0_set_pgprep_disreq();
+	return rc;
+}
+
+static int sifive_tmc0_tile_pg(void)
+{
+	int rc;
+
+	rc = sifive_tmc0_prep();
+	if (rc)
+		return rc;
+
+	return sifive_tmc0_enter();
+}
+
+static struct sifive_tmc0 *sifive_tmc0_find(u32 id)
+{
+	struct sifive_tmc0 *tmc0;
+
+	sbi_list_for_each_entry(tmc0, &tmc0_list, node) {
+		if (tmc0->id == id)
+			return tmc0;
+	}
+
+	return NULL;
+}
+
+static int sifive_tmc0_add(struct sifive_tmc0 *tmc0)
+{
+	if (!tmc0)
+		return SBI_ENODEV;
+
+	if (sifive_tmc0_find(tmc0->id))
+		return SBI_EALREADY;
+
+	sbi_list_add(&tmc0->node, &tmc0_list);
+
+	return SBI_OK;
+}
+
+static int sifive_tmc0_probe(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+	struct sifive_tmc0 *tmc0;
+	int rc;
+	u64 addr;
+
+	tmc0 = sbi_zalloc(sizeof(*tmc0));
+	if (!tmc0)
+		return SBI_ENOMEM;
+
+	rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
+	if (rc)
+		goto free_tmc0;
+
+	tmc0->reg = (unsigned long)addr;
+	tmc0->id = nodeoff;
+
+	rc = sifive_tmc0_add(tmc0);
+	if (rc)
+		goto free_tmc0;
+
+	return SBI_OK;
+
+free_tmc0:
+	sbi_free(tmc0);
+	return rc;
+}
+
+static const struct fdt_match sifive_tmc0_match[] = {
+	{ .compatible = "sifive,tmc0" },
+	{ },
+};
+
+const struct fdt_driver fdt_sifive_tmc0 = {
+	.match_table = sifive_tmc0_match,
+	.init = sifive_tmc0_probe,
+};
+
+static const struct fdt_driver *const sifive_tmc0_drivers[] = {
+	&fdt_sifive_tmc0,
+	NULL
+};
+
+static int fdt_sifive_tmc0_get(const void *fdt, int noff, struct sifive_tmc0 **out)
+{
+	struct sifive_tmc0 *tmc0;
+	int rc;
+
+	noff = fdt_node_offset_by_phandle(fdt, noff);
+	if (noff < 0)
+		return noff;
+
+	rc = fdt_driver_init_by_offset(fdt, noff, sifive_tmc0_drivers);
+	if (rc)
+		return rc;
+
+	tmc0 = sifive_tmc0_find(noff);
+	if (!tmc0)
+		return SBI_EFAIL;
+
+	if (out)
+		*out = tmc0;
+
+	return SBI_OK;
+}
+
+static int fdt_sifive_tmc0_cold_init(const void *fdt)
+{
+	struct sbi_scratch *scratch;
+	struct sifive_tmc0 *tmc0;
+	const fdt32_t *val;
+	int cpus_off, cpu_off, rc;
+	u32 hartid;
+
+	cpus_off = fdt_path_offset(fdt, "/cpus");
+	if (cpus_off < 0)
+		return SBI_ENOENT;
+
+	fdt_for_each_subnode(cpu_off, fdt, cpus_off) {
+		rc = fdt_parse_hart_id(fdt, cpu_off, &hartid);
+		if (rc)
+			continue;
+
+		val = fdt_getprop(fdt, cpu_off, "power-domains", NULL);
+		if (!val)
+			return SBI_ENOENT;
+
+		rc = fdt_sifive_tmc0_get(fdt, fdt32_to_cpu(val[0]), &tmc0);
+		if (rc)
+			return rc;
+
+		scratch = sbi_hartid_to_scratch(hartid);
+		if (!scratch)
+			continue;
+
+		tmc0_ptr_set(scratch, tmc0);
+	}
+
+	return SBI_OK;
+}
+
+static int sifive_tmc0_start(u32 hartid, ulong saddr)
+{
+	struct sbi_ipi_device *clint = aclint_mswi_get();
+
+	/*
+	 * In system suspend, the IMSIC will be reset in SiFive platform so
+	 * we use the CLINT IPI as the wake event.
+	 */
+	if (clint && clint->ipi_send)
+		clint->ipi_send(sbi_hartid_to_hartindex(hartid));
+	else
+		sbi_ipi_raw_send(sbi_hartid_to_hartindex(hartid));
+
+	return SBI_OK;
+}
+
+static int sifive_tmc0_stop(void)
+{
+	unsigned long mie = csr_read(CSR_MIE);
+	int rc;
+	// Set IPI as wake up source
+	csr_set(CSR_MIE, MIP_MEIP | MIP_MSIP);
+
+	rc = sifive_tmc0_tile_pg();
+	if (rc) {
+		csr_write(CSR_MIE, mie);
+		return rc;
+	}
+
+	return SBI_OK;
+}
+
+static struct sbi_hsm_device tmc0_hsm_dev = {
+	.name = "SiFive TMC0",
+	.hart_start = sifive_tmc0_start,
+	.hart_stop = sifive_tmc0_stop,
+};
+
+int sifive_tmc0_cold_init(void)
+{
+	tmc0_offset = sbi_scratch_alloc_type_offset(struct sifive_tmc0 *);
+	if (!tmc0_offset)
+		return SBI_ENOMEM;
+
+	sbi_hsm_set_device(&tmc0_hsm_dev);
+	return fdt_sifive_tmc0_cold_init(fdt_get_address());
+}
diff --git a/platform/generic/sifive/sifive_dev_platform.c b/platform/generic/sifive/sifive_dev_platform.c
index ac659868..3e433bb3 100644
--- a/platform/generic/sifive/sifive_dev_platform.c
+++ b/platform/generic/sifive/sifive_dev_platform.c
@@ -5,7 +5,11 @@
  */
 
 #include <platform_override.h>
+#include <sbi/sbi_ipi.h>
 #include <sbi_utils/cache/fdt_cmo_helper.h>
+#include <sbi_utils/ipi/aclint_mswi.h>
+
+#include <sifive/sifive_tmc0.h>
 
 static int sifive_early_init(bool cold_boot)
 {
@@ -19,13 +23,30 @@ static int sifive_early_init(bool cold_boot)
 	if (rc)
 		return rc;
 
+	if (cold_boot) {
+		rc = sifive_tmc0_cold_init();
+		if (rc)
+			return rc;
+	}
+
 	return 0;
 }
 
+static int sifive_final_init(bool cold_boot)
+{
+	struct sbi_ipi_device *clint = aclint_mswi_get();
+
+	if (clint && clint->ipi_clear)
+		clint->ipi_clear();
+
+	return generic_final_init(cold_boot);
+}
+
 static int sifive_platform_init(const void *fdt, int nodeoff,
 				const struct fdt_match *match)
 {
 	generic_platform_ops.early_init = sifive_early_init;
+	generic_platform_ops.final_init = sifive_final_init;
 
 	return 0;
 }
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:39 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:39 +0800
Subject: [PATCH v3 11/12] lib: utils/timer: Expose timer update function
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-12-nick.hu@sifive.com>

Exposing the ACLINT timer update APIs so the user can update the mtimer
after waking up from the non-retentive suspend.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 include/sbi_utils/timer/aclint_mtimer.h |  5 +++++
 lib/utils/timer/aclint_mtimer.c         | 28 ++++++++++++++++++-------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/include/sbi_utils/timer/aclint_mtimer.h b/include/sbi_utils/timer/aclint_mtimer.h
index a245e13e..f8d2e5b4 100644
--- a/include/sbi_utils/timer/aclint_mtimer.h
+++ b/include/sbi_utils/timer/aclint_mtimer.h
@@ -42,6 +42,11 @@ struct aclint_mtimer_data {
 	void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
 };
 
+struct aclint_mtimer_data *aclint_get_mtimer_data(void);
+
+void aclint_mtimer_update(struct aclint_mtimer_data *mt,
+			  struct aclint_mtimer_data *ref);
+
 void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
 
 void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
diff --git a/lib/utils/timer/aclint_mtimer.c b/lib/utils/timer/aclint_mtimer.c
index 3db3c3be..fd6189aa 100644
--- a/lib/utils/timer/aclint_mtimer.c
+++ b/lib/utils/timer/aclint_mtimer.c
@@ -109,28 +109,42 @@ static struct sbi_timer_device mtimer = {
 	.timer_event_stop = mtimer_event_stop
 };
 
-void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
+struct aclint_mtimer_data *aclint_get_mtimer_data(void)
+{
+	return mtimer_get_hart_data_ptr(sbi_scratch_thishart_ptr());
+}
+
+void aclint_mtimer_update(struct aclint_mtimer_data *mt,
+			  struct aclint_mtimer_data *ref)
 {
 	u64 v1, v2, mv, delta;
 	u64 *mt_time_val, *ref_time_val;
-	struct aclint_mtimer_data *reference;
 
-	/* Sync-up non-shared MTIME if reference is available */
-	if (mt->has_shared_mtime || !mt->time_delta_reference)
+	if (!mt || !ref || !mt->time_rd || !mt->time_wr || !ref->time_rd)
 		return;
 
-	reference = mt->time_delta_reference;
 	mt_time_val = (void *)mt->mtime_addr;
-	ref_time_val = (void *)reference->mtime_addr;
+	ref_time_val = (void *)ref->mtime_addr;
 	if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
 		v1 = mt->time_rd(mt_time_val);
-		mv = reference->time_rd(ref_time_val);
+		mv = ref->time_rd(ref_time_val);
 		v2 = mt->time_rd(mt_time_val);
 		delta = mv - ((v1 / 2) + (v2 / 2));
 		mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
 			    mt_time_val);
 	}
+}
 
+void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
+{
+	struct aclint_mtimer_data *reference;
+
+	/* Sync-up non-shared MTIME if reference is available */
+	if (mt->has_shared_mtime || !mt->time_delta_reference)
+		return;
+
+	reference = mt->time_delta_reference;
+	aclint_mtimer_update(mt, reference);
 }
 
 void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
-- 
2.17.1



From nick.hu at sifive.com  Tue Jul  8 00:49:40 2025
From: nick.hu at sifive.com (Nick Hu)
Date: Tue,  8 Jul 2025 15:49:40 +0800
Subject: [PATCH v3 12/12] platform: sifive: Add SiFive SMC0 driver
In-Reply-To: <20250708074940.10904-1-nick.hu@sifive.com>
References: <20250708074940.10904-1-nick.hu@sifive.com>
Message-ID: <20250708074940.10904-13-nick.hu@sifive.com>

The SiFive SMC0 controls the clock and power domain of the core complex
on the SiFive platform. The core complex enters the low power state
after the secondary cores enter the tile power gating and last core
execute the `CEASE` instruction with the corresponding SMC0
configurations. The devices that inside both tile power domain and core
complex power domain will be off, including caches and timer. Therefore
we need to flush the last level cache before entering the core complex
power gating and update the timer after waking up.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
Reviewed-by: Cyan Yang <cyan.yang at sifive.com>
---
 platform/generic/Kconfig                      |   1 +
 platform/generic/include/sifive/sifive_smc0.h |  13 +
 platform/generic/include/sifive/sifive_tmc0.h |   3 +
 platform/generic/sifive/Kconfig               |   5 +
 platform/generic/sifive/objects.mk            |   2 +
 .../pmdomain/fdt_pmdomain_sifive_smc0.c       | 322 ++++++++++++++++++
 .../pmdomain/fdt_pmdomain_sifive_tmc0.c       |  88 +++++
 7 files changed, 434 insertions(+)
 create mode 100644 platform/generic/include/sifive/sifive_smc0.h
 create mode 100644 platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_smc0.c

diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 1d6ea3f4..048822ef 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -46,6 +46,7 @@ config PLATFORM_RENESAS_RZFIVE
 config PLATFORM_SIFIVE_DEV
 	bool "SiFive development platform support"
 	depends on FDT_CACHE
+	select SIFIVE_SMC0
 	select SIFIVE_TMC0
 	default n
 
diff --git a/platform/generic/include/sifive/sifive_smc0.h b/platform/generic/include/sifive/sifive_smc0.h
new file mode 100644
index 00000000..d13bdf4d
--- /dev/null
+++ b/platform/generic/include/sifive/sifive_smc0.h
@@ -0,0 +1,13 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __SIFIVE_SMC0_H__
+#define __SIFIVE_SMC0_H__
+
+bool sifive_smc0_check_warm_reset(void);
+void sifive_smc0_mtime_update(void);
+
+#endif
diff --git a/platform/generic/include/sifive/sifive_tmc0.h b/platform/generic/include/sifive/sifive_tmc0.h
index 6100e0dc..ad0d2407 100644
--- a/platform/generic/include/sifive/sifive_tmc0.h
+++ b/platform/generic/include/sifive/sifive_tmc0.h
@@ -7,6 +7,9 @@
 #ifndef __SIFIVE_TMC0_H__
 #define __SIFIVE_TMC0_H__
 
+int sifive_tmc0_set_wakemask_enareq(u32 hartid);
+void sifive_tmc0_set_wakemask_disreq(u32 hartid);
+bool sifive_tmc0_is_pg(u32 hartid);
 int sifive_tmc0_cold_init(void);
 
 #endif
diff --git a/platform/generic/sifive/Kconfig b/platform/generic/sifive/Kconfig
index 2cbcea08..efb00c02 100644
--- a/platform/generic/sifive/Kconfig
+++ b/platform/generic/sifive/Kconfig
@@ -1,5 +1,10 @@
 # SPDX-License-Identifier: BSD-2-Clause
 
+
+config SIFIVE_SMC0
+	bool "SiFive SMC v0 driver support"
+	default n
+
 config SIFIVE_TMC0
 	bool "SiFive TMC v0 driver support"
 	default n
diff --git a/platform/generic/sifive/objects.mk b/platform/generic/sifive/objects.mk
index f8938713..28001453 100644
--- a/platform/generic/sifive/objects.mk
+++ b/platform/generic/sifive/objects.mk
@@ -11,4 +11,6 @@ platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive/fu540.o
 carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive_fu740
 platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive/fu740.o
 
+carray-fdt_early_drivers-$(CONFIG_SIFIVE_SMC0) += fdt_sifive_smc0
+platform-objs-$(CONFIG_SIFIVE_SMC0) += sifive/pmdomain/fdt_pmdomain_sifive_smc0.o
 platform-objs-$(CONFIG_SIFIVE_TMC0) += sifive/pmdomain/fdt_pmdomain_sifive_tmc0.o
diff --git a/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_smc0.c b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_smc0.c
new file mode 100644
index 00000000..6c6d5d1f
--- /dev/null
+++ b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_smc0.c
@@ -0,0 +1,322 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/timer/aclint_mtimer.h>
+#include <sifive/sifive_inst.h>
+#include <sifive/sifive_smc0.h>
+#include <sifive/sifive_tmc0.h>
+
+#define SIFIVE_SMC_PGPREP_OFF			0x0
+#define SIFIVE_SMC_PG_OFF			0x4
+#define SIFIVE_SMC_CCTIMER_OFF			0xc
+#define SIFIVE_SMC_RESUMEPC_LO_OFF		0x10
+#define SIFIVE_SMC_RESUMEPC_HI_OFF		0x14
+#define SIFIVE_SMC_SYNC_PMC_OFF			0x24
+#define SIFIVE_SMC_CYCLECOUNT_LO_OFF		0x28
+#define SIFIVE_SMC_CYCLECOUNT_HI_OFF		0x2c
+#define SIFIVE_SMC_WFI_UNCORE_CG_OFF		0x50
+
+#define SIFIVE_SMC_PGPREP_ENA_REQ		BIT(31)
+#define SIFIVE_SMC_PGPREP_ENA_ACK		BIT(30)
+#define SIFIVE_SMC_PGPREP_DIS_REQ		BIT(29)
+#define SIFIVE_SMC_PGPREP_DIS_ACK		BIT(29)
+#define SIFIVE_SMC_PGPREP_FRONTNOTQ		BIT(19)
+#define SIFIVE_SMC_PGPREP_CLFPNOTQ		BIT(18)
+#define SIFIVE_SMC_PGPREP_PMCENAERR		BIT(17)
+#define SIFIVE_SMC_PGPREP_WAKE_DETECT		BIT(16)
+#define SIFIVE_SMC_PGPREP_BUSERR		BIT(15)
+#define SIFIVE_SMC_PGPREP_EARLY_ABORT		BIT(3)
+#define SIFIVE_SMC_PGPREP_INTERNAL_ABORT	BIT(2)
+#define SIFIVE_SMC_PGPREP_ENARSP		(SIFIVE_SMC_PGPREP_FRONTNOTQ | \
+						 SIFIVE_SMC_PGPREP_CLFPNOTQ | \
+						 SIFIVE_SMC_PGPREP_PMCENAERR | \
+						 SIFIVE_SMC_PGPREP_WAKE_DETECT | \
+						 SIFIVE_SMC_PGPREP_BUSERR)
+
+#define SIFIVE_SMC_PGPREP_ABORT			(SIFIVE_SMC_PGPREP_EARLY_ABORT | \
+						 SIFIVE_SMC_PGPREP_INTERNAL_ABORT)
+
+#define SIFIVE_SMC_PG_ENA_REQ			BIT(31)
+#define SIFIVE_SMC_PG_WARM_RESET		BIT(1)
+
+#define SIFIVE_SMC_SYNCPMC_SYNC_REQ		BIT(31)
+#define SIFIVE_SMC_SYNCPMC_SYNC_WREQ		BIT(30)
+#define SIFIVE_SMC_SYNCPMC_SYNC_ACK		BIT(29)
+
+static struct aclint_mtimer_data smc_sync_timer;
+static unsigned long smc0_base;
+
+static void sifive_smc0_set_pmcsync(char regid, bool write_mode)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_SYNC_PMC_OFF;
+	u32 v = regid | SIFIVE_SMC_SYNCPMC_SYNC_REQ;
+
+	if (write_mode)
+		v |= SIFIVE_SMC_SYNCPMC_SYNC_WREQ;
+
+	writel(v, (void *)addr);
+	while (!(readl((void *)addr) & SIFIVE_SMC_SYNCPMC_SYNC_ACK));
+}
+
+static u64 sifive_smc0_time_read(volatile u64 *addr)
+{
+	u32 lo, hi;
+
+	do {
+		sifive_smc0_set_pmcsync(SIFIVE_SMC_CYCLECOUNT_LO_OFF, false);
+		sifive_smc0_set_pmcsync(SIFIVE_SMC_CYCLECOUNT_HI_OFF, false);
+		hi = readl_relaxed((u32 *)addr + 1);
+		lo = readl_relaxed((u32 *)addr);
+	} while (hi != readl_relaxed((u32 *)addr + 1));
+
+	return ((u64)hi << 32) | (u64)lo;
+}
+
+static void sifive_smc0_set_resumepc(physical_addr_t raddr)
+{
+	/* Set resumepc_lo */
+	writel((u32)raddr, (void *)(smc0_base + SIFIVE_SMC_RESUMEPC_LO_OFF));
+	/* copy resumepc_lo from SMC to PMC */
+	sifive_smc0_set_pmcsync(SIFIVE_SMC_RESUMEPC_LO_OFF, true);
+
+	/* Set resumepc_hi */
+	writel((u32)(raddr >> 32), (void *)(smc0_base + SIFIVE_SMC_RESUMEPC_HI_OFF));
+	/* copy resumepc_hi from SMC to PMC */
+	sifive_smc0_set_pmcsync(SIFIVE_SMC_RESUMEPC_HI_OFF, true);
+}
+
+static u32 sifive_smc0_get_pgprep_enarsp(void)
+{
+	u32 v = readl((void *)(smc0_base + SIFIVE_SMC_PGPREP_OFF));
+
+	return v & SIFIVE_SMC_PGPREP_ENARSP;
+}
+
+static void sifive_smc0_set_pgprep_disreq(void)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_PGPREP_OFF;
+	u32 v = readl((void *)addr);
+
+	writel(v | SIFIVE_SMC_PGPREP_DIS_REQ, (void *)addr);
+	while (!(readl((void *)addr) & SIFIVE_SMC_PGPREP_DIS_ACK));
+}
+
+static u32 sifive_smc0_set_pgprep_enareq(void)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_PGPREP_OFF;
+	u32 v = readl((void *)addr);
+
+	writel(v | SIFIVE_SMC_PGPREP_ENA_REQ, (void *)addr);
+	while (!(readl((void *)addr) & SIFIVE_SMC_PGPREP_ENA_ACK));
+
+	v = readl((void *)addr);
+
+	return v & SIFIVE_SMC_PGPREP_ABORT;
+}
+
+static void sifive_smc0_set_pg_enareq(void)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_PG_OFF;
+	u32 v = readl((void *)addr);
+
+	writel(v | SIFIVE_SMC_PG_ENA_REQ, (void *)addr);
+}
+
+bool sifive_smc0_check_warm_reset(void)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_PG_OFF;
+
+	if (!smc0_base)
+		return false;
+
+	sifive_smc0_set_pmcsync(SIFIVE_SMC_PG_OFF, false);
+
+	return readl((void *)addr) & SIFIVE_SMC_PG_WARM_RESET ? true : false;
+}
+
+static inline void sifive_smc0_set_cg(bool enable)
+{
+	unsigned long addr = smc0_base + SIFIVE_SMC_WFI_UNCORE_CG_OFF;
+
+	if (enable)
+		writel(0, (void *)addr);
+	else
+		writel(1, (void *)addr);
+}
+
+static int sifive_smc0_prep(void)
+{
+	const struct sbi_domain *dom = &root;
+	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+	unsigned long i;
+	int rc;
+	u32 target;
+
+	if (!smc0_base)
+		return SBI_ENODEV;
+
+	/* Prevent all secondary tiles from waking up from PG state */
+	sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
+		target = sbi_hartindex_to_hartid(i);
+		if (target != current_hartid()) {
+			rc = sifive_tmc0_set_wakemask_enareq(target);
+			if (rc) {
+				sbi_printf("Fail to enable wakemask for hart %d\n",
+					   target);
+				goto fail;
+			}
+		}
+	}
+
+	/* Check if all secondary tiles enter PG state */
+	sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
+		target = sbi_hartindex_to_hartid(i);
+		if (target != current_hartid() &&
+		    !sifive_tmc0_is_pg(target)) {
+			sbi_printf("Hart %d not in the PG state\n", target);
+			goto fail;
+		}
+	}
+
+	rc = sifive_smc0_set_pgprep_enareq();
+	if (rc) {
+		sbi_printf("SMC0 error: abort code: 0x%x\n", rc);
+		goto fail;
+	}
+
+	rc = sifive_smc0_get_pgprep_enarsp();
+	if (rc) {
+		sifive_smc0_set_pgprep_disreq();
+		sbi_printf("SMC0 error: error response code: 0x%x\n", rc);
+		goto fail;
+	}
+
+	sifive_smc0_set_resumepc(scratch->warmboot_addr);
+	return SBI_OK;
+fail:
+	sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
+		target = sbi_hartindex_to_hartid(i);
+		if (target != current_hartid())
+			sifive_tmc0_set_wakemask_disreq(target);
+	}
+
+	return SBI_EFAIL;
+}
+
+static int sifive_smc0_enter(void)
+{
+	const struct sbi_domain *dom = &root;
+	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+	unsigned long i;
+	u32 target, rc;
+
+	/* Flush cache and check if there is wake detect or bus error */
+	if (fdt_cmo_llc_flush_all() &&
+	    sbi_hart_has_extension(scratch, SBI_HART_EXT_XSF_CFLUSH_D_L1))
+		sifive_cflush();
+
+	rc = sifive_smc0_get_pgprep_enarsp();
+	if (rc) {
+		sbi_printf("SMC0 error: error response code: 0x%x\n", rc);
+		rc = SBI_EFAIL;
+		goto fail;
+	}
+
+	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_XSF_CEASE)) {
+		sifive_smc0_set_pg_enareq();
+		while (1)
+			sifive_cease();
+	}
+
+	rc = SBI_ENOTSUPP;
+fail:
+	sifive_smc0_set_pgprep_disreq();
+	sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
+		target = sbi_hartindex_to_hartid(i);
+		if (target != current_hartid())
+			sifive_tmc0_set_wakemask_disreq(target);
+	}
+	return rc;
+}
+
+static int sifive_smc0_pg(void)
+{
+	int rc;
+
+	rc = sifive_smc0_prep();
+	if (rc)
+		return rc;
+
+	return sifive_smc0_enter();
+}
+
+static int sifive_smc0_system_suspend(u32 sleep_type, unsigned long addr)
+{
+	/* Disable the timer interrupt */
+	sbi_timer_exit(sbi_scratch_thishart_ptr());
+
+	return sifive_smc0_pg();
+}
+
+static int sifive_smc0_system_suspend_check(u32 sleep_type)
+{
+	return sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND ? SBI_OK : SBI_EINVAL;
+}
+
+static struct sbi_system_suspend_device smc0_sys_susp = {
+	.name = "Sifive SMC0",
+	.system_suspend_check = sifive_smc0_system_suspend_check,
+	.system_suspend = sifive_smc0_system_suspend,
+};
+
+void sifive_smc0_mtime_update(void)
+{
+	struct aclint_mtimer_data *mt = aclint_get_mtimer_data();
+
+	aclint_mtimer_update(mt, &smc_sync_timer);
+}
+
+static int sifive_smc0_probe(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+	int rc;
+	u64 addr;
+
+	rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
+	if (rc)
+		return rc;
+
+	smc0_base = (unsigned long)addr;
+	smc_sync_timer.time_rd = sifive_smc0_time_read;
+	smc_sync_timer.mtime_addr = smc0_base + SIFIVE_SMC_CYCLECOUNT_LO_OFF;
+
+	sbi_system_suspend_set_device(&smc0_sys_susp);
+	sifive_smc0_set_cg(true);
+
+	return SBI_OK;
+}
+
+static const struct fdt_match sifive_smc0_match[] = {
+	{ .compatible = "sifive,smc0" },
+	{ },
+};
+
+const struct fdt_driver fdt_sifive_smc0 = {
+	.match_table = sifive_smc0_match,
+	.init = sifive_smc0_probe,
+};
diff --git a/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
index 70d02b33..359c0be7 100644
--- a/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
+++ b/platform/generic/sifive/pmdomain/fdt_pmdomain_sifive_tmc0.c
@@ -18,7 +18,9 @@
 #include <sbi_utils/fdt/fdt_driver.h>
 #include <sbi_utils/fdt/fdt_helper.h>
 #include <sbi_utils/ipi/aclint_mswi.h>
+#include <sbi_utils/irqchip/aplic.h>
 #include <sifive/sifive_inst.h>
+#include <sifive/sifive_smc0.h>
 #include <sifive/sifive_tmc0.h>
 
 struct sifive_tmc0 {
@@ -79,6 +81,73 @@ static unsigned long tmc0_offset;
 #define SIFIVE_TMC_WAKE_MASK_WREQ		BIT(31)
 #define SIFIVE_TMC_WAKE_MASK_ACK		BIT(30)
 
+int sifive_tmc0_set_wakemask_enareq(u32 hartid)
+{
+	struct sbi_scratch *scratch = sbi_hartid_to_scratch(hartid);
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(scratch);
+	unsigned long addr;
+	u32 v;
+
+	if (!tmc0)
+		return SBI_ENODEV;
+
+	addr = tmc0->reg + SIFIVE_TMC_WAKE_MASK_OFF;
+	v = readl((void *)addr);
+	writel(v | SIFIVE_TMC_WAKE_MASK_WREQ, (void *)addr);
+
+	while (!(readl((void *)addr) & SIFIVE_TMC_WAKE_MASK_ACK));
+
+	return SBI_OK;
+}
+
+void sifive_tmc0_set_wakemask_disreq(u32 hartid)
+{
+	struct sbi_scratch *scratch = sbi_hartid_to_scratch(hartid);
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(scratch);
+	unsigned long addr;
+	u32 v;
+
+	if (!tmc0)
+		return;
+
+	addr = tmc0->reg + SIFIVE_TMC_WAKE_MASK_OFF;
+	v = readl((void *)addr);
+	writel(v & ~SIFIVE_TMC_WAKE_MASK_WREQ, (void *)addr);
+
+	while (readl((void *)addr) & SIFIVE_TMC_WAKE_MASK_ACK);
+}
+
+bool sifive_tmc0_is_pg(u32 hartid)
+{
+	struct sbi_scratch *scratch = sbi_hartid_to_scratch(hartid);
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(scratch);
+	unsigned long addr;
+	u32 v;
+
+	if (!tmc0)
+		return false;
+
+	addr = tmc0->reg + SIFIVE_TMC_PG_OFF;
+	v = readl((void *)addr);
+	if (!(v & SIFIVE_TMC_PG_ENA_ACK) ||
+	    (v & SIFIVE_TMC_PG_ENARSP) ||
+	    (v & SIFIVE_TMC_PG_DIS_REQ))
+		return false;
+
+	return true;
+}
+
+static bool sifive_tmc0_check_warm_reset(void)
+{
+	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
+	unsigned long addr = tmc0->reg + SIFIVE_TMC_PG_OFF;
+
+	if (!tmc0)
+		return false;
+
+	return readl((void *)addr) & SIFIVE_TMC_PG_WARM_RESET ? true : false;
+}
+
 static void sifive_tmc0_set_resumepc(physical_addr_t addr)
 {
 	struct sifive_tmc0 *tmc0 = tmc0_ptr_get(sbi_scratch_thishart_ptr());
@@ -354,10 +423,29 @@ static int sifive_tmc0_stop(void)
 	return SBI_OK;
 }
 
+static void sifive_pg_resume(void)
+{
+	/*
+	 * To simplify the implementation, the SW won't clear the warm
+	 * reset bit. If the system woken up from the Core Complex power
+	 * gating, the warm reset bit of the TMC0 will be clear. Therefore
+	 * we need to check the warm reset bit of the TMC0 first as the
+	 * Tile power gating won't clear the warm reset bit of the SMC0.
+	 */
+	if (sifive_tmc0_check_warm_reset())
+		return;
+
+	if (sifive_smc0_check_warm_reset()) {
+		aplic_restore();
+		sifive_smc0_mtime_update();
+	}
+}
+
 static struct sbi_hsm_device tmc0_hsm_dev = {
 	.name = "SiFive TMC0",
 	.hart_start = sifive_tmc0_start,
 	.hart_stop = sifive_tmc0_stop,
+	.hart_resume = sifive_pg_resume,
 };
 
 int sifive_tmc0_cold_init(void)
-- 
2.17.1



From max.hsu at sifive.com  Tue Jul  8 03:48:09 2025
From: max.hsu at sifive.com (Max Hsu)
Date: Tue, 08 Jul 2025 18:48:09 +0800
Subject: [PATCH] lib: utils: fdt: fix "ranges" translation
Message-ID: <20250708-dev-maxh-master_fdt_helper-v1-1-866c165f1f85@sifive.com>

According to the Device Tree Spec, Chapter 2.3.8 "ranges" [1]:
The parent address size will be determined from the #address-cells
property of the node that defines the parent?s address space.

In fdt_translate_address(), which considered the parent address size
is equal to the child address size; This commit fix to parse two
address sizes and parsing the address independently.

Link: https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#ranges [1]

Signed-off-by: Max Hsu <max.hsu at sifive.com>
---
 lib/utils/fdt/fdt_helper.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index 0f4859c1a721bc7c2871bacefe27caba7780f752..779149942dd9c7eb5182fee32e9fe7f05c3752cf 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -84,12 +84,16 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
 				 uint64_t *addr)
 {
 	int i, rlen;
-	int cell_addr, cell_size;
+	int cell_parent_addr, cell_child_addr, cell_size;
 	const fdt32_t *ranges;
 	uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
 
-	cell_addr = fdt_address_cells(fdt, parent);
-	if (cell_addr < 1)
+	cell_child_addr = fdt_address_cells(fdt, parent);
+	if (cell_child_addr < 1)
+		return SBI_ENODEV;
+
+	cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
+	if (cell_parent_addr < 1)
 		return SBI_ENODEV;
 
 	cell_size = fdt_size_cells(fdt, parent);
@@ -98,9 +102,9 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
 
 	ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
 	if (ranges && rlen > 0) {
-		for (i = 0; i < cell_addr; i++)
+		for (i = 0; i < cell_child_addr; i++)
 			caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
-		for (i = 0; i < cell_addr; i++)
+		for (i = 0; i < cell_parent_addr; i++)
 			paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
 		for (i = 0; i < cell_size; i++)
 			rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);

---
base-commit: a32a91069119e7a5aa31e6bc51d5e00860be3d80
change-id: 20250708-dev-maxh-master_fdt_helper-46d2eeeb07cd

Best regards,
-- 
Max Hsu <max.hsu at sifive.com>



From maherme.dev at gmail.com  Tue Jul  8 11:09:14 2025
From: maherme.dev at gmail.com (=?UTF-8?q?Manuel=20Hern=C3=A1ndez=20M=C3=A9ndez?=)
Date: Tue,  8 Jul 2025 20:09:14 +0200
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
Message-ID: <20250708180914.1131-1-maherme.dev@gmail.com>

The plic_data struct was uninitialized. This led to misfunction behavior
since it was subsequently assigned to the global plic struct, and some
struct fields, such as flags and irqchip, contained random values.
The fix proposes to initialize the plic_data to the global plic struct,
so, after parsing the fdt, the fields of the struct will be set to the
default values set in global plic struct definition, or the parsed values
in the fdt, or zero.

Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
device tree")
Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
---
 platform/fpga/openpiton/platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
index d2cf3e32..faa299ce 100644
--- a/platform/fpga/openpiton/platform.c
+++ b/platform/fpga/openpiton/platform.c
@@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
 {
 	const void *fdt;
 	struct platform_uart_data uart_data = { 0 };
-	struct plic_data plic_data;
+	struct plic_data plic_data = plic;
 	unsigned long aclint_freq;
 	uint64_t clint_addr;
 	int rc;
-- 
2.34.1



From rahul at summations.net  Tue Jul  8 19:15:05 2025
From: rahul at summations.net (Rahul Pathak)
Date: Wed, 9 Jul 2025 07:45:05 +0530
Subject: [PATCH] include: sbi: fix swap errors with newer gcc -Werror=sequence-point
In-Reply-To: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
References: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
Message-ID: <CABdD5xnyfwv3u7pBLwVfUWhpH0cr+SzFMOQKdWb3OgUgLDNB_g@mail.gmail.com>

On Fri, Jul 4, 2025 at 5:59?PM Ben Dooks <ben.dooks at codethink.co.uk> wrote:
>
> The BSWAPxx() macros are now throwing the following warnings with
> newer gcc versions. This is due to throwing an argument in that may
> be evaluated more than one (I think) and therefore things like the
> example below should be avoided.
>
> Fix by making a set of BSWAPxx() wrappers which specifically onlt

nit: %s/only/onlt ?

> evaluate 'x' once.
>
> In file included lib/sbi/sbi_mpxy.c:21:
> lib/sbi/sbi_mpxy.c: In function ?sbi_mpxy_write_attrs?:
> ib/sbi/sbi_mpxy.c:632:63: error: operation on ?mem_idx? may be undefined [-Werror=sequence-point]
>   632 |                         attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
>       |                                                        ~~~~~~~^~
>

May I ask which gcc version?

LGTM

Reviewed-by: Rahul Pathak <rahul at summations.net>


From wxjstz at 126.com  Tue Jul  8 23:04:32 2025
From: wxjstz at 126.com (Xiang W)
Date: Wed, 09 Jul 2025 14:04:32 +0800
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
In-Reply-To: <20250708180914.1131-1-maherme.dev@gmail.com>
References: <20250708180914.1131-1-maherme.dev@gmail.com>
Message-ID: <bf236a28adababc9cf5b34265ad8a6e6ad6c3c9f.camel@126.com>

? 2025-07-08?? 20:09 +0200?Manuel Hern?ndez M?ndez???
> The plic_data struct was uninitialized. This led to misfunction behavior
> since it was subsequently assigned to the global plic struct, and some
> struct fields, such as flags and irqchip, contained random values.
> The fix proposes to initialize the plic_data to the global plic struct,
> so, after parsing the fdt, the fields of the struct will be set to the
> default values set in global plic struct definition, or the parsed values
> in the fdt, or zero.
> 
> Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
> device tree")
> Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>

Good catch. Maybe we can directy pass uart/plic to?
fdt_parse_uart8250/fdt_parse_plic

Regards,
Xiang W
> ---
> ?platform/fpga/openpiton/platform.c | 2 +-
> ?1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index d2cf3e32..faa299ce 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
> ?{
> ?	const void *fdt;
> ?	struct platform_uart_data uart_data = { 0 };
> -	struct plic_data plic_data;
> +	struct plic_data plic_data = plic;
> ?	unsigned long aclint_freq;
> ?	uint64_t clint_addr;
> ?	int rc;
> -- 
> 2.34.1
> 



From maherme.dev at gmail.com  Wed Jul  9 01:33:58 2025
From: maherme.dev at gmail.com (=?UTF-8?Q?Manuel_Hern=C3=A1ndez_M=C3=A9ndez?=)
Date: Wed, 9 Jul 2025 10:33:58 +0200
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
In-Reply-To: <bf236a28adababc9cf5b34265ad8a6e6ad6c3c9f.camel@126.com>
References: <20250708180914.1131-1-maherme.dev@gmail.com> <bf236a28adababc9cf5b34265ad8a6e6ad6c3c9f.camel@126.com>
Message-ID: <CACwcpNua92O91DRsYmuOgs8ZetOG4FzvXJ82=+Qp+cf4GU2vUw@mail.gmail.com>

With this approach, the struct will be set either to all the parsed values
from the FDT or to the default ones, but not to an intermediate state.
If we directly pass uart/plic to fdt_parse_uart8250/fdt_parse_plic and
some failure happens during the parsing process, we end up with an
intermediate state (some values in the struct will be set from the FDT,
while others will remain at their default values).
After all, don't we prefer to leave the structures in a well-defined
state rather than in an intermediate one?


On Wed, Jul 9, 2025 at 8:04?AM Xiang W <wxjstz at 126.com> wrote:
>
> ? 2025-07-08?? 20:09 +0200?Manuel Hern?ndez M?ndez???
> > The plic_data struct was uninitialized. This led to misfunction behavior
> > since it was subsequently assigned to the global plic struct, and some
> > struct fields, such as flags and irqchip, contained random values.
> > The fix proposes to initialize the plic_data to the global plic struct,
> > so, after parsing the fdt, the fields of the struct will be set to the
> > default values set in global plic struct definition, or the parsed values
> > in the fdt, or zero.
> >
> > Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
> > device tree")
> > Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
>
> Good catch. Maybe we can directy pass uart/plic to
> fdt_parse_uart8250/fdt_parse_plic
>
> Regards,
> Xiang W
> > ---
> >  platform/fpga/openpiton/platform.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> > index d2cf3e32..faa299ce 100644
> > --- a/platform/fpga/openpiton/platform.c
> > +++ b/platform/fpga/openpiton/platform.c
> > @@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
> >  {
> >       const void *fdt;
> >       struct platform_uart_data uart_data = { 0 };
> > -     struct plic_data plic_data;
> > +     struct plic_data plic_data = plic;
> >       unsigned long aclint_freq;
> >       uint64_t clint_addr;
> >       int rc;
> > --
> > 2.34.1
> >
>


From ben.dooks at codethink.co.uk  Wed Jul  9 02:22:53 2025
From: ben.dooks at codethink.co.uk (Ben Dooks)
Date: Wed, 9 Jul 2025 10:22:53 +0100
Subject: [PATCH] include: sbi: fix swap errors with newer gcc
 -Werror=sequence-point
In-Reply-To: <CABdD5xnyfwv3u7pBLwVfUWhpH0cr+SzFMOQKdWb3OgUgLDNB_g@mail.gmail.com>
References: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
 <CABdD5xnyfwv3u7pBLwVfUWhpH0cr+SzFMOQKdWb3OgUgLDNB_g@mail.gmail.com>
Message-ID: <36b2031a-9123-43be-a66c-cecbdb626c8a@codethink.co.uk>

On 09/07/2025 03:15, Rahul Pathak wrote:
> On Fri, Jul 4, 2025 at 5:59?PM Ben Dooks <ben.dooks at codethink.co.uk> wrote:
>>
>> The BSWAPxx() macros are now throwing the following warnings with
>> newer gcc versions. This is due to throwing an argument in that may
>> be evaluated more than one (I think) and therefore things like the
>> example below should be avoided.
>>
>> Fix by making a set of BSWAPxx() wrappers which specifically onlt
> 
> nit: %s/only/onlt ?
> 
>> evaluate 'x' once.
>>
>> In file included lib/sbi/sbi_mpxy.c:21:
>> lib/sbi/sbi_mpxy.c: In function ?sbi_mpxy_write_attrs?:
>> ib/sbi/sbi_mpxy.c:632:63: error: operation on ?mem_idx? may be undefined [-Werror=sequence-point]
>>    632 |                         attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
>>        |                                                        ~~~~~~~^~
>>
> 
> May I ask which gcc version?

gcc 15.1 (required as it is the only one that currently builds a
big-endian rootfs with glibc on buildroot)

> LGTM
> 
> Reviewed-by: Rahul Pathak <rahul at summations.net>


-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

https://www.codethink.co.uk/privacy.html


From wxjstz at 126.com  Wed Jul  9 04:45:38 2025
From: wxjstz at 126.com (Xiang W)
Date: Wed, 09 Jul 2025 19:45:38 +0800
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
In-Reply-To: <CACwcpNua92O91DRsYmuOgs8ZetOG4FzvXJ82=+Qp+cf4GU2vUw@mail.gmail.com>
References: <20250708180914.1131-1-maherme.dev@gmail.com>
	 <bf236a28adababc9cf5b34265ad8a6e6ad6c3c9f.camel@126.com>
	 <CACwcpNua92O91DRsYmuOgs8ZetOG4FzvXJ82=+Qp+cf4GU2vUw@mail.gmail.com>
Message-ID: <9410d588c8baaba2a3e866b922e9c70e4f497dad.camel@126.com>

? 2025-07-09?? 10:33 +0200?Manuel Hern?ndez M?ndez???
> With this approach, the struct will be set either to all the parsed values
> from the FDT or to the default ones, but not to an intermediate state.
> If we directly pass uart/plic to fdt_parse_uart8250/fdt_parse_plic and
> some failure happens during the parsing process, we end up with an
> intermediate state (some values in the struct will be set from the FDT,
> while others will remain at their default values).
> After all, don't we prefer to leave the structures in a well-defined
> state rather than in an intermediate one?

These two functions will not produce intermediate states. But in order?
to facilitate future modifications, intermediate states may be introduced.?
So you are right.

Regards,
Xiang W
> 
> 
> On Wed, Jul 9, 2025 at 8:04?AM Xiang W <wxjstz at 126.com> wrote:
> > 
> > ? 2025-07-08?? 20:09 +0200?Manuel Hern?ndez M?ndez???
> > > The plic_data struct was uninitialized. This led to misfunction behavior
> > > since it was subsequently assigned to the global plic struct, and some
> > > struct fields, such as flags and irqchip, contained random values.
> > > The fix proposes to initialize the plic_data to the global plic struct,
> > > so, after parsing the fdt, the fields of the struct will be set to the
> > > default values set in global plic struct definition, or the parsed values
> > > in the fdt, or zero.
> > > 
> > > Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
> > > device tree")
> > > Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
> > 
> > Good catch. Maybe we can directy pass uart/plic to
> > fdt_parse_uart8250/fdt_parse_plic
> > 
> > Regards,
> > Xiang W
> > > ---
> > > ?platform/fpga/openpiton/platform.c | 2 +-
> > > ?1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> > > index d2cf3e32..faa299ce 100644
> > > --- a/platform/fpga/openpiton/platform.c
> > > +++ b/platform/fpga/openpiton/platform.c
> > > @@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
> > > ?{
> > > ????? const void *fdt;
> > > ????? struct platform_uart_data uart_data = { 0 };
> > > -???? struct plic_data plic_data;
> > > +???? struct plic_data plic_data = plic;
> > > ????? unsigned long aclint_freq;
> > > ????? uint64_t clint_addr;
> > > ????? int rc;
> > > --
> > > 2.34.1
> > > 
> > 



From wxjstz at 126.com  Wed Jul  9 04:46:46 2025
From: wxjstz at 126.com (Xiang W)
Date: Wed, 09 Jul 2025 19:46:46 +0800
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
In-Reply-To: <20250708180914.1131-1-maherme.dev@gmail.com>
References: <20250708180914.1131-1-maherme.dev@gmail.com>
Message-ID: <4e1bdd5521fd09e6ebecc3f0fa93a74979801678.camel@126.com>

? 2025-07-08?? 20:09 +0200?Manuel Hern?ndez M?ndez???
> The plic_data struct was uninitialized. This led to misfunction behavior
> since it was subsequently assigned to the global plic struct, and some
> struct fields, such as flags and irqchip, contained random values.
> The fix proposes to initialize the plic_data to the global plic struct,
> so, after parsing the fdt, the fields of the struct will be set to the
> default values set in global plic struct definition, or the parsed values
> in the fdt, or zero.
> 
> Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
> device tree")
> Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
LGTM

Reviewed-by: Xiang W <wxjstz at 126.com>
> ---
> ?platform/fpga/openpiton/platform.c | 2 +-
> ?1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index d2cf3e32..faa299ce 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
> ?{
> ?	const void *fdt;
> ?	struct platform_uart_data uart_data = { 0 };
> -	struct plic_data plic_data;
> +	struct plic_data plic_data = plic;
> ?	unsigned long aclint_freq;
> ?	uint64_t clint_addr;
> ?	int rc;
> -- 
> 2.34.1
> 



From jrtc27 at jrtc27.com  Wed Jul  9 16:28:39 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Thu, 10 Jul 2025 00:28:39 +0100
Subject: [PATCH] include: sbi: Don't use #pragma when preprocessing device tree sources
Message-ID: <20250709232840.37551-1-jrtc27@jrtc27.com>

Since this persists in the preprocessed output (so that it can affect
the subsequent compilation), it ends up in the input to dtc and is a
syntax error, breaking the k210 build. Ideally we wouldn't add the
-include flag to DTSCPPFLAGS in the first place as this header is wholly
pointless there, but that's a more invasive build system change compared
to just making this header safe to include there.

Fixes: 86c01a73ff9d ("lib: sbi: Avoid GOT indirection for global symbol references")
Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
---
 include/sbi/sbi_visibility.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/sbi/sbi_visibility.h b/include/sbi/sbi_visibility.h
index e9c401c..f900c44 100644
--- a/include/sbi/sbi_visibility.h
+++ b/include/sbi/sbi_visibility.h
@@ -7,10 +7,12 @@
 #ifndef __SBI_VISIBILITY_H__
 #define __SBI_VISIBILITY_H__
 
+#ifndef __DTS__
 /*
  * Declare all global objects with hidden visibility so access is PC-relative
  * instead of going through the GOT.
  */
 #pragma GCC visibility push(hidden)
+#endif
 
 #endif
-- 
2.34.1



From jrtc27 at jrtc27.com  Wed Jul  9 16:29:28 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Thu, 10 Jul 2025 00:29:28 +0100
Subject: [PATCH 1/3] include: sbi: Use array for struct sbi_trap_regs and GET/SET macros
Message-ID: <20250709232932.37622-1-jrtc27@jrtc27.com>

Rather than hand-rolling scaled pointer arithmetic with casts and
shifts, let the compiler do so by indexing an array of GPRs, taking
advantage of the language's type system to scale based on whatever type
the register happens to be. This makes it easier to support CHERI where
the registers are capabilities, not plain integers, and so this pointer
arithmetic would need to change (and currently REGBYTES is both the size
of a register and the size of an integer word upstream).

Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
---
 include/sbi/riscv_encoding.h |  25 ++----
 include/sbi/sbi_trap.h       | 148 ++++++++++++++++++++---------------
 2 files changed, 92 insertions(+), 81 deletions(-)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index e1256e3..f4df1ae 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -1291,6 +1291,8 @@
 #define SHIFT_FUNCT3			12
 
 #define MASK_RS1			0xf8000
+#define MASK_RS2			0x1f00000
+#define MASK_RD				0xf80
 
 #define MASK_CSR			0xfff00000
 #define SHIFT_CSR			20
@@ -1356,28 +1358,17 @@
 #define SHIFT_RIGHT(x, y)		\
 	((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
 
-#define REG_MASK			\
-	((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
-
-#define REG_OFFSET(insn, pos)		\
-	(SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
-
-#define REG_PTR(insn, pos, regs)	\
-	(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
-
 #define GET_FUNC3(insn)			((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
 #define GET_RM(insn)			GET_FUNC3(insn)
-#define GET_RS1_NUM(insn)		((insn & MASK_RS1) >> 15)
+#define GET_RS1_NUM(insn)		((insn & MASK_RS1) >> SH_RS1)
+#define GET_RS2_NUM(insn)		((insn & MASK_RS2) >> SH_RS2)
+#define GET_RS1S_NUM(insn)		RVC_RS1S(insn)
+#define GET_RS2S_NUM(insn)		RVC_RS2S(insn)
+#define GET_RS2C_NUM(insn)		RVC_RS2(insn)
+#define GET_RD_NUM(insn)		((insn & MASK_RD) >> SH_RD)
 #define GET_CSR_NUM(insn)		((insn & MASK_CSR) >> SHIFT_CSR)
 #define GET_AQRL(insn)			((insn & MASK_AQRL) >> SHIFT_AQRL)
 
-#define GET_RS1(insn, regs)		(*REG_PTR(insn, SH_RS1, regs))
-#define GET_RS2(insn, regs)		(*REG_PTR(insn, SH_RS2, regs))
-#define GET_RS1S(insn, regs)		(*REG_PTR(RVC_RS1S(insn), 0, regs))
-#define GET_RS2S(insn, regs)		(*REG_PTR(RVC_RS2S(insn), 0, regs))
-#define GET_RS2C(insn, regs)		(*REG_PTR(insn, SH_RS2C, regs))
-#define GET_SP(regs)			(*REG_PTR(2, 0, regs))
-#define SET_RD(insn, regs, val)		(*REG_PTR(insn, SH_RD, regs) = (val))
 #define IMM_I(insn)			((s32)(insn) >> 20)
 #define IMM_S(insn)			(((s32)(insn) >> 25 << 5) | \
 					 (s32)(((insn) >> 7) & 0x1f))
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index 5eec4da..731a0c9 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -127,70 +127,75 @@
 
 /** Representation of register state at time of trap/interrupt */
 struct sbi_trap_regs {
-	/** zero register state */
-	unsigned long zero;
-	/** ra register state */
-	unsigned long ra;
-	/** sp register state */
-	unsigned long sp;
-	/** gp register state */
-	unsigned long gp;
-	/** tp register state */
-	unsigned long tp;
-	/** t0 register state */
-	unsigned long t0;
-	/** t1 register state */
-	unsigned long t1;
-	/** t2 register state */
-	unsigned long t2;
-	/** s0 register state */
-	unsigned long s0;
-	/** s1 register state */
-	unsigned long s1;
-	/** a0 register state */
-	unsigned long a0;
-	/** a1 register state */
-	unsigned long a1;
-	/** a2 register state */
-	unsigned long a2;
-	/** a3 register state */
-	unsigned long a3;
-	/** a4 register state */
-	unsigned long a4;
-	/** a5 register state */
-	unsigned long a5;
-	/** a6 register state */
-	unsigned long a6;
-	/** a7 register state */
-	unsigned long a7;
-	/** s2 register state */
-	unsigned long s2;
-	/** s3 register state */
-	unsigned long s3;
-	/** s4 register state */
-	unsigned long s4;
-	/** s5 register state */
-	unsigned long s5;
-	/** s6 register state */
-	unsigned long s6;
-	/** s7 register state */
-	unsigned long s7;
-	/** s8 register state */
-	unsigned long s8;
-	/** s9 register state */
-	unsigned long s9;
-	/** s10 register state */
-	unsigned long s10;
-	/** s11 register state */
-	unsigned long s11;
-	/** t3 register state */
-	unsigned long t3;
-	/** t4 register state */
-	unsigned long t4;
-	/** t5 register state */
-	unsigned long t5;
-	/** t6 register state */
-	unsigned long t6;
+	union {
+		unsigned long gprs[32];
+		struct {
+			/** zero register state */
+			unsigned long zero;
+			/** ra register state */
+			unsigned long ra;
+			/** sp register state */
+			unsigned long sp;
+			/** gp register state */
+			unsigned long gp;
+			/** tp register state */
+			unsigned long tp;
+			/** t0 register state */
+			unsigned long t0;
+			/** t1 register state */
+			unsigned long t1;
+			/** t2 register state */
+			unsigned long t2;
+			/** s0 register state */
+			unsigned long s0;
+			/** s1 register state */
+			unsigned long s1;
+			/** a0 register state */
+			unsigned long a0;
+			/** a1 register state */
+			unsigned long a1;
+			/** a2 register state */
+			unsigned long a2;
+			/** a3 register state */
+			unsigned long a3;
+			/** a4 register state */
+			unsigned long a4;
+			/** a5 register state */
+			unsigned long a5;
+			/** a6 register state */
+			unsigned long a6;
+			/** a7 register state */
+			unsigned long a7;
+			/** s2 register state */
+			unsigned long s2;
+			/** s3 register state */
+			unsigned long s3;
+			/** s4 register state */
+			unsigned long s4;
+			/** s5 register state */
+			unsigned long s5;
+			/** s6 register state */
+			unsigned long s6;
+			/** s7 register state */
+			unsigned long s7;
+			/** s8 register state */
+			unsigned long s8;
+			/** s9 register state */
+			unsigned long s9;
+			/** s10 register state */
+			unsigned long s10;
+			/** s11 register state */
+			unsigned long s11;
+			/** t3 register state */
+			unsigned long t3;
+			/** t4 register state */
+			unsigned long t4;
+			/** t5 register state */
+			unsigned long t5;
+			/** t6 register state */
+			unsigned long t6;
+		};
+	};
 	/** mepc register state */
 	unsigned long mepc;
 	/** mstatus register state */
@@ -199,6 +204,21 @@ struct sbi_trap_regs {
 	unsigned long mstatusH;
 };
 
+_Static_assert(
+	sizeof(((struct sbi_trap_regs *)0)->gprs) ==
+	offsetof(struct sbi_trap_regs, t6) +
+	sizeof(((struct sbi_trap_regs *)0)->t6),
+	"struct sbi_trap_regs's layout differs between gprs and named members");
+
+#define REG_VAL(idx, regs)		((regs)->gprs[(idx)])
+
+#define GET_RS1(insn, regs)		REG_VAL(GET_RS1_NUM(insn), regs)
+#define GET_RS2(insn, regs)		REG_VAL(GET_RS2_NUM(insn), regs)
+#define GET_RS1S(insn, regs)		REG_VAL(GET_RS1S_NUM(insn), regs)
+#define GET_RS2S(insn, regs)		REG_VAL(GET_RS2S_NUM(insn), regs)
+#define GET_RS2C(insn, regs)		REG_VAL(GET_RS2C_NUM(insn), regs)
+#define SET_RD(insn, regs, val)		(REG_VAL(GET_RD_NUM(insn), regs) = (val))
+
 /** Representation of trap details */
 struct sbi_trap_info {
 	/** cause Trap exception cause */
-- 
2.34.1



From jrtc27 at jrtc27.com  Wed Jul  9 16:29:29 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Thu, 10 Jul 2025 00:29:29 +0100
Subject: [PATCH 2/3] firmware: Replace sole uses of REGBYTES with __SIZEOF_LONG__
In-Reply-To: <20250709232932.37622-1-jrtc27@jrtc27.com>
References: <20250709232932.37622-1-jrtc27@jrtc27.com>
Message-ID: <20250709232932.37622-2-jrtc27@jrtc27.com>

This code has nothing to do with the ISA's registers, it's about the
format of ELF relocations. As such, __SIZEOF_LONG__, being a language /
ABI-level property, is a more appropriate constant to use. This also
makes it easier to support CHERI, where general-purpose registers are
extended to be capabilities, not just integers, and so the register size
is not the same as the machine word size. This also happens to make it
more correct for RV64ILP32, where the registers are 64-bit integers but
the ABI is 32-bit (both for long and for the ELF format), though
properly supporting that ABI is not part of the motivation here, just a
consequence of improving the code for CHERI.

Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
---
 firmware/fw_base.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 2498797..aa8e264 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -80,17 +80,17 @@ _sc_fail:
 	lla	t1, __rel_dyn_end
 	beq	t0, t1, _relocate_done
 2:
-	REG_L	t5, REGBYTES(t0)	/* t5 <-- relocation info:type */
+	REG_L	t5, __SIZEOF_LONG__(t0)	/* t5 <-- relocation info:type */
 	li	t3, R_RISCV_RELATIVE	/* reloc type R_RISCV_RELATIVE */
 	bne	t5, t3, 3f
 	REG_L	t3, 0(t0)
-	REG_L	t5, (REGBYTES * 2)(t0)	/* t5 <-- addend */
+	REG_L	t5, (__SIZEOF_LONG__ * 2)(t0)	/* t5 <-- addend */
 	add	t5, t5, t2
 	add	t3, t3, t2
 	REG_S	t5, 0(t3)		/* store runtime address to the GOT entry */
 
 3:
-	addi	t0, t0, (REGBYTES * 3)
+	addi	t0, t0, (__SIZEOF_LONG__ * 3)
 	blt	t0, t1, 2b
 _relocate_done:
 	/* At this point we are running from link address */
-- 
2.34.1



From jrtc27 at jrtc27.com  Wed Jul  9 16:29:30 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Thu, 10 Jul 2025 00:29:30 +0100
Subject: [PATCH 3/3] include: sbi: Remove unused (LOG_)REGBYTES
In-Reply-To: <20250709232932.37622-1-jrtc27@jrtc27.com>
References: <20250709232932.37622-1-jrtc27@jrtc27.com>
Message-ID: <20250709232932.37622-3-jrtc27@jrtc27.com>

These are no longer used, so remove them.

Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
---
 include/sbi/riscv_encoding.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index f4df1ae..40a854e 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -1317,13 +1317,6 @@
 
 #define INSN_LEN(insn)			(INSN_IS_16BIT(insn) ? 2 : 4)
 
-#if __riscv_xlen == 64
-#define LOG_REGBYTES			3
-#else
-#define LOG_REGBYTES			2
-#endif
-#define REGBYTES			(1 << LOG_REGBYTES)
-
 #define SH_VSEW			3
 #define SH_VIEW			12
 #define SH_VD				7
-- 
2.34.1



From jrtc27 at jrtc27.com  Wed Jul  9 17:29:35 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Thu, 10 Jul 2025 01:29:35 +0100
Subject: [PATCH] firmware: Rename __rel_dyn_start/end to __rela_dyn_start/end
Message-ID: <20250710002937.44307-1-jrtc27@jrtc27.com>

We are using and expecting the RELA format, not the REL format, and this
is the conventional linker-generated name for the start/end symbols, so
use it rather than confusing things by making it look like we're
accessing .rel.dyn, which would be in the REL format with no explicit
addend.

Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
---
 firmware/fw_base.S   | 4 ++--
 firmware/fw_base.ldS | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index aa8e264..b675c9e 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -76,8 +76,8 @@ _sc_fail:
 	li	t0, FW_TEXT_START	/* link start */
 	lla	t1, _fw_start		/* load start */
 	sub	t2, t1, t0		/* load offset */
-	lla	t0, __rel_dyn_start
-	lla	t1, __rel_dyn_end
+	lla	t0, __rela_dyn_start
+	lla	t1, __rela_dyn_end
 	beq	t0, t1, _relocate_done
 2:
 	REG_L	t5, __SIZEOF_LONG__(t0)	/* t5 <-- relocation info:type */
diff --git a/firmware/fw_base.ldS b/firmware/fw_base.ldS
index a33746a..12c7a84 100644
--- a/firmware/fw_base.ldS
+++ b/firmware/fw_base.ldS
@@ -47,9 +47,9 @@
 	. = ALIGN(0x1000); /* Ensure next section is page aligned */
 
 	.rela.dyn : {
-		PROVIDE(__rel_dyn_start = .);
+		PROVIDE(__rela_dyn_start = .);
 		*(.rela*)
-		PROVIDE(__rel_dyn_end = .);
+		PROVIDE(__rela_dyn_end = .);
 	}
 
 	PROVIDE(_rodata_end = .);
-- 
2.34.1



From wxjstz at 126.com  Wed Jul  9 19:46:46 2025
From: wxjstz at 126.com (Xiang W)
Date: Thu, 10 Jul 2025 10:46:46 +0800
Subject: [PATCH] include: sbi: Don't use #pragma when preprocessing
 device tree sources
In-Reply-To: <20250709232840.37551-1-jrtc27@jrtc27.com>
References: <20250709232840.37551-1-jrtc27@jrtc27.com>
Message-ID: <fad0dc2070017e96cd6cf3cb14e387d5aca11cad.camel@126.com>

? 2025-07-10?? 00:28 +0100?Jessica Clarke???
> Since this persists in the preprocessed output (so that it can affect
> the subsequent compilation), it ends up in the input to dtc and is a
> syntax error, breaking the k210 build. Ideally we wouldn't add the
> -include flag to DTSCPPFLAGS in the first place as this header is wholly
> pointless there, but that's a more invasive build system change compared
> to just making this header safe to include there.
> 
> Fixes: 86c01a73ff9d ("lib: sbi: Avoid GOT indirection for global symbol references")
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
This error will reappear when PLATFORM=kendryte/k210 LLVM=1.
No problem under gcc.

Tested-by: Xiang W <wxjstz at 126.com>
Reviewed-by: Xiang W <wxjstz at 126.com>
> ---
> ?include/sbi/sbi_visibility.h | 2 ++
> ?1 file changed, 2 insertions(+)
> 
> diff --git a/include/sbi/sbi_visibility.h b/include/sbi/sbi_visibility.h
> index e9c401c..f900c44 100644
> --- a/include/sbi/sbi_visibility.h
> +++ b/include/sbi/sbi_visibility.h
> @@ -7,10 +7,12 @@
> ?#ifndef __SBI_VISIBILITY_H__
> ?#define __SBI_VISIBILITY_H__
> ?
> +#ifndef __DTS__
> ?/*
> ? * Declare all global objects with hidden visibility so access is PC-relative
> ? * instead of going through the GOT.
> ? */
> ?#pragma GCC visibility push(hidden)
> +#endif
> ?
> ?#endif
> -- 
> 2.34.1
> 



From max.hsu at sifive.com  Thu Jul 10 09:12:53 2025
From: max.hsu at sifive.com (Max Hsu)
Date: Fri, 11 Jul 2025 00:12:53 +0800
Subject: [PATCH v2] lib: utils: fdt: fix "ranges" translation
Message-ID: <20250711-dev-maxh-master_fdt_helper-v2-1-9579e1f02ee1@sifive.com>

According to the Device Tree Spec, Chapter 2.3.8 "ranges" [1]:
The parent address size will be determined from the #address-cells
property of the node that defines the parent?s address space.

In fdt_translate_address(), which considered the parent address size
is the child address size, this commit fix the two address sizes
and parsing the address independently.

Signed-off-by: Max Hsu <max.hsu at sifive.com>
---
v1 fix will introduce another bug in the following case.

The node in DTS depth 1 if execute fdt_get_node_addr_size(), inside
the function, the fdt_translate_address() will try to get the child
"#address-cells" and "#size-cells" in DTS depth 0, and the parent
"#address-cells" in DTS depth -1. which will cause early abort.
With fdt_translate_address() early abort, the parameter "addr" didn't
got any assignment of the address value. This let
fdt_get_node_addr_size() return with unknown value of parameter "addr".

For the v2 fix, which will check the "ranges" first, since the above
case shouldn't happen in the DTS as the "ranges" should be existed in
DTS depth more than 0. This fix also improve execution cycle. 
---
Changes in v2:
- fix v1 bug mentioned in the cover letter.
- Link to v1: https://lore.kernel.org/r/20250708-dev-maxh-master_fdt_helper-v1-1-866c165f1f85 at sifive.com
---
 lib/utils/fdt/fdt_helper.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index 0f4859c1a721bc7c2871bacefe27caba7780f752..799fd48dc3abf0a3c1963f84dd6bde271e6c08d7 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -84,23 +84,27 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
 				 uint64_t *addr)
 {
 	int i, rlen;
-	int cell_addr, cell_size;
+	int cell_parent_addr, cell_child_addr, cell_size;
 	const fdt32_t *ranges;
 	uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
 
-	cell_addr = fdt_address_cells(fdt, parent);
-	if (cell_addr < 1)
-		return SBI_ENODEV;
-
-	cell_size = fdt_size_cells(fdt, parent);
-	if (cell_size < 0)
-		return SBI_ENODEV;
-
 	ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
 	if (ranges && rlen > 0) {
-		for (i = 0; i < cell_addr; i++)
+		cell_child_addr = fdt_address_cells(fdt, parent);
+		if (cell_child_addr < 1)
+			return SBI_ENODEV;
+
+		cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
+		if (cell_parent_addr < 1)
+			return SBI_ENODEV;
+
+		cell_size = fdt_size_cells(fdt, parent);
+		if (cell_size < 0)
+			return SBI_ENODEV;
+
+		for (i = 0; i < cell_child_addr; i++)
 			caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
-		for (i = 0; i < cell_addr; i++)
+		for (i = 0; i < cell_parent_addr; i++)
 			paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
 		for (i = 0; i < cell_size; i++)
 			rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);

---
base-commit: a32a91069119e7a5aa31e6bc51d5e00860be3d80
change-id: 20250708-dev-maxh-master_fdt_helper-46d2eeeb07cd

Best regards,
-- 
Max Hsu <max.hsu at sifive.com>



From icebergfu at gmail.com  Thu Jul 10 16:17:08 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Thu, 10 Jul 2025 16:17:08 -0700
Subject: [PATCH v1] generic: mips: support harts to boot from mips_warm_boot
Message-ID: <20250710231708.4553-1-cfu@mips.com>

We program reset base for harts (other than hart 0) to boot at
mips_warm_boot that jumps to _start_warm. This helps to skip some code
sequence to speed up.

Signed-off-by: Chao-ying Fu <cfu at mips.com>
---
 platform/generic/mips/p8700.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
index 888a45c..687912a 100644
--- a/platform/generic/mips/p8700.c
+++ b/platform/generic/mips/p8700.c
@@ -140,6 +140,22 @@ static void power_up_other_cluster(u32 hartid)
 }
 #endif
 
+static void __attribute__((naked,no_instrument_function,aligned(4096)))
+mips_warm_boot(void)
+{
+  __asm__ __volatile__(
+	"	j	1f\n"
+	"	.align	2\n"
+	"	j	1f\n"
+	"	.align	2\n"
+	"	j	1f\n"
+	"	.align	2\n"
+	"	j	1f\n"
+	"1:	lla	t0, _start_warm\n"
+	"	jr	t0\n"
+	);
+}
+
 static int mips_hart_start(u32 hartid, ulong saddr)
 {
 	unsigned int stat;
@@ -150,6 +166,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
 	if (hartid == 0)
 		return SBI_ENOTSUPP;
 
+	/* Change reset base to mips_warm_boot */
+	write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
+
 	if (cpu_hart(hartid) == 0) {
 		/* Ensure its coherency is disabled */
 		write_gcr_co_coherence(hartid, 0, local_p);
-- 
2.47.1



From jrtc27 at jrtc27.com  Thu Jul 10 21:33:55 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Fri, 11 Jul 2025 05:33:55 +0100
Subject: [PATCH v1] generic: mips: support harts to boot from
 mips_warm_boot
In-Reply-To: <20250710231708.4553-1-cfu@mips.com>
References: <20250710231708.4553-1-cfu@mips.com>
Message-ID: <06A6B90B-EB43-4CF9-8840-DE0DDB8210BD@jrtc27.com>

On 11 Jul 2025, at 00:17, Chao-ying Fu <icebergfu at gmail.com> wrote:
> 
> We program reset base for harts (other than hart 0) to boot at
> mips_warm_boot that jumps to _start_warm. This helps to skip some code
> sequence to speed up.
> 
> Signed-off-by: Chao-ying Fu <cfu at mips.com>
> ---
> platform/generic/mips/p8700.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
> 
> diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> index 888a45c..687912a 100644
> --- a/platform/generic/mips/p8700.c
> +++ b/platform/generic/mips/p8700.c
> @@ -140,6 +140,22 @@ static void power_up_other_cluster(u32 hartid)
> }
> #endif
> 
> +static void __attribute__((naked,no_instrument_function,aligned(4096)))
> +mips_warm_boot(void)
> +{
> +  __asm__ __volatile__(
> + " j 1f\n"
> + " .align 2\n"
> + " j 1f\n"
> + " .align 2\n"
> + " j 1f\n"
> + " .align 2\n"
> + " j 1f\n"
> + "1: lla t0, _start_warm\n"
> + " jr t0\n"
> + );
> +}

What is the point of writing this as a C function if it?s going to be
entirely assembly? Just write an assembly function?

Jess



From icebergfu at gmail.com  Wed Jul 16 16:17:38 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Wed, 16 Jul 2025 16:17:38 -0700
Subject: [PATCH v1] generic: mips: support harts to boot from mips_warm_boot
In-Reply-To: <06A6B90B-EB43-4CF9-8840-DE0DDB8210BD@jrtc27.com>
References: <20250710231708.4553-1-cfu@mips.com> <06A6B90B-EB43-4CF9-8840-DE0DDB8210BD@jrtc27.com>
Message-ID: <CAM1rFzFb9mTzs1_xCKMAa3WdmkvuL5jbUQdQkjQY4i6sRRHrVA@mail.gmail.com>

On Thu, Jul 10, 2025 at 9:34?PM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> On 11 Jul 2025, at 00:17, Chao-ying Fu <icebergfu at gmail.com> wrote:
> >
> > We program reset base for harts (other than hart 0) to boot at
> > mips_warm_boot that jumps to _start_warm. This helps to skip some code
> > sequence to speed up.
> >
> > Signed-off-by: Chao-ying Fu <cfu at mips.com>
> > ---
> > platform/generic/mips/p8700.c | 19 +++++++++++++++++++
> > 1 file changed, 19 insertions(+)
> >
> > diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> > index 888a45c..687912a 100644
> > --- a/platform/generic/mips/p8700.c
> > +++ b/platform/generic/mips/p8700.c
> > @@ -140,6 +140,22 @@ static void power_up_other_cluster(u32 hartid)
> > }
> > #endif
> >
> > +static void __attribute__((naked,no_instrument_function,aligned(4096)))
> > +mips_warm_boot(void)
> > +{
> > +  __asm__ __volatile__(
> > + " j 1f\n"
> > + " .align 2\n"
> > + " j 1f\n"
> > + " .align 2\n"
> > + " j 1f\n"
> > + " .align 2\n"
> > + " j 1f\n"
> > + "1: lla t0, _start_warm\n"
> > + " jr t0\n"
> > + );
> > +}
>
> What is the point of writing this as a C function if it?s going to be
> entirely assembly? Just write an assembly function?

  My intention is to have a minimum change, as there is only one file
modified in the patch.
Either writing assembly code or writing C code for mips_warm_boot is
fine or equivalent.
To have assembly code, we will need to modify Makefile and create a
new assembly file in the patch.

  Thanks a lot!

Regards,
Chao-ying


From samuel.holland at sifive.com  Wed Jul 16 17:04:20 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Wed, 16 Jul 2025 19:04:20 -0500
Subject: [PATCH v1] generic: mips: support harts to boot from
 mips_warm_boot
In-Reply-To: <20250710231708.4553-1-cfu@mips.com>
References: <20250710231708.4553-1-cfu@mips.com>
Message-ID: <65346468-9810-4f4a-9360-c588f758184f@sifive.com>

On 2025-07-10 6:17 PM, Chao-ying Fu wrote:
> We program reset base for harts (other than hart 0) to boot at
> mips_warm_boot that jumps to _start_warm. This helps to skip some code
> sequence to speed up.
> 
> Signed-off-by: Chao-ying Fu <cfu at mips.com>
> ---
>  platform/generic/mips/p8700.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> index 888a45c..687912a 100644
> --- a/platform/generic/mips/p8700.c
> +++ b/platform/generic/mips/p8700.c
> @@ -140,6 +140,22 @@ static void power_up_other_cluster(u32 hartid)
>  }
>  #endif
>  
> +static void __attribute__((naked,no_instrument_function,aligned(4096)))
> +mips_warm_boot(void)
> +{
> +  __asm__ __volatile__(
> +	"	j	1f\n"
> +	"	.align	2\n"
> +	"	j	1f\n"
> +	"	.align	2\n"
> +	"	j	1f\n"
> +	"	.align	2\n"
> +	"	j	1f\n"
> +	"1:	lla	t0, _start_warm\n"
> +	"	jr	t0\n"

The double/indirect jump is not necessary. jal (j) range is +/- 1 MiB, which is
much larger than the OpenSBI firmware size. So each entry point can jump to
_start_warm directly.

Regards,
Samuel

> +	);
> +}
> +
>  static int mips_hart_start(u32 hartid, ulong saddr)
>  {
>  	unsigned int stat;
> @@ -150,6 +166,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
>  	if (hartid == 0)
>  		return SBI_ENOTSUPP;
>  
> +	/* Change reset base to mips_warm_boot */
> +	write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
> +
>  	if (cpu_hart(hartid) == 0) {
>  		/* Ensure its coherency is disabled */
>  		write_gcr_co_coherence(hartid, 0, local_p);



From samuel.holland at sifive.com  Fri Jul 18 00:55:25 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Fri, 18 Jul 2025 02:55:25 -0500
Subject: [PATCH] include: sbi: Don't use #pragma when preprocessing device
 tree sources
In-Reply-To: <20250709232840.37551-1-jrtc27@jrtc27.com>
References: <20250709232840.37551-1-jrtc27@jrtc27.com>
Message-ID: <79305dcb-fce6-4b6c-86b5-34824029e274@sifive.com>

On 2025-07-09 6:28 PM, Jessica Clarke wrote:
> Since this persists in the preprocessed output (so that it can affect
> the subsequent compilation), it ends up in the input to dtc and is a
> syntax error, breaking the k210 build. Ideally we wouldn't add the
> -include flag to DTSCPPFLAGS in the first place as this header is wholly
> pointless there, but that's a more invasive build system change compared
> to just making this header safe to include there.
> 
> Fixes: 86c01a73ff9d ("lib: sbi: Avoid GOT indirection for global symbol references")
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
> ---
>  include/sbi/sbi_visibility.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/include/sbi/sbi_visibility.h b/include/sbi/sbi_visibility.h
> index e9c401c..f900c44 100644
> --- a/include/sbi/sbi_visibility.h
> +++ b/include/sbi/sbi_visibility.h
> @@ -7,10 +7,12 @@
>  #ifndef __SBI_VISIBILITY_H__
>  #define __SBI_VISIBILITY_H__
>  
> +#ifndef __DTS__
>  /*
>   * Declare all global objects with hidden visibility so access is PC-relative
>   * instead of going through the GOT.
>   */
>  #pragma GCC visibility push(hidden)
> +#endif
>  
>  #endif

Thanks for the fix!

Reviewed-by: Samuel Holland <samuel.holland at sifive.com>



From samuel.holland at sifive.com  Fri Jul 18 01:01:39 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Fri, 18 Jul 2025 03:01:39 -0500
Subject: [PATCH] firmware: Rename __rel_dyn_start/end to
 __rela_dyn_start/end
In-Reply-To: <20250710002937.44307-1-jrtc27@jrtc27.com>
References: <20250710002937.44307-1-jrtc27@jrtc27.com>
Message-ID: <3d8ace28-3c8e-4bef-a6c5-92b0fd60fa60@sifive.com>

On 2025-07-09 7:29 PM, Jessica Clarke wrote:
> We are using and expecting the RELA format, not the REL format, and this
> is the conventional linker-generated name for the start/end symbols, so
> use it rather than confusing things by making it look like we're
> accessing .rel.dyn, which would be in the REL format with no explicit
> addend.
> 
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>
> ---
>  firmware/fw_base.S   | 4 ++--
>  firmware/fw_base.ldS | 4 ++--
>  2 files changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
Tested-by: Samuel Holland <samuel.holland at sifive.com>



From anup at brainfault.org  Sun Jul 20 01:43:02 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 14:13:02 +0530
Subject: [PATCH] platform: generic: Add support for UltraRISC DP1000 SoC platform
In-Reply-To: <CAFPVDjSstmSEeF=YLzVrV2mUSAU1UVO4_zu4RyUzgvE1g_awYQ@mail.gmail.com>
References: <CAFPVDjSstmSEeF=YLzVrV2mUSAU1UVO4_zu4RyUzgvE1g_awYQ@mail.gmail.com>
Message-ID: <CAAhSdy3UJEoBjOtXuRyYaN3_cDqGaLAq_kV2cn3zteH5EL7+sw@mail.gmail.com>

On Mon, Jun 16, 2025 at 11:27?AM Neo <neopimail at gmail.com> wrote:
>
> This patch adds initial platform support for the UltraRISC DP1000 SoC
> to OpenSBI.
>
> The UltraRISC DP1000 is a multi-core RISC-V 64-bit SoC developed by
> UltraRISC Technology (Shanghai) Co., Ltd.
>
> We intend to upstream DP1000 support to align with OpenSBI's mission
> of supporting diverse RISC-V platforms and to simplify support for
> Linux and U-Boot on UltraRISC hardware.
>
> Signed-off-by: Yi Pei <neopimail at gmail.com>
> ---
> platform/generic/Kconfig | 4 ++++
> platform/generic/configs/defconfig | 1 +
> platform/generic/ultrarisc/dp1000.c | 17 +++++++++++++++++
> platform/generic/ultrarisc/objects.mk | 8 ++++++++
> 4 files changed, 36 insertions(+)
> create mode 100644 platform/generic/ultrarisc/dp1000.c
> create mode 100644 platform/generic/ultrarisc/objects.mk
> diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
> index 688da3f4..54f1674d 100644
> --- a/platform/generic/Kconfig
> +++ b/platform/generic/Kconfig
> @@ -68,6 +68,10 @@ config PLATFORM_THEAD
> select THEAD_C9XX_PMU
> default n
> +config PLATFORM_ULTRARISC_DP1000
> + bool "UltraRISC DP1000 support"
> + default n
> +
> source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
> source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
> diff --git a/platform/generic/configs/defconfig
> b/platform/generic/configs/defconfig
> index bb260626..717906ef 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
> CONFIG_PLATFORM_SOPHGO_SG2042=y
> CONFIG_PLATFORM_STARFIVE_JH7110=y
> CONFIG_PLATFORM_THEAD=y
> +CONFIG_PLATFORM_ULTRARISC_DP1000=y
> CONFIG_FDT_CPPC=y
> CONFIG_FDT_CPPC_RPMI=y
> CONFIG_FDT_GPIO=y
> diff --git a/platform/generic/ultrarisc/dp1000.c
> b/platform/generic/ultrarisc/dp1000.c
> new file mode 100644
> index 00000000..f21b2875
> --- /dev/null
> +++ b/platform/generic/ultrarisc/dp1000.c
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: BSD-2-Clause
> +/*
> + * Copyright (C) 2025 UltraRISC,Inc
> + */
> +
> +#include <platform_override.h>
> +#include <sbi/sbi_platform.h>
> +#include <sbi_utils/fdt/fdt_helper.h>
> +
> +static const struct fdt_match ultrarisc_dp1000_match[] = {
> + {.compatible = "ultrarisc,dp1000"},
> + {},
> +};
> +
> +const struct platform_override ultrarisc_dp1000 = {
> + .match_table = ultrarisc_dp1000_match,
> +};

Adding platform_override to OpenSBI generic platform is
only needed if there is some platform specific initialization
required.  It seems there is no UltraRISC DP1000 specific
initialization so this patch is not needed.

Regards,
Anup

> diff --git a/platform/generic/ultrarisc/objects.mk
> b/platform/generic/ultrarisc/objects.mk
> new file mode 100644
> index 00000000..71e66f35
> --- /dev/null
> +++ b/platform/generic/ultrarisc/objects.mk
> @@ -0,0 +1,8 @@
> +#
> +# SPDX-License-Identifier: BSD-2-Clause
> +#
> +# Copyright (C) 2025 UltraRISC,Inc
> +#
> +
> +carray-platform_override_modules-$(CONFIG_PLATFORM_ULTRARISC_DP1000)
> += ultrarisc_dp1000
> +platform-objs-$(CONFIG_PLATFORM_ULTRARISC_DP1000) += ultrarisc/dp1000.o
> --
> 2.34.1
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Sun Jul 20 08:14:25 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 20:44:25 +0530
Subject: [PATCH] lib: utils/serial: Clear LSR status and check RBR status
In-Reply-To: <CAFPVDjQZ1gpf8-u--RBbAL1Y0FfDN2vZ3g=wBw+Bp-8ppuz3HA@mail.gmail.com>
References: <CAFPVDjQZ1gpf8-u--RBbAL1Y0FfDN2vZ3g=wBw+Bp-8ppuz3HA@mail.gmail.com>
Message-ID: <CAAhSdy2YXO3nzT-yM788rn8+qJ=kcEr=wJr-H-mFOtdWjKcu5g@mail.gmail.com>

On Mon, Jun 16, 2025 at 3:53?PM Neo <neopimail at gmail.com> wrote:
>
> On some platforms, read RBR when it is empty may result in an error.
>
> Signed-off-by: Yi Pei <neopimail at gmail.com>
> ---
> lib/utils/serial/uart8250.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/lib/utils/serial/uart8250.c b/lib/utils/serial/uart8250.c
> index 82fb142a..ddae0aa3 100644
> --- a/lib/utils/serial/uart8250.c
> +++ b/lib/utils/serial/uart8250.c
> @@ -134,9 +134,9 @@ int uart8250_init(unsigned long base, u32 in_freq,
> u32 baudrate, u32 reg_shift,
> /* No modem control DTR RTS */
> set_reg(UART_MCR_OFFSET, 0x00);
> /* Clear line status */
> - get_reg(UART_LSR_OFFSET);
> - /* Read receive buffer */
> - get_reg(UART_RBR_OFFSET);
> + if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
> + /* Read receive buffer */
> + get_reg(UART_RBR_OFFSET);
> /* Set scratchpad */
> set_reg(UART_SCR_OFFSET, 0x00);
> --
> 2.34.1
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

The changes in the patch are fine but I am not able to apply this
patch because it is not generated correctly. Prefer generating patch
using "git format-patch -M -C ..." and prefer sending patch using
"git send-email ..."

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

I have taken care of the above patch formatting issues manually.
Applied this patch to the riscv/opensbi repo.

Regards,
Anup


From anup at brainfault.org  Sun Jul 20 08:17:25 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 20:47:25 +0530
Subject: [PATCH 1/1] lib: sbi_list: add a helper for safe list iteration
In-Reply-To: <20250618025416.5331-1-yongxuan.wang@sifive.com>
References: <20250618025416.5331-1-yongxuan.wang@sifive.com>
Message-ID: <CAAhSdy2w4kBP1CYGRvppAkJs8h6_VoAdPykinfBU2NsSWaTOsg@mail.gmail.com>

On Wed, Jun 18, 2025 at 8:24?AM Yong-Xuan Wang <yongxuan.wang at sifive.com> wrote:
>
> Some use cases require iterating safe against removal of list entry.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang at sifive.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/sbi_list.h | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>
> diff --git a/include/sbi/sbi_list.h b/include/sbi/sbi_list.h
> index 9e56c526faf2..be69fc4314e0 100644
> --- a/include/sbi/sbi_list.h
> +++ b/include/sbi/sbi_list.h
> @@ -160,4 +160,17 @@ static inline void sbi_list_del_init(struct sbi_dlist *entry)
>              &pos->member != (head);    \
>              pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
>
> +/**
> + * Iterate over list of given type safe against removal of list entry
> + * @param pos the type * to use as a loop cursor.
> + * @param n another type * to use as temporary storage.
> + * @param head the head for your list.
> + * @param member the name of the list_struct within the struct.
> + */
> +#define sbi_list_for_each_entry_safe(pos, n, head, member) \
> +       for (pos = sbi_list_entry((head)->next, typeof(*pos), member),  \
> +            n = sbi_list_entry(pos->member.next, typeof(*pos), member);        \
> +            &pos->member != (head);    \
> +            pos = n, n = sbi_list_entry(pos->member.next, typeof(*pos), member))
> +
>  #endif
> --
> 2.17.1
>


From anup at brainfault.org  Sun Jul 20 08:21:11 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 20:51:11 +0530
Subject: [PATCH] firmware: payload: test: Add SBI shutdown call after test message
In-Reply-To: <20250624084210.229564-1-wxjstz@126.com>
References: <20250624084210.229564-1-wxjstz@126.com>
Message-ID: <CAAhSdy3BPdswtvkzREJrw=kx6ooq35NYfFcLunM3_T-6cigj1Q@mail.gmail.com>

On Tue, Jun 24, 2025 at 2:13?PM Xiang W <wxjstz at 126.com> wrote:
>
> Previously, 'make run' would hang in WFI after printing the test message.
> This commit adds an SBI ecall to ensure QEMU exits cleanly after the test
> payload runs.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
>  firmware/payloads/test_main.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
> index 194dbbe6..021bc3b8 100644
> --- a/firmware/payloads/test_main.c
> +++ b/firmware/payloads/test_main.c
> @@ -46,6 +46,13 @@ static inline void sbi_ecall_console_puts(const char *str)
>                   sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
>  }
>
> +static inline void sbi_ecall_shutdown(void)
> +{
> +       sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
> +                 SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
> +                 0, 0, 0, 0);
> +}
> +
>  #define wfi()                                             \
>         do {                                              \
>                 __asm__ __volatile__("wfi" ::: "memory"); \
> @@ -54,6 +61,7 @@ static inline void sbi_ecall_console_puts(const char *str)
>  void test_main(unsigned long a0, unsigned long a1)
>  {
>         sbi_ecall_console_puts("\nTest payload running\n");
> +       sbi_ecall_shutdown();
>
>         while (1)
>                 wfi();

Drop the while loop and also print an error message
if sbi_ecall_shutdown() fails.

Regards,
Anup


From anup at brainfault.org  Sun Jul 20 08:29:10 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 20:59:10 +0530
Subject: [PATCH v3 1/2] lib: sbi: Remove redundant call to sbi_hart_expected_trap_addr()
In-Reply-To: <20250703151957.2545958-2-alvinga@andestech.com>
References: <20250703151957.2545958-1-alvinga@andestech.com> <20250703151957.2545958-2-alvinga@andestech.com>
Message-ID: <CAAhSdy2A5Xp8BK8+3zR59rxdL31jjrkxGQayZOt=3LS16BacmA@mail.gmail.com>

On Thu, Jul 3, 2025 at 8:50?PM Alvin Chang <alvinga at andestech.com> wrote:
>
> The variable "sbi_hart_expected_trap" has already been extern variable.
> Therefore, the program can directly refer to it instead of calling
> sbi_hart_expected_trap_addr().
>
> Signed-off-by: Alvin Chang <alvinga at andestech.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/sbi_csr_detect.h | 4 ++--
>  include/sbi/sbi_hart.h       | 4 ----
>  lib/sbi/sbi_illegal_atomic.c | 4 ++--
>  lib/sbi/sbi_unpriv.c         | 6 +++---
>  4 files changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/include/sbi/sbi_csr_detect.h b/include/sbi/sbi_csr_detect.h
> index 89ba294..097c31c 100644
> --- a/include/sbi/sbi_csr_detect.h
> +++ b/include/sbi/sbi_csr_detect.h
> @@ -18,7 +18,7 @@
>         ({                                                              \
>         register ulong tinfo asm("a3") = (ulong)trap;                   \
>         register ulong ttmp asm("a4");                                  \
> -       register ulong mtvec = sbi_hart_expected_trap_addr();           \
> +       register ulong mtvec = (ulong)sbi_hart_expected_trap;           \
>         register ulong ret = 0;                                         \
>         ((struct sbi_trap_info *)(trap))->cause = 0;                    \
>         asm volatile(                                                   \
> @@ -37,7 +37,7 @@
>         ({                                                              \
>         register ulong tinfo asm("a3") = (ulong)trap;                   \
>         register ulong ttmp asm("a4");                                  \
> -       register ulong mtvec = sbi_hart_expected_trap_addr();           \
> +       register ulong mtvec = (ulong)sbi_hart_expected_trap;           \
>         ((struct sbi_trap_info *)(trap))->cause = 0;                    \
>         asm volatile(                                                   \
>                 "add %[ttmp], %[tinfo], zero\n"                         \
> diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
> index dfbe8e4..82b19dc 100644
> --- a/include/sbi/sbi_hart.h
> +++ b/include/sbi/sbi_hart.h
> @@ -134,10 +134,6 @@ int sbi_hart_reinit(struct sbi_scratch *scratch);
>  int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
>
>  extern void (*sbi_hart_expected_trap)(void);
> -static inline ulong sbi_hart_expected_trap_addr(void)
> -{
> -       return (ulong)sbi_hart_expected_trap;
> -}
>
>  unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
>  void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
> diff --git a/lib/sbi/sbi_illegal_atomic.c b/lib/sbi/sbi_illegal_atomic.c
> index 2161b23..8fd6c55 100644
> --- a/lib/sbi/sbi_illegal_atomic.c
> +++ b/lib/sbi/sbi_illegal_atomic.c
> @@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
>         {                                                                       \
>                 register ulong tinfo asm("a3");                                 \
>                 register ulong mstatus = 0;                                     \
> -               register ulong mtvec = sbi_hart_expected_trap_addr();           \
> +               register ulong mtvec = (ulong)sbi_hart_expected_trap;           \
>                 type ret = 0;                                                   \
>                 trap->cause = 0;                                                \
>                 asm volatile(                                                   \
> @@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
>         {                                                                       \
>                 register ulong tinfo asm("a3");                                 \
>                 register ulong mstatus = 0;                                     \
> -               register ulong mtvec = sbi_hart_expected_trap_addr();           \
> +               register ulong mtvec = (ulong)sbi_hart_expected_trap;           \
>                 type ret = 0;                                                   \
>                 trap->cause = 0;                                                \
>                 asm volatile(                                                   \
> diff --git a/lib/sbi/sbi_unpriv.c b/lib/sbi/sbi_unpriv.c
> index 2a55d9d..f9bbec5 100644
> --- a/lib/sbi/sbi_unpriv.c
> +++ b/lib/sbi/sbi_unpriv.c
> @@ -24,7 +24,7 @@
>         {                                                                     \
>                 register ulong tinfo asm("a3");                               \
>                 register ulong mstatus = 0;                                   \
> -               register ulong mtvec = sbi_hart_expected_trap_addr();         \
> +               register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
>                 type ret = 0;                                                 \
>                 trap->cause = 0;                                              \
>                 asm volatile(                                                 \
> @@ -51,7 +51,7 @@
>         {                                                                     \
>                 register ulong tinfo asm("a3") = (ulong)trap;                 \
>                 register ulong mstatus = 0;                                   \
> -               register ulong mtvec = sbi_hart_expected_trap_addr();         \
> +               register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
>                 trap->cause = 0;                                              \
>                 asm volatile(                                                 \
>                         "add %[tinfo], %[taddr], zero\n"                      \
> @@ -121,7 +121,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
>         register ulong tinfo asm("a3");
>         register ulong ttmp asm("a4");
>         register ulong mstatus = 0;
> -       register ulong mtvec = sbi_hart_expected_trap_addr();
> +       register ulong mtvec = (ulong)sbi_hart_expected_trap;
>         ulong insn = 0;
>
>         trap->cause = 0;
> --
> 2.43.0
>


From anup at brainfault.org  Sun Jul 20 08:42:44 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 21:12:44 +0530
Subject: [PATCH v3 2/2] firmware: Initial compiler built-in stack
 protector support
In-Reply-To: <20250703151957.2545958-3-alvinga@andestech.com>
References: <20250703151957.2545958-1-alvinga@andestech.com> <20250703151957.2545958-3-alvinga@andestech.com>
Message-ID: <CAAhSdy3QOYRp5rVSyK0w2ZJj1EqT-8ZNLa-xFUv633szu0Vz0Q@mail.gmail.com>

On Thu, Jul 3, 2025 at 8:50?PM Alvin Chang <alvinga at andestech.com> wrote:
>
> Add __stack_chk_fail() and __stack_chk_guard variable which are used by
> compiler built-in stack protector.
>
> This patch just try to support stack-protector so the value of the stack
> guard variable is simply fixed for now. It could be improved by
> deriving from a random number generator, such as Zkr extension or any
> platform-specific random number sources.
>
> Introduce three configurations for the stack protector:
> 1. CONFIG_STACK_PROTECTOR to enable the stack protector feature by
>    providing "-fstack-protector" compiler flag
> 2. CONFIG_STACK_PROTECTOR_STRONG to provide "-fstack-protector-strong"
> 3. CONFIG_STACK_PROTECTOR_ALL to provide "-fstack-protector-all"

The only issue I noticed is that test payload fails to run for
CONFIG_STACK_PROTECTOR_ALL=y but Linux boots fine.
Other two kconfig options are fine.

This is a good addition so I won't delay further. Please send
separate patch to fix test payload for CONFIG_STACK_PROTECTOR_ALL=y.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

>
> Instead of fixing the compiler flag of stack-protector feature as
> "-fstack-protector", we derive it from the introduced Kconfig
> configurations. The compiler flag "stack-protector-cflags-y" is defined
> as Makefile "immediately expanded variables" with ":=". Thus, the
> stronger configuration of the stack protector can overwrite the
> preceding one.
>
> Signed-off-by: Alvin Chang <alvinga at andestech.com>
> ---
>  firmware/Kconfig              | 27 +++++++++++++++++++++++++++
>  firmware/fw_base.S            | 21 +++++++++++++++++++++
>  firmware/objects.mk           |  9 +++++++++
>  firmware/payloads/test_head.S | 15 +++++++++++++++
>  4 files changed, 72 insertions(+)
>
> diff --git a/firmware/Kconfig b/firmware/Kconfig
> index d6e0506..c1fee19 100644
> --- a/firmware/Kconfig
> +++ b/firmware/Kconfig
> @@ -1 +1,28 @@
>  # SPDX-License-Identifier: BSD-2-Clause
> +
> +menu "Stack Protector Support"
> +
> +config STACK_PROTECTOR
> +       bool "Stack Protector buffer overflow detection"
> +       default n
> +       help
> +         This option turns on the "stack-protector" compiler feature.
> +
> +config STACK_PROTECTOR_STRONG
> +       bool "Strong Stack Protector"
> +       depends on STACK_PROTECTOR
> +       default n
> +       help
> +         Turn on the "stack-protector" with "-fstack-protector-strong" option.
> +         Like -fstack-protector but includes additional functions to be
> +         protected.
> +
> +config STACK_PROTECTOR_ALL
> +       bool "Almighty Stack Protector"
> +       depends on STACK_PROTECTOR
> +       default n
> +       help
> +         Turn on the "stack-protector" with "-fstack-protector-all" option.
> +         Like -fstack-protector except that all functions are protected.
> +
> +endmenu
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 2498797..a008fa7 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -736,6 +736,27 @@ _reset_regs:
>
>         ret
>
> +       .section .rodata
> +.Lstack_corrupt_msg:
> +       .string "stack smashing detected\n"
> +
> +       /* This will be called when the stack corruption is detected */
> +       .section .text
> +       .align 3
> +       .globl __stack_chk_fail
> +       .type __stack_chk_fail, %function
> +__stack_chk_fail:
> +       la      a0, .Lstack_corrupt_msg
> +       call    sbi_panic
> +
> +       /* Initial value of the stack guard variable */
> +       .section .data
> +       .align 3
> +       .globl __stack_chk_guard
> +       .type __stack_chk_guard, %object
> +__stack_chk_guard:
> +       RISCV_PTR       0x95B5FF5A
> +
>  #ifdef FW_FDT_PATH
>         .section .rodata
>         .align 4
> diff --git a/firmware/objects.mk b/firmware/objects.mk
> index a90485d..bfec467 100644
> --- a/firmware/objects.mk
> +++ b/firmware/objects.mk
> @@ -66,3 +66,12 @@ endif
>  ifdef FW_OPTIONS
>  firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
>  endif
> +
> +ifeq ($(CONFIG_STACK_PROTECTOR),y)
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
> +stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
> +else
> +stack-protector-cflags-y := -fno-stack-protector
> +endif
> +firmware-cflags-y += $(stack-protector-cflags-y)
> diff --git a/firmware/payloads/test_head.S b/firmware/payloads/test_head.S
> index 7d25e07..070ce8a 100644
> --- a/firmware/payloads/test_head.S
> +++ b/firmware/payloads/test_head.S
> @@ -97,3 +97,18 @@ _boot_a0:
>         RISCV_PTR       0
>  _boot_a1:
>         RISCV_PTR       0
> +
> +       /* This will be called when the stack corruption is detected */
> +       .section .text
> +       .align 3
> +       .globl __stack_chk_fail
> +       .type __stack_chk_fail, %function
> +       .equ  __stack_chk_fail, _start_hang
> +
> +       /* Initial value of the stack guard variable */
> +       .section .data
> +       .align 3
> +       .globl __stack_chk_guard
> +       .type __stack_chk_guard, %object
> +__stack_chk_guard:
> +       RISCV_PTR       0x95B5FF5A
> --
> 2.43.0
>


From anup at brainfault.org  Sun Jul 20 08:46:12 2025
From: anup at brainfault.org (Anup Patel)
Date: Sun, 20 Jul 2025 21:16:12 +0530
Subject: [PATCH] include: sbi: fix swap errors with newer gcc -Werror=sequence-point
In-Reply-To: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
References: <20250704122938.897832-1-ben.dooks@codethink.co.uk>
Message-ID: <CAAhSdy3z-HD_kK9hHNtW2RfzRyJtHaovPeFZJq_7oH=-ugivYg@mail.gmail.com>

On Fri, Jul 4, 2025 at 5:59?PM Ben Dooks <ben.dooks at codethink.co.uk> wrote:
>
> The BSWAPxx() macros are now throwing the following warnings with
> newer gcc versions. This is due to throwing an argument in that may
> be evaluated more than one (I think) and therefore things like the
> example below should be avoided.
>
> Fix by making a set of BSWAPxx() wrappers which specifically onlt
> evaluate 'x' once.
>
> In file included lib/sbi/sbi_mpxy.c:21:
> lib/sbi/sbi_mpxy.c: In function ?sbi_mpxy_write_attrs?:
> ib/sbi/sbi_mpxy.c:632:63: error: operation on ?mem_idx? may be undefined [-Werror=sequence-point]
>   632 |                         attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
>       |                                                        ~~~~~~~^~
>
> Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>

I have taken care of Rahul's comment at the time
of merging this patch.

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/sbi_byteorder.h | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/include/sbi/sbi_byteorder.h b/include/sbi/sbi_byteorder.h
> index 2b4981e..ed7cad1 100644
> --- a/include/sbi/sbi_byteorder.h
> +++ b/include/sbi/sbi_byteorder.h
> @@ -14,13 +14,13 @@
>  # define _conv_cast(type, val) ((type)(val))
>  #endif
>
> -#define BSWAP16(x)     ((((x) & 0x00ff) << 8) | \
> +#define __BSWAP16(x)   ((((x) & 0x00ff) << 8) | \
>                          (((x) & 0xff00) >> 8))
> -#define BSWAP32(x)     ((((x) & 0x000000ff) << 24) | \
> +#define __BSWAP32(x)   ((((x) & 0x000000ff) << 24) | \
>                          (((x) & 0x0000ff00) << 8) | \
>                          (((x) & 0x00ff0000) >> 8) | \
>                          (((x) & 0xff000000) >> 24))
> -#define BSWAP64(x)     ((((x) & 0x00000000000000ffULL) << 56) | \
> +#define __BSWAP64(x)   ((((x) & 0x00000000000000ffULL) << 56) | \
>                          (((x) & 0x000000000000ff00ULL) << 40) | \
>                          (((x) & 0x0000000000ff0000ULL) << 24) | \
>                          (((x) & 0x00000000ff000000ULL) << 8) | \
> @@ -29,6 +29,10 @@
>                          (((x) & 0x00ff000000000000ULL) >> 40) | \
>                          (((x) & 0xff00000000000000ULL) >> 56))
>
> +#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
> +#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
> +#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
> +
>  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* CPU(little-endian) */
>  #define cpu_to_be16(x)         _conv_cast(uint16_t, BSWAP16(x))
>  #define cpu_to_be32(x)         _conv_cast(uint32_t, BSWAP32(x))
> --
> 2.37.2.352.g3c44437643
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From wxjstz at 126.com  Sun Jul 20 18:02:21 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 21 Jul 2025 09:02:21 +0800
Subject: [PATCH v2] firmware: payload: test: Add SBI shutdown call after test message
Message-ID: <20250721010807.460788-1-wxjstz@126.com>

Previously, 'make run' would hang in WFI after printing the test message.
This commit adds an SBI ecall to ensure QEMU exits cleanly after the test
payload runs.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
v2 changes:
- Remove the while loop and print the error message as suggested 
  by Anup.

 firmware/payloads/test_main.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
index 194dbbe6..03f6ba39 100644
--- a/firmware/payloads/test_main.c
+++ b/firmware/payloads/test_main.c
@@ -46,6 +46,13 @@ static inline void sbi_ecall_console_puts(const char *str)
 		  sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
 }
 
+static inline void sbi_ecall_shutdown(void)
+{
+	sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
+		  SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
+		  0, 0, 0, 0);
+}
+
 #define wfi()                                             \
 	do {                                              \
 		__asm__ __volatile__("wfi" ::: "memory"); \
@@ -54,7 +61,6 @@ static inline void sbi_ecall_console_puts(const char *str)
 void test_main(unsigned long a0, unsigned long a1)
 {
 	sbi_ecall_console_puts("\nTest payload running\n");
-
-	while (1)
-		wfi();
+	sbi_ecall_shutdown();
+	sbi_ecall_console_puts("sbi_ecall_shutdown failed to execute.\n");
 }
-- 
2.47.2



From anup at brainfault.org  Mon Jul 21 03:53:40 2025
From: anup at brainfault.org (Anup Patel)
Date: Mon, 21 Jul 2025 16:23:40 +0530
Subject: [PATCH] lib: sbi: Only enable TM bit in scounteren
In-Reply-To: <1069d437-7689-4ca6-9455-13c224ee773d@linux.dev>
References: <20250513-fix_scounteren-v1-1-01018e0c0b0a@rivosinc.com>
 <B1E3B737-3E3D-4FCD-ADA1-136F69433F39@jrtc27.com> <1069d437-7689-4ca6-9455-13c224ee773d@linux.dev>
Message-ID: <CAAhSdy1GBkK7u_tjK9C6R+zVUKxh=xBa5-pCi1dTcgAXn9ZkSQ@mail.gmail.com>

On Wed, May 14, 2025 at 1:04?PM Atish Patra <atish.patra at linux.dev> wrote:
>
> On 5/13/25 5:35 PM, Jessica Clarke wrote:
> > On 14 May 2025, at 01:25, Atish Patra <atishp at rivosinc.com> wrote:
> >
> >> The S-mode should disable Cycle and instruction counter for user space
> >> to avoid side channel attacks. The Linux kernel already does this so that
> >> any random user space code shouldn't be able to monitor cycle/instruction
> >> without higher privilege mode involvement.
> >>
> >> Remove the CY/IR bits in scountern in OpenSBI.
> >
> > Isn?t this a breaking change? S-mode OSes that are happy to allow
> > U-mode to read the counters are now broken, such as FreeBSD. BBL always
> > set scounteren to all ones (with bits above 2 being pointless without
> > programming mhpmeventX), and OpenSBI did that until it switched to this
> > behaviour of CY|TM|IR. So whether or not it was explicit in the
> > specification what these were initialised to, S-mode OSes exist that
> > assumed CY, TM and IR at least were available. Please do not break
> > things; treat the firmware<->S-mode interface in the same way as
> > kernel<->userspace, i.e. don?t break userspace/S-mode.
> >
>
> Allowing CY and IR direct access is a big security concern which was
> discussed in multiple threads[1] almost two year back. This resulted in
> patches in Linux that restricts that behavior. I assumed that other OS
> might have adopted a similar behavior by now. Hence the patch.
>
> [1]
> https://lore.kernel.org/linux-riscv/CAOnJCUKCwnOXGWKiwQQxZ92t4138JAOqzkkqtwApHRy6YuS0Kw at mail.gmail.com/
> > OSes that want to opt out can. And if you really want to push for this,
> > you need to wait for OSes to be changed to explicitly initialise
> > scounteren and only do it once old versions are sufficiently rare. But
> > you can?t just go doing this with no warning / deprecation period.
> >
>
> It seems FreeBSD continue to have the legacy behavior. It would be great
> if you can fix the freeBSD code sooner than later. Please let us know
> once that is done.
>
> I am absolutely fine waiting for some more time until the the commonly
> used S-mode OS behave as expected. However, we can not wait forever as
> well. So we have to set a flag day in the future avoid carrying this
> forever.
>
> How about OpenSBI v1.7(~2-3 months) or OpenSBI v1.8 (planned towards end
> of 2025) for this fix to be merged ?

KVM RISC-V is already updated to not initialize scounteren
for Guest/VM so along these lines lets go ahead with this patch.

I have applied this patch to the riscv/opensbi and this will be
part of OpenSBI v1.8 release in Dec 2025.

Thanks,
Anup


From anup at brainfault.org  Mon Jul 21 04:06:16 2025
From: anup at brainfault.org (Anup Patel)
Date: Mon, 21 Jul 2025 16:36:16 +0530
Subject: [PATCH v2] firmware: payload: test: Add SBI shutdown call after
 test message
In-Reply-To: <20250721010807.460788-1-wxjstz@126.com>
References: <20250721010807.460788-1-wxjstz@126.com>
Message-ID: <CAAhSdy2QajRpFubdUw+md7ppU1nd6-yWOXhRcE07kMszv_DbUA@mail.gmail.com>

On Mon, Jul 21, 2025 at 6:39?AM Xiang W <wxjstz at 126.com> wrote:
>
> Previously, 'make run' would hang in WFI after printing the test message.
> This commit adds an SBI ecall to ensure QEMU exits cleanly after the test
> payload runs.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
> v2 changes:
> - Remove the while loop and print the error message as suggested
>   by Anup.
>
>  firmware/payloads/test_main.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/firmware/payloads/test_main.c b/firmware/payloads/test_main.c
> index 194dbbe6..03f6ba39 100644
> --- a/firmware/payloads/test_main.c
> +++ b/firmware/payloads/test_main.c
> @@ -46,6 +46,13 @@ static inline void sbi_ecall_console_puts(const char *str)
>                   sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
>  }
>
> +static inline void sbi_ecall_shutdown(void)
> +{
> +       sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
> +                 SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
> +                 0, 0, 0, 0);
> +}
> +
>  #define wfi()                                             \
>         do {                                              \
>                 __asm__ __volatile__("wfi" ::: "memory"); \
> @@ -54,7 +61,6 @@ static inline void sbi_ecall_console_puts(const char *str)
>  void test_main(unsigned long a0, unsigned long a1)
>  {
>         sbi_ecall_console_puts("\nTest payload running\n");
> -
> -       while (1)
> -               wfi();
> +       sbi_ecall_shutdown();
> +       sbi_ecall_console_puts("sbi_ecall_shutdown failed to execute.\n");
>  }
> --
> 2.47.2
>


From anup at brainfault.org  Mon Jul 21 04:13:14 2025
From: anup at brainfault.org (Anup Patel)
Date: Mon, 21 Jul 2025 16:43:14 +0530
Subject: [PATCH] include: sbi: Don't use #pragma when preprocessing device
 tree sources
In-Reply-To: <20250709232840.37551-1-jrtc27@jrtc27.com>
References: <20250709232840.37551-1-jrtc27@jrtc27.com>
Message-ID: <CAAhSdy0h1-ikCv2wFnm0gxbFhnOGMXhDPKeGjjsycG_dHY6NFw@mail.gmail.com>

On Thu, Jul 10, 2025 at 4:58?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> Since this persists in the preprocessed output (so that it can affect
> the subsequent compilation), it ends up in the input to dtc and is a
> syntax error, breaking the k210 build. Ideally we wouldn't add the
> -include flag to DTSCPPFLAGS in the first place as this header is wholly
> pointless there, but that's a more invasive build system change compared
> to just making this header safe to include there.
>
> Fixes: 86c01a73ff9d ("lib: sbi: Avoid GOT indirection for global symbol references")
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/sbi_visibility.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/include/sbi/sbi_visibility.h b/include/sbi/sbi_visibility.h
> index e9c401c..f900c44 100644
> --- a/include/sbi/sbi_visibility.h
> +++ b/include/sbi/sbi_visibility.h
> @@ -7,10 +7,12 @@
>  #ifndef __SBI_VISIBILITY_H__
>  #define __SBI_VISIBILITY_H__
>
> +#ifndef __DTS__
>  /*
>   * Declare all global objects with hidden visibility so access is PC-relative
>   * instead of going through the GOT.
>   */
>  #pragma GCC visibility push(hidden)
> +#endif
>
>  #endif
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Mon Jul 21 04:13:34 2025
From: anup at brainfault.org (Anup Patel)
Date: Mon, 21 Jul 2025 16:43:34 +0530
Subject: [PATCH] firmware: Rename __rel_dyn_start/end to __rela_dyn_start/end
In-Reply-To: <20250710002937.44307-1-jrtc27@jrtc27.com>
References: <20250710002937.44307-1-jrtc27@jrtc27.com>
Message-ID: <CAAhSdy0xDquKS2LXaEK5mpKKz3aHrRk5xAWk+_KP8HiADX_yEw@mail.gmail.com>

On Thu, Jul 10, 2025 at 6:34?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> We are using and expecting the RELA format, not the REL format, and this
> is the conventional linker-generated name for the start/end symbols, so
> use it rather than confusing things by making it look like we're
> accessing .rel.dyn, which would be in the REL format with no explicit
> addend.
>
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  firmware/fw_base.S   | 4 ++--
>  firmware/fw_base.ldS | 4 ++--
>  2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index aa8e264..b675c9e 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -76,8 +76,8 @@ _sc_fail:
>         li      t0, FW_TEXT_START       /* link start */
>         lla     t1, _fw_start           /* load start */
>         sub     t2, t1, t0              /* load offset */
> -       lla     t0, __rel_dyn_start
> -       lla     t1, __rel_dyn_end
> +       lla     t0, __rela_dyn_start
> +       lla     t1, __rela_dyn_end
>         beq     t0, t1, _relocate_done
>  2:
>         REG_L   t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
> diff --git a/firmware/fw_base.ldS b/firmware/fw_base.ldS
> index a33746a..12c7a84 100644
> --- a/firmware/fw_base.ldS
> +++ b/firmware/fw_base.ldS
> @@ -47,9 +47,9 @@
>         . = ALIGN(0x1000); /* Ensure next section is page aligned */
>
>         .rela.dyn : {
> -               PROVIDE(__rel_dyn_start = .);
> +               PROVIDE(__rela_dyn_start = .);
>                 *(.rela*)
> -               PROVIDE(__rel_dyn_end = .);
> +               PROVIDE(__rela_dyn_end = .);
>         }
>
>         PROVIDE(_rodata_end = .);
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From maherme.dev at gmail.com  Mon Jul 21 09:07:12 2025
From: maherme.dev at gmail.com (=?UTF-8?q?Manuel=20Hern=C3=A1ndez=20M=C3=A9ndez?=)
Date: Mon, 21 Jul 2025 18:07:12 +0200
Subject: [PATCH] lib: sbi: pmu: Improve loop in pmu_ctr_find_hw
Message-ID: <20250721160712.8766-1-maherme.dev@gmail.com>

We do not need to iterate over all values in the loop,
we can break the loop when we found a valid counter
that is not started yet.

Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
---
 lib/sbi/sbi_pmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index 07a5c544..635cb0c7 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -780,6 +780,7 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs,
 				continue;
 			/* We found a valid counter that is not started yet */
 			ctr_idx = cbase;
+			break;
 		}
 	}
 
-- 
2.34.1



From maherme.dev at gmail.com  Mon Jul 21 09:09:20 2025
From: maherme.dev at gmail.com (=?UTF-8?q?Manuel=20Hern=C3=A1ndez=20M=C3=A9ndez?=)
Date: Mon, 21 Jul 2025 18:09:20 +0200
Subject: [PATCH] platform: openpiton: Add PMU initialization
Message-ID: <20250721160920.8818-1-maherme.dev@gmail.com>

The OpenPiton framework has a generic PMU that is not used by OpenSBI.
Due to OpenSBI?s build system we cannot directly reuse the generic
platform functions, so simply copy them to the OpenPiton platform.

Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
---
 platform/fpga/openpiton/platform.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
index d2cf3e32..08136859 100644
--- a/platform/fpga/openpiton/platform.c
+++ b/platform/fpga/openpiton/platform.c
@@ -11,6 +11,7 @@
 #include <sbi/sbi_platform.h>
 #include <sbi_utils/fdt/fdt_helper.h>
 #include <sbi_utils/fdt/fdt_fixup.h>
+#include <sbi_utils/fdt/fdt_pmu.h>
 #include <sbi_utils/ipi/aclint_mswi.h>
 #include <sbi_utils/irqchip/plic.h>
 #include <sbi_utils/serial/uart8250.h>
@@ -156,6 +157,42 @@ static int openpiton_timer_init(void)
 	return aclint_mtimer_cold_init(&mtimer, NULL);
 }
 
+/*
+ * Initialize openpiton pmu during cold boot.
+ */
+int openpiton_pmu_init(void)
+{
+	int rc;
+
+	rc = fdt_pmu_setup(fdt_get_address());
+	if (rc && rc != SBI_ENOENT)
+		return rc;
+
+	return 0;
+}
+
+uint64_t openpiton_pmu_xlate_to_mhpmevent(uint32_t event_idx, uint64_t data)
+{
+	uint64_t evt_val = 0;
+
+	/* data is valid only for raw events and is equal to event selector */
+	if (event_idx == SBI_PMU_EVENT_RAW_IDX ||
+		event_idx == SBI_PMU_EVENT_RAW_V2_IDX)
+		evt_val = data;
+	else {
+		/**
+		 * Generic platform follows the SBI specification recommendation
+		 * i.e. zero extended event_idx is used as mhpmevent value for
+		 * hardware general/cache events if platform does't define one.
+		 */
+		evt_val = fdt_pmu_get_select_value(event_idx);
+		if (!evt_val)
+			evt_val = (uint64_t)event_idx;
+	}
+
+	return evt_val;
+}
+
 /*
  * Platform descriptor.
  */
@@ -165,6 +202,8 @@ const struct sbi_platform_operations platform_ops = {
 	.irqchip_init = openpiton_irqchip_init,
 	.ipi_init = openpiton_ipi_init,
 	.timer_init = openpiton_timer_init,
+	.pmu_init = openpiton_pmu_init,
+	.pmu_xlate_to_mhpmevent = openpiton_pmu_xlate_to_mhpmevent,
 };
 
 const struct sbi_platform platform = {
-- 
2.34.1



From samuel.holland at sifive.com  Mon Jul 21 11:36:48 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Mon, 21 Jul 2025 13:36:48 -0500
Subject: [PATCH] platform: openpiton: Add PMU initialization
In-Reply-To: <20250721160920.8818-1-maherme.dev@gmail.com>
References: <20250721160920.8818-1-maherme.dev@gmail.com>
Message-ID: <42fb18cc-d579-490f-b7db-89cb8d228ee8@sifive.com>

Hi,

On 2025-07-21 11:09 AM, Manuel Hern?ndez M?ndez wrote:
> The OpenPiton framework has a generic PMU that is not used by OpenSBI.
> Due to OpenSBI?s build system we cannot directly reuse the generic
> platform functions, so simply copy them to the OpenPiton platform.

Since you must be using a FDT for the new PMU functions to work, is there
anything preventing you from using that FDT with the generic platform? The
generic platform is where new features are added; the other platforms get only
minimal maintenance and testing. So it might be better to migrate OpenPiton to
the generic platform if possible.

If firmware size is a concern, we can create a slimmed-down defconfig -- a
generic platform build with a limited set of drivers is only about 13 KiB larger
than a fpga/openpiton build.

> Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>
> ---
>  platform/fpga/openpiton/platform.c | 39 ++++++++++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index d2cf3e32..08136859 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -11,6 +11,7 @@
>  #include <sbi/sbi_platform.h>
>  #include <sbi_utils/fdt/fdt_helper.h>
>  #include <sbi_utils/fdt/fdt_fixup.h>
> +#include <sbi_utils/fdt/fdt_pmu.h>
>  #include <sbi_utils/ipi/aclint_mswi.h>
>  #include <sbi_utils/irqchip/plic.h>
>  #include <sbi_utils/serial/uart8250.h>
> @@ -156,6 +157,42 @@ static int openpiton_timer_init(void)
>  	return aclint_mtimer_cold_init(&mtimer, NULL);
>  }
>  
> +/*
> + * Initialize openpiton pmu during cold boot.
> + */
> +int openpiton_pmu_init(void)
> +{
> +	int rc;
> +
> +	rc = fdt_pmu_setup(fdt_get_address());

You would also need a defconfig change enabling CONFIG_FDT_PMU for this function
call to do anything.

Regards,
Samuel

> +	if (rc && rc != SBI_ENOENT)
> +		return rc;
> +
> +	return 0;
> +}
> +
> +uint64_t openpiton_pmu_xlate_to_mhpmevent(uint32_t event_idx, uint64_t data)
> +{
> +	uint64_t evt_val = 0;
> +
> +	/* data is valid only for raw events and is equal to event selector */
> +	if (event_idx == SBI_PMU_EVENT_RAW_IDX ||
> +		event_idx == SBI_PMU_EVENT_RAW_V2_IDX)
> +		evt_val = data;
> +	else {
> +		/**
> +		 * Generic platform follows the SBI specification recommendation
> +		 * i.e. zero extended event_idx is used as mhpmevent value for
> +		 * hardware general/cache events if platform does't define one.
> +		 */
> +		evt_val = fdt_pmu_get_select_value(event_idx);
> +		if (!evt_val)
> +			evt_val = (uint64_t)event_idx;
> +	}
> +
> +	return evt_val;
> +}
> +
>  /*
>   * Platform descriptor.
>   */
> @@ -165,6 +202,8 @@ const struct sbi_platform_operations platform_ops = {
>  	.irqchip_init = openpiton_irqchip_init,
>  	.ipi_init = openpiton_ipi_init,
>  	.timer_init = openpiton_timer_init,
> +	.pmu_init = openpiton_pmu_init,
> +	.pmu_xlate_to_mhpmevent = openpiton_pmu_xlate_to_mhpmevent,
>  };
>  
>  const struct sbi_platform platform = {



From anup at brainfault.org  Tue Jul 22 03:36:01 2025
From: anup at brainfault.org (Anup Patel)
Date: Tue, 22 Jul 2025 16:06:01 +0530
Subject: [PATCH] platform: openpiton: fix uninitialized plic_data struct
In-Reply-To: <20250708180914.1131-1-maherme.dev@gmail.com>
References: <20250708180914.1131-1-maherme.dev@gmail.com>
Message-ID: <CAAhSdy0K+dyCU4OoHC1W-trqFwGEoq6+hOm7GGY6oUJ5qwWkJg@mail.gmail.com>

On Wed, Jul 9, 2025 at 1:10?AM Manuel Hern?ndez M?ndez
<maherme.dev at gmail.com> wrote:
>
> The plic_data struct was uninitialized. This led to misfunction behavior
> since it was subsequently assigned to the global plic struct, and some
> struct fields, such as flags and irqchip, contained random values.
> The fix proposes to initialize the plic_data to the global plic struct,
> so, after parsing the fdt, the fields of the struct will be set to the
> default values set in global plic struct definition, or the parsed values
> in the fdt, or zero.
>
> Fixes: 4c37451 ("platform: openpiton: Read the device configurations from
> device tree")
> Signed-off-by: Manuel Hern?ndez M?ndez <maherme.dev at gmail.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  platform/fpga/openpiton/platform.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c
> index d2cf3e32..faa299ce 100644
> --- a/platform/fpga/openpiton/platform.c
> +++ b/platform/fpga/openpiton/platform.c
> @@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
>  {
>         const void *fdt;
>         struct platform_uart_data uart_data = { 0 };
> -       struct plic_data plic_data;
> +       struct plic_data plic_data = plic;
>         unsigned long aclint_freq;
>         uint64_t clint_addr;
>         int rc;
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Tue Jul 22 03:45:56 2025
From: anup at brainfault.org (Anup Patel)
Date: Tue, 22 Jul 2025 16:15:56 +0530
Subject: [PATCH 1/3] include: sbi: Use array for struct sbi_trap_regs and
 GET/SET macros
In-Reply-To: <20250709232932.37622-1-jrtc27@jrtc27.com>
References: <20250709232932.37622-1-jrtc27@jrtc27.com>
Message-ID: <CAAhSdy1LqrL9ngoF=sfGa=KCpXanmKrZWnU2Tc94_wrUqsNuCg@mail.gmail.com>

On Thu, Jul 10, 2025 at 4:59?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> Rather than hand-rolling scaled pointer arithmetic with casts and
> shifts, let the compiler do so by indexing an array of GPRs, taking
> advantage of the language's type system to scale based on whatever type
> the register happens to be. This makes it easier to support CHERI where
> the registers are capabilities, not plain integers, and so this pointer
> arithmetic would need to change (and currently REGBYTES is both the size
> of a register and the size of an integer word upstream).
>
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/riscv_encoding.h |  25 ++----
>  include/sbi/sbi_trap.h       | 148 ++++++++++++++++++++---------------
>  2 files changed, 92 insertions(+), 81 deletions(-)
>
> diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
> index e1256e3..f4df1ae 100644
> --- a/include/sbi/riscv_encoding.h
> +++ b/include/sbi/riscv_encoding.h
> @@ -1291,6 +1291,8 @@
>  #define SHIFT_FUNCT3                   12
>
>  #define MASK_RS1                       0xf8000
> +#define MASK_RS2                       0x1f00000
> +#define MASK_RD                                0xf80
>
>  #define MASK_CSR                       0xfff00000
>  #define SHIFT_CSR                      20
> @@ -1356,28 +1358,17 @@
>  #define SHIFT_RIGHT(x, y)              \
>         ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
>
> -#define REG_MASK                       \
> -       ((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
> -
> -#define REG_OFFSET(insn, pos)          \
> -       (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
> -
> -#define REG_PTR(insn, pos, regs)       \
> -       (ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
> -
>  #define GET_FUNC3(insn)                        ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
>  #define GET_RM(insn)                   GET_FUNC3(insn)
> -#define GET_RS1_NUM(insn)              ((insn & MASK_RS1) >> 15)
> +#define GET_RS1_NUM(insn)              ((insn & MASK_RS1) >> SH_RS1)
> +#define GET_RS2_NUM(insn)              ((insn & MASK_RS2) >> SH_RS2)
> +#define GET_RS1S_NUM(insn)             RVC_RS1S(insn)
> +#define GET_RS2S_NUM(insn)             RVC_RS2S(insn)
> +#define GET_RS2C_NUM(insn)             RVC_RS2(insn)
> +#define GET_RD_NUM(insn)               ((insn & MASK_RD) >> SH_RD)
>  #define GET_CSR_NUM(insn)              ((insn & MASK_CSR) >> SHIFT_CSR)
>  #define GET_AQRL(insn)                 ((insn & MASK_AQRL) >> SHIFT_AQRL)
>
> -#define GET_RS1(insn, regs)            (*REG_PTR(insn, SH_RS1, regs))
> -#define GET_RS2(insn, regs)            (*REG_PTR(insn, SH_RS2, regs))
> -#define GET_RS1S(insn, regs)           (*REG_PTR(RVC_RS1S(insn), 0, regs))
> -#define GET_RS2S(insn, regs)           (*REG_PTR(RVC_RS2S(insn), 0, regs))
> -#define GET_RS2C(insn, regs)           (*REG_PTR(insn, SH_RS2C, regs))
> -#define GET_SP(regs)                   (*REG_PTR(2, 0, regs))
> -#define SET_RD(insn, regs, val)                (*REG_PTR(insn, SH_RD, regs) = (val))
>  #define IMM_I(insn)                    ((s32)(insn) >> 20)
>  #define IMM_S(insn)                    (((s32)(insn) >> 25 << 5) | \
>                                          (s32)(((insn) >> 7) & 0x1f))
> diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
> index 5eec4da..731a0c9 100644
> --- a/include/sbi/sbi_trap.h
> +++ b/include/sbi/sbi_trap.h
> @@ -127,70 +127,75 @@
>
>  /** Representation of register state at time of trap/interrupt */
>  struct sbi_trap_regs {
> -       /** zero register state */
> -       unsigned long zero;
> -       /** ra register state */
> -       unsigned long ra;
> -       /** sp register state */
> -       unsigned long sp;
> -       /** gp register state */
> -       unsigned long gp;
> -       /** tp register state */
> -       unsigned long tp;
> -       /** t0 register state */
> -       unsigned long t0;
> -       /** t1 register state */
> -       unsigned long t1;
> -       /** t2 register state */
> -       unsigned long t2;
> -       /** s0 register state */
> -       unsigned long s0;
> -       /** s1 register state */
> -       unsigned long s1;
> -       /** a0 register state */
> -       unsigned long a0;
> -       /** a1 register state */
> -       unsigned long a1;
> -       /** a2 register state */
> -       unsigned long a2;
> -       /** a3 register state */
> -       unsigned long a3;
> -       /** a4 register state */
> -       unsigned long a4;
> -       /** a5 register state */
> -       unsigned long a5;
> -       /** a6 register state */
> -       unsigned long a6;
> -       /** a7 register state */
> -       unsigned long a7;
> -       /** s2 register state */
> -       unsigned long s2;
> -       /** s3 register state */
> -       unsigned long s3;
> -       /** s4 register state */
> -       unsigned long s4;
> -       /** s5 register state */
> -       unsigned long s5;
> -       /** s6 register state */
> -       unsigned long s6;
> -       /** s7 register state */
> -       unsigned long s7;
> -       /** s8 register state */
> -       unsigned long s8;
> -       /** s9 register state */
> -       unsigned long s9;
> -       /** s10 register state */
> -       unsigned long s10;
> -       /** s11 register state */
> -       unsigned long s11;
> -       /** t3 register state */
> -       unsigned long t3;
> -       /** t4 register state */
> -       unsigned long t4;
> -       /** t5 register state */
> -       unsigned long t5;
> -       /** t6 register state */
> -       unsigned long t6;
> +       union {
> +               unsigned long gprs[32];
> +               struct {
> +                       /** zero register state */
> +                       unsigned long zero;
> +                       /** ra register state */
> +                       unsigned long ra;
> +                       /** sp register state */
> +                       unsigned long sp;
> +                       /** gp register state */
> +                       unsigned long gp;
> +                       /** tp register state */
> +                       unsigned long tp;
> +                       /** t0 register state */
> +                       unsigned long t0;
> +                       /** t1 register state */
> +                       unsigned long t1;
> +                       /** t2 register state */
> +                       unsigned long t2;
> +                       /** s0 register state */
> +                       unsigned long s0;
> +                       /** s1 register state */
> +                       unsigned long s1;
> +                       /** a0 register state */
> +                       unsigned long a0;
> +                       /** a1 register state */
> +                       unsigned long a1;
> +                       /** a2 register state */
> +                       unsigned long a2;
> +                       /** a3 register state */
> +                       unsigned long a3;
> +                       /** a4 register state */
> +                       unsigned long a4;
> +                       /** a5 register state */
> +                       unsigned long a5;
> +                       /** a6 register state */
> +                       unsigned long a6;
> +                       /** a7 register state */
> +                       unsigned long a7;
> +                       /** s2 register state */
> +                       unsigned long s2;
> +                       /** s3 register state */
> +                       unsigned long s3;
> +                       /** s4 register state */
> +                       unsigned long s4;
> +                       /** s5 register state */
> +                       unsigned long s5;
> +                       /** s6 register state */
> +                       unsigned long s6;
> +                       /** s7 register state */
> +                       unsigned long s7;
> +                       /** s8 register state */
> +                       unsigned long s8;
> +                       /** s9 register state */
> +                       unsigned long s9;
> +                       /** s10 register state */
> +                       unsigned long s10;
> +                       /** s11 register state */
> +                       unsigned long s11;
> +                       /** t3 register state */
> +                       unsigned long t3;
> +                       /** t4 register state */
> +                       unsigned long t4;
> +                       /** t5 register state */
> +                       unsigned long t5;
> +                       /** t6 register state */
> +                       unsigned long t6;
> +               };
> +       };
>         /** mepc register state */
>         unsigned long mepc;
>         /** mstatus register state */
> @@ -199,6 +204,21 @@ struct sbi_trap_regs {
>         unsigned long mstatusH;
>  };
>
> +_Static_assert(
> +       sizeof(((struct sbi_trap_regs *)0)->gprs) ==
> +       offsetof(struct sbi_trap_regs, t6) +
> +       sizeof(((struct sbi_trap_regs *)0)->t6),
> +       "struct sbi_trap_regs's layout differs between gprs and named members");
> +
> +#define REG_VAL(idx, regs)             ((regs)->gprs[(idx)])
> +
> +#define GET_RS1(insn, regs)            REG_VAL(GET_RS1_NUM(insn), regs)
> +#define GET_RS2(insn, regs)            REG_VAL(GET_RS2_NUM(insn), regs)
> +#define GET_RS1S(insn, regs)           REG_VAL(GET_RS1S_NUM(insn), regs)
> +#define GET_RS2S(insn, regs)           REG_VAL(GET_RS2S_NUM(insn), regs)
> +#define GET_RS2C(insn, regs)           REG_VAL(GET_RS2C_NUM(insn), regs)
> +#define SET_RD(insn, regs, val)                (REG_VAL(GET_RD_NUM(insn), regs) = (val))
> +
>  /** Representation of trap details */
>  struct sbi_trap_info {
>         /** cause Trap exception cause */
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Tue Jul 22 03:46:22 2025
From: anup at brainfault.org (Anup Patel)
Date: Tue, 22 Jul 2025 16:16:22 +0530
Subject: [PATCH 2/3] firmware: Replace sole uses of REGBYTES with __SIZEOF_LONG__
In-Reply-To: <20250709232932.37622-2-jrtc27@jrtc27.com>
References: <20250709232932.37622-1-jrtc27@jrtc27.com> <20250709232932.37622-2-jrtc27@jrtc27.com>
Message-ID: <CAAhSdy39f5+XbghEyZkR50zCM+qpUYsyZnK6_cwV3M9v8CK42g@mail.gmail.com>

On Thu, Jul 10, 2025 at 4:59?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> This code has nothing to do with the ISA's registers, it's about the
> format of ELF relocations. As such, __SIZEOF_LONG__, being a language /
> ABI-level property, is a more appropriate constant to use. This also
> makes it easier to support CHERI, where general-purpose registers are
> extended to be capabilities, not just integers, and so the register size
> is not the same as the machine word size. This also happens to make it
> more correct for RV64ILP32, where the registers are 64-bit integers but
> the ABI is 32-bit (both for long and for the ELF format), though
> properly supporting that ABI is not part of the motivation here, just a
> consequence of improving the code for CHERI.
>
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>

LGTM.

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, 3 insertions(+), 3 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 2498797..aa8e264 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -80,17 +80,17 @@ _sc_fail:
>         lla     t1, __rel_dyn_end
>         beq     t0, t1, _relocate_done
>  2:
> -       REG_L   t5, REGBYTES(t0)        /* t5 <-- relocation info:type */
> +       REG_L   t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
>         li      t3, R_RISCV_RELATIVE    /* reloc type R_RISCV_RELATIVE */
>         bne     t5, t3, 3f
>         REG_L   t3, 0(t0)
> -       REG_L   t5, (REGBYTES * 2)(t0)  /* t5 <-- addend */
> +       REG_L   t5, (__SIZEOF_LONG__ * 2)(t0)   /* t5 <-- addend */
>         add     t5, t5, t2
>         add     t3, t3, t2
>         REG_S   t5, 0(t3)               /* store runtime address to the GOT entry */
>
>  3:
> -       addi    t0, t0, (REGBYTES * 3)
> +       addi    t0, t0, (__SIZEOF_LONG__ * 3)
>         blt     t0, t1, 2b
>  _relocate_done:
>         /* At this point we are running from link address */
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Tue Jul 22 03:47:21 2025
From: anup at brainfault.org (Anup Patel)
Date: Tue, 22 Jul 2025 16:17:21 +0530
Subject: [PATCH 3/3] include: sbi: Remove unused (LOG_)REGBYTES
In-Reply-To: <20250709232932.37622-3-jrtc27@jrtc27.com>
References: <20250709232932.37622-1-jrtc27@jrtc27.com> <20250709232932.37622-3-jrtc27@jrtc27.com>
Message-ID: <CAAhSdy18+u1PtPkofNDp0V6bmpEDXtYHSrmUFRShUGZTg5i8Jg@mail.gmail.com>

On Thu, Jul 10, 2025 at 4:59?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> These are no longer used, so remove them.
>
> Signed-off-by: Jessica Clarke <jrtc27 at jrtc27.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
>  include/sbi/riscv_encoding.h | 7 -------
>  1 file changed, 7 deletions(-)
>
> diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
> index f4df1ae..40a854e 100644
> --- a/include/sbi/riscv_encoding.h
> +++ b/include/sbi/riscv_encoding.h
> @@ -1317,13 +1317,6 @@
>
>  #define INSN_LEN(insn)                 (INSN_IS_16BIT(insn) ? 2 : 4)
>
> -#if __riscv_xlen == 64
> -#define LOG_REGBYTES                   3
> -#else
> -#define LOG_REGBYTES                   2
> -#endif
> -#define REGBYTES                       (1 << LOG_REGBYTES)
> -
>  #define SH_VSEW                        3
>  #define SH_VIEW                        12
>  #define SH_VD                          7
> --
> 2.34.1
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From icebergfu at gmail.com  Tue Jul 22 14:35:21 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Tue, 22 Jul 2025 14:35:21 -0700
Subject: [PATCH v1] generic: mips: support harts to boot from mips_warm_boot
In-Reply-To: <65346468-9810-4f4a-9360-c588f758184f@sifive.com>
References: <20250710231708.4553-1-cfu@mips.com> <65346468-9810-4f4a-9360-c588f758184f@sifive.com>
Message-ID: <CAM1rFzFxWbCf8SLXhGYyRtVx33m4F0-H7m87fmoPCBzp_k_C8g@mail.gmail.com>

On Wed, Jul 16, 2025 at 5:04?PM Samuel Holland
<samuel.holland at sifive.com> wrote:
>
> On 2025-07-10 6:17 PM, Chao-ying Fu wrote:
> > We program reset base for harts (other than hart 0) to boot at
> > mips_warm_boot that jumps to _start_warm. This helps to skip some code
> > sequence to speed up.
> >
> > Signed-off-by: Chao-ying Fu <cfu at mips.com>
> > ---
> >  platform/generic/mips/p8700.c | 19 +++++++++++++++++++
> >  1 file changed, 19 insertions(+)
> >
> > diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> > index 888a45c..687912a 100644
> > --- a/platform/generic/mips/p8700.c
> > +++ b/platform/generic/mips/p8700.c
> > @@ -140,6 +140,22 @@ static void power_up_other_cluster(u32 hartid)
> >  }
> >  #endif
> >
> > +static void __attribute__((naked,no_instrument_function,aligned(4096)))
> > +mips_warm_boot(void)
> > +{
> > +  __asm__ __volatile__(
> > +     "       j       1f\n"
> > +     "       .align  2\n"
> > +     "       j       1f\n"
> > +     "       .align  2\n"
> > +     "       j       1f\n"
> > +     "       .align  2\n"
> > +     "       j       1f\n"
> > +     "1:     lla     t0, _start_warm\n"
> > +     "       jr      t0\n"
>
> The double/indirect jump is not necessary. jal (j) range is +/- 1 MiB, which is
> much larger than the OpenSBI firmware size. So each entry point can jump to
> _start_warm directly.
>
> Regards,
> Samuel
  Yes, we can use only one jump instruction to _start_warm for each
entry point, as you pointed out.
I will send out a new patch.

  Thanks a lot!

Regards,
Chao-ying

>
> > +     );
> > +}
> > +
> >  static int mips_hart_start(u32 hartid, ulong saddr)
> >  {
> >       unsigned int stat;
> > @@ -150,6 +166,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
> >       if (hartid == 0)
> >               return SBI_ENOTSUPP;
> >
> > +     /* Change reset base to mips_warm_boot */
> > +     write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
> > +
> >       if (cpu_hart(hartid) == 0) {
> >               /* Ensure its coherency is disabled */
> >               write_gcr_co_coherence(hartid, 0, local_p);
>


From icebergfu at gmail.com  Tue Jul 22 16:04:14 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Tue, 22 Jul 2025 16:04:14 -0700
Subject: [PATCH v2] generic: mips: support harts to boot from mips_warm_boot
Message-ID: <20250722230414.6815-1-cfu@mips.com>

We program reset base for harts (other than hart 0) to boot at
mips_warm_boot that jumps to _start_warm. This helps to skip some code
sequence to speed up.

Signed-off-by: Chao-ying Fu <cfu at mips.com>
---
 platform/generic/mips/p8700.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
index 888a45c..8c93ebf 100644
--- a/platform/generic/mips/p8700.c
+++ b/platform/generic/mips/p8700.c
@@ -140,6 +140,20 @@ static void power_up_other_cluster(u32 hartid)
 }
 #endif
 
+static void __attribute__((naked,no_instrument_function,aligned(4096)))
+mips_warm_boot(void)
+{
+  __asm__ __volatile__(
+	"	j	_start_warm\n"
+	"	.align	2\n"
+	"	j	_start_warm\n"
+	"	.align	2\n"
+	"	j	_start_warm\n"
+	"	.align	2\n"
+	"	j	_start_warm\n"
+	);
+}
+
 static int mips_hart_start(u32 hartid, ulong saddr)
 {
 	unsigned int stat;
@@ -150,6 +164,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
 	if (hartid == 0)
 		return SBI_ENOTSUPP;
 
+	/* Change reset base to mips_warm_boot */
+	write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
+
 	if (cpu_hart(hartid) == 0) {
 		/* Ensure its coherency is disabled */
 		write_gcr_co_coherence(hartid, 0, local_p);
-- 
2.47.1



From samuel.holland at sifive.com  Tue Jul 22 16:39:20 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Tue, 22 Jul 2025 16:39:20 -0700
Subject: [PATCH] platform: generic: Pack the FDT after applying fixups
Message-ID: <20250722233923.1356605-1-samuel.holland@sifive.com>

This minimizes the size that will be reserved by the OS for the FDT, and
it prevents the FDT buffer from containing uninitialized memory, which
can be important for some simulation platforms and for attestation.

Closes: https://github.com/riscv-software-src/opensbi/issues/388
Signed-off-by: Samuel Holland <samuel.holland at sifive.com>
---

 platform/generic/platform.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 47e771ad..889d6905 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -245,6 +245,8 @@ int generic_final_init(bool cold_boot)
 	fdt_fixups(fdt);
 	fdt_domain_fixup(fdt);
 
+	fdt_pack(fdt);
+
 	return 0;
 }
 
-- 
2.47.2

base-commit: cc546e1a06930c5ebaf6e90a9a28dca4218f1954
branch: up/fdt-pack


From samuel.holland at sifive.com  Tue Jul 22 17:18:23 2025
From: samuel.holland at sifive.com (Samuel Holland)
Date: Tue, 22 Jul 2025 19:18:23 -0500
Subject: [PATCH v2] generic: mips: support harts to boot from
 mips_warm_boot
In-Reply-To: <20250722230414.6815-1-cfu@mips.com>
References: <20250722230414.6815-1-cfu@mips.com>
Message-ID: <7b16297c-3b48-425e-a7bb-176440d21f29@sifive.com>

Hi Chao-ying,

On 2025-07-22 6:04 PM, Chao-ying Fu wrote:
> We program reset base for harts (other than hart 0) to boot at
> mips_warm_boot that jumps to _start_warm. This helps to skip some code
> sequence to speed up.
> 
> Signed-off-by: Chao-ying Fu <cfu at mips.com>
> ---
>  platform/generic/mips/p8700.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> index 888a45c..8c93ebf 100644
> --- a/platform/generic/mips/p8700.c
> +++ b/platform/generic/mips/p8700.c
> @@ -140,6 +140,20 @@ static void power_up_other_cluster(u32 hartid)
>  }
>  #endif
>  
> +static void __attribute__((naked,no_instrument_function,aligned(4096)))

Please follow Jess's suggestion and use an assembly file like we already do for
platform/generic/andes/sleep.S. This will be more reliable than forever fighting
the compiler to keep it from inserting any instructions on its own. (Are you
_sure_ that this list of attributes covers every toolchain and configuration?)

Regards,
Samuel

> +mips_warm_boot(void)
> +{
> +  __asm__ __volatile__(
> +	"	j	_start_warm\n"
> +	"	.align	2\n"
> +	"	j	_start_warm\n"
> +	"	.align	2\n"
> +	"	j	_start_warm\n"
> +	"	.align	2\n"
> +	"	j	_start_warm\n"
> +	);
> +}
> +
>  static int mips_hart_start(u32 hartid, ulong saddr)
>  {
>  	unsigned int stat;
> @@ -150,6 +164,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
>  	if (hartid == 0)
>  		return SBI_ENOTSUPP;
>  
> +	/* Change reset base to mips_warm_boot */
> +	write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
> +
>  	if (cpu_hart(hartid) == 0) {
>  		/* Ensure its coherency is disabled */
>  		write_gcr_co_coherence(hartid, 0, local_p);



From anup at brainfault.org  Tue Jul 22 22:20:04 2025
From: anup at brainfault.org (Anup Patel)
Date: Wed, 23 Jul 2025 10:50:04 +0530
Subject: [PATCH v2] lib: utils: fdt: fix "ranges" translation
In-Reply-To: <20250711-dev-maxh-master_fdt_helper-v2-1-9579e1f02ee1@sifive.com>
References: <20250711-dev-maxh-master_fdt_helper-v2-1-9579e1f02ee1@sifive.com>
Message-ID: <CAAhSdy1T00Stpb0OLwE=0=Brq6+x0aH8Seqgfv5mCEqyk2oWPg@mail.gmail.com>

On Fri, Jul 11, 2025 at 12:02?AM Max Hsu <max.hsu at sifive.com> wrote:
>
> According to the Device Tree Spec, Chapter 2.3.8 "ranges" [1]:
> The parent address size will be determined from the #address-cells
> property of the node that defines the parent?s address space.
>
> In fdt_translate_address(), which considered the parent address size
> is the child address size, this commit fix the two address sizes
> and parsing the address independently.
>
> Signed-off-by: Max Hsu <max.hsu at sifive.com>

LGTM.

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

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
> v1 fix will introduce another bug in the following case.
>
> The node in DTS depth 1 if execute fdt_get_node_addr_size(), inside
> the function, the fdt_translate_address() will try to get the child
> "#address-cells" and "#size-cells" in DTS depth 0, and the parent
> "#address-cells" in DTS depth -1. which will cause early abort.
> With fdt_translate_address() early abort, the parameter "addr" didn't
> got any assignment of the address value. This let
> fdt_get_node_addr_size() return with unknown value of parameter "addr".
>
> For the v2 fix, which will check the "ranges" first, since the above
> case shouldn't happen in the DTS as the "ranges" should be existed in
> DTS depth more than 0. This fix also improve execution cycle.
> ---
> Changes in v2:
> - fix v1 bug mentioned in the cover letter.
> - Link to v1: https://lore.kernel.org/r/20250708-dev-maxh-master_fdt_helper-v1-1-866c165f1f85 at sifive.com
> ---
>  lib/utils/fdt/fdt_helper.c | 26 +++++++++++++++-----------
>  1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index 0f4859c1a721bc7c2871bacefe27caba7780f752..799fd48dc3abf0a3c1963f84dd6bde271e6c08d7 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -84,23 +84,27 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
>                                  uint64_t *addr)
>  {
>         int i, rlen;
> -       int cell_addr, cell_size;
> +       int cell_parent_addr, cell_child_addr, cell_size;
>         const fdt32_t *ranges;
>         uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
>
> -       cell_addr = fdt_address_cells(fdt, parent);
> -       if (cell_addr < 1)
> -               return SBI_ENODEV;
> -
> -       cell_size = fdt_size_cells(fdt, parent);
> -       if (cell_size < 0)
> -               return SBI_ENODEV;
> -
>         ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
>         if (ranges && rlen > 0) {
> -               for (i = 0; i < cell_addr; i++)
> +               cell_child_addr = fdt_address_cells(fdt, parent);
> +               if (cell_child_addr < 1)
> +                       return SBI_ENODEV;
> +
> +               cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
> +               if (cell_parent_addr < 1)
> +                       return SBI_ENODEV;
> +
> +               cell_size = fdt_size_cells(fdt, parent);
> +               if (cell_size < 0)
> +                       return SBI_ENODEV;
> +
> +               for (i = 0; i < cell_child_addr; i++)
>                         caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
> -               for (i = 0; i < cell_addr; i++)
> +               for (i = 0; i < cell_parent_addr; i++)
>                         paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
>                 for (i = 0; i < cell_size; i++)
>                         rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);
>
> ---
> base-commit: a32a91069119e7a5aa31e6bc51d5e00860be3d80
> change-id: 20250708-dev-maxh-master_fdt_helper-46d2eeeb07cd
>
> Best regards,
> --
> Max Hsu <max.hsu at sifive.com>
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From anup at brainfault.org  Tue Jul 22 23:56:49 2025
From: anup at brainfault.org (Anup Patel)
Date: Wed, 23 Jul 2025 12:26:49 +0530
Subject: [PATCH] platform: generic: Pack the FDT after applying fixups
In-Reply-To: <20250722233923.1356605-1-samuel.holland@sifive.com>
References: <20250722233923.1356605-1-samuel.holland@sifive.com>
Message-ID: <CAAhSdy1DQdriFvvMu=J0AaiS2hezYwZpnEVuQkjwxu-bNDmz8g@mail.gmail.com>

On Wed, Jul 23, 2025 at 5:09?AM Samuel Holland
<samuel.holland at sifive.com> wrote:
>
> This minimizes the size that will be reserved by the OS for the FDT, and
> it prevents the FDT buffer from containing uninitialized memory, which
> can be important for some simulation platforms and for attestation.
>
> Closes: https://github.com/riscv-software-src/opensbi/issues/388
> Signed-off-by: Samuel Holland <samuel.holland at sifive.com>

LGTM.

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

Regards,
Anup

> ---
>
>  platform/generic/platform.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index 47e771ad..889d6905 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -245,6 +245,8 @@ int generic_final_init(bool cold_boot)
>         fdt_fixups(fdt);
>         fdt_domain_fixup(fdt);
>
> +       fdt_pack(fdt);
> +
>         return 0;
>  }
>
> --
> 2.47.2
>
> base-commit: cc546e1a06930c5ebaf6e90a9a28dca4218f1954
> branch: up/fdt-pack
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From icebergfu at gmail.com  Wed Jul 23 13:37:26 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Wed, 23 Jul 2025 13:37:26 -0700
Subject: [PATCH v2] generic: mips: support harts to boot from mips_warm_boot
In-Reply-To: <7b16297c-3b48-425e-a7bb-176440d21f29@sifive.com>
References: <20250722230414.6815-1-cfu@mips.com> <7b16297c-3b48-425e-a7bb-176440d21f29@sifive.com>
Message-ID: <CAM1rFzExBcwtSm+dMCn3byBZ9-Yza+SbPzmMX_Hd3DU7U+gW2A@mail.gmail.com>

On Tue, Jul 22, 2025 at 5:18?PM Samuel Holland
<samuel.holland at sifive.com> wrote:
>
> Hi Chao-ying,
>
> On 2025-07-22 6:04 PM, Chao-ying Fu wrote:
> > We program reset base for harts (other than hart 0) to boot at
> > mips_warm_boot that jumps to _start_warm. This helps to skip some code
> > sequence to speed up.
> >
> > Signed-off-by: Chao-ying Fu <cfu at mips.com>
> > ---
> >  platform/generic/mips/p8700.c | 17 +++++++++++++++++
> >  1 file changed, 17 insertions(+)
> >
> > diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
> > index 888a45c..8c93ebf 100644
> > --- a/platform/generic/mips/p8700.c
> > +++ b/platform/generic/mips/p8700.c
> > @@ -140,6 +140,20 @@ static void power_up_other_cluster(u32 hartid)
> >  }
> >  #endif
> >
> > +static void __attribute__((naked,no_instrument_function,aligned(4096)))
>
> Please follow Jess's suggestion and use an assembly file like we already do for
> platform/generic/andes/sleep.S. This will be more reliable than forever fighting
> the compiler to keep it from inserting any instructions on its own. (Are you
> _sure_ that this list of attributes covers every toolchain and configuration?)
>
Hi Sam,

  Ok. I will change to use an assembly file and send out v3 soon,
similar to sleep.S.
  Thanks a lot!

Regards,
Chao-ying


From icebergfu at gmail.com  Wed Jul 23 13:40:10 2025
From: icebergfu at gmail.com (Chao-ying Fu)
Date: Wed, 23 Jul 2025 13:40:10 -0700
Subject: [PATCH v3] generic: mips: support harts to boot from mips_warm_boot
Message-ID: <20250723204010.9927-1-cfu@mips.com>

We program reset base for harts (other than hart 0) to boot at
mips_warm_boot that jumps to _start_warm. This helps to skip some code
sequence to speed up.

Signed-off-by: Chao-ying Fu <cfu at mips.com>
---
 platform/generic/mips/mips_warm_boot.S | 20 ++++++++++++++++++++
 platform/generic/mips/objects.mk       |  2 +-
 platform/generic/mips/p8700.c          |  5 +++++
 3 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 platform/generic/mips/mips_warm_boot.S

diff --git a/platform/generic/mips/mips_warm_boot.S b/platform/generic/mips/mips_warm_boot.S
new file mode 100644
index 0000000..25cdb83
--- /dev/null
+++ b/platform/generic/mips/mips_warm_boot.S
@@ -0,0 +1,20 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+	.text
+	.align	12
+	.globl	mips_warm_boot
+mips_warm_boot:
+	j	_start_warm
+	.align	2
+nmi_vector:
+	j	_start_warm
+	.align	2
+cacheerr_vector:
+	j	_start_warm
+	.align	2
+debugexc_vector:
+	j	_start_warm
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
index bbbc15a..a08c4c6 100644
--- a/platform/generic/mips/objects.mk
+++ b/platform/generic/mips/objects.mk
@@ -4,5 +4,5 @@
 
 ifeq ($(PLATFORM_RISCV_XLEN), 64)
 carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
-platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/mips_warm_boot.o
 endif
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
index 888a45c..d3e015b 100644
--- a/platform/generic/mips/p8700.c
+++ b/platform/generic/mips/p8700.c
@@ -16,6 +16,8 @@
 #include <mips/p8700.h>
 #include <mips/mips-cm.h>
 
+extern void mips_warm_boot(void);
+
 static unsigned long mips_csr_read_num(int csr_num)
 {
 #define switchcase_csr_read(__csr_num, __val)		\
@@ -150,6 +152,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
 	if (hartid == 0)
 		return SBI_ENOTSUPP;
 
+	/* Change reset base to mips_warm_boot */
+	write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
+
 	if (cpu_hart(hartid) == 0) {
 		/* Ensure its coherency is disabled */
 		write_gcr_co_coherence(hartid, 0, local_p);
-- 
2.47.1



From jesse at rivosinc.com  Thu Jul 24 11:31:20 2025
From: jesse at rivosinc.com (Jesse Taube)
Date: Thu, 24 Jul 2025 11:31:20 -0700
Subject: [PATCH] dbtr: Add support for icount trigger type
Message-ID: <20250724183120.1822667-1-jesse@rivosinc.com>

The linux kernel needs icount to implement hardware breakpoints.

Signed-off-by: Jesse Taube <jesse at rivosinc.com>
---
 include/sbi/riscv_dbtr.h | 44 ++++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_dbtr.c       | 35 ++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/include/sbi/riscv_dbtr.h b/include/sbi/riscv_dbtr.h
index 96c7d3e3..e249eaed 100644
--- a/include/sbi/riscv_dbtr.h
+++ b/include/sbi/riscv_dbtr.h
@@ -122,6 +122,50 @@ enum {
 	RV_DBTR_DECLARE_BIT_MASK(MC, TYPE,    4),
 };
 
+
+/* ICOUNT - Match Control Type Register */
+enum {
+	RV_DBTR_DECLARE_BIT(ICOUNT, ACTION,   0),
+	RV_DBTR_DECLARE_BIT(ICOUNT, U,        6),
+	RV_DBTR_DECLARE_BIT(ICOUNT, S,        7),
+	RV_DBTR_DECLARE_BIT(ICOUNT, PENDING,  8),
+	RV_DBTR_DECLARE_BIT(ICOUNT, M,        9),
+	RV_DBTR_DECLARE_BIT(ICOUNT, COUNT,   10),
+	RV_DBTR_DECLARE_BIT(ICOUNT, HIT,     24),
+	RV_DBTR_DECLARE_BIT(ICOUNT, VU,      25),
+	RV_DBTR_DECLARE_BIT(ICOUNT, VS,      26),
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT(ICOUNT, DMODE,   59),
+	RV_DBTR_DECLARE_BIT(ICOUNT, TYPE,    60),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT(ICOUNT, DMODE,   27),
+	RV_DBTR_DECLARE_BIT(ICOUNT, TYPE,    28),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, ACTION,   6),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, U,        1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, S,        1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, PENDING,  1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, M,        1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, COUNT,   14),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, HIT,      1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VU,       1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VS,       1),
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE,    1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE,     4),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE,    1),
+	RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE,     4),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
 /* MC6 - Match Control 6 Type Register */
 enum {
 	RV_DBTR_DECLARE_BIT(MC6, LOAD,   0),
diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
index a832c7f1..c30c2fd6 100644
--- a/lib/sbi/sbi_dbtr.c
+++ b/lib/sbi/sbi_dbtr.c
@@ -336,6 +336,19 @@ static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
 		if (__test_bit(RV_DBTR_BIT(MC6, VS), &tdata1))
 			__set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
 		break;
+	case RISCV_DBTR_TRIG_ICOUNT:
+		if (__test_bit(RV_DBTR_BIT(ICOUNT, U), &tdata1))
+			__set_bit(RV_DBTR_BIT(TS, U), &trig->state);
+
+		if (__test_bit(RV_DBTR_BIT(ICOUNT, S), &tdata1))
+			__set_bit(RV_DBTR_BIT(TS, S), &trig->state);
+
+		if (__test_bit(RV_DBTR_BIT(ICOUNT, VU), &tdata1))
+			__set_bit(RV_DBTR_BIT(TS, VU), &trig->state);
+
+		if (__test_bit(RV_DBTR_BIT(ICOUNT, VS), &tdata1))
+			__set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
+		break;
 	default:
 		sbi_dprintf("%s: Unknown type (tdata1: 0x%lx Type: %ld)\n",
 			    __func__, tdata1, TDATA1_GET_TYPE(tdata1));
@@ -379,6 +392,16 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
 		update_bit(state & RV_DBTR_BIT_MASK(TS, S),
 			   RV_DBTR_BIT(MC6, S), &trig->tdata1);
 		break;
+	case RISCV_DBTR_TRIG_ICOUNT:
+		update_bit(state & RV_DBTR_BIT_MASK(TS, VU),
+			   RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
+		update_bit(state & RV_DBTR_BIT_MASK(TS, VS),
+			   RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
+		update_bit(state & RV_DBTR_BIT_MASK(TS, U),
+			   RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
+		update_bit(state & RV_DBTR_BIT_MASK(TS, S),
+			   RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
+		break;
 	default:
 		break;
 	}
@@ -418,6 +441,12 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
 		__clear_bit(RV_DBTR_BIT(MC6, U), &trig->tdata1);
 		__clear_bit(RV_DBTR_BIT(MC6, S), &trig->tdata1);
 		break;
+	case RISCV_DBTR_TRIG_ICOUNT:
+		__clear_bit(RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
+		__clear_bit(RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
+		__clear_bit(RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
+		__clear_bit(RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
+		break;
 	default:
 		break;
 	}
@@ -441,6 +470,7 @@ static int dbtr_trigger_supported(unsigned long type)
 	switch (type) {
 	case RISCV_DBTR_TRIG_MCONTROL:
 	case RISCV_DBTR_TRIG_MCONTROL6:
+	case RISCV_DBTR_TRIG_ICOUNT:
 		return 1;
 	default:
 		break;
@@ -462,6 +492,11 @@ static int dbtr_trigger_valid(unsigned long type, unsigned long tdata)
 		    !(tdata & RV_DBTR_BIT_MASK(MC6, M)))
 			return 1;
 		break;
+	case RISCV_DBTR_TRIG_ICOUNT:
+		if (!(tdata & RV_DBTR_BIT_MASK(ICOUNT, DMODE)) &&
+		    !(tdata & RV_DBTR_BIT_MASK(ICOUNT, M)))
+			return 1;
+		break;
 	default:
 		break;
 	}
-- 
2.43.0



From zhihong at nzhnb.com  Fri Jul 25 02:14:53 2025
From: zhihong at nzhnb.com (Niu Zhihong)
Date: Fri, 25 Jul 2025 17:14:53 +0800
Subject: [PATCH] lib: utils: Add PSCI implementation support
Message-ID: <20250725091453.188077-1-zhihong@nzhnb.com>

This patch adds Power State Coordination Interface (PSCI) support to OpenSBI.
PSCI provides a standard interface for power management operations such as
CPU power on/off, system suspend/resume, and system reset.

The implementation includes:
- PSCI version information and feature detection
- CPU power management (on/off/suspend)
- System power management (reset/off)
- Affinity level management
- PSCI library utilities and helper functions

This follows the PSCI specification version 1.3 and provides a foundation
for platform-specific power management implementations.

Signed-off-by: Niu Zhihong <zhihong at nzhnb.com>
---
diff --git a/include/sbi_utils/psci/psci.h b/include/sbi_utils/psci/psci.h
new file mode 100644
index 0000000..f063ec2
--- /dev/null
+++ b/include/sbi_utils/psci/psci.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright The OpenSBI Contributors
+ *
+ * See PSCI specification (Version 1.3 issue F.b) for more details.
+ */
+
+#ifndef __PSCI_H__
+#define __PSCI_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_hart.h>
+
+#define psci_assert(cond)                                                   \
+	do {                                                                \
+		if (!(cond)) {                                              \
+			sbi_printf("%s:%d, invalid psci state\n", __func__, \
+				   __LINE__);                               \
+			sbi_hart_hang();                                    \
+		}                                                           \
+	} while (0)
+
+/* Version 1.1 */
+#define PSCI_MAJOR_VER (1 << 16)
+#define PSCI_MINOR_VER 1
+
+#define PSCI_E_SUCCESS 0
+#define PSCI_E_NOT_SUPPORTED -1
+#define PSCI_E_INVALID_PARAMS -2
+#define PSCI_E_DENIED -3
+#define PSCI_E_ALREADY_ON -4
+#define PSCI_E_ON_PENDING -5
+#define PSCI_E_INTERN_FAIL -6
+#define PSCI_E_NOT_PRESENT -7
+#define PSCI_E_DISABLED -8
+#define PSCI_E_INVALID_ADDRESS -9
+
+/* PSCI function IDs */
+#define PSCI_FN_VERSION 0x84000000
+#define PSCI_FN_CPU_SUSPEND_SMC32 0x84000001
+#define PSCI_FN_CPU_SUSPEND_SMC64 0xC4000001
+#define PSCI_FN_CPU_OFF 0x84000002
+#define PSCI_FN_CPU_ON_SMC32 0x84000003
+#define PSCI_FN_CPU_ON_SMC64 0xC4000003
+#define PSCI_FN_AFFINITY_INFO_SMC32 0x84000004
+#define PSCI_FN_AFFINITY_INFO_SMC64 0xC4000004
+#define PSCI_FN_SYSTEM_OFF 0x84000008
+#define PSCI_FN_SYSTEM_RESET 0x84000009
+#define PSCI_FN_PSCI_FEATURES 0x8400000A
+#define PSCI_FN_SYSTEM_OFF2_SMC32 0x84000015
+#define PSCI_FN_SYSTEM_OFF2_SMC64 0xC4000015
+
+/* SMCCC function IDs */
+#define SMCCC_VERSION 0x80000000
+
+/* PSCI AFFINITY_INFO return values */
+#define PSCI_AFFINITY_STATE_ON 0
+#define PSCI_AFFINITY_STATE_OFF 1
+#define PSCI_AFFINITY_STATE_ON_PENDING 2
+
+/* PSCI power state TYPEs */
+#define PSCI_PSTATE_TYPE_STANDBY 0x0
+#define PSCI_PSTATE_TYPE_POWERDOWN 0x1
+
+/* PSCI power state IDs */
+#define PSCI_PSTATE_ID_RUN 0x0
+#define PSCI_PSTATE_ID_STANDBY 0x1
+#define PSCI_PSTATE_ID_RETENTION 0x2
+#define PSCI_PSTATE_ID_POWERDOWN 0x3
+
+/**
+ * Description:
+ * Return the version of PSCI implemented. This function allows a caller
+ * to ascertain the current version of the PSCI interface.
+ * 
+ * Return Value:
+ * uint32_t - 31-bit unsigned integer containing version information:
+ * - Bits[31:16]: Major Version (upper 15 bits)
+ * - Bits[15:0]:  Minor Version (lower 16 bits)
+ * 
+ * Current Implementation:
+ * - Major Version: 1 (PSCI_MAJOR_VER)
+ * - Minor Version: 1 (PSCI_MINOR_VER)
+ * - Combined Version: 0x00010001
+ */
+uint32_t psci_version();
+
+/**
+ * Description:
+ * Suspend execution on a core or higher-level topology node. This call is
+ * intended for use in idle subsystems where the core is expected to return
+ * to execution through a wakeup event.
+ * 
+ * Parameters:
+ * - power_state: Describes the target power state for suspension
+ *   - uint32 value defining the power state characteristics
+ *   - Extended StateID format:
+ *     - Bit[31]: Reserved, must be zero
+ *     - Bit[30]: StateType
+ *       - PSCI_PSTATE_TYPE_STANDBY (0): Standby or retention state (no core context lost)
+ *       - PSCI_PSTATE_TYPE_POWERDOWN (1): Powerdown state (core context lost, entry_point_address and context_id valid)
+ *     - Bits[29:28]: Reserved, must be zero
+ *     - Bits[27:0]: StateID (platform-specific state identifier)
+ *         - PSCI_PSTATE_ID_RUN (0x0): Normal running state
+ *         - PSCI_PSTATE_ID_STANDBY (0x1): Standby state (quick wake-up)
+ *         - PSCI_PSTATE_ID_RETENTION (0x2): Retention state (context preserved)
+ *         - PSCI_PSTATE_ID_POWERDOWN (0x3): Powerdown state (context lost)
+ *   - Format is determined by PSCI_FEATURES bit[1] for CPU_SUSPEND
+ *
+ * - entry_point_address: Resume execution address after wakeup
+ *   - Only valid for powerdown states; ignored for standby states
+ * 
+ * - context_id: Context value for powerdown states
+ *   - Only valid for powerdown states; ignored for standby states
+ * 
+ * Return Value:
+ * intptr_t - Result of the CPU_SUSPEND operation:
+ * - PSCI_E_SUCCESS: Operation completed successfully
+ * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
+ * - PSCI_E_INVALID_ADDRESS: Invalid entry point address
+ * - PSCI_E_DENIED: Operation denied (only in OS-initiated mode)
+ */
+intptr_t psci_cpu_suspend(uint32_t power_state, uintptr_t entry_point_address,
+			  uintptr_t context_id);
+
+/**
+ * Description:
+ * Power down the calling core. This call is intended for use in hotplug.
+ * A core that is powered down by CPU_OFF can only be powered up again
+ * in response to a CPU_ON call.
+ * 
+ * Return Value:
+ * int32_t - Result of the CPU_OFF operation:
+ * - Does not return when successful (core is powered down)
+ * - PSCI_E_DENIED: Operation denied (only possible return value on failure)
+ */
+int32_t psci_cpu_off();
+
+/**
+ * Description:
+ * Power up a core. This call is used to power up cores that either:
+ * - Have not yet been booted into the calling supervisory software
+ * - Have been previously powered down with a CPU_OFF call
+ * 
+ * Parameters:
+ * - target_cpu: Target CPU to power on
+ *   - In OpenSBI implementation: this corresponds to hartid
+ * 
+ * - entry_point_address: Physical address where core should start execution
+ * 
+ * - context_id: Context value passed to the target core
+ * 
+ * Return Value:
+ * intptr_t - Result of the CPU_ON operation:
+ * - PSCI_E_SUCCESS: Operation completed successfully
+ * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
+ * - PSCI_E_INVALID_ADDRESS: Invalid entry point address
+ * - PSCI_E_ALREADY_ON: Target CPU is already powered on
+ * - PSCI_E_ON_PENDING: Target CPU is already being powered on
+ * - PSCI_E_INTERN_FAIL: Internal failure occurred
+ * - PSCI_E_DENIED: Operation denied
+ */
+intptr_t psci_cpu_on(uintptr_t target_cpu, uintptr_t entry_point_address,
+		     uintptr_t context_id);
+
+/**
+ * Description:
+ * Enable the caller to request status of an affinity instance.
+ * 
+ * Parameters:
+ * - target_affinity: Target affinity instance to query
+ *   - In OpenSBI implementation: this corresponds to hartid
+ * 
+ * - lowest_affinity_level: 
+ *   - From PSCI version 1.0 onwards, AFFINITY_INFO is no longer required to
+ *     support affinity levels higher than 0.
+ *
+ * Return Value:
+ * intptr_t - Status of the affinity instance:
+ * - PSCI_AFFINITY_STATE_ON (0): At least one core in the affinity instance is ON
+ * - PSCI_AFFINITY_STATE_OFF (1): Affinity instance is OFF
+ * - PSCI_AFFINITY_STATE_ON_PENDING (2): Affinity instance is transitioning to ON state
+ * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
+ */
+intptr_t psci_affinity_info(uintptr_t target_affinity,
+			    uint32_t lowest_affinity_level);
+
+/**
+ * Description:
+ * Shut down the system.
+ */
+void psci_system_off();
+
+/**
+ * Description:
+ * Reset the system.
+ */
+void psci_system_reset();
+
+/**
+ * Description:
+ * Query API that allows discovering whether SMCCC_VERSION or a specific PSCI 
+ * function is implemented and its features. This function is introduced in 
+ * PSCI 1.0 specification.
+ * 
+ * Parameters:
+ * - psci_func_id: Function ID of PSCI Function or SMCCC_VERSION
+ * 
+ * Return values:
+ * - PSCI_E_NOT_SUPPORTED: if the function identified by psci_func_id is not 
+ *   implemented or is an invalid function ID
+ * - Feature flags (int32): A set of feature flags associated with the 
+ *   implemented function indicated by psci_func_id. Feature flags are specific 
+ *   to each function. Format:
+ *   - Bit[31] is zero
+ *   - Bits[30:0] represent the feature flags
+ */
+int32_t psci_features(uint32_t psci_func_id);
+
+#endif /* __PSCI_H__ */
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index 901ba56..5dada1e 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -34,4 +34,6 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig"
 
 source "$(OPENSBI_SRC_DIR)/lib/utils/mpxy/Kconfig"
 
+source "$(OPENSBI_SRC_DIR)/lib/utils/psci/Kconfig"
+
 endmenu
diff --git a/lib/utils/psci/Kconfig b/lib/utils/psci/Kconfig
new file mode 100644
index 0000000..f818cf7
--- /dev/null
+++ b/lib/utils/psci/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+# Copyright The OpenSBI Contributors
+
+menu "Arm Power State Coordination Interface Support"
+
+config ARM_PSCI
+	bool "Support PSCI protocol"
+	default n
+
+endmenu
diff --git a/lib/utils/psci/objects.mk b/lib/utils/psci/objects.mk
new file mode 100644
index 0000000..558dcae
--- /dev/null
+++ b/lib/utils/psci/objects.mk
@@ -0,0 +1,19 @@
+#
+# Copyright The OpenSBI Contributors
+#
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_version.o
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_cpu_suspend.o
+
+libsbiutils-objs-$(CONFIG_ARM_PSCI) += psci/psci_cpu_off.o
+
+libsbiutils-objs-$(CONFIG_ARM_PSCI) += psci/psci_cpu_on.o
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_affinity_info.o
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_system_off.o
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_system_reset.o
+
+libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_features.o
diff --git a/lib/utils/psci/psci_affinity_info.c b/lib/utils/psci/psci_affinity_info.c
new file mode 100644
index 0000000..e9b795f
--- /dev/null
+++ b/lib/utils/psci/psci_affinity_info.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_ecall_interface.h>
+
+intptr_t psci_affinity_info(uintptr_t target_affinity,
+			    uint32_t lowest_affinity_level)
+{
+	struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
+	const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+	uint32_t target_hartid	     = (uint32_t)target_affinity;
+	int hart_state;
+
+	/* Validate that we have a valid scratch area and domain */
+	if (!scratch || !dom)
+		return PSCI_E_INTERN_FAIL;
+
+	/* 
+	 * PSCI v1.0+ allows implementations to only support level 0 (individual cores)
+	 * For now, we only support querying individual hart/core state (level 0)
+	 */
+	if (lowest_affinity_level > 0)
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Check if target_affinity describes a valid hartid */
+	if (!sbi_hartid_valid(target_hartid))
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Check if the target hart is assigned to the current domain */
+	if (!sbi_domain_is_assigned_hart(
+		    dom, sbi_hartid_to_hartindex(target_hartid)))
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Get the current state of the target hart */
+	hart_state = sbi_hsm_hart_get_state(dom, target_hartid);
+	if (hart_state < 0)
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Map SBI HSM states to PSCI affinity states */
+	switch (hart_state) {
+	case SBI_HSM_STATE_STARTED:
+	case SBI_HSM_STATE_SUSPENDED:
+	case SBI_HSM_STATE_RESUME_PENDING:
+		/*
+		 * PSCI ON: At least one core in the affinity instance is ON
+		 */
+		return PSCI_AFFINITY_STATE_ON;
+
+	case SBI_HSM_STATE_STOPPED:
+		/*
+		 * PSCI OFF: All cores in the affinity instance are OFF
+		 */
+		return PSCI_AFFINITY_STATE_OFF;
+
+	case SBI_HSM_STATE_START_PENDING:
+	case SBI_HSM_STATE_STOP_PENDING:
+	case SBI_HSM_STATE_SUSPEND_PENDING:
+		/*
+		 * PSCI ON_PENDING: The affinity instance is transitioning to an ON state
+		 */
+		return PSCI_AFFINITY_STATE_ON_PENDING;
+
+	default:
+		/* Invalid or unknown state */
+		return PSCI_E_INTERN_FAIL;
+	}
+}
diff --git a/lib/utils/psci/psci_cpu_off.c b/lib/utils/psci/psci_cpu_off.c
new file mode 100644
index 0000000..3e1940a
--- /dev/null
+++ b/lib/utils/psci/psci_cpu_off.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+
+int32_t psci_cpu_off()
+{
+	struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
+	const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+	int ret;
+
+	/* Validate that we have a valid scratch area */
+	psci_assert(scratch != NULL);
+	psci_assert(dom != NULL);
+
+	ret = sbi_hsm_hart_stop(scratch, true);
+
+	/* We should never reach here if the hart stop succeeds */
+	if (ret != 0) {
+		return PSCI_E_DENIED;
+	}
+
+	/* This point should never be reached */
+	psci_assert(0);
+	return PSCI_E_DENIED;
+}
diff --git a/lib/utils/psci/psci_cpu_on.c b/lib/utils/psci/psci_cpu_on.c
new file mode 100644
index 0000000..17e5e1b
--- /dev/null
+++ b/lib/utils/psci/psci_cpu_on.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+
+intptr_t psci_cpu_on(uintptr_t target_cpu, uintptr_t entry_point_address,
+		     uintptr_t context_id)
+{
+	struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
+	const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+	struct sbi_scratch *remote_scratch;
+	uint32_t target_hartid = (uint32_t)target_cpu;
+	int hart_state;
+	int ret;
+
+	/* Validate that we have a valid scratch area and domain */
+	psci_assert(scratch != NULL);
+	psci_assert(dom != NULL);
+
+	/* Check if target_cpu describes a valid MPIDR/hartid */
+	if (!sbi_hartid_valid(target_hartid)) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/* Get scratch pointer for target hart */
+	remote_scratch = sbi_hartid_to_scratch(target_hartid);
+	if (!remote_scratch) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/* Check if the entry point address is valid for the caller's domain */
+	if (!sbi_domain_check_addr(dom, entry_point_address, PRV_S,
+				   SBI_DOMAIN_EXECUTE)) {
+		return PSCI_E_INVALID_ADDRESS;
+	}
+
+	/* Get current state of the target hart */
+	hart_state = sbi_hsm_hart_get_state(dom, target_hartid);
+
+	switch (hart_state) {
+	case SBI_HSM_STATE_STARTED:
+		/* Hart is already running */
+		return PSCI_E_ALREADY_ON;
+
+	case SBI_HSM_STATE_START_PENDING:
+		/* Hart start is already pending */
+		return PSCI_E_ON_PENDING;
+
+	case SBI_HSM_STATE_STOPPED:
+		/* Hart is stopped, we can start it */
+		break;
+
+	default:
+		/* Invalid state or other error */
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/* 
+	 * Start the target hart
+	 * - target_hartid: the hart to start
+	 * - entry_point_address: where the hart should start execution
+	 * - PRV_S: start in supervisor mode
+	 * - context_id: passed as argument to the started hart
+	 */
+	ret = sbi_hsm_hart_start(remote_scratch, dom, target_hartid,
+				 entry_point_address, PRV_S, context_id);
+
+	/* Convert SBI error codes to PSCI error codes */
+	switch (ret) {
+	case SBI_SUCCESS:
+		return PSCI_E_SUCCESS;
+	case SBI_ERR_INVALID_PARAM:
+		return PSCI_E_INVALID_PARAMS;
+	case SBI_ERR_INVALID_ADDRESS:
+		return PSCI_E_INVALID_ADDRESS;
+	case SBI_ERR_ALREADY_STARTED:
+		return PSCI_E_ALREADY_ON;
+	case SBI_ERR_DENIED:
+		return PSCI_E_DENIED;
+	default:
+		return PSCI_E_INTERN_FAIL;
+	}
+}
diff --git a/lib/utils/psci/psci_cpu_suspend.c b/lib/utils/psci/psci_cpu_suspend.c
new file mode 100644
index 0000000..16b0e5c
--- /dev/null
+++ b/lib/utils/psci/psci_cpu_suspend.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+
+/* PSCI power state TYPEs */
+#define PSCI_PSTATE_TYPE_SHIFT 30
+#define PSCI_PSTATE_TYPE_MASK 0x1
+
+/* PSCI power state StateID */
+#define PSCI_PSTATE_ID_SHIFT 0
+#define PSCI_PSTATE_ID_MASK 0x0FFFFFFF
+
+/* Helper macros for power state */
+#define psci_get_pstate_type(pstate) \
+	(((pstate) >> PSCI_PSTATE_TYPE_SHIFT) & PSCI_PSTATE_TYPE_MASK)
+#define psci_get_pstate_id(pstate) \
+	(((pstate) >> PSCI_PSTATE_ID_SHIFT) & PSCI_PSTATE_ID_MASK)
+
+intptr_t psci_cpu_suspend(uint32_t power_state, uintptr_t entry_point_address,
+			  uintptr_t context_id)
+{
+	struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
+	const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+	uint32_t pstate_type, pstate_id, suspend_type;
+	int ret;
+
+	/* Validate runtime environment */
+	psci_assert(scratch != NULL);
+	psci_assert(dom != NULL);
+
+	/* Validate power state format - check reserved bits */
+	if (power_state & 0x80000000) { /* Bit[31] must be zero */
+		return PSCI_E_INVALID_PARAMS;
+	}
+	if (power_state & 0x30000000) { /* Bits[29:28] must be zero */
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/* Extract StateType and StateID from power_state */
+	pstate_type = psci_get_pstate_type(power_state);
+	pstate_id   = psci_get_pstate_id(power_state);
+
+	/* Validate StateID values */
+	if (pstate_id > PSCI_PSTATE_ID_POWERDOWN) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/*
+	 * Handle different suspend types based on PSCI specification:
+	 * - STANDBY: Retention state, context preserved, quick wake-up
+	 * - POWERDOWN: Context lost, requires entry_point_address and context_id
+	 * 
+	 * StateID provides platform-specific power state information:
+	 * - PSCI_PSTATE_ID_RUN (0x0): Normal running state (invalid for suspend)
+	 * - PSCI_PSTATE_ID_STANDBY (0x1): Standby state (quick wake-up)
+	 * - PSCI_PSTATE_ID_RETENTION (0x2): Retention state (context preserved)
+	 * - PSCI_PSTATE_ID_POWERDOWN (0x3): Powerdown state (context lost)
+	 */
+	if (pstate_type == PSCI_PSTATE_TYPE_STANDBY) {
+		/*
+		 * Standby/Retention suspend:
+		 * - Core context is preserved
+		 * - entry_point_address and context_id are ignored
+		 * - Use retentive suspend mode
+		 * - Valid StateIDs: STANDBY, RETENTION
+		 */
+		if (pstate_id != PSCI_PSTATE_ID_STANDBY &&
+		    pstate_id != PSCI_PSTATE_ID_RETENTION) {
+			return PSCI_E_INVALID_PARAMS;
+		}
+
+		suspend_type = SBI_HSM_SUSPEND_RET_DEFAULT;
+
+		/* For standby, entry_point_address is ignored but we use current context */
+		entry_point_address = 0; /* Will be ignored by SBI HSM */
+		context_id	    = 0; /* Will be ignored by SBI HSM */
+
+	} else if (pstate_type == PSCI_PSTATE_TYPE_POWERDOWN) {
+		/*
+		 * Powerdown suspend:
+		 * - Core context will be lost
+		 * - entry_point_address must be valid and accessible
+		 * - context_id will be passed to resumed execution
+		 * - Use non-retentive suspend mode
+		 * - Valid StateID: POWERDOWN
+		 */
+		if (pstate_id != PSCI_PSTATE_ID_POWERDOWN) {
+			return PSCI_E_INVALID_PARAMS;
+		}
+
+		suspend_type = SBI_HSM_SUSPEND_NON_RET_DEFAULT;
+
+		/* Validate entry point address for powerdown states */
+		if (!entry_point_address) {
+			return PSCI_E_INVALID_ADDRESS;
+		}
+
+		/* Verify entry point is within caller's domain and executable */
+		if (!sbi_domain_check_addr(dom, entry_point_address, PRV_S,
+					   SBI_DOMAIN_EXECUTE)) {
+			return PSCI_E_INVALID_ADDRESS;
+		}
+
+	} else {
+		/* Invalid StateType - only STANDBY(0) and POWERDOWN(1) are valid */
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	/*
+	 * Initiate hart suspension through SBI HSM:
+	 * - suspend_type: SBI_HSM_SUSPEND_RET_DEFAULT or SBI_HSM_SUSPEND_NON_RET_DEFAULT
+	 * - entry_point_address: Resume address (powerdown) or 0 (standby)
+	 * - PRV_S: Resume in supervisor privilege mode
+	 * - context_id: Context value passed to resumed execution
+	 */
+	ret = sbi_hsm_hart_suspend(scratch, suspend_type, entry_point_address,
+				   PRV_S, context_id);
+
+	/*
+	 * Handle return values:
+	 * 
+	 * For STANDBY (retentive) suspend:
+	 * - Normal return with PSCI_E_SUCCESS indicates successful wake-up
+	 * 
+	 * For POWERDOWN (non-retentive) suspend:
+	 * - Should NOT return here on success (execution resumes at entry_point_address)
+	 * - If we return here, it indicates suspend was rejected, downgraded, or failed
+	 */
+	switch (ret) {
+	case SBI_SUCCESS:
+		/* Success - either completed standby or failed powerdown */
+		return PSCI_E_SUCCESS;
+	case SBI_ERR_INVALID_PARAM:
+		return PSCI_E_INVALID_PARAMS;
+	case SBI_ERR_INVALID_ADDRESS:
+		return PSCI_E_INVALID_ADDRESS;
+	case SBI_ERR_DENIED:
+		return PSCI_E_DENIED;
+	case SBI_ERR_NOT_SUPPORTED:
+		return PSCI_E_NOT_SUPPORTED;
+	default:
+		return PSCI_E_INTERN_FAIL;
+	}
+}
diff --git a/lib/utils/psci/psci_features.c b/lib/utils/psci/psci_features.c
new file mode 100644
index 0000000..120cbc3
--- /dev/null
+++ b/lib/utils/psci/psci_features.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+
+int32_t psci_features(uint32_t psci_func_id)
+{
+	switch (psci_func_id) {
+	case PSCI_FN_VERSION:
+	case PSCI_FN_PSCI_FEATURES:
+	case PSCI_FN_CPU_OFF:
+	case PSCI_FN_CPU_ON_SMC32:
+	case PSCI_FN_CPU_ON_SMC64:
+	case PSCI_FN_AFFINITY_INFO_SMC32:
+	case PSCI_FN_AFFINITY_INFO_SMC64:
+	case PSCI_FN_SYSTEM_OFF:
+	case PSCI_FN_SYSTEM_RESET:
+		return 0;
+
+	case PSCI_FN_CPU_SUSPEND_SMC32:
+	case PSCI_FN_CPU_SUSPEND_SMC64:
+		return 1;
+
+	default:
+		return PSCI_E_NOT_SUPPORTED;
+	}
+}
diff --git a/lib/utils/psci/psci_system_off.c b/lib/utils/psci/psci_system_off.c
new file mode 100644
index 0000000..a2c1058
--- /dev/null
+++ b/lib/utils/psci/psci_system_off.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_ecall_interface.h>
+
+void __noreturn psci_system_off()
+{
+	sbi_system_reset(SBI_SRST_RESET_TYPE_SHUTDOWN,
+			 SBI_SRST_RESET_REASON_NONE);
+
+	/* We should never reach this point */
+	psci_assert(0);
+}
diff --git a/lib/utils/psci/psci_system_reset.c b/lib/utils/psci/psci_system_reset.c
new file mode 100644
index 0000000..6800322
--- /dev/null
+++ b/lib/utils/psci/psci_system_reset.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_ecall_interface.h>
+
+void __noreturn psci_system_reset()
+{
+	sbi_system_reset(SBI_SRST_RESET_TYPE_COLD_REBOOT,
+			 SBI_SRST_RESET_REASON_NONE);
+
+	/* We should never reach this point */
+	psci_assert(0);
+}
diff --git a/lib/utils/psci/psci_version.c b/lib/utils/psci/psci_version.c
new file mode 100644
index 0000000..1dbadf6
--- /dev/null
+++ b/lib/utils/psci/psci_version.c
@@ -0,0 +1,10 @@
+/*
+ * Copyright The OpenSBI Contributors
+ */
+
+#include <sbi_utils/psci/psci.h>
+
+uint32_t psci_version(void)
+{
+	return PSCI_MAJOR_VER | PSCI_MINOR_VER;
+}
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index c7a6531..dbb4039 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -58,3 +58,4 @@ CONFIG_FDT_MPXY=y
 CONFIG_FDT_MPXY_RPMI_MBOX=y
 CONFIG_FDT_MPXY_RPMI_CLOCK=y
 CONFIG_FDT_MPXY_RPMI_SYSMSI=y
+CONFIG_ARM_PSCI=y


From rahul at summations.net  Fri Jul 25 20:23:32 2025
From: rahul at summations.net (Rahul Pathak)
Date: Sat, 26 Jul 2025 08:53:32 +0530
Subject: [PATCH] lib: utils: Add PSCI implementation support
In-Reply-To: <20250725091453.188077-1-zhihong@nzhnb.com>
References: <20250725091453.188077-1-zhihong@nzhnb.com>
Message-ID: <CABdD5xn_YEKceXEhr78zCP_ENni-5bSE-cFaQ4tWi0Mmy--K5A@mail.gmail.com>

Why? PSCI is specific to ARM. What is the purpose for this support?

SBI interface already has support for the CPU power on/off, system
suspend/resume
and system reset.

On Fri, Jul 25, 2025 at 2:45?PM Niu Zhihong <zhihong at nzhnb.com> wrote:
>
> This patch adds Power State Coordination Interface (PSCI) support to OpenSBI.
> PSCI provides a standard interface for power management operations such as
> CPU power on/off, system suspend/resume, and system reset.
>
> The implementation includes:
> - PSCI version information and feature detection
> - CPU power management (on/off/suspend)
> - System power management (reset/off)
> - Affinity level management
> - PSCI library utilities and helper functions
>
> This follows the PSCI specification version 1.3 and provides a foundation
> for platform-specific power management implementations.
>
> Signed-off-by: Niu Zhihong <zhihong at nzhnb.com>
> ---
> diff --git a/include/sbi_utils/psci/psci.h b/include/sbi_utils/psci/psci.h
> new file mode 100644
> index 0000000..f063ec2
> --- /dev/null
> +++ b/include/sbi_utils/psci/psci.h
> @@ -0,0 +1,222 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + *
> + * See PSCI specification (Version 1.3 issue F.b) for more details.
> + */
> +
> +#ifndef __PSCI_H__
> +#define __PSCI_H__
> +
> +#include <stdint.h>
> +#include <stddef.h>
> +
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_hart.h>
> +
> +#define psci_assert(cond)                                                   \
> +       do {                                                                \
> +               if (!(cond)) {                                              \
> +                       sbi_printf("%s:%d, invalid psci state\n", __func__, \
> +                                  __LINE__);                               \
> +                       sbi_hart_hang();                                    \
> +               }                                                           \
> +       } while (0)
> +
> +/* Version 1.1 */
> +#define PSCI_MAJOR_VER (1 << 16)
> +#define PSCI_MINOR_VER 1
> +
> +#define PSCI_E_SUCCESS 0
> +#define PSCI_E_NOT_SUPPORTED -1
> +#define PSCI_E_INVALID_PARAMS -2
> +#define PSCI_E_DENIED -3
> +#define PSCI_E_ALREADY_ON -4
> +#define PSCI_E_ON_PENDING -5
> +#define PSCI_E_INTERN_FAIL -6
> +#define PSCI_E_NOT_PRESENT -7
> +#define PSCI_E_DISABLED -8
> +#define PSCI_E_INVALID_ADDRESS -9
> +
> +/* PSCI function IDs */
> +#define PSCI_FN_VERSION 0x84000000
> +#define PSCI_FN_CPU_SUSPEND_SMC32 0x84000001
> +#define PSCI_FN_CPU_SUSPEND_SMC64 0xC4000001
> +#define PSCI_FN_CPU_OFF 0x84000002
> +#define PSCI_FN_CPU_ON_SMC32 0x84000003
> +#define PSCI_FN_CPU_ON_SMC64 0xC4000003
> +#define PSCI_FN_AFFINITY_INFO_SMC32 0x84000004
> +#define PSCI_FN_AFFINITY_INFO_SMC64 0xC4000004
> +#define PSCI_FN_SYSTEM_OFF 0x84000008
> +#define PSCI_FN_SYSTEM_RESET 0x84000009
> +#define PSCI_FN_PSCI_FEATURES 0x8400000A
> +#define PSCI_FN_SYSTEM_OFF2_SMC32 0x84000015
> +#define PSCI_FN_SYSTEM_OFF2_SMC64 0xC4000015
> +
> +/* SMCCC function IDs */
> +#define SMCCC_VERSION 0x80000000
> +
> +/* PSCI AFFINITY_INFO return values */
> +#define PSCI_AFFINITY_STATE_ON 0
> +#define PSCI_AFFINITY_STATE_OFF 1
> +#define PSCI_AFFINITY_STATE_ON_PENDING 2
> +
> +/* PSCI power state TYPEs */
> +#define PSCI_PSTATE_TYPE_STANDBY 0x0
> +#define PSCI_PSTATE_TYPE_POWERDOWN 0x1
> +
> +/* PSCI power state IDs */
> +#define PSCI_PSTATE_ID_RUN 0x0
> +#define PSCI_PSTATE_ID_STANDBY 0x1
> +#define PSCI_PSTATE_ID_RETENTION 0x2
> +#define PSCI_PSTATE_ID_POWERDOWN 0x3
> +
> +/**
> + * Description:
> + * Return the version of PSCI implemented. This function allows a caller
> + * to ascertain the current version of the PSCI interface.
> + *
> + * Return Value:
> + * uint32_t - 31-bit unsigned integer containing version information:
> + * - Bits[31:16]: Major Version (upper 15 bits)
> + * - Bits[15:0]:  Minor Version (lower 16 bits)
> + *
> + * Current Implementation:
> + * - Major Version: 1 (PSCI_MAJOR_VER)
> + * - Minor Version: 1 (PSCI_MINOR_VER)
> + * - Combined Version: 0x00010001
> + */
> +uint32_t psci_version();
> +
> +/**
> + * Description:
> + * Suspend execution on a core or higher-level topology node. This call is
> + * intended for use in idle subsystems where the core is expected to return
> + * to execution through a wakeup event.
> + *
> + * Parameters:
> + * - power_state: Describes the target power state for suspension
> + *   - uint32 value defining the power state characteristics
> + *   - Extended StateID format:
> + *     - Bit[31]: Reserved, must be zero
> + *     - Bit[30]: StateType
> + *       - PSCI_PSTATE_TYPE_STANDBY (0): Standby or retention state (no core context lost)
> + *       - PSCI_PSTATE_TYPE_POWERDOWN (1): Powerdown state (core context lost, entry_point_address and context_id valid)
> + *     - Bits[29:28]: Reserved, must be zero
> + *     - Bits[27:0]: StateID (platform-specific state identifier)
> + *         - PSCI_PSTATE_ID_RUN (0x0): Normal running state
> + *         - PSCI_PSTATE_ID_STANDBY (0x1): Standby state (quick wake-up)
> + *         - PSCI_PSTATE_ID_RETENTION (0x2): Retention state (context preserved)
> + *         - PSCI_PSTATE_ID_POWERDOWN (0x3): Powerdown state (context lost)
> + *   - Format is determined by PSCI_FEATURES bit[1] for CPU_SUSPEND
> + *
> + * - entry_point_address: Resume execution address after wakeup
> + *   - Only valid for powerdown states; ignored for standby states
> + *
> + * - context_id: Context value for powerdown states
> + *   - Only valid for powerdown states; ignored for standby states
> + *
> + * Return Value:
> + * intptr_t - Result of the CPU_SUSPEND operation:
> + * - PSCI_E_SUCCESS: Operation completed successfully
> + * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
> + * - PSCI_E_INVALID_ADDRESS: Invalid entry point address
> + * - PSCI_E_DENIED: Operation denied (only in OS-initiated mode)
> + */
> +intptr_t psci_cpu_suspend(uint32_t power_state, uintptr_t entry_point_address,
> +                         uintptr_t context_id);
> +
> +/**
> + * Description:
> + * Power down the calling core. This call is intended for use in hotplug.
> + * A core that is powered down by CPU_OFF can only be powered up again
> + * in response to a CPU_ON call.
> + *
> + * Return Value:
> + * int32_t - Result of the CPU_OFF operation:
> + * - Does not return when successful (core is powered down)
> + * - PSCI_E_DENIED: Operation denied (only possible return value on failure)
> + */
> +int32_t psci_cpu_off();
> +
> +/**
> + * Description:
> + * Power up a core. This call is used to power up cores that either:
> + * - Have not yet been booted into the calling supervisory software
> + * - Have been previously powered down with a CPU_OFF call
> + *
> + * Parameters:
> + * - target_cpu: Target CPU to power on
> + *   - In OpenSBI implementation: this corresponds to hartid
> + *
> + * - entry_point_address: Physical address where core should start execution
> + *
> + * - context_id: Context value passed to the target core
> + *
> + * Return Value:
> + * intptr_t - Result of the CPU_ON operation:
> + * - PSCI_E_SUCCESS: Operation completed successfully
> + * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
> + * - PSCI_E_INVALID_ADDRESS: Invalid entry point address
> + * - PSCI_E_ALREADY_ON: Target CPU is already powered on
> + * - PSCI_E_ON_PENDING: Target CPU is already being powered on
> + * - PSCI_E_INTERN_FAIL: Internal failure occurred
> + * - PSCI_E_DENIED: Operation denied
> + */
> +intptr_t psci_cpu_on(uintptr_t target_cpu, uintptr_t entry_point_address,
> +                    uintptr_t context_id);
> +
> +/**
> + * Description:
> + * Enable the caller to request status of an affinity instance.
> + *
> + * Parameters:
> + * - target_affinity: Target affinity instance to query
> + *   - In OpenSBI implementation: this corresponds to hartid
> + *
> + * - lowest_affinity_level:
> + *   - From PSCI version 1.0 onwards, AFFINITY_INFO is no longer required to
> + *     support affinity levels higher than 0.
> + *
> + * Return Value:
> + * intptr_t - Status of the affinity instance:
> + * - PSCI_AFFINITY_STATE_ON (0): At least one core in the affinity instance is ON
> + * - PSCI_AFFINITY_STATE_OFF (1): Affinity instance is OFF
> + * - PSCI_AFFINITY_STATE_ON_PENDING (2): Affinity instance is transitioning to ON state
> + * - PSCI_E_INVALID_PARAMS: Invalid parameters provided
> + */
> +intptr_t psci_affinity_info(uintptr_t target_affinity,
> +                           uint32_t lowest_affinity_level);
> +
> +/**
> + * Description:
> + * Shut down the system.
> + */
> +void psci_system_off();
> +
> +/**
> + * Description:
> + * Reset the system.
> + */
> +void psci_system_reset();
> +
> +/**
> + * Description:
> + * Query API that allows discovering whether SMCCC_VERSION or a specific PSCI
> + * function is implemented and its features. This function is introduced in
> + * PSCI 1.0 specification.
> + *
> + * Parameters:
> + * - psci_func_id: Function ID of PSCI Function or SMCCC_VERSION
> + *
> + * Return values:
> + * - PSCI_E_NOT_SUPPORTED: if the function identified by psci_func_id is not
> + *   implemented or is an invalid function ID
> + * - Feature flags (int32): A set of feature flags associated with the
> + *   implemented function indicated by psci_func_id. Feature flags are specific
> + *   to each function. Format:
> + *   - Bit[31] is zero
> + *   - Bits[30:0] represent the feature flags
> + */
> +int32_t psci_features(uint32_t psci_func_id);
> +
> +#endif /* __PSCI_H__ */
> diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
> index 901ba56..5dada1e 100644
> --- a/lib/utils/Kconfig
> +++ b/lib/utils/Kconfig
> @@ -34,4 +34,6 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig"
>
>  source "$(OPENSBI_SRC_DIR)/lib/utils/mpxy/Kconfig"
>
> +source "$(OPENSBI_SRC_DIR)/lib/utils/psci/Kconfig"
> +
>  endmenu
> diff --git a/lib/utils/psci/Kconfig b/lib/utils/psci/Kconfig
> new file mode 100644
> index 0000000..f818cf7
> --- /dev/null
> +++ b/lib/utils/psci/Kconfig
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: BSD-2-Clause
> +# Copyright The OpenSBI Contributors
> +
> +menu "Arm Power State Coordination Interface Support"
> +
> +config ARM_PSCI
> +       bool "Support PSCI protocol"
> +       default n
> +
> +endmenu
> diff --git a/lib/utils/psci/objects.mk b/lib/utils/psci/objects.mk
> new file mode 100644
> index 0000000..558dcae
> --- /dev/null
> +++ b/lib/utils/psci/objects.mk
> @@ -0,0 +1,19 @@
> +#
> +# Copyright The OpenSBI Contributors
> +#
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_version.o
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_cpu_suspend.o
> +
> +libsbiutils-objs-$(CONFIG_ARM_PSCI) += psci/psci_cpu_off.o
> +
> +libsbiutils-objs-$(CONFIG_ARM_PSCI) += psci/psci_cpu_on.o
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_affinity_info.o
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_system_off.o
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_system_reset.o
> +
> +libsbiutils-objs-${CONFIG_ARM_PSCI} += psci/psci_features.o
> diff --git a/lib/utils/psci/psci_affinity_info.c b/lib/utils/psci/psci_affinity_info.c
> new file mode 100644
> index 0000000..e9b795f
> --- /dev/null
> +++ b/lib/utils/psci/psci_affinity_info.c
> @@ -0,0 +1,72 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_hsm.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_domain.h>
> +#include <sbi/sbi_ecall_interface.h>
> +
> +intptr_t psci_affinity_info(uintptr_t target_affinity,
> +                           uint32_t lowest_affinity_level)
> +{
> +       struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
> +       const struct sbi_domain *dom = sbi_domain_thishart_ptr();
> +       uint32_t target_hartid       = (uint32_t)target_affinity;
> +       int hart_state;
> +
> +       /* Validate that we have a valid scratch area and domain */
> +       if (!scratch || !dom)
> +               return PSCI_E_INTERN_FAIL;
> +
> +       /*
> +        * PSCI v1.0+ allows implementations to only support level 0 (individual cores)
> +        * For now, we only support querying individual hart/core state (level 0)
> +        */
> +       if (lowest_affinity_level > 0)
> +               return PSCI_E_INVALID_PARAMS;
> +
> +       /* Check if target_affinity describes a valid hartid */
> +       if (!sbi_hartid_valid(target_hartid))
> +               return PSCI_E_INVALID_PARAMS;
> +
> +       /* Check if the target hart is assigned to the current domain */
> +       if (!sbi_domain_is_assigned_hart(
> +                   dom, sbi_hartid_to_hartindex(target_hartid)))
> +               return PSCI_E_INVALID_PARAMS;
> +
> +       /* Get the current state of the target hart */
> +       hart_state = sbi_hsm_hart_get_state(dom, target_hartid);
> +       if (hart_state < 0)
> +               return PSCI_E_INVALID_PARAMS;
> +
> +       /* Map SBI HSM states to PSCI affinity states */
> +       switch (hart_state) {
> +       case SBI_HSM_STATE_STARTED:
> +       case SBI_HSM_STATE_SUSPENDED:
> +       case SBI_HSM_STATE_RESUME_PENDING:
> +               /*
> +                * PSCI ON: At least one core in the affinity instance is ON
> +                */
> +               return PSCI_AFFINITY_STATE_ON;
> +
> +       case SBI_HSM_STATE_STOPPED:
> +               /*
> +                * PSCI OFF: All cores in the affinity instance are OFF
> +                */
> +               return PSCI_AFFINITY_STATE_OFF;
> +
> +       case SBI_HSM_STATE_START_PENDING:
> +       case SBI_HSM_STATE_STOP_PENDING:
> +       case SBI_HSM_STATE_SUSPEND_PENDING:
> +               /*
> +                * PSCI ON_PENDING: The affinity instance is transitioning to an ON state
> +                */
> +               return PSCI_AFFINITY_STATE_ON_PENDING;
> +
> +       default:
> +               /* Invalid or unknown state */
> +               return PSCI_E_INTERN_FAIL;
> +       }
> +}
> diff --git a/lib/utils/psci/psci_cpu_off.c b/lib/utils/psci/psci_cpu_off.c
> new file mode 100644
> index 0000000..3e1940a
> --- /dev/null
> +++ b/lib/utils/psci/psci_cpu_off.c
> @@ -0,0 +1,30 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_hsm.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_domain.h>
> +
> +int32_t psci_cpu_off()
> +{
> +       struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
> +       const struct sbi_domain *dom = sbi_domain_thishart_ptr();
> +       int ret;
> +
> +       /* Validate that we have a valid scratch area */
> +       psci_assert(scratch != NULL);
> +       psci_assert(dom != NULL);
> +
> +       ret = sbi_hsm_hart_stop(scratch, true);
> +
> +       /* We should never reach here if the hart stop succeeds */
> +       if (ret != 0) {
> +               return PSCI_E_DENIED;
> +       }
> +
> +       /* This point should never be reached */
> +       psci_assert(0);
> +       return PSCI_E_DENIED;
> +}
> diff --git a/lib/utils/psci/psci_cpu_on.c b/lib/utils/psci/psci_cpu_on.c
> new file mode 100644
> index 0000000..17e5e1b
> --- /dev/null
> +++ b/lib/utils/psci/psci_cpu_on.c
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_hsm.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_domain.h>
> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/sbi_error.h>
> +
> +intptr_t psci_cpu_on(uintptr_t target_cpu, uintptr_t entry_point_address,
> +                    uintptr_t context_id)
> +{
> +       struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
> +       const struct sbi_domain *dom = sbi_domain_thishart_ptr();
> +       struct sbi_scratch *remote_scratch;
> +       uint32_t target_hartid = (uint32_t)target_cpu;
> +       int hart_state;
> +       int ret;
> +
> +       /* Validate that we have a valid scratch area and domain */
> +       psci_assert(scratch != NULL);
> +       psci_assert(dom != NULL);
> +
> +       /* Check if target_cpu describes a valid MPIDR/hartid */
> +       if (!sbi_hartid_valid(target_hartid)) {
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /* Get scratch pointer for target hart */
> +       remote_scratch = sbi_hartid_to_scratch(target_hartid);
> +       if (!remote_scratch) {
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /* Check if the entry point address is valid for the caller's domain */
> +       if (!sbi_domain_check_addr(dom, entry_point_address, PRV_S,
> +                                  SBI_DOMAIN_EXECUTE)) {
> +               return PSCI_E_INVALID_ADDRESS;
> +       }
> +
> +       /* Get current state of the target hart */
> +       hart_state = sbi_hsm_hart_get_state(dom, target_hartid);
> +
> +       switch (hart_state) {
> +       case SBI_HSM_STATE_STARTED:
> +               /* Hart is already running */
> +               return PSCI_E_ALREADY_ON;
> +
> +       case SBI_HSM_STATE_START_PENDING:
> +               /* Hart start is already pending */
> +               return PSCI_E_ON_PENDING;
> +
> +       case SBI_HSM_STATE_STOPPED:
> +               /* Hart is stopped, we can start it */
> +               break;
> +
> +       default:
> +               /* Invalid state or other error */
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /*
> +        * Start the target hart
> +        * - target_hartid: the hart to start
> +        * - entry_point_address: where the hart should start execution
> +        * - PRV_S: start in supervisor mode
> +        * - context_id: passed as argument to the started hart
> +        */
> +       ret = sbi_hsm_hart_start(remote_scratch, dom, target_hartid,
> +                                entry_point_address, PRV_S, context_id);
> +
> +       /* Convert SBI error codes to PSCI error codes */
> +       switch (ret) {
> +       case SBI_SUCCESS:
> +               return PSCI_E_SUCCESS;
> +       case SBI_ERR_INVALID_PARAM:
> +               return PSCI_E_INVALID_PARAMS;
> +       case SBI_ERR_INVALID_ADDRESS:
> +               return PSCI_E_INVALID_ADDRESS;
> +       case SBI_ERR_ALREADY_STARTED:
> +               return PSCI_E_ALREADY_ON;
> +       case SBI_ERR_DENIED:
> +               return PSCI_E_DENIED;
> +       default:
> +               return PSCI_E_INTERN_FAIL;
> +       }
> +}
> diff --git a/lib/utils/psci/psci_cpu_suspend.c b/lib/utils/psci/psci_cpu_suspend.c
> new file mode 100644
> index 0000000..16b0e5c
> --- /dev/null
> +++ b/lib/utils/psci/psci_cpu_suspend.c
> @@ -0,0 +1,151 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_hsm.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_domain.h>
> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/sbi_error.h>
> +
> +/* PSCI power state TYPEs */
> +#define PSCI_PSTATE_TYPE_SHIFT 30
> +#define PSCI_PSTATE_TYPE_MASK 0x1
> +
> +/* PSCI power state StateID */
> +#define PSCI_PSTATE_ID_SHIFT 0
> +#define PSCI_PSTATE_ID_MASK 0x0FFFFFFF
> +
> +/* Helper macros for power state */
> +#define psci_get_pstate_type(pstate) \
> +       (((pstate) >> PSCI_PSTATE_TYPE_SHIFT) & PSCI_PSTATE_TYPE_MASK)
> +#define psci_get_pstate_id(pstate) \
> +       (((pstate) >> PSCI_PSTATE_ID_SHIFT) & PSCI_PSTATE_ID_MASK)
> +
> +intptr_t psci_cpu_suspend(uint32_t power_state, uintptr_t entry_point_address,
> +                         uintptr_t context_id)
> +{
> +       struct sbi_scratch *scratch  = sbi_scratch_thishart_ptr();
> +       const struct sbi_domain *dom = sbi_domain_thishart_ptr();
> +       uint32_t pstate_type, pstate_id, suspend_type;
> +       int ret;
> +
> +       /* Validate runtime environment */
> +       psci_assert(scratch != NULL);
> +       psci_assert(dom != NULL);
> +
> +       /* Validate power state format - check reserved bits */
> +       if (power_state & 0x80000000) { /* Bit[31] must be zero */
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +       if (power_state & 0x30000000) { /* Bits[29:28] must be zero */
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /* Extract StateType and StateID from power_state */
> +       pstate_type = psci_get_pstate_type(power_state);
> +       pstate_id   = psci_get_pstate_id(power_state);
> +
> +       /* Validate StateID values */
> +       if (pstate_id > PSCI_PSTATE_ID_POWERDOWN) {
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /*
> +        * Handle different suspend types based on PSCI specification:
> +        * - STANDBY: Retention state, context preserved, quick wake-up
> +        * - POWERDOWN: Context lost, requires entry_point_address and context_id
> +        *
> +        * StateID provides platform-specific power state information:
> +        * - PSCI_PSTATE_ID_RUN (0x0): Normal running state (invalid for suspend)
> +        * - PSCI_PSTATE_ID_STANDBY (0x1): Standby state (quick wake-up)
> +        * - PSCI_PSTATE_ID_RETENTION (0x2): Retention state (context preserved)
> +        * - PSCI_PSTATE_ID_POWERDOWN (0x3): Powerdown state (context lost)
> +        */
> +       if (pstate_type == PSCI_PSTATE_TYPE_STANDBY) {
> +               /*
> +                * Standby/Retention suspend:
> +                * - Core context is preserved
> +                * - entry_point_address and context_id are ignored
> +                * - Use retentive suspend mode
> +                * - Valid StateIDs: STANDBY, RETENTION
> +                */
> +               if (pstate_id != PSCI_PSTATE_ID_STANDBY &&
> +                   pstate_id != PSCI_PSTATE_ID_RETENTION) {
> +                       return PSCI_E_INVALID_PARAMS;
> +               }
> +
> +               suspend_type = SBI_HSM_SUSPEND_RET_DEFAULT;
> +
> +               /* For standby, entry_point_address is ignored but we use current context */
> +               entry_point_address = 0; /* Will be ignored by SBI HSM */
> +               context_id          = 0; /* Will be ignored by SBI HSM */
> +
> +       } else if (pstate_type == PSCI_PSTATE_TYPE_POWERDOWN) {
> +               /*
> +                * Powerdown suspend:
> +                * - Core context will be lost
> +                * - entry_point_address must be valid and accessible
> +                * - context_id will be passed to resumed execution
> +                * - Use non-retentive suspend mode
> +                * - Valid StateID: POWERDOWN
> +                */
> +               if (pstate_id != PSCI_PSTATE_ID_POWERDOWN) {
> +                       return PSCI_E_INVALID_PARAMS;
> +               }
> +
> +               suspend_type = SBI_HSM_SUSPEND_NON_RET_DEFAULT;
> +
> +               /* Validate entry point address for powerdown states */
> +               if (!entry_point_address) {
> +                       return PSCI_E_INVALID_ADDRESS;
> +               }
> +
> +               /* Verify entry point is within caller's domain and executable */
> +               if (!sbi_domain_check_addr(dom, entry_point_address, PRV_S,
> +                                          SBI_DOMAIN_EXECUTE)) {
> +                       return PSCI_E_INVALID_ADDRESS;
> +               }
> +
> +       } else {
> +               /* Invalid StateType - only STANDBY(0) and POWERDOWN(1) are valid */
> +               return PSCI_E_INVALID_PARAMS;
> +       }
> +
> +       /*
> +        * Initiate hart suspension through SBI HSM:
> +        * - suspend_type: SBI_HSM_SUSPEND_RET_DEFAULT or SBI_HSM_SUSPEND_NON_RET_DEFAULT
> +        * - entry_point_address: Resume address (powerdown) or 0 (standby)
> +        * - PRV_S: Resume in supervisor privilege mode
> +        * - context_id: Context value passed to resumed execution
> +        */
> +       ret = sbi_hsm_hart_suspend(scratch, suspend_type, entry_point_address,
> +                                  PRV_S, context_id);
> +
> +       /*
> +        * Handle return values:
> +        *
> +        * For STANDBY (retentive) suspend:
> +        * - Normal return with PSCI_E_SUCCESS indicates successful wake-up
> +        *
> +        * For POWERDOWN (non-retentive) suspend:
> +        * - Should NOT return here on success (execution resumes at entry_point_address)
> +        * - If we return here, it indicates suspend was rejected, downgraded, or failed
> +        */
> +       switch (ret) {
> +       case SBI_SUCCESS:
> +               /* Success - either completed standby or failed powerdown */
> +               return PSCI_E_SUCCESS;
> +       case SBI_ERR_INVALID_PARAM:
> +               return PSCI_E_INVALID_PARAMS;
> +       case SBI_ERR_INVALID_ADDRESS:
> +               return PSCI_E_INVALID_ADDRESS;
> +       case SBI_ERR_DENIED:
> +               return PSCI_E_DENIED;
> +       case SBI_ERR_NOT_SUPPORTED:
> +               return PSCI_E_NOT_SUPPORTED;
> +       default:
> +               return PSCI_E_INTERN_FAIL;
> +       }
> +}
> diff --git a/lib/utils/psci/psci_features.c b/lib/utils/psci/psci_features.c
> new file mode 100644
> index 0000000..120cbc3
> --- /dev/null
> +++ b/lib/utils/psci/psci_features.c
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +
> +int32_t psci_features(uint32_t psci_func_id)
> +{
> +       switch (psci_func_id) {
> +       case PSCI_FN_VERSION:
> +       case PSCI_FN_PSCI_FEATURES:
> +       case PSCI_FN_CPU_OFF:
> +       case PSCI_FN_CPU_ON_SMC32:
> +       case PSCI_FN_CPU_ON_SMC64:
> +       case PSCI_FN_AFFINITY_INFO_SMC32:
> +       case PSCI_FN_AFFINITY_INFO_SMC64:
> +       case PSCI_FN_SYSTEM_OFF:
> +       case PSCI_FN_SYSTEM_RESET:
> +               return 0;
> +
> +       case PSCI_FN_CPU_SUSPEND_SMC32:
> +       case PSCI_FN_CPU_SUSPEND_SMC64:
> +               return 1;
> +
> +       default:
> +               return PSCI_E_NOT_SUPPORTED;
> +       }
> +}
> diff --git a/lib/utils/psci/psci_system_off.c b/lib/utils/psci/psci_system_off.c
> new file mode 100644
> index 0000000..a2c1058
> --- /dev/null
> +++ b/lib/utils/psci/psci_system_off.c
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_system.h>
> +#include <sbi/sbi_ecall_interface.h>
> +
> +void __noreturn psci_system_off()
> +{
> +       sbi_system_reset(SBI_SRST_RESET_TYPE_SHUTDOWN,
> +                        SBI_SRST_RESET_REASON_NONE);
> +
> +       /* We should never reach this point */
> +       psci_assert(0);
> +}
> diff --git a/lib/utils/psci/psci_system_reset.c b/lib/utils/psci/psci_system_reset.c
> new file mode 100644
> index 0000000..6800322
> --- /dev/null
> +++ b/lib/utils/psci/psci_system_reset.c
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +#include <sbi/sbi_system.h>
> +#include <sbi/sbi_ecall_interface.h>
> +
> +void __noreturn psci_system_reset()
> +{
> +       sbi_system_reset(SBI_SRST_RESET_TYPE_COLD_REBOOT,
> +                        SBI_SRST_RESET_REASON_NONE);
> +
> +       /* We should never reach this point */
> +       psci_assert(0);
> +}
> diff --git a/lib/utils/psci/psci_version.c b/lib/utils/psci/psci_version.c
> new file mode 100644
> index 0000000..1dbadf6
> --- /dev/null
> +++ b/lib/utils/psci/psci_version.c
> @@ -0,0 +1,10 @@
> +/*
> + * Copyright The OpenSBI Contributors
> + */
> +
> +#include <sbi_utils/psci/psci.h>
> +
> +uint32_t psci_version(void)
> +{
> +       return PSCI_MAJOR_VER | PSCI_MINOR_VER;
> +}
> diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
> index c7a6531..dbb4039 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -58,3 +58,4 @@ CONFIG_FDT_MPXY=y
>  CONFIG_FDT_MPXY_RPMI_MBOX=y
>  CONFIG_FDT_MPXY_RPMI_CLOCK=y
>  CONFIG_FDT_MPXY_RPMI_SYSMSI=y
> +CONFIG_ARM_PSCI=y
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi


From wxjstz at 126.com  Sun Jul 27 21:55:24 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 28 Jul 2025 12:55:24 +0800
Subject: [PATCH] platform: andes:  Fix license to compatible GPL
Message-ID: <20250728045551.355122-1-wxjstz@126.com>

Since platform/generic/include/andes/andes.h and
platform/generic/include/andes/andes_pma.h are licensed under the
GPL, any C files that use them should also be modified to comply
with the GPL. Otherwise, there may be potential legal issues.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 platform/generic/andes/ae350.c     | 2 +-
 platform/generic/andes/andes_pmu.c | 2 +-
 platform/generic/andes/andes_sbi.c | 2 +-
 platform/generic/andes/sleep.S     | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/platform/generic/andes/ae350.c b/platform/generic/andes/ae350.c
index f06e207d..880d5803 100644
--- a/platform/generic/andes/ae350.c
+++ b/platform/generic/andes/ae350.c
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: GPL-2.0
  *
  * Copyright (c) 2022 Andes Technology Corporation
  *
diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
index 9eee4edc..6099a73b 100644
--- a/platform/generic/andes/andes_pmu.c
+++ b/platform/generic/andes/andes_pmu.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: BSD-2-Clause
+// SPDX-License-Identifier: GPL-2.0
 /*
  * andes_pmu.c - Andes PMU device callbacks and platform overrides
  *
diff --git a/platform/generic/andes/andes_sbi.c b/platform/generic/andes/andes_sbi.c
index f68ac908..6c155e10 100644
--- a/platform/generic/andes/andes_sbi.c
+++ b/platform/generic/andes/andes_sbi.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: BSD-2-Clause
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2023 Renesas Electronics Corp.
  *
diff --git a/platform/generic/andes/sleep.S b/platform/generic/andes/sleep.S
index 361aff3a..967fdaef 100644
--- a/platform/generic/andes/sleep.S
+++ b/platform/generic/andes/sleep.S
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: GPL-2.0
  *
  * Copyright (c) 2023 Andes Technology Corporation
  *
-- 
2.47.2



From jrtc27 at jrtc27.com  Sun Jul 27 22:03:55 2025
From: jrtc27 at jrtc27.com (Jessica Clarke)
Date: Mon, 28 Jul 2025 06:03:55 +0100
Subject: [PATCH] platform: andes:  Fix license to compatible GPL
In-Reply-To: <20250728045551.355122-1-wxjstz@126.com>
References: <20250728045551.355122-1-wxjstz@126.com>
Message-ID: <E921AB6A-1390-4BFC-9B13-91D3036B9F1B@jrtc27.com>

On 28 Jul 2025, at 05:55, Xiang W <wxjstz at 126.com> wrote:
> 
> Since platform/generic/include/andes/andes.h and
> platform/generic/include/andes/andes_pma.h are licensed under the
> GPL, any C files that use them should also be modified to comply
> with the GPL. Otherwise, there may be potential legal issues.

Firstly, that?s not how licenses work. The combined work is GPL, but
that doesn?t mean these files are. They can be BSD, and should be,
because that?s what they were contributed under.

Secondly, why are there GPL?ed files in OpenSBI? It?s a BSD-licensed
project, and anything else* is problematic for vendors. Especially for
source files that are included by default in the generic platform build.

So a hard NAK from me, and a call to delete the GPL?ed Andes files or
replace them with BSD-licensed ones (which can just be getting the
author(s) to relicense them). I doubt there?s anything interesting in
them anyway.

Jess

* Well, anything copyleft / non-permissive

> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
> platform/generic/andes/ae350.c     | 2 +-
> platform/generic/andes/andes_pmu.c | 2 +-
> platform/generic/andes/andes_sbi.c | 2 +-
> platform/generic/andes/sleep.S     | 2 +-
> 4 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/platform/generic/andes/ae350.c b/platform/generic/andes/ae350.c
> index f06e207d..880d5803 100644
> --- a/platform/generic/andes/ae350.c
> +++ b/platform/generic/andes/ae350.c
> @@ -1,5 +1,5 @@
> /*
> - * SPDX-License-Identifier: BSD-2-Clause
> + * SPDX-License-Identifier: GPL-2.0
>  *
>  * Copyright (c) 2022 Andes Technology Corporation
>  *
> diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
> index 9eee4edc..6099a73b 100644
> --- a/platform/generic/andes/andes_pmu.c
> +++ b/platform/generic/andes/andes_pmu.c
> @@ -1,4 +1,4 @@
> -// SPDX-License-Identifier: BSD-2-Clause
> +// SPDX-License-Identifier: GPL-2.0
> /*
>  * andes_pmu.c - Andes PMU device callbacks and platform overrides
>  *
> diff --git a/platform/generic/andes/andes_sbi.c b/platform/generic/andes/andes_sbi.c
> index f68ac908..6c155e10 100644
> --- a/platform/generic/andes/andes_sbi.c
> +++ b/platform/generic/andes/andes_sbi.c
> @@ -1,4 +1,4 @@
> -// SPDX-License-Identifier: BSD-2-Clause
> +// SPDX-License-Identifier: GPL-2.0
> /*
>  * Copyright (C) 2023 Renesas Electronics Corp.
>  *
> diff --git a/platform/generic/andes/sleep.S b/platform/generic/andes/sleep.S
> index 361aff3a..967fdaef 100644
> --- a/platform/generic/andes/sleep.S
> +++ b/platform/generic/andes/sleep.S
> @@ -1,5 +1,5 @@
> /*
> - * SPDX-License-Identifier: BSD-2-Clause
> + * SPDX-License-Identifier: GPL-2.0
>  *
>  * Copyright (c) 2023 Andes Technology Corporation
>  *
> -- 
> 2.47.2
> 
> 
> -- 
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi



From anup at brainfault.org  Sun Jul 27 22:11:27 2025
From: anup at brainfault.org (Anup Patel)
Date: Mon, 28 Jul 2025 10:41:27 +0530
Subject: [PATCH] platform: andes: Fix license to compatible GPL
In-Reply-To: <E921AB6A-1390-4BFC-9B13-91D3036B9F1B@jrtc27.com>
References: <20250728045551.355122-1-wxjstz@126.com> <E921AB6A-1390-4BFC-9B13-91D3036B9F1B@jrtc27.com>
Message-ID: <CAAhSdy3fsJK2Mgq9ixCMq9UDyP9vHxg9XysnfqjrPWDQAD+s+Q@mail.gmail.com>

On Mon, Jul 28, 2025 at 10:34?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> On 28 Jul 2025, at 05:55, Xiang W <wxjstz at 126.com> wrote:
> >
> > Since platform/generic/include/andes/andes.h and
> > platform/generic/include/andes/andes_pma.h are licensed under the
> > GPL, any C files that use them should also be modified to comply
> > with the GPL. Otherwise, there may be potential legal issues.
>
> Firstly, that?s not how licenses work. The combined work is GPL, but
> that doesn?t mean these files are. They can be BSD, and should be,
> because that?s what they were contributed under.
>
> Secondly, why are there GPL?ed files in OpenSBI? It?s a BSD-licensed
> project, and anything else* is problematic for vendors. Especially for
> source files that are included by default in the generic platform build.
>
> So a hard NAK from me, and a call to delete the GPL?ed Andes files or
> replace them with BSD-licensed ones (which can just be getting the
> author(s) to relicense them). I doubt there?s anything interesting in
> them anyway.

I agree with Jessica on this. Lets not have any non-permissive
sources in OpenSBI.

The Andes headers have been overlooked in patch reviews so
I suggest updating these headers to use BSD-license.

Regards,
Anup

>
> Jess
>
> * Well, anything copyleft / non-permissive
>
> > Signed-off-by: Xiang W <wxjstz at 126.com>
> > ---
> > platform/generic/andes/ae350.c     | 2 +-
> > platform/generic/andes/andes_pmu.c | 2 +-
> > platform/generic/andes/andes_sbi.c | 2 +-
> > platform/generic/andes/sleep.S     | 2 +-
> > 4 files changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/platform/generic/andes/ae350.c b/platform/generic/andes/ae350.c
> > index f06e207d..880d5803 100644
> > --- a/platform/generic/andes/ae350.c
> > +++ b/platform/generic/andes/ae350.c
> > @@ -1,5 +1,5 @@
> > /*
> > - * SPDX-License-Identifier: BSD-2-Clause
> > + * SPDX-License-Identifier: GPL-2.0
> >  *
> >  * Copyright (c) 2022 Andes Technology Corporation
> >  *
> > diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
> > index 9eee4edc..6099a73b 100644
> > --- a/platform/generic/andes/andes_pmu.c
> > +++ b/platform/generic/andes/andes_pmu.c
> > @@ -1,4 +1,4 @@
> > -// SPDX-License-Identifier: BSD-2-Clause
> > +// SPDX-License-Identifier: GPL-2.0
> > /*
> >  * andes_pmu.c - Andes PMU device callbacks and platform overrides
> >  *
> > diff --git a/platform/generic/andes/andes_sbi.c b/platform/generic/andes/andes_sbi.c
> > index f68ac908..6c155e10 100644
> > --- a/platform/generic/andes/andes_sbi.c
> > +++ b/platform/generic/andes/andes_sbi.c
> > @@ -1,4 +1,4 @@
> > -// SPDX-License-Identifier: BSD-2-Clause
> > +// SPDX-License-Identifier: GPL-2.0
> > /*
> >  * Copyright (C) 2023 Renesas Electronics Corp.
> >  *
> > diff --git a/platform/generic/andes/sleep.S b/platform/generic/andes/sleep.S
> > index 361aff3a..967fdaef 100644
> > --- a/platform/generic/andes/sleep.S
> > +++ b/platform/generic/andes/sleep.S
> > @@ -1,5 +1,5 @@
> > /*
> > - * SPDX-License-Identifier: BSD-2-Clause
> > + * SPDX-License-Identifier: GPL-2.0
> >  *
> >  * Copyright (c) 2023 Andes Technology Corporation
> >  *
> > --
> > 2.47.2
> >
> >
> > --
> > opensbi mailing list
> > opensbi at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
>


From wxjstz at 126.com  Sun Jul 27 22:26:48 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 28 Jul 2025 13:26:48 +0800
Subject: [PATCH] Fix license to compatible BSD-2-Clause
Message-ID: <20250728052713.361094-1-wxjstz@126.com>

OpenBI is a BSD project. We need to modify some codes to compatible
with BSD protocol.

Signed-off-by: Xiang W <wxjstz at 126.com>
---
 .editorconfig                              | 2 +-
 platform/generic/andes/andes_pma.c         | 2 +-
 platform/generic/include/andes/andes.h     | 2 +-
 platform/generic/include/andes/andes_pma.h | 2 +-
 platform/generic/renesas/rzfive/rzfive.c   | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.editorconfig b/.editorconfig
index e66b1ca3..26f90534 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: BSD-2-Clause
 # See here for more information about the format and editor support:
 # https://editorconfig.org/
 
diff --git a/platform/generic/andes/andes_pma.c b/platform/generic/andes/andes_pma.c
index 09e5a30c..eeeb110e 100644
--- a/platform/generic/andes/andes_pma.c
+++ b/platform/generic/andes/andes_pma.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (C) 2023 Renesas Electronics Corp.
  * Copyright (c) 2024 Andes Technology Corporation
diff --git a/platform/generic/include/andes/andes.h b/platform/generic/include/andes/andes.h
index 3403a58b..bfedf034 100644
--- a/platform/generic/include/andes/andes.h
+++ b/platform/generic/include/andes/andes.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (C) 2024 Andes Technology Corporation
  */
diff --git a/platform/generic/include/andes/andes_pma.h b/platform/generic/include/andes/andes_pma.h
index be614964..4a66e1b6 100644
--- a/platform/generic/include/andes/andes_pma.h
+++ b/platform/generic/include/andes/andes_pma.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (C) 2023 Renesas Electronics Corp.
  */
diff --git a/platform/generic/renesas/rzfive/rzfive.c b/platform/generic/renesas/rzfive/rzfive.c
index 44db3671..6c3da095 100644
--- a/platform/generic/renesas/rzfive/rzfive.c
+++ b/platform/generic/renesas/rzfive/rzfive.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (C) 2022 Renesas Electronics Corp.
  *
-- 
2.47.2



From wxjstz at 126.com  Sun Jul 27 22:33:39 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 28 Jul 2025 13:33:39 +0800
Subject: [PATCH] platform: andes: Fix license to compatible GPL
In-Reply-To: <CAAhSdy3fsJK2Mgq9ixCMq9UDyP9vHxg9XysnfqjrPWDQAD+s+Q@mail.gmail.com>
References: <20250728045551.355122-1-wxjstz@126.com>
	 <E921AB6A-1390-4BFC-9B13-91D3036B9F1B@jrtc27.com>
	 <CAAhSdy3fsJK2Mgq9ixCMq9UDyP9vHxg9XysnfqjrPWDQAD+s+Q@mail.gmail.com>
Message-ID: <d0d9c5c09dc71b38a71f341d91f1eb5b53cc06f8.camel@126.com>

? 2025-07-28?? 10:41 +0530?Anup Patel???
> On Mon, Jul 28, 2025 at 10:34?AM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
> > 
> > On 28 Jul 2025, at 05:55, Xiang W <wxjstz at 126.com> wrote:
> > > 
> > > Since platform/generic/include/andes/andes.h and
> > > platform/generic/include/andes/andes_pma.h are licensed under the
> > > GPL, any C files that use them should also be modified to comply
> > > with the GPL. Otherwise, there may be potential legal issues.
> > 
> > Firstly, that?s not how licenses work. The combined work is GPL, but
> > that doesn?t mean these files are. They can be BSD, and should be,
> > because that?s what they were contributed under.
> > 
> > Secondly, why are there GPL?ed files in OpenSBI? It?s a BSD-licensed
> > project, and anything else* is problematic for vendors. Especially for
> > source files that are included by default in the generic platform build.
> > 
> > So a hard NAK from me, and a call to delete the GPL?ed Andes files or
> > replace them with BSD-licensed ones (which can just be getting the
> > author(s) to relicense them). I doubt there?s anything interesting in
> > them anyway.
> 
> I agree with Jessica on this. Lets not have any non-permissive
> sources in OpenSBI.
> 
> The Andes headers have been overlooked in patch reviews so
> I suggest updating these headers to use BSD-license.
> 
> Regards,
> Anup
Yes, I agree too. We need a review from the original author.

New patch at:
https://patchwork.ozlabs.org/project/opensbi/patch/20250728052713.361094-1-wxjstz at 126.com/

Regards,
Xiang W


> > 
> > Jess
> > 
> > * Well, anything copyleft / non-permissive
> > 
> > > Signed-off-by: Xiang W <wxjstz at 126.com>
> > > ---
> > > platform/generic/andes/ae350.c???? | 2 +-
> > > platform/generic/andes/andes_pmu.c | 2 +-
> > > platform/generic/andes/andes_sbi.c | 2 +-
> > > platform/generic/andes/sleep.S???? | 2 +-
> > > 4 files changed, 4 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/platform/generic/andes/ae350.c b/platform/generic/andes/ae350.c
> > > index f06e207d..880d5803 100644
> > > --- a/platform/generic/andes/ae350.c
> > > +++ b/platform/generic/andes/ae350.c
> > > @@ -1,5 +1,5 @@
> > > /*
> > > - * SPDX-License-Identifier: BSD-2-Clause
> > > + * SPDX-License-Identifier: GPL-2.0
> > > ?*
> > > ?* Copyright (c) 2022 Andes Technology Corporation
> > > ?*
> > > diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
> > > index 9eee4edc..6099a73b 100644
> > > --- a/platform/generic/andes/andes_pmu.c
> > > +++ b/platform/generic/andes/andes_pmu.c
> > > @@ -1,4 +1,4 @@
> > > -// SPDX-License-Identifier: BSD-2-Clause
> > > +// SPDX-License-Identifier: GPL-2.0
> > > /*
> > > ?* andes_pmu.c - Andes PMU device callbacks and platform overrides
> > > ?*
> > > diff --git a/platform/generic/andes/andes_sbi.c b/platform/generic/andes/andes_sbi.c
> > > index f68ac908..6c155e10 100644
> > > --- a/platform/generic/andes/andes_sbi.c
> > > +++ b/platform/generic/andes/andes_sbi.c
> > > @@ -1,4 +1,4 @@
> > > -// SPDX-License-Identifier: BSD-2-Clause
> > > +// SPDX-License-Identifier: GPL-2.0
> > > /*
> > > ?* Copyright (C) 2023 Renesas Electronics Corp.
> > > ?*
> > > diff --git a/platform/generic/andes/sleep.S b/platform/generic/andes/sleep.S
> > > index 361aff3a..967fdaef 100644
> > > --- a/platform/generic/andes/sleep.S
> > > +++ b/platform/generic/andes/sleep.S
> > > @@ -1,5 +1,5 @@
> > > /*
> > > - * SPDX-License-Identifier: BSD-2-Clause
> > > + * SPDX-License-Identifier: GPL-2.0
> > > ?*
> > > ?* Copyright (c) 2023 Andes Technology Corporation
> > > ?*
> > > --
> > > 2.47.2
> > > 
> > > 
> > > --
> > > opensbi mailing list
> > > opensbi at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/opensbi
> > 



From wxjstz at 126.com  Mon Jul 28 00:01:54 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 28 Jul 2025 15:01:54 +0800
Subject: [PATCH] Fix license to compatible BSD-2-Clause
In-Reply-To: <20250728052713.361094-1-wxjstz@126.com>
References: <20250728052713.361094-1-wxjstz@126.com>
Message-ID: <b2363cfd71e26656b6160ba05fa151ebbf4cadfc.camel@126.com>

? 2025-07-28?? 13:26 +0800?Xiang W???
> OpenBI is a BSD project. We need to modify some codes to compatible
> with BSD protocol.
> 
Welcome Ben Zong-You Xie from Andes Technology.

Regards,
Xiang W
> Signed-off-by: Xiang W <wxjstz at 126.com>
> ---
> ?.editorconfig????????????????????????????? | 2 +-
> ?platform/generic/andes/andes_pma.c???????? | 2 +-
> ?platform/generic/include/andes/andes.h???? | 2 +-
> ?platform/generic/include/andes/andes_pma.h | 2 +-
> ?platform/generic/renesas/rzfive/rzfive.c?? | 2 +-
> ?5 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/.editorconfig b/.editorconfig
> index e66b1ca3..26f90534 100644
> --- a/.editorconfig
> +++ b/.editorconfig
> @@ -1,4 +1,4 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> +# SPDX-License-Identifier: BSD-2-Clause
> ?# See here for more information about the format and editor support:
> ?# https://editorconfig.org/
> ?
> diff --git a/platform/generic/andes/andes_pma.c b/platform/generic/andes/andes_pma.c
> index 09e5a30c..eeeb110e 100644
> --- a/platform/generic/andes/andes_pma.c
> +++ b/platform/generic/andes/andes_pma.c
> @@ -1,4 +1,4 @@
> -// SPDX-License-Identifier: GPL-2.0
> +// SPDX-License-Identifier: BSD-2-Clause
> ?/*
> ? * Copyright (C) 2023 Renesas Electronics Corp.
> ? * Copyright (c) 2024 Andes Technology Corporation
> diff --git a/platform/generic/include/andes/andes.h b/platform/generic/include/andes/andes.h
> index 3403a58b..bfedf034 100644
> --- a/platform/generic/include/andes/andes.h
> +++ b/platform/generic/include/andes/andes.h
> @@ -1,4 +1,4 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> +/* SPDX-License-Identifier: BSD-2-Clause */
> ?/*
> ? * Copyright (C) 2024 Andes Technology Corporation
> ? */
> diff --git a/platform/generic/include/andes/andes_pma.h b/platform/generic/include/andes/andes_pma.h
> index be614964..4a66e1b6 100644
> --- a/platform/generic/include/andes/andes_pma.h
> +++ b/platform/generic/include/andes/andes_pma.h
> @@ -1,4 +1,4 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> +/* SPDX-License-Identifier: BSD-2-Clause */
> ?/*
> ? * Copyright (C) 2023 Renesas Electronics Corp.
> ? */
> diff --git a/platform/generic/renesas/rzfive/rzfive.c b/platform/generic/renesas/rzfive/rzfive.c
> index 44db3671..6c3da095 100644
> --- a/platform/generic/renesas/rzfive/rzfive.c
> +++ b/platform/generic/renesas/rzfive/rzfive.c
> @@ -1,4 +1,4 @@
> -// SPDX-License-Identifier: GPL-2.0
> +// SPDX-License-Identifier: BSD-2-Clause
> ?/*
> ? * Copyright (C) 2022 Renesas Electronics Corp.
> ? *
> -- 
> 2.47.2
> 



From ben717 at andestech.com  Mon Jul 28 00:18:54 2025
From: ben717 at andestech.com (Ben Zong-You Xie)
Date: Mon, 28 Jul 2025 15:18:54 +0800
Subject: [PATCH] Fix license to compatible BSD-2-Clause
In-Reply-To: <b2363cfd71e26656b6160ba05fa151ebbf4cadfc.camel@126.com>
References: <20250728052713.361094-1-wxjstz@126.com>
 <b2363cfd71e26656b6160ba05fa151ebbf4cadfc.camel@126.com>
Message-ID: <aIckXoj8OPoPb1Jh@atctrx.andestech.com>

On Mon, Jul 28, 2025 at 03:01:54PM +0800, Xiang W wrote:
> [EXTERNAL MAIL]
> 
> ? 2025-07-28?? 13:26 +0800?Xiang W???
> > OpenBI is a BSD project. We need to modify some codes to compatible

s/OpenBI/OpenSBI

> > with BSD protocol.
> >
> > Signed-off-by: Xiang W <wxjstz at 126.com>

Reviewed-by: Ben Zong-You Xie <ben717 at andestech.com>

> > ---
> >  .editorconfig                              | 2 +-
> >  platform/generic/andes/andes_pma.c         | 2 +-
> >  platform/generic/include/andes/andes.h     | 2 +-
> >  platform/generic/include/andes/andes_pma.h | 2 +-
> >  platform/generic/renesas/rzfive/rzfive.c   | 2 +-
> >  5 files changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/.editorconfig b/.editorconfig
> > index e66b1ca3..26f90534 100644
> > --- a/.editorconfig
> > +++ b/.editorconfig
> > @@ -1,4 +1,4 @@
> > -# SPDX-License-Identifier: GPL-2.0-only
> > +# SPDX-License-Identifier: BSD-2-Clause
> >  # See here for more information about the format and editor support:
> >  # https://editorconfig.org/
> >
> > diff --git a/platform/generic/andes/andes_pma.c b/platform/generic/andes/andes_pma.c
> > index 09e5a30c..eeeb110e 100644
> > --- a/platform/generic/andes/andes_pma.c
> > +++ b/platform/generic/andes/andes_pma.c
> > @@ -1,4 +1,4 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > +// SPDX-License-Identifier: BSD-2-Clause
> >  /*
> >   * Copyright (C) 2023 Renesas Electronics Corp.
> >   * Copyright (c) 2024 Andes Technology Corporation
> > diff --git a/platform/generic/include/andes/andes.h b/platform/generic/include/andes/andes.h
> > index 3403a58b..bfedf034 100644
> > --- a/platform/generic/include/andes/andes.h
> > +++ b/platform/generic/include/andes/andes.h
> > @@ -1,4 +1,4 @@
> > -/* SPDX-License-Identifier: GPL-2.0 */
> > +/* SPDX-License-Identifier: BSD-2-Clause */
> >  /*
> >   * Copyright (C) 2024 Andes Technology Corporation
> >   */
> > diff --git a/platform/generic/include/andes/andes_pma.h b/platform/generic/include/andes/andes_pma.h
> > index be614964..4a66e1b6 100644
> > --- a/platform/generic/include/andes/andes_pma.h
> > +++ b/platform/generic/include/andes/andes_pma.h
> > @@ -1,4 +1,4 @@
> > -/* SPDX-License-Identifier: GPL-2.0 */
> > +/* SPDX-License-Identifier: BSD-2-Clause */
> >  /*
> >   * Copyright (C) 2023 Renesas Electronics Corp.
> >   */
> > diff --git a/platform/generic/renesas/rzfive/rzfive.c b/platform/generic/renesas/rzfive/rzfive.c
> > index 44db3671..6c3da095 100644
> > --- a/platform/generic/renesas/rzfive/rzfive.c
> > +++ b/platform/generic/renesas/rzfive/rzfive.c
> > @@ -1,4 +1,4 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > +// SPDX-License-Identifier: BSD-2-Clause
> >  /*
> >   * Copyright (C) 2022 Renesas Electronics Corp.
> >   *
> > --
> > 2.47.2
> >
> 


From wxjstz at 126.com  Mon Jul 28 00:38:10 2025
From: wxjstz at 126.com (Xiang W)
Date: Mon, 28 Jul 2025 15:38:10 +0800
Subject: [PATCH v2] Fix license to compatible BSD-2-Clause
Message-ID: <20250728074334.372355-1-wxjstz@126.com>

OpenSBI is a BSD project. We need to modify some codes to compatible
with BSD-2-Clause license.

Signed-off-by: Xiang W <wxjstz at 126.com>
Reviewed-by: Ben Zong-You Xie <ben717 at andestech.com>
---
v2 changes:
- fix typo and reword

Andes Technology agrees to change license.
We also need the consent of Renesas Electronics Corp.

 .editorconfig                              | 2 +-
 platform/generic/andes/andes_pma.c         | 2 +-
 platform/generic/include/andes/andes.h     | 2 +-
 platform/generic/include/andes/andes_pma.h | 2 +-
 platform/generic/renesas/rzfive/rzfive.c   | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.editorconfig b/.editorconfig
index e66b1ca3..26f90534 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: BSD-2-Clause
 # See here for more information about the format and editor support:
 # https://editorconfig.org/
 
diff --git a/platform/generic/andes/andes_pma.c b/platform/generic/andes/andes_pma.c
index 09e5a30c..eeeb110e 100644
--- a/platform/generic/andes/andes_pma.c
+++ b/platform/generic/andes/andes_pma.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (C) 2023 Renesas Electronics Corp.
  * Copyright (c) 2024 Andes Technology Corporation
diff --git a/platform/generic/include/andes/andes.h b/platform/generic/include/andes/andes.h
index 3403a58b..bfedf034 100644
--- a/platform/generic/include/andes/andes.h
+++ b/platform/generic/include/andes/andes.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (C) 2024 Andes Technology Corporation
  */
diff --git a/platform/generic/include/andes/andes_pma.h b/platform/generic/include/andes/andes_pma.h
index be614964..4a66e1b6 100644
--- a/platform/generic/include/andes/andes_pma.h
+++ b/platform/generic/include/andes/andes_pma.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (C) 2023 Renesas Electronics Corp.
  */
diff --git a/platform/generic/renesas/rzfive/rzfive.c b/platform/generic/renesas/rzfive/rzfive.c
index 44db3671..6c3da095 100644
--- a/platform/generic/renesas/rzfive/rzfive.c
+++ b/platform/generic/renesas/rzfive/rzfive.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (C) 2022 Renesas Electronics Corp.
  *
-- 
2.47.2



From jesse at rivosinc.com  Tue Jul 29 10:36:01 2025
From: jesse at rivosinc.com (Jesse Taube)
Date: Tue, 29 Jul 2025 10:36:01 -0700
Subject: [PATCH] Clarify sbi_debug_read_triggers return values
Message-ID: <20250729173601.2098669-1-jesse@rivosinc.com>

Clarify that `sbi_debug_read_triggers` must read the configuration
from CSRs.

Closes: #213
Signed-off-by: Jesse Taube <jesse at rivosinc.com>
---
 src/ext-debug-triggers.adoc | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/ext-debug-triggers.adoc b/src/ext-debug-triggers.adoc
index 2a5bcf9..3fd9093 100644
--- a/src/ext-debug-triggers.adoc
+++ b/src/ext-debug-triggers.adoc
@@ -133,8 +133,9 @@ struct sbiret sbi_debug_read_triggers(unsigned long trig_idx_base,
                                       unsigned long trig_count)
 ----
 
-Read the debug trigger state and configuration into shared memory for a range of debug
-triggers specified by the `trig_idx_base` and `trig_count` parameters on the calling hart.
+Read the saved debug trigger software state and read the current configuration
+from their respective CSRs into shared memory for a range of debug triggers
+specified by the `trig_idx_base` and `trig_count` parameters on the calling hart.
 
 For each debug trigger with index `trig_idx_base + i` where `-1 < i < trig_count`, the
 debug trigger state and configuration consisting of four XLEN-bit words are written in
-- 
2.43.0



