Skip to content

Changes related to hartid in the Linux SDK for freeloader, opensbi, uboot, and optee when utilizing the Nuclei RISC-V CPU. #29

@matthewgui

Description

@matthewgui

Nuclei CPU IP design defines the value of the mhartid csr, which includes the cluster id and hartid. The cluster id and hartid are either 32 bits (rv32) or 64 bits (rv64), and the number of bits occupied by the hartid varies with the number of hart. For instance, if some cluster has 4 harts, then the hartid in this cluster occupies 2 bits. By default, the Nuclei linux sdk on the Nuclei Evalsoc platform occupies 8 bits for hartid. You need to modify the source code in the linux sdk that involve hartid values based on your hardware system. mhartid csr can only be accessed in M mode. Therefore, code running in M mode that uses mhartid csr may need to be modified, such as freeloader, opensbi, uboot spl, etc. If the S mode can use the shartid nuclei customized csr, you can also refer to this document.

Note

  • This doc assumes that linux is running on only one cluster
  • You can grep hartid in all the related source code, and then take care of the changes.

1. freeloader hartid patch

Define the value of MHARTID_MASK based on the number of bits occupied by the hardware hartid. For example, if your hartid is 4, then hartid occupies 2 bits. Define the following macro:

#define MHARTID_MASK 0x3

The following code does not define MHARTID_MASK macro,your need to define it based on real hardware solution,otherwise,an error will be reported when compiling. In addition, we define GET_MASKED_HARTID macro to obtain hartid value.

diff --git a/freeloader.S b/freeloader.S
index 3266f1f..43b2d8a 100644
--- a/freeloader.S
+++ b/freeloader.S
@@ -80,6 +80,19 @@
 #define LWU                 lw
 #endif

+/* define hartid mask bits */
+#ifndef MHARTID_MASK
+#error "MHARTID_MASK is not defined!"
+#else
+#define HARTID_MASK      MHARTID_MASK
+#endif
+
+.macro GET_MASKED_HARTID result_reg
+    # Read hartid into result register
+    csrr    \result_reg, mhartid
+    and     \result_reg, \result_reg, HARTID_MASK
+.endm


 _check_hart:
     /* Hart 0 copy images, other hart wait copy finished, and jump to boot */
-    csrr a0, mhartid
+    GET_MASKED_HARTID a0
     beq a0, zero, _copy_image

 _wait_copy:
@@ -233,7 +246,7 @@ _loop_wait:
     j _wait_copy

 _start_smporamp:
-    csrr t0, mhartid
+    GET_MASKED_HARTID t0
     li t1, AMP_START_CORE
+    GET_MASKED_HARTID t0
     li t1, AMP_START_CORE
     // branch to amp boot if amp start core >= hartid
     bgeu t0, t1, _start_amp
@@ -242,7 +255,7 @@ _start_smporamp:
 _start_amp:
     // Increase REBOOT_CNT_BASE + hartid * 4
     li t0, REBOOT_CNT_BASE
-    csrr t2, mhartid
+    GET_MASKED_HARTID t2
     li t1, 4
     mul t1, t1, t2
     add t0, t0, t1
@@ -255,7 +268,7 @@ _start_amp:
     // jump address t0 = AMPFW_START_BASE + AMPFW_SIZE * (mhartid - 1)
     li t0, AMPFW_START_BASE
     li t1, AMPFW_SIZE
-    csrr t2, mhartid
+    GET_MASKED_HARTID t2
     // mhartid must > 1 here
     addi t2, t2, -1
     // hart program offset = AMPfw_size * (hartid-1)
@@ -415,7 +428,8 @@ _start_boot:
      * hartid via a0 register
      * device tree blob address in memory via a1 register. The address must be aligned to 8 bytes.
      */
-    csrr a0, mhartid /* hart ID */
+    GET_MASKED_HARTID a0 /* hart ID */

2. opensbi hartid patch

Define the value of MHARTID_MASK based on the number of bits occupied by the hardware hartid. For example, if your hartid is 4, then hartid occupies 2 bits. Define the following macro:

#define MHARTID_MASK 0x3

The following code does not define MHARTID_MASK macro,your need to define it based on real hardware solution,otherwise,an error will be reported when compiling. In addition, we define GET_MASKED_HARTID macro to obtain hartid value.

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index b947423..205e795 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -42,6 +42,12 @@
 999:
 .endm

+.macro GET_MASKED_HARTID result_reg
+    # Read hartid into result register
+    csrr    \result_reg, mhartid
+    and     \result_reg, \result_reg, HARTID_MASK
+.endm
+
        .section .entry, "ax", %progbits
        .align 3
        .globl _start
@@ -456,7 +462,7 @@ _start_warm:
        REG_L   s9, SBI_PLATFORM_HART_INDEX2ID_OFFSET(a4)

        /* Find HART id */
-       csrr    s6, CSR_MHARTID
+       GET_MASKED_HARTID s6

        /* Find HART index */
        beqz    s9, 3f
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index 1ff36de..2342535 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -162,8 +162,15 @@ void csr_write_num(int csr_num, unsigned long val);
                __asm__ __volatile__("ebreak" ::: "memory"); \
        } while (0)

+/* define hartid mask bits */
+#ifndef MHARTID_MASK
+#error "MHARTID_MASK is not defined!"
+#else
+#define HARTID_MASK      MHARTID_MASK
+#endif
+
 /* Get current HART id */
-#define current_hartid()       ((unsigned int)csr_read(CSR_MHARTID))
+#define current_hartid()       ((unsigned int)csr_read(CSR_MHARTID) & HARTID_MASK)

3. uboot spl hartid patch

Define the value of MHARTID_MASK based on the number of bits occupied by the hardware hartid. For example, if your hartid is 4, then hartid occupies 2 bits. Define the following macro:

#define MHARTID_MASK 0x3

The following code does not define MHARTID_MASK macro,your need to define it based on real hardware solution,otherwise,an error will be reported when compiling. In addition, we define GET_MASKED_HARTID macro to obtain hartid value.

diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 6cecadfac..c7528f422 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -32,6 +32,19 @@
 #define SYM_SIZE               0x18
 #endif

+/* define hartid mask bits */
+#ifndef MHARTID_MASK
+#error "MHARTID_MASK is not defined!"
+#else
+#define HARTID_MASK      MHARTID_MASK
+#endif
+
+.macro GET_MASKED_HARTID result_reg
+    # Read hartid into result register
+    csrr    \result_reg, mhartid
+    and     \result_reg, \result_reg, HARTID_MASK
+.endm
+
 .section .data
 secondary_harts_relocation_error:
        .ascii "Relocation of secondary harts has failed, error %d\n"
@@ -40,7 +53,7 @@ secondary_harts_relocation_error:
 .globl _start
 _start:
 #if CONFIG_IS_ENABLED(RISCV_MMODE)
-       csrr    a0, CSR_MHARTID
+       GET_MASKED_HARTID       a0
:

4. optee os shartid patch

Perhaps you use shartid csr to read hartid in supervisor mode. you need to modify code like above. The following example
is optee os may use shartid.

Define the value of SHARTID_MASK based on the number of bits occupied by the hardware hartid. For example, if your hartid is 4, then hartid occupies 2 bits. Define the following macro:

#define SHARTID_MASK 0x3

The following code does not define SHARTID_MASK macro,your need to define it based on real hardware solution.

diff --git a/core/arch/riscv/include/riscv.h b/core/arch/riscv/include/riscv.h
index 2d5042f..a148eba 100644
--- a/core/arch/riscv/include/riscv.h
+++ b/core/arch/riscv/include/riscv.h
@@ -60,13 +60,20 @@
 #ifndef __ASSEMBLER__

 #ifdef CFG_SHART_FEATURE
+
+#ifndef SHARTID_MASK
+#error "SHARTID_MASK is not defined!"
+#else
+#define HARTID_MASK      SHARTID_MASK
+#endif
+
 static inline __noprof unsigned long read_hartid(void)
 {
        unsigned long hartid;

        asm volatile("csrr %0, 0xdc0" : "=r" (hartid));

-       return hartid;
+       return hartid & HARTID_MASK;
 }

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions