diff options
| author | GUI <[email protected]> | 2026-10-17 09:44:26 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-10-17 09:44:26 +0800 |
| commit | 8d8dc96b67eee53af2841a8819364d52fbec39cb (patch) | |
| tree | eb2ac2f0984261f526c5d9c14462db47eceeb193 /libcpu/risc-v/common/include | |
| parent | c1d931bcc78915f24c3526a07bdecc64d5110d51 (diff) | |
[ARCH/RISC-V] Next RISC-V (#10320)
* [libcpu][risc-v] Refactor the RISC-V architecture port
Introduce an opt-in unified RISC-V common layer for RV32 and RV64 while keeping existing BSPs on the legacy implementation during migration.
- use ARCH_RISCV and ARCH_CPU_64BIT for architecture and XLEN selection
- unify context, trap, MMU, cache, timer, SBI, SMP and ISA handling
- add PLIC, CLIC, ACLINT, APLIC and IMSIC support
- map physical hart IDs to contiguous logical CPU IDs
- add T-Head vendor overrides while preserving legacy ports
- migrate qemu-virt64-riscv with RV32 and RV64 support
- update clock_time, MM, LWP, OFW, PCI and Rust integration
Existing BSPs continue using legacy_common or common64 unless they select RT_USING_RISCV_NEW_COMMON.
Signed-off-by: GuEe-GUI <[email protected]>
* [libcpu][risc-v] skip disabled CPU nodes in early FDT walk
Rbb666 noted that rt_hw_fdt_install_early() walked every /cpus child
without checking status, so disabled cores still joined hart registration
and MMU capability probing. Skip nodes that are not okay/ok via
rt_fdt_device_is_available() before reading reg or mmu-type.
Signed-off-by: seteiro <[email protected]>
* [libcpu][risc-v] Fix per-CPU page table mapping
- reuse existing non-leaf page table entries when mapping per-CPU areas
- reject leaf entry conflicts instead of overwriting mappings
Signed-off-by: GuEe-GUI <[email protected]>
---------
Signed-off-by: GuEe-GUI <[email protected]>
Signed-off-by: seteiro <[email protected]>
Co-authored-by: seteiro <[email protected]>
Diffstat (limited to 'libcpu/risc-v/common/include')
| -rw-r--r-- | libcpu/risc-v/common/include/asm-generic.h | 105 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/asm.h | 304 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/cache.h | 32 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/context_ext.h | 88 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/cpu.h | 47 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/cpuport.h | 71 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/csr.h | 580 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/interrupt.h | 67 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/isa_ext.h | 95 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/mmu.h | 277 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/opcode.h | 85 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/page_def.h | 31 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/riscv_timer.h | 29 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/sbi.h | 272 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/setup.h | 17 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/stack.h | 145 | ||||
| -rw-r--r-- | libcpu/risc-v/common/include/tlb.h | 103 |
17 files changed, 2348 insertions, 0 deletions
diff --git a/libcpu/risc-v/common/include/asm-generic.h b/libcpu/risc-v/common/include/asm-generic.h new file mode 100644 index 0000000000..6f29a6034d --- /dev/null +++ b/libcpu/risc-v/common/include/asm-generic.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-03-12 WangXiaoyao the first version + * 2025-04-20 GuEe-GUI Merge 64 and 32 mode + */ + +#ifndef __ASM_GENERIC_H__ +#define __ASM_GENERIC_H__ + +#if defined(__ASSEMBLER__) && !defined(__ASSEMBLY__) +/* For XuanTie GCC */ +#define __ASSEMBLY__ +#endif + +#include <rtconfig.h> + +#ifdef __ASSEMBLY__ +/* use to mark a start point where every task start from */ +#define START_POINT(funcname) \ + .global funcname; \ + .type funcname, %function; \ + funcname: \ + .cfi_sections .debug_frame, .eh_frame; \ + .cfi_startproc; \ + .cfi_undefined ra + +#define START_POINT_END(name) \ + .cfi_endproc; \ + .size name, .-name; + +#define _AC(X,Y) X +#define _AT(T,X) X +#define __ASM_STR(x) x +#else +#define _AC(X,Y) (X##Y) +#define _AT(T,X) ((T)(X)) +#define __ASM_STR(x) #x +#endif + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#if __riscv_xlen == 64 +#define BITS_PER_LONG 64 +#define __REG_SEL(a, b) __ASM_STR(a) +#elif __riscv_xlen == 32 +#define BITS_PER_LONG 32 +#define __REG_SEL(a, b) __ASM_STR(b) +#else +#error "Unexpected __riscv_xlen" +#endif + +#ifndef RT_BITS_PER_LONG +#define RT_BITS_PER_LONG BITS_PER_LONG +#endif + +#ifndef BIT +#define BIT(x) (_UL(1) << (x)) +#endif + +#ifndef GENMASK +#define GENMASK(h, l) (((_UL(~0)) << (l)) & (_UL(~0) >> (BITS_PER_LONG - 1 - (h)))) +#endif + +#define REG_WIDTH __REG_SEL(d, w) +#define REG_L __REG_SEL(ld, lw) +#define REG_S __REG_SEL(sd, sw) +#define REG_SC __REG_SEL(sc.d, sc.w) +#define REG_AMOSWAP_AQ __REG_SEL(amoswap.d.aq, amoswap.w.aq) +#define REG_ASM __REG_SEL(.dword, .word) +#define SZREG __REG_SEL(8, 4) +#define LGREG __REG_SEL(3, 2) +#define FREG_L __REG_SEL(fld, flw) +#define FREG_S __REG_SEL(fsd, fsw) + +#if __riscv_xlen == 64 +#ifdef __ASSEMBLY__ +#define RISCV_PTR .dword +#define RISCV_SZPTR 8 +#define RISCV_LGPTR 3 +#else +#define RISCV_PTR ".dword" +#define RISCV_SZPTR "8" +#define RISCV_LGPTR "3" +#endif +#elif __riscv_xlen == 32 +#ifdef __ASSEMBLY__ +#define RISCV_PTR .word +#define RISCV_SZPTR 4 +#define RISCV_LGPTR 2 +#else +#define RISCV_PTR ".word" +#define RISCV_SZPTR "4" +#define RISCV_LGPTR "2" +#endif +#else +#error "Unexpected __riscv_xlen" +#endif + +#endif /* __ASM_GENERIC_H__ */ diff --git a/libcpu/risc-v/common/include/asm.h b/libcpu/risc-v/common/include/asm.h new file mode 100644 index 0000000000..500247a57e --- /dev/null +++ b/libcpu/risc-v/common/include/asm.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-02 lizhirui first version + * 2021-02-11 lizhirui fixed gp save/store bug + * 2021-11-18 JasonHu add fpu registers save/restore + * 2022-10-22 Shell Support kernel mode RVV + * 2025-04-20 GuEe-GUI Merge 64I and 32I/E + */ + +#ifndef __ASM_H__ +#define __ASM_H__ + +#include <rtconfig.h> + +#include <csr.h> +#include <stack.h> + +#ifdef __GNUC__ +.macro LOAD_GLOBAL_POINTER +.option push +.option norelax + la gp, __global_pointer$ +.option pop +.endm + +.macro XRET +#ifdef ARCH_RISCV_M_MODE + mret +#else + sret +#endif +.endm + +.macro PUSH reg + addi sp, sp, -SZREG + REG_S \reg, 0(sp) +.endm + +.macro POP reg + REG_L \reg, 0(sp) + addi sp, sp, SZREG +.endm + +.macro OPEN_INTERRUPT + csrsi CSR_STATUS, 2 +.endm + +.macro CLOSE_INTERRUPT + csrci CSR_STATUS, 2 +.endm + +.macro SAVE_ALL +#ifdef ARCH_RISCV_FPU + /* Reserve float registers */ + addi sp, sp, -CTX_FPU_REG_NR * SZREG +#endif +#ifdef ARCH_RISCV_VECTOR + /* Reserve float registers */ + addi sp, sp, -CTX_VECTOR_REG_NR * SZREG +#endif + + /* Save general registers */ + addi sp, sp, -CTX_GENERAL_REG_NR * SZREG + REG_S x1, 1 * SZREG(sp) + + csrr x1, CSR_STATUS + REG_S x1, FRAME_OFF_XSTATUS(sp) + + csrr x1, CSR_CAUSE + REG_S x1, FRAME_OFF_XCAUSE(sp) + + csrr x1, CSR_EPC + REG_S x1, 0 * SZREG(sp) + + REG_S x3, 4 * SZREG(sp) + REG_S x4, 5 * SZREG(sp) + REG_S x5, 6 * SZREG(sp) + REG_S x6, 7 * SZREG(sp) + REG_S x7, 8 * SZREG(sp) + REG_S x8, 9 * SZREG(sp) + REG_S x9, 10 * SZREG(sp) + REG_S x10, 11 * SZREG(sp) + REG_S x11, 12 * SZREG(sp) + REG_S x12, 13 * SZREG(sp) + REG_S x13, 14 * SZREG(sp) + REG_S x14, 15 * SZREG(sp) + REG_S x15, 16 * SZREG(sp) +#ifndef ARCH_RISCV_32E + REG_S x16, 17 * SZREG(sp) + REG_S x17, 18 * SZREG(sp) + REG_S x18, 19 * SZREG(sp) + REG_S x19, 20 * SZREG(sp) + REG_S x20, 21 * SZREG(sp) + REG_S x21, 22 * SZREG(sp) + REG_S x22, 23 * SZREG(sp) + REG_S x23, 24 * SZREG(sp) + REG_S x24, 25 * SZREG(sp) + REG_S x25, 26 * SZREG(sp) + REG_S x26, 27 * SZREG(sp) + REG_S x27, 28 * SZREG(sp) + REG_S x28, 29 * SZREG(sp) + REG_S x29, 30 * SZREG(sp) + REG_S x30, 31 * SZREG(sp) + REG_S x31, 32 * SZREG(sp) +#endif /* !ARCH_RISCV_32E */ + csrr t0, CSR_SCRATCH + REG_S t0, FRAME_OFF_SP(sp) + +#ifdef ARCH_RISCV_FPU + /* Backup sp and adjust sp to save float registers */ + mv t1, sp + addi t1, t1, CTX_GENERAL_REG_NR * SZREG + + li t0, SR_FS + csrs CSR_STATUS, t0 + CTX_FREG_S f0, FPU_CTX_F0_OFF(t1) + CTX_FREG_S f1, FPU_CTX_F1_OFF(t1) + CTX_FREG_S f2, FPU_CTX_F2_OFF(t1) + CTX_FREG_S f3, FPU_CTX_F3_OFF(t1) + CTX_FREG_S f4, FPU_CTX_F4_OFF(t1) + CTX_FREG_S f5, FPU_CTX_F5_OFF(t1) + CTX_FREG_S f6, FPU_CTX_F6_OFF(t1) + CTX_FREG_S f7, FPU_CTX_F7_OFF(t1) + CTX_FREG_S f8, FPU_CTX_F8_OFF(t1) + CTX_FREG_S f9, FPU_CTX_F9_OFF(t1) + CTX_FREG_S f10, FPU_CTX_F10_OFF(t1) + CTX_FREG_S f11, FPU_CTX_F11_OFF(t1) + CTX_FREG_S f12, FPU_CTX_F12_OFF(t1) + CTX_FREG_S f13, FPU_CTX_F13_OFF(t1) + CTX_FREG_S f14, FPU_CTX_F14_OFF(t1) + CTX_FREG_S f15, FPU_CTX_F15_OFF(t1) + CTX_FREG_S f16, FPU_CTX_F16_OFF(t1) + CTX_FREG_S f17, FPU_CTX_F17_OFF(t1) + CTX_FREG_S f18, FPU_CTX_F18_OFF(t1) + CTX_FREG_S f19, FPU_CTX_F19_OFF(t1) + CTX_FREG_S f20, FPU_CTX_F20_OFF(t1) + CTX_FREG_S f21, FPU_CTX_F21_OFF(t1) + CTX_FREG_S f22, FPU_CTX_F22_OFF(t1) + CTX_FREG_S f23, FPU_CTX_F23_OFF(t1) + CTX_FREG_S f24, FPU_CTX_F24_OFF(t1) + CTX_FREG_S f25, FPU_CTX_F25_OFF(t1) + CTX_FREG_S f26, FPU_CTX_F26_OFF(t1) + CTX_FREG_S f27, FPU_CTX_F27_OFF(t1) + CTX_FREG_S f28, FPU_CTX_F28_OFF(t1) + CTX_FREG_S f29, FPU_CTX_F29_OFF(t1) + CTX_FREG_S f30, FPU_CTX_F30_OFF(t1) + CTX_FREG_S f31, FPU_CTX_F31_OFF(t1) + + /* Clean FS domain */ + csrc CSR_STATUS, t0 + + /* Clean status would clr sr_sd; */ + li t0, SR_FS_CLEAN + csrs CSR_STATUS, t0 + +#endif /* ARCH_RISCV_FPU */ + +#ifdef ARCH_RISCV_VECTOR + csrr t0, CSR_STATUS + andi t0, t0, SR_VS + beqz t0, 0f + + /* push vector frame */ + addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG + + SAVE_VECTOR t1 +0: +#endif /* ARCH_RISCV_VECTOR */ +.endm + +.macro RESTORE_TP offset +#if !defined(RT_USING_SMP) + REG_L tp, \offset(sp) +#elif defined(ARCH_MM_MMU) && !defined(ARCH_RISCV_M_MODE) + /* Bare SMP uses tp as a hart-local CPU ID, including interrupt returns. */ + la t0, rt_hw_arch_vaddr_width + lbu t0, 0(t0) + beqz t0, .Lkeep_tp\@ + REG_L tp, \offset(sp) +.Lkeep_tp\@: +#endif +.endm + +.macro RESTORE_ALL +#ifdef ARCH_RISCV_VECTOR + /* Skip on close */ + REG_L t0, FRAME_OFF_XSTATUS(sp) + /* Cannot use vector on initial */ + andi t0, t0, SR_VS_CLEAN + beqz t0, 0f + + /* Restore vector frame */ + addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG + + RESTORE_VECTOR t1 +0: +#endif /* ARCH_RISCV_VECTOR */ + +#ifdef ARCH_RISCV_FPU + /* Restore float register */ + addi t2, sp, CTX_GENERAL_REG_NR * SZREG + + li t0, SR_FS + csrs CSR_STATUS, t0 + CTX_FREG_L f0, FPU_CTX_F0_OFF(t2) + CTX_FREG_L f1, FPU_CTX_F1_OFF(t2) + CTX_FREG_L f2, FPU_CTX_F2_OFF(t2) + CTX_FREG_L f3, FPU_CTX_F3_OFF(t2) + CTX_FREG_L f4, FPU_CTX_F4_OFF(t2) + CTX_FREG_L f5, FPU_CTX_F5_OFF(t2) + CTX_FREG_L f6, FPU_CTX_F6_OFF(t2) + CTX_FREG_L f7, FPU_CTX_F7_OFF(t2) + CTX_FREG_L f8, FPU_CTX_F8_OFF(t2) + CTX_FREG_L f9, FPU_CTX_F9_OFF(t2) + CTX_FREG_L f10, FPU_CTX_F10_OFF(t2) + CTX_FREG_L f11, FPU_CTX_F11_OFF(t2) + CTX_FREG_L f12, FPU_CTX_F12_OFF(t2) + CTX_FREG_L f13, FPU_CTX_F13_OFF(t2) + CTX_FREG_L f14, FPU_CTX_F14_OFF(t2) + CTX_FREG_L f15, FPU_CTX_F15_OFF(t2) + CTX_FREG_L f16, FPU_CTX_F16_OFF(t2) + CTX_FREG_L f17, FPU_CTX_F17_OFF(t2) + CTX_FREG_L f18, FPU_CTX_F18_OFF(t2) + CTX_FREG_L f19, FPU_CTX_F19_OFF(t2) + CTX_FREG_L f20, FPU_CTX_F20_OFF(t2) + CTX_FREG_L f21, FPU_CTX_F21_OFF(t2) + CTX_FREG_L f22, FPU_CTX_F22_OFF(t2) + CTX_FREG_L f23, FPU_CTX_F23_OFF(t2) + CTX_FREG_L f24, FPU_CTX_F24_OFF(t2) + CTX_FREG_L f25, FPU_CTX_F25_OFF(t2) + CTX_FREG_L f26, FPU_CTX_F26_OFF(t2) + CTX_FREG_L f27, FPU_CTX_F27_OFF(t2) + CTX_FREG_L f28, FPU_CTX_F28_OFF(t2) + CTX_FREG_L f29, FPU_CTX_F29_OFF(t2) + CTX_FREG_L f30, FPU_CTX_F30_OFF(t2) + CTX_FREG_L f31, FPU_CTX_F31_OFF(t2) + + /* Clean FS domain */ + csrc CSR_STATUS, t0 + + /* Clean status would clr sr_sd; */ + li t0, SR_FS_CLEAN + csrs CSR_STATUS, t0 + +#endif /* ARCH_RISCV_FPU */ + + /* Restore general register */ +#ifndef ARCH_RISCV_USING_IRQ_STACK + addi t0, sp, CTX_ALL_REG_NR * SZREG + csrw CSR_SCRATCH, t0 +#endif + + /* resw ra to CSR_EPC */ + REG_L x1, 0 * SZREG(sp) + csrw CSR_EPC, x1 + + REG_L x1, 2 * SZREG(sp) + csrw CSR_STATUS, x1 + + REG_L x1, 1 * SZREG(sp) + + REG_L x3, 4 * SZREG(sp) + RESTORE_TP (5 * SZREG) + REG_L x5, 6 * SZREG(sp) + REG_L x6, 7 * SZREG(sp) + REG_L x7, 8 * SZREG(sp) + REG_L x8, 9 * SZREG(sp) + REG_L x9, 10 * SZREG(sp) + REG_L x10, 11 * SZREG(sp) + REG_L x11, 12 * SZREG(sp) + REG_L x12, 13 * SZREG(sp) + REG_L x13, 14 * SZREG(sp) + REG_L x14, 15 * SZREG(sp) + REG_L x15, 16 * SZREG(sp) +#ifndef ARCH_RISCV_32E + REG_L x16, 17 * SZREG(sp) + REG_L x17, 18 * SZREG(sp) + REG_L x18, 19 * SZREG(sp) + REG_L x19, 20 * SZREG(sp) + REG_L x20, 21 * SZREG(sp) + REG_L x21, 22 * SZREG(sp) + REG_L x22, 23 * SZREG(sp) + REG_L x23, 24 * SZREG(sp) + REG_L x24, 25 * SZREG(sp) + REG_L x25, 26 * SZREG(sp) + REG_L x26, 27 * SZREG(sp) + REG_L x27, 28 * SZREG(sp) + REG_L x28, 29 * SZREG(sp) + REG_L x29, 30 * SZREG(sp) + REG_L x30, 31 * SZREG(sp) + REG_L x31, 32 * SZREG(sp) +#endif /* !ARCH_RISCV_32E */ + + /* Restore user sp */ + REG_L sp, FRAME_OFF_SP(sp) +.endm +#endif /* __GNUC__ */ + +#endif /* __ASM_H__ */ diff --git a/libcpu/risc-v/common/include/cache.h b/libcpu/risc-v/common/include/cache.h new file mode 100644 index 0000000000..a8224a9e59 --- /dev/null +++ b/libcpu/risc-v/common/include/cache.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI the first version + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#ifndef __ASSEMBLY__ +#include <rtdef.h> + +void riscv_cache_set_cbom_block_size(rt_uint32_t size); +rt_uint32_t riscv_cache_get_cbom_block_size(void); + +void rt_hw_cpu_icache_invalidate_all(void); +void rt_hw_cpu_icache_invalidate(void *addr, rt_size_t size); +void rt_hw_cpu_dcache_clean_and_invalidate(void *addr, rt_size_t size); + +void rt_hw_icache_invalidate_all(void); + +void rt_hw_sync_cache_local(void *addr, int size); +#endif /* !__ASSEMBLY__ */ + +#endif /* __CACHE_H__ */ diff --git a/libcpu/risc-v/common/include/context_ext.h b/libcpu/risc-v/common/include/context_ext.h new file mode 100644 index 0000000000..2c2676e2b6 --- /dev/null +++ b/libcpu/risc-v/common/include/context_ext.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-10 RT-Thread the first version + */ + +#ifndef __CONTEXT_EXT_H__ +#define __CONTEXT_EXT_H__ + +#include <asm-generic.h> + +#ifdef ARCH_RISCV_FPU +#ifndef __riscv_flen +#error "ARCH_RISCV_FPU requires a toolchain target with F or D extension" +#endif +/* Number of XLEN-sized stack slots occupied by 32 floating-point registers. */ +#define CTX_FPU_REG_NR (32 * __riscv_flen / __riscv_xlen) +#else +#define CTX_FPU_REG_NR 0 +#endif + +#ifdef __ASSEMBLY__ + +/** + * ================================== + * RISC-V D ISA (Floating) + * ================================== + */ + +#ifdef ARCH_RISCV_FPU +#define FPU_CTX_REG_OFF(n) ((__riscv_flen / 8) * (n)) +#define FPU_CTX_F0_OFF FPU_CTX_REG_OFF(0) +#define FPU_CTX_F1_OFF FPU_CTX_REG_OFF(1) +#define FPU_CTX_F2_OFF FPU_CTX_REG_OFF(2) +#define FPU_CTX_F3_OFF FPU_CTX_REG_OFF(3) +#define FPU_CTX_F4_OFF FPU_CTX_REG_OFF(4) +#define FPU_CTX_F5_OFF FPU_CTX_REG_OFF(5) +#define FPU_CTX_F6_OFF FPU_CTX_REG_OFF(6) +#define FPU_CTX_F7_OFF FPU_CTX_REG_OFF(7) +#define FPU_CTX_F8_OFF FPU_CTX_REG_OFF(8) +#define FPU_CTX_F9_OFF FPU_CTX_REG_OFF(9) +#define FPU_CTX_F10_OFF FPU_CTX_REG_OFF(10) +#define FPU_CTX_F11_OFF FPU_CTX_REG_OFF(11) +#define FPU_CTX_F12_OFF FPU_CTX_REG_OFF(12) +#define FPU_CTX_F13_OFF FPU_CTX_REG_OFF(13) +#define FPU_CTX_F14_OFF FPU_CTX_REG_OFF(14) +#define FPU_CTX_F15_OFF FPU_CTX_REG_OFF(15) +#define FPU_CTX_F16_OFF FPU_CTX_REG_OFF(16) +#define FPU_CTX_F17_OFF FPU_CTX_REG_OFF(17) +#define FPU_CTX_F18_OFF FPU_CTX_REG_OFF(18) +#define FPU_CTX_F19_OFF FPU_CTX_REG_OFF(19) +#define FPU_CTX_F20_OFF FPU_CTX_REG_OFF(20) +#define FPU_CTX_F21_OFF FPU_CTX_REG_OFF(21) +#define FPU_CTX_F22_OFF FPU_CTX_REG_OFF(22) +#define FPU_CTX_F23_OFF FPU_CTX_REG_OFF(23) +#define FPU_CTX_F24_OFF FPU_CTX_REG_OFF(24) +#define FPU_CTX_F25_OFF FPU_CTX_REG_OFF(25) +#define FPU_CTX_F26_OFF FPU_CTX_REG_OFF(26) +#define FPU_CTX_F27_OFF FPU_CTX_REG_OFF(27) +#define FPU_CTX_F28_OFF FPU_CTX_REG_OFF(28) +#define FPU_CTX_F29_OFF FPU_CTX_REG_OFF(29) +#define FPU_CTX_F30_OFF FPU_CTX_REG_OFF(30) +#define FPU_CTX_F31_OFF FPU_CTX_REG_OFF(31) + +#if __riscv_flen == 64 +#define CTX_FREG_L fld +#define CTX_FREG_S fsd +#elif __riscv_flen == 32 +#define CTX_FREG_L flw +#define CTX_FREG_S fsw +#else +#error "Unexpected __riscv_flen" +#endif +#endif /* ARCH_RISCV_FPU */ + +#endif /* __ASSEMBLY__ */ + +#ifdef ARCH_RISCV_VECTOR +#include "rvv_context.h" +#else /* !ARCH_RISCV_VECTOR */ +#define CTX_VECTOR_REG_NR 0 +#endif /* ARCH_RISCV_VECTOR */ + +#endif /* __CONTEXT_EXT_H__ */ diff --git a/libcpu/risc-v/common/include/cpu.h b/libcpu/risc-v/common/include/cpu.h new file mode 100644 index 0000000000..c78a574e20 --- /dev/null +++ b/libcpu/risc-v/common/include/cpu.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __CPU_H__ +#define __CPU_H__ + +#include <rtdef.h> + +#ifndef RT_CPUS_NR +#define RT_CPUS_NR 1 +#endif + +#if defined(RT_USING_DM) && defined(RT_USING_SMP) +struct cpu_ops_t +{ + const char *method; + int (*cpu_init)(rt_uint32_t id, void *param); + int (*cpu_boot)(rt_uint32_t id, rt_uint64_t entry); + void (*cpu_shutdown)(void); +}; +#endif + +extern rt_ubase_t boot_cpu_hartid; +extern void _secondary_cpu_entry(void); + +#if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) +extern char __percpu_real_end, __percpu_end, __percpu_start; +#endif /* RT_USING_SMP && ARCH_MM_MMU */ + +rt_ubase_t riscv_cpu_id_to_hartid(int cpu_id); +rt_bool_t riscv_cpu_id_available(int cpu_id); +int riscv_hartid_to_cpu_id(rt_ubase_t hartid); +int riscv_hartid_register(rt_ubase_t hartid); +void riscv_cpu_id_set(int cpu_id); +#if defined(RT_USING_SMP) && !defined(RT_USING_DM) +rt_size_t riscv_hartid_list_get(rt_ubase_t *hartids, rt_size_t max_harts); +#endif +void riscv_boot_hart_init(rt_ubase_t hartid); + +#endif /* __CPU_H__ */ diff --git a/libcpu/risc-v/common/include/cpuport.h b/libcpu/risc-v/common/include/cpuport.h new file mode 100644 index 0000000000..10f265ed38 --- /dev/null +++ b/libcpu/risc-v/common/include/cpuport.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-03 Bernard The first version + */ + +#ifndef CPUPORT_H__ +#define CPUPORT_H__ + +#include <rtconfig.h> + +#ifdef RT_USING_CACHE +#include <cache.h> +#define RT_CPU_CACHE_LINE_SZ L1_CACHE_BYTES +#endif + +#include <opcode.h> + +#ifdef RT_USING_SMP +typedef union +{ + unsigned long slock; + struct __arch_tickets + { + unsigned short owner; + unsigned short next; + } tickets; +} rt_hw_spinlock_t; +#endif /* RT_USING_SMP */ + +#define RISCV_FENCE(p, s) __asm__ volatile ("fence " #p "," #s:::"memory") + +#define rt_hw_barrier(...) RISCV_FENCE(iorw, iorw) +#define rt_hw_wfi() __asm__ volatile ("wfi") +#define rt_hw_rmb() RISCV_FENCE(ir, ir) +#define rt_hw_wmb() RISCV_FENCE(ow, ow) + +#ifndef __ASSEMBLY__ +#ifdef RT_USING_CACHE +rt_inline void rt_hw_dsb(void) +{ + __asm__ volatile ("fence":::"memory"); +} + +rt_inline void rt_hw_dmb(void) +{ + __asm__ volatile ("fence":::"memory"); +} + +rt_inline void rt_hw_isb(void) +{ +#ifndef ARCH_RISCV_DISABLE_FENCE_I + __asm__ volatile (OPC_FENCE_I:::"memory"); +#endif +} +#endif /* RT_USING_CACHE */ + +rt_inline void rt_hw_cpu_relax(void) +{ + __asm__ volatile (OPC_PAUSE_I); + rt_hw_barrier(); +} + +void _thread_start(void); +#endif /* !__ASSEMBLY__ */ + +#endif /* CPUPORT_H__ */ diff --git a/libcpu/risc-v/common/include/csr.h b/libcpu/risc-v/common/include/csr.h new file mode 100644 index 0000000000..f5ddca9c40 --- /dev/null +++ b/libcpu/risc-v/common/include/csr.h @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __CSR_H__ +#define __CSR_H__ + +#include <asm-generic.h> + +/* Status register flags */ +#define SR_SIE _UL(0x00000002) /* Supervisor Interrupt Enable */ +#define SR_MIE _UL(0x00000008) /* Machine Interrupt Enable */ +#define SR_SPIE _UL(0x00000020) /* Previous Supervisor IE */ +#define SR_MPIE _UL(0x00000080) /* Previous Machine IE */ +#define SR_SPP _UL(0x00000100) /* Previously Supervisor */ +#define SR_MPP _UL(0x00001800) /* Previously Machine */ +#define SR_SUM _UL(0x00040000) /* Supervisor User Memory Access */ +#define SR_MXR _UL(0x00080000) /* Make eXecutable Readable */ + +#define SR_FS _UL(0x00006000) /* Floating-point Status */ +#define SR_FS_OFF _UL(0x00000000) +#define SR_FS_INITIAL _UL(0x00002000) +#define SR_FS_CLEAN _UL(0x00004000) +#define SR_FS_DIRTY _UL(0x00006000) + +#define SR_VS _UL(0x00000600) /* Vector Status */ +#define SR_VS_OFF _UL(0x00000000) +#define SR_VS_INITIAL _UL(0x00000200) +#define SR_VS_CLEAN _UL(0x00000400) +#define SR_VS_DIRTY _UL(0x00000600) + +#define SR_XS _UL(0x00018000) /* Extension Status */ +#define SR_XS_OFF _UL(0x00000000) +#define SR_XS_INITIAL _UL(0x00008000) +#define SR_XS_CLEAN _UL(0x00010000) +#define SR_XS_DIRTY _UL(0x00018000) + +#define SR_FS_VS (SR_FS | SR_VS) /* Vector and Floating-Point Unit */ + +#if __riscv_xlen == 32 +#define SR_SD _UL(0x80000000) /* FS/VS/XS dirty */ +#else +#define SR_SD _UL(0x8000000000000000) /* FS/VS/XS dirty */ +#endif + +#if __riscv_xlen == 64 +#define SR_UXL _UL(0x300000000) /* XLEN mask for U-mode */ +#define SR_UXL_32 _UL(0x100000000) /* XLEN = 32 for U-mode */ +#define SR_UXL_64 _UL(0x200000000) /* XLEN = 64 for U-mode */ +#endif + +/* SATP flags */ +#if __riscv_xlen == 32 +#define SATP_PPN _UL(0x003fffff) +#define SATP_MODE_BARE _UL(0x00000000) +#define SATP_MODE_32 _UL(0x80000000) +#define SATP_MODE_SHIFT 31 +#define SATP_MODE_MASK (_UL(0x1) << SATP_MODE_SHIFT) +#define SATP_ASID_BITS 9 +#define SATP_ASID_SHIFT 22 +#define SATP_ASID_MASK _UL(0x1ff) +#else +#define SATP_PPN _UL(0x00000fffffffffff) +#define SATP_MODE_BARE _UL(0x0000000000000000) +#define SATP_MODE_39 _UL(0x8000000000000000) +#define SATP_MODE_48 _UL(0x9000000000000000) +#define SATP_MODE_57 _UL(0xa000000000000000) +#define SATP_MODE_64 _UL(0xb000000000000000) +#define SATP_MODE_SHIFT 60 +#define SATP_MODE_MASK (_UL(0xf) << SATP_MODE_SHIFT) +#define SATP_ASID_BITS 16 +#define SATP_ASID_SHIFT 44 +#define SATP_ASID_MASK _UL(0xffff) +#endif + +/* Exception cause high bit - is an interrupt if set */ +#define CAUSE_IRQ_FLAG (_UL(1) << (__riscv_xlen - 1)) + +/* Interrupt causes (minus the high bit) */ +#define IRQ_S_SOFT 1 +#define IRQ_VS_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_VS_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_VS_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_S_GEXT 12 +#define IRQ_PMU_OVF 13 +#define IRQ_LOCAL_MAX (IRQ_PMU_OVF + 1) +#define IRQ_LOCAL_MASK GENMASK((IRQ_LOCAL_MAX - 1), 0) + +/* Exception causes */ +#define EXC_INST_MISALIGNED 0 +#define EXC_INST_ACCESS 1 +#define EXC_INST_ILLEGAL 2 +#define EXC_BREAKPOINT 3 +#define EXC_LOAD_MISALIGNED 4 +#define EXC_LOAD_ACCESS 5 +#define EXC_STORE_MISALIGNED 6 +#define EXC_STORE_ACCESS 7 +#define EXC_SYSCALL 8 +#define EXC_HYPERVISOR_SYSCALL 9 +#define EXC_SUPERVISOR_SYSCALL 10 +#define EXC_INST_PAGE_FAULT 12 +#define EXC_LOAD_PAGE_FAULT 13 +#define EXC_STORE_PAGE_FAULT 15 +#define EXC_INST_GUEST_PAGE_FAULT 20 +#define EXC_LOAD_GUEST_PAGE_FAULT 21 +#define EXC_VIRTUAL_INST_FAULT 22 +#define EXC_STORE_GUEST_PAGE_FAULT 23 + +/* PMP configuration */ +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_A_TOR 0x08 +#define PMP_A_NA4 0x10 +#define PMP_A_NAPOT 0x18 +#define PMP_L 0x80 + +/* HSTATUS flags */ +#if __riscv_xlen == 64 +#define HSTATUS_VSXL _UL(0x300000000) +#define HSTATUS_VSXL_SHIFT 32 +#endif +#define HSTATUS_VTSR _UL(0x00400000) +#define HSTATUS_VTW _UL(0x00200000) +#define HSTATUS_VTVM _UL(0x00100000) +#define HSTATUS_VGEIN _UL(0x0003f000) +#define HSTATUS_VGEIN_SHIFT 12 +#define HSTATUS_HU _UL(0x00000200) +#define HSTATUS_SPVP _UL(0x00000100) +#define HSTATUS_SPV _UL(0x00000080) +#define HSTATUS_GVA _UL(0x00000040) +#define HSTATUS_VSBE _UL(0x00000020) + +/* HGATP flags */ +#define HGATP_MODE_OFF _UL(0) +#define HGATP_MODE_SV32X4 _UL(1) +#define HGATP_MODE_SV39X4 _UL(8) +#define HGATP_MODE_SV48X4 _UL(9) +#define HGATP_MODE_SV57X4 _UL(10) + +#define HGATP32_MODE_SHIFT 31 +#define HGATP32_VMID_SHIFT 22 +#define HGATP32_VMID GENMASK(28, 22) +#define HGATP32_PPN GENMASK(21, 0) + +#define HGATP64_MODE_SHIFT 60 +#define HGATP64_VMID_SHIFT 44 +#define HGATP64_VMID GENMASK(57, 44) +#define HGATP64_PPN GENMASK(43, 0) + +#define HGATP_PAGE_SHIFT 12 + +#if __riscv_xlen == 64 +#define HGATP_PPN HGATP64_PPN +#define HGATP_VMID_SHIFT HGATP64_VMID_SHIFT +#define HGATP_VMID HGATP64_VMID +#define HGATP_MODE_SHIFT HGATP64_MODE_SHIFT +#else +#define HGATP_PPN HGATP32_PPN +#define HGATP_VMID_SHIFT HGATP32_VMID_SHIFT +#define HGATP_VMID HGATP32_VMID +#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT +#endif + +/* VSIP & HVIP relation */ +#define VSIP_TO_HVIP_SHIFT (IRQ_VS_SOFT - IRQ_S_SOFT) +#define VSIP_VALID_MASK ((_UL(1) << IRQ_S_SOFT) | \ + (_UL(1) << IRQ_S_TIMER) | \ + (_UL(1) << IRQ_S_EXT) | \ + (_UL(1) << IRQ_PMU_OVF)) + +/* AIA CSR bits */ +#define TOPI_IID_SHIFT 16 +#define TOPI_IID_MASK GENMASK(11, 0) +#define TOPI_IPRIO_MASK GENMASK(7, 0) +#define TOPI_IPRIO_BITS 8 + +#define TOPEI_ID_SHIFT 16 +#define TOPEI_ID_MASK GENMASK(10, 0) +#define TOPEI_PRIO_MASK GENMASK(10, 0) + +#define ISELECT_IPRIO0 0x30 +#define ISELECT_IPRIO15 0x3f +#define ISELECT_MASK GENMASK(8, 0) + +#define HVICTL_VTI BIT(30) +#define HVICTL_IID GENMASK(27, 16) +#define HVICTL_IID_SHIFT 16 +#define HVICTL_DPR BIT(9) +#define HVICTL_IPRIOM BIT(8) +#define HVICTL_IPRIO GENMASK(7, 0) + +/* xENVCFG flags */ +#define ENVCFG_STCE (_ULL(1) << 63) +#define ENVCFG_PBMTE (_ULL(1) << 62) +#define ENVCFG_CBZE (_UL(1) << 7) +#define ENVCFG_CBCFE (_UL(1) << 6) +#define ENVCFG_CBIE_SHIFT 4 +#define ENVCFG_CBIE (_UL(0x3) << ENVCFG_CBIE_SHIFT) +#define ENVCFG_CBIE_ILL _UL(0x0) +#define ENVCFG_CBIE_FLUSH _UL(0x1) +#define ENVCFG_CBIE_INV _UL(0x3) +#define ENVCFG_FIOM _UL(0x1) + +/* Smstateen bits */ +#define SMSTATEEN0_AIA_IMSIC_SHIFT 58 +#define SMSTATEEN0_AIA_IMSIC (_ULL(1) << SMSTATEEN0_AIA_IMSIC_SHIFT) +#define SMSTATEEN0_AIA_SHIFT 59 +#define SMSTATEEN0_AIA (_ULL(1) << SMSTATEEN0_AIA_SHIFT) +#define SMSTATEEN0_AIA_ISEL_SHIFT 60 +#define SMSTATEEN0_AIA_ISEL (_ULL(1) << SMSTATEEN0_AIA_ISEL_SHIFT) +#define SMSTATEEN0_HSENVCFG_SHIFT 62 +#define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT) +#define SMSTATEEN0_SSTATEEN0_SHIFT 63 +#define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT) + +/* symbolic CSR names: */ +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f + +#define CSR_SCOUNTOVF 0xda0 + +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 +#define CSR_SENVCFG 0x10a +#define CSR_SSTATEEN0 0x10c +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 +#define CSR_SATP 0x180 + +/* Supervisor-Level Interrupts (CLIC) */ +#define CSR_STVT 0x107 +#define CSR_SNXTI 0x145 + +#define CSR_STIMECMP 0x14d +#define CSR_STIMECMPH 0x15d + +/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ +#define CSR_SISELECT 0x150 +#define CSR_SIREG 0x151 + +/* Supervisor-Level Interrupts (AIA) */ +#define CSR_STOPEI 0x15c +#define CSR_STOPI 0xdb0 + +/* Supervisor-Level High-Half CSRs (AIA) */ +#define CSR_SIEH 0x114 +#define CSR_SIPH 0x154 + +#define CSR_VSSTATUS 0x200 +#define CSR_VSIE 0x204 +#define CSR_VSTVEC 0x205 +#define CSR_VSSCRATCH 0x240 +#define CSR_VSEPC 0x241 +#define CSR_VSCAUSE 0x242 +#define CSR_VSTVAL 0x243 +#define CSR_VSIP 0x244 +#define CSR_VSATP 0x280 +#define CSR_VSTIMECMP 0x24d +#define CSR_VSTIMECMPH 0x25d + +#define CSR_HSTATUS 0x600 +#define CSR_HEDELEG 0x602 +#define CSR_HIDELEG 0x603 +#define CSR_HIE 0x604 +#define CSR_HTIMEDELTA 0x605 +#define CSR_HCOUNTEREN 0x606 +#define CSR_HGEIE 0x607 +#define CSR_HENVCFG 0x60a +#define CSR_HTIMEDELTAH 0x615 +#define CSR_HENVCFGH 0x61a +#define CSR_HTVAL 0x643 +#define CSR_HIP 0x644 +#define CSR_HVIP 0x645 +#define CSR_HTINST 0x64a +#define CSR_HGATP 0x680 +#define CSR_HGEIP 0xe12 + +/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ +#define CSR_HVIEN 0x608 +#define CSR_HVICTL 0x609 +#define CSR_HVIPRIO1 0x646 +#define CSR_HVIPRIO2 0x647 + +/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ +#define CSR_VSISELECT 0x250 +#define CSR_VSIREG 0x251 + +/* VS-Level Interrupts (H-extension with AIA) */ +#define CSR_VSTOPEI 0x25c +#define CSR_VSTOPI 0xeb0 + +/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ +#define CSR_HIDELEGH 0x613 +#define CSR_HVIENH 0x618 +#define CSR_HVIPH 0x655 +#define CSR_HVIPRIO1H 0x656 +#define CSR_HVIPRIO2H 0x657 +#define CSR_VSIEH 0x214 +#define CSR_VSIPH 0x254 + +/* Hypervisor stateen CSRs */ +#define CSR_HSTATEEN0 0x60c +#define CSR_HSTATEEN0H 0x61c + +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MENVCFG 0x30a +#define CSR_MENVCFGH 0x31a +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPADDR0 0x3b0 +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 + +/* Machine-Level Interrupts (CLIC) */ +#define CSR_MTVT 0x307 +#define CSR_MNXTI 0x345 + +/* Machine-Level Window to Indirectly Accessed Registers (AIA) */ +#define CSR_MISELECT 0x350 +#define CSR_MIREG 0x351 + +/* Machine-Level Interrupts (AIA) */ +#define CSR_MTOPEI 0x35c +#define CSR_MTOPI 0xfb0 + +/* Virtual Interrupts for Supervisor Level (AIA) */ +#define CSR_MVIEN 0x308 +#define CSR_MVIP 0x309 + +/* Machine-Level High-Half CSRs (AIA) */ +#define CSR_MIDELEGH 0x313 +#define CSR_MIEH 0x314 +#define CSR_MVIENH 0x318 +#define CSR_MVIPH 0x319 +#define CSR_MIPH 0x354 + +#define CSR_VSTART 0x8 +#define CSR_VCSR 0xf +#define CSR_VL 0xc20 +#define CSR_VTYPE 0xc21 +#define CSR_VLENB 0xc22 + +/* Scalar Crypto Extension - Entropy */ +#define CSR_SEED 0x015 +#define SEED_OPST_MASK _UL(0xc0000000) +#define SEED_OPST_BIST _UL(0x00000000) +#define SEED_OPST_WAIT _UL(0x40000000) +#define SEED_OPST_ES16 _UL(0x80000000) +#define SEED_OPST_DEAD _UL(0xc0000000) +#define SEED_ENTROPY_MASK _UL(0xffff) + +#ifdef ARCH_RISCV_M_MODE +#define CSR_STATUS CSR_MSTATUS +#define CSR_IE CSR_MIE +#define CSR_TVEC CSR_MTVEC +#define CSR_ENVCFG CSR_MENVCFG +#define CSR_SCRATCH CSR_MSCRATCH +#define CSR_EPC CSR_MEPC +#define CSR_CAUSE CSR_MCAUSE +#define CSR_TVAL CSR_MTVAL +#define CSR_IP CSR_MIP +#define CSR_TVT CSR_MTVT +#define CSR_NXTI CSR_MNXTI + +#define CSR_IEH CSR_MIEH +#define CSR_ISELECT CSR_MISELECT +#define CSR_IREG CSR_MIREG +#define CSR_IPH CSR_MIPH +#define CSR_TOPEI CSR_MTOPEI +#define CSR_TOPI CSR_MTOPI + +#define SR_IE SR_MIE +#define SR_PIE SR_MPIE +#define SR_PP SR_MPP + +#define RV_IRQ_SOFT IRQ_M_SOFT +#define RV_IRQ_TIMER IRQ_M_TIMER +#define RV_IRQ_EXT IRQ_M_EXT +#else /* ARCH_RISCV_M_MODE */ +#define CSR_STATUS CSR_SSTATUS +#define CSR_IE CSR_SIE +#define CSR_TVEC CSR_STVEC +#define CSR_ENVCFG CSR_SENVCFG +#define CSR_SCRATCH CSR_SSCRATCH +#define CSR_EPC CSR_SEPC +#define CSR_CAUSE CSR_SCAUSE +#define CSR_TVAL CSR_STVAL +#define CSR_IP CSR_SIP +#define CSR_TVT CSR_STVT +#define CSR_NXTI CSR_SNXTI + +#define CSR_IEH CSR_SIEH +#define CSR_ISELECT CSR_SISELECT +#define CSR_IREG CSR_SIREG +#define CSR_IPH CSR_SIPH +#define CSR_TOPEI CSR_STOPEI +#define CSR_TOPI CSR_STOPI + +#define SR_IE SR_SIE +#define SR_PIE SR_SPIE +#define SR_PP SR_SPP + +#define RV_IRQ_SOFT IRQ_S_SOFT +#define RV_IRQ_TIMER IRQ_S_TIMER +#define RV_IRQ_EXT IRQ_S_EXT +#define RV_IRQ_PMU IRQ_PMU_OVF +#define SIP_LCOFIP (_AC(0x1, UL) << IRQ_PMU_OVF) +#endif /* !ARCH_RISCV_M_MODE */ + +/* IE/IP (Supervisor/Machine Interrupt Enable/Pending) flags */ +#define IE_SIE (_UL(0x1) << RV_IRQ_SOFT) +#define IE_TIE (_UL(0x1) << RV_IRQ_TIMER) +#define IE_EIE (_UL(0x1) << RV_IRQ_EXT) + +#ifndef __ASSEMBLY__ + +#ifdef __GNUC__ +#define csr_swap(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrw %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_read(csr) \ +({ \ + register rt_ubase_t __v; \ + __asm__ volatile ("csrr %0, " __ASM_STR(csr) \ + : "=r" (__v) : \ + : "memory"); \ + __v; \ +}) + +#define csr_write(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrw " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_set(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrs %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_read_or(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrsi %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "i" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_set(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrs " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_clear(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrc %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_clear(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrc " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) +#endif /* __GNUC__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* __CSR_H__ */ diff --git a/libcpu/risc-v/common/include/interrupt.h b/libcpu/risc-v/common/include/interrupt.h new file mode 100644 index 0000000000..d7cbb2a3f3 --- /dev/null +++ b/libcpu/risc-v/common/include/interrupt.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-01 Bernard The first version + * 2025-04-20 GuEe-GUI Port for not DM + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include <rthw.h> + +#ifndef RT_USING_DM +#ifdef RT_USING_ADT_BITMAP +#include <bitmap.h> + +#define RISCV_PLIC_QUIRK_EDGE_INTERRUPT RT_BIT(0) + +#define RISCV_CLIC_QUIRK_MODE_FIXED RT_BIT(0) +#define RISCV_CLIC_QUIRK_MINTTHRESH RT_BIT(1) +#define RISCV_CLIC_QUIRK_SHV RT_BIT(2) +#endif /* RT_USING_ADT_BITMAP */ + +#define INTC_TYPE_RISCV 0 +#define INTC_TYPE_ANDESTECH 1 +#define INTC_TYPE_CLIC 2 + +#define IRQ_INTC(vector) (vector) +#ifdef RT_USING_SMP +#define IPI_INTC(vector) (ipi_intc_base + (vector)) +#endif + +#define IRQ_PLIC(vector) (irq_plic_base + (vector)) + +#define IRQ_CLIC(vector) (vector) +#ifdef RT_USING_SMP +#define IPI_CLIC(vector) (ipi_clic_base + (vector)) +extern int ipi_intc_base; +extern int ipi_clic_base; +#endif +extern int irq_plic_base; + +rt_ubase_t platform_get_plic_base(void); +rt_size_t platform_get_plic_size(void); +rt_ubase_t platform_get_plic_quirks(void); +rt_ubase_t platform_get_clic_base(void); +rt_size_t platform_get_clic_size(void); +rt_ubase_t platform_get_clic_quirks(void); + +#ifdef ARCH_RISCV_M_MODE +rt_ubase_t platform_get_clint_base(void); +rt_size_t platform_get_clint_size(void); +#endif + +#endif /* !RT_USING_DM */ + +#ifdef RT_USING_SMP +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler); +#endif + +void rt_hw_interrupt_handle(rt_uint32_t vector, void *param); + +#endif /* __INTERRUPT_H__ */ diff --git a/libcpu/risc-v/common/include/isa_ext.h b/libcpu/risc-v/common/include/isa_ext.h new file mode 100644 index 0000000000..f806421aba --- /dev/null +++ b/libcpu/risc-v/common/include/isa_ext.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __ISA_EXT_H__ +#define __ISA_EXT_H__ + +#include <rtdef.h> + +#define RISCV_ISA_EXT_I 0 +#define RISCV_ISA_EXT_M 1 +#define RISCV_ISA_EXT_A 2 +#define RISCV_ISA_EXT_F 3 +#define RISCV_ISA_EXT_D 4 +#define RISCV_ISA_EXT_Q 5 +#define RISCV_ISA_EXT_C 6 +#define RISCV_ISA_EXT_V 7 +#define RISCV_ISA_EXT_H 8 + +#define RISCV_ISA_EXT_BASE 26 + +#define RISCV_ISA_EXT_SSCOFPMF 26 +#define RISCV_ISA_EXT_SSTC 27 +#define RISCV_ISA_EXT_SVINVAL 28 +#define RISCV_ISA_EXT_SVPBMT 29 +#define RISCV_ISA_EXT_ZBB 30 +#define RISCV_ISA_EXT_ZICBOM 31 +#define RISCV_ISA_EXT_ZIHINTPAUSE 32 +#define RISCV_ISA_EXT_SVNAPOT 33 +#define RISCV_ISA_EXT_ZICBOZ 34 +#define RISCV_ISA_EXT_SMAIA 35 +#define RISCV_ISA_EXT_SSAIA 36 +#define RISCV_ISA_EXT_ZBA 37 +#define RISCV_ISA_EXT_ZBS 38 +#define RISCV_ISA_EXT_ZICNTR 39 +#define RISCV_ISA_EXT_ZICSR 40 +#define RISCV_ISA_EXT_ZIFENCEI 41 +#define RISCV_ISA_EXT_ZIHPM 42 +#define RISCV_ISA_EXT_SMSTATEEN 43 +#define RISCV_ISA_EXT_ZICOND 44 +#define RISCV_ISA_EXT_ZBC 45 +#define RISCV_ISA_EXT_ZBKB 46 +#define RISCV_ISA_EXT_ZBKC 47 +#define RISCV_ISA_EXT_ZBKX 48 +#define RISCV_ISA_EXT_ZKND 49 +#define RISCV_ISA_EXT_ZKNE 50 +#define RISCV_ISA_EXT_ZKNH 51 +#define RISCV_ISA_EXT_ZKR 52 +#define RISCV_ISA_EXT_ZKSED 53 +#define RISCV_ISA_EXT_ZKSH 54 +#define RISCV_ISA_EXT_ZKT 55 +#define RISCV_ISA_EXT_ZVBB 56 +#define RISCV_ISA_EXT_ZVBC 57 +#define RISCV_ISA_EXT_ZVKB 58 +#define RISCV_ISA_EXT_ZVKG 59 +#define RISCV_ISA_EXT_ZVKNED 60 +#define RISCV_ISA_EXT_ZVKNHA 61 +#define RISCV_ISA_EXT_ZVKNHB 62 +#define RISCV_ISA_EXT_ZVKSED 63 +#define RISCV_ISA_EXT_ZVKSH 64 +#define RISCV_ISA_EXT_ZVKT 65 +#define RISCV_ISA_EXT_ZFH 66 +#define RISCV_ISA_EXT_ZFHMIN 67 +#define RISCV_ISA_EXT_ZIHINTNTL 68 +#define RISCV_ISA_EXT_ZVFH 69 +#define RISCV_ISA_EXT_ZVFHMIN 70 +#define RISCV_ISA_EXT_ZFA 71 +#define RISCV_ISA_EXT_ZTSO 72 +#define RISCV_ISA_EXT_ZACAS 73 +#define RISCV_ISA_EXT_XANDESPMU 74 + +#define RISCV_ISA_EXT_MAX 75 +#define RISCV_ISA_EXT_INVALID RT_UINT32_MAX + +#ifdef ARCH_RISCV_M_MODE +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA +#else +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA +#endif + +void riscv_isa_ext_set_raw(rt_uint32_t isa); +void riscv_isa_ext_clear_raw(rt_uint32_t isa); +rt_bool_t riscv_isa_ext_test_raw(rt_uint32_t isa); + +#define riscv_isa_ext_set(isa) riscv_isa_ext_set_raw(RISCV_ISA_EXT_##isa) +#define riscv_isa_ext_clear(isa) riscv_isa_ext_clear_raw(RISCV_ISA_EXT_##isa) +#define riscv_isa_ext_test(isa) riscv_isa_ext_test_raw(RISCV_ISA_EXT_##isa) + +#endif /* __ISA_EXT_H__ */ diff --git a/libcpu/risc-v/common/include/mmu.h b/libcpu/risc-v/common/include/mmu.h new file mode 100644 index 0000000000..286143ecdf --- /dev/null +++ b/libcpu/risc-v/common/include/mmu.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2023-10-12 Shell Add permission control API + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __MMU_H__ +#define __MMU_H__ + +#include <page_def.h> +#include <asm-generic.h> + +#ifndef __ASSEMBLY__ +#include <mm_aspace.h> + +/* Normal memory wra mapping type */ +#define NORMAL_MEM 0 +/* Normal nocache memory mapping type */ +#define NORMAL_NOCACHE_MEM 1 +/* Device mapping type */ +#define DEVICE_MEM 2 + +struct mem_desc +{ + unsigned long vaddr_start; + unsigned long vaddr_end; + unsigned long paddr_start; + unsigned long attr; + struct rt_varea varea; +}; + +#ifdef __HAS_MMU_VENDOR__ +#include <mmu_vendor.h> +#endif + +#endif /* !__ASSEMBLY__ */ + +#define RT_HW_MMU_PROT_READ 1 +#define RT_HW_MMU_PROT_WRITE 2 +#define RT_HW_MMU_PROT_EXECUTE 4 +#define RT_HW_MMU_PROT_KERNEL 8 +#define RT_HW_MMU_PROT_USER 16 +#define RT_HW_MMU_PROT_CACHE 32 + +/* Page table entry (PTE) fields */ +#define PTE_V BIT(0) /* Valid */ +#define PTE_R BIT(1) /* Read */ +#define PTE_W BIT(2) /* Write */ +#define PTE_X BIT(3) /* Execute */ +#define PTE_U BIT(4) /* User */ +#define PTE_G BIT(5) /* Global */ +#define PTE_A BIT(6) /* Accessed */ +#define PTE_D BIT(7) /* Dirty */ +#define PTE_SOFT GENMASK(9, 8) /* Reserved for Software */ + +#define PTE_BITS 10 +#if __riscv_xlen == 32 +#define PTE_PPN_MASK GENMASK(31, 10) +#else +#define PTE_PPN_MASK GENMASK(53, 10) +#endif + +#define PTE_ATTR_NONE _UL(0) +#define PTE_ATTR_RW (PTE_R | PTE_W) +#define PTE_ATTR_RWX (PTE_ATTR_RW | PTE_X) +#define PTE_ATTR_KERNEL (PTE_V | PTE_ATTR_RWX | PTE_A | PTE_D) +#define PTE_ATTR_USER (PTE_ATTR_KERNEL | PTE_U) + +#if !defined(__HAS_MMU_VENDOR__) && __riscv_xlen != 32 +#define SVPBMT_SHIFT 61 /* ISA SVPBMT */ + +#define PTE_VENDOR_PMA (0x0ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_NOCACHE (0x1ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_IO (0x2ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_MTMASK (0x3ULL << SVPBMT_SHIFT) +#endif /* !__HAS_MMU_VENDOR__ && __riscv_xlen != 32 */ + +#ifndef PTE_VENDOR_PMA +#define PTE_VENDOR_PMA PTE_ATTR_NONE +#endif + +#ifndef PTE_VENDOR_NOCACHE +#define PTE_VENDOR_NOCACHE PTE_ATTR_NONE +#endif + +#ifndef PTE_VENDOR_IO +#define PTE_VENDOR_IO PTE_ATTR_NONE +#endif +#ifndef PTE_VENDOR_MTMASK +#define PTE_VENDOR_MTMASK PTE_ATTR_NONE +#endif + +#ifndef MMU_VENDOR_MAP_K_ROCB +#define MMU_VENDOR_MAP_K_ROCB ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_K_RO +#define MMU_VENDOR_MAP_K_RO ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_K_RWCB +#define MMU_VENDOR_MAP_K_RWCB (PTE_ATTR_KERNEL | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_K_RW +#define MMU_VENDOR_MAP_K_RW (PTE_ATTR_KERNEL | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_K_DEVICE +#define MMU_VENDOR_MAP_K_DEVICE ((PTE_ATTR_KERNEL & ~PTE_X) | PTE_VENDOR_IO) +#endif +#ifndef MMU_VENDOR_MAP_U_ROCB +#define MMU_VENDOR_MAP_U_ROCB ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_U_RO +#define MMU_VENDOR_MAP_U_RO ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_U_RWCB +#define MMU_VENDOR_MAP_U_RWCB (PTE_ATTR_USER | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_U_RW +#define MMU_VENDOR_MAP_U_RW (PTE_ATTR_USER | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_U_DEVICE +#define MMU_VENDOR_MAP_U_DEVICE ((PTE_ATTR_USER & ~PTE_X) | PTE_VENDOR_IO) +#endif +#ifndef MMU_VENDOR_MAP_EARLY +#define MMU_VENDOR_MAP_EARLY (PTE_RWX | PTE_G | PTE_V) +#endif + +#define MMU_MAP_K_ROCB MMU_VENDOR_MAP_K_ROCB +#define MMU_MAP_K_RO MMU_VENDOR_MAP_K_RO +#define MMU_MAP_K_RWCB MMU_VENDOR_MAP_K_RWCB +#define MMU_MAP_K_RW MMU_VENDOR_MAP_K_RW +#define MMU_MAP_K_DEVICE MMU_VENDOR_MAP_K_DEVICE +#define MMU_MAP_U_ROCB MMU_VENDOR_MAP_U_ROCB +#define MMU_MAP_U_RO MMU_VENDOR_MAP_U_RO +#define MMU_MAP_U_RWCB MMU_VENDOR_MAP_U_RWCB +#define MMU_MAP_U_RW MMU_VENDOR_MAP_U_RW +#define MMU_MAP_U_DEVICE MMU_VENDOR_MAP_U_DEVICE + +#define MMU_MAP_ERROR_VANOTALIGN -1 +#define MMU_MAP_ERROR_PANOTALIGN -2 +#define MMU_MAP_ERROR_NOPAGE -3 +#define MMU_MAP_ERROR_CONFLICT -4 + +#ifdef RT_PAGE_MPR_SIZE_DYNAMIC +#define ARCH_VADDR_WIDTH rt_hw_arch_vaddr_width +#elif __riscv_xlen == 32 +#define ARCH_VADDR_WIDTH 32 +#elif defined(ARCH_MM_MMU_SV48) +#define ARCH_VADDR_WIDTH 48 +#elif defined(ARCH_MM_MMU_SV57) +#define ARCH_VADDR_WIDTH 57 +#else +#define ARCH_VADDR_WIDTH 39 +#endif +#define ARCH_ADDRESS_WIDTH_BITS __riscv_xlen + +#define ARCH_MAP_FAILED _AT(void *, _ULL(-1)) + +#define ARCH_EARLY_MAP_SIZE 0x80000000 + +#ifndef __ASSEMBLY__ + +struct rt_aspace; + +extern rt_uint8_t rt_hw_arch_vaddr_width; + +void *rt_hw_mmu_tbl_get(void); +void rt_hw_mmu_tbl_set(rt_ubase_t tbl); +int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, + rt_ubase_t *vtable, rt_ubase_t pv_off); +void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr); +void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size, + size_t attr); +void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size); +void rt_hw_aspace_switch(rt_aspace_t aspace); +void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr); + +int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, + enum rt_mmu_cntl cmd); + +void *rt_hw_mmu_pgtbl_create(void); +void rt_hw_mmu_pgtbl_delete(void *pgtbl); + +#ifndef MMU_VENDOR_ATTR_RM_PERM_IMPL +/** + * @brief Remove permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be removed + * @return size_t returned attribution + */ +rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, rt_base_t prot) +{ + switch (prot) + { + /* remove write permission for user */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + attr &= ~PTE_W; + break; + /* remove write permission for kernel */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + attr &= ~PTE_W; + break; + default: + RT_ASSERT(0); + } + return attr; +} +#endif /* MMU_VENDOR_ATTR_RM_PERM_IMPL */ + +#ifndef MMU_VENDOR_ATTR_ADD_PERM_IMPL +/** + * @brief Add permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be added + * @return size_t returned attribution + */ +rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot) +{ + switch (prot) + { + /* add write permission for user */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + attr |= (PTE_R | PTE_W | PTE_U); + break; + default: + RT_ASSERT(0); + } + return attr; +} +#endif /* MMU_VENDOR_ATTR_ADD_PERM_IMPL */ + +#ifndef MMU_VENDOR_ATTR_TEST_PERM_IMPL +/** + * @brief Test permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be test + * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE + */ +rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) +{ + rt_bool_t rc = 0; + + switch (prot & ~RT_HW_MMU_PROT_USER) + { + /* test write permission for user */ + case RT_HW_MMU_PROT_WRITE: + rc = ((attr & PTE_W) && (attr & PTE_R)); + break; + case RT_HW_MMU_PROT_READ: + rc = !!(attr & PTE_R); + break; + case RT_HW_MMU_PROT_EXECUTE: + rc = !!(attr & PTE_X); + break; + default: + RT_ASSERT(0); + } + + if (rc && (prot & RT_HW_MMU_PROT_USER)) + { + rc = !!(attr & PTE_U); + } + return rc; +} +#endif /* MMU_VENDOR_ATTR_TEST_PERM_IMPL */ + +#endif /* !__ASSEMBLY__ */ + +#endif /* __MMU_H__ */ diff --git a/libcpu/risc-v/common/include/opcode.h b/libcpu/risc-v/common/include/opcode.h new file mode 100644 index 0000000000..f98b529d48 --- /dev/null +++ b/libcpu/risc-v/common/include/opcode.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-09 Shell Add portable asm support + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __OPCODE_H__ +#define __OPCODE_H__ + +#include <rtcompiler.h> + +#include <asm-generic.h> +#ifdef __HAS_OPCODE_VENDOR__ +#include <opcode_vendor.h> +#endif + +/** + * @brief binary opcode pseudo operations + * Used to bypass toolchain restriction on extension ISA + * + */ + +/** + * @brief RISC-V instruction formats + */ + +#define OPCODE_MISC_MEM 15 +#define OPCODE_SYSTEM 115 + +#ifndef __OPC_INSN_FORMAT_R +/** + * R type: .insn r opcode6, func3, func7, rd, rs1, rs2 + * + * +-------+-----+-----+-------+----+---------+ + * | func7 | rs2 | rs1 | func3 | rd | opcode6 | + * +-------+-----+-----+-------+----+---------+ + * 31 25 20 15 12 7 0 + */ +#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \ + ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2)"\n\t" +#endif /* !__OPC_INSN_FORMAT_R */ + +#ifndef __OPC_INSN_FORMAT_I +/** + * I type: .insn i opcode6, func3, rd, rs1, simm12 + * + * +--------+-----+-------+----+---------+ + * | simm12 | rs1 | func3 | rd | opcode6 | + * +--------+-----+-------+----+---------+ + * 31 20 15 12 7 0 + */ +#define __OPC_INSN_FORMAT_I(opcode, func3, rd, rs1, simm12) \ + ".insn i "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(simm12)"\n\t" +#endif /* !__OPC_INSN_FORMAT_I */ + +#ifndef OPC_CBO_INVAL +#define OPC_CBO_INVAL(base) __OPC_INSN_FORMAT_I(OPCODE_MISC_MEM, 2, x0, base, 0) +#endif + +#ifndef OPC_CBO_CLEAN +#define OPC_CBO_CLEAN(base) __OPC_INSN_FORMAT_I(OPCODE_MISC_MEM, 2, x0, base, 1) +#endif + +#ifndef OPC_FENCE_I +#ifdef ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA +#define OPC_FENCE_I __ASM_STR(fence.i) +#else /* !ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA */ +#define OPC_FENCE_I __ASM_STR(.long 0x0000100f) +#endif /* ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA */ +#endif /* !OPC_FENCE_I */ + +#ifndef OPC_PAUSE_I +#ifdef ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE +#define OPC_PAUSE_I __ASM_STR(pause) +#else /* !ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE */ +#define OPC_PAUSE_I __ASM_STR(.4byte 0x0100000f) +#endif /* ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE */ +#endif /* !OPC_PAUSE_I */ + +#endif /* __OPCODE_H__ */
\ No newline at end of file diff --git a/libcpu/risc-v/common/include/page_def.h b/libcpu/risc-v/common/include/page_def.h new file mode 100644 index 0000000000..0b70d3084e --- /dev/null +++ b/libcpu/risc-v/common/include/page_def.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __PAGE_DEF_H__ +#define __PAGE_DEF_H__ + +#include <asm-generic.h> + +#ifndef ARCH_PAGE_SHIFT +#define ARCH_PAGE_SHIFT 12 +#elif ARCH_PAGE_SHIFT != 12 +#warning Make sure you fully understand what you are doing +#endif +#define ARCH_PAGE_SIZE (_UL(1) << ARCH_PAGE_SHIFT) +#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1) + +#if __riscv_xlen == 32 +#define SUPPER_PAGE_SIZE 0x400000 +#else +#define SUPPER_PAGE_SIZE 0x200000 +#endif +#define SUPPER_PAGE_MASK (SUPPER_PAGE_SIZE - 1) + +#endif /* __PAGE_DEF_H__ */ diff --git a/libcpu/risc-v/common/include/riscv_timer.h b/libcpu/risc-v/common/include/riscv_timer.h new file mode 100644 index 0000000000..d02e2170bf --- /dev/null +++ b/libcpu/risc-v/common/include/riscv_timer.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-28 Bernard The unify RISC-V porting code. + */ + +#ifndef __RISCV_TIMER_H__ +#define __RISCV_TIMER_H__ + +#include <rtdef.h> + +void riscv_timer_set_frequency(rt_uint32_t freq); +rt_uint32_t riscv_timer_get_frequency(void); + +rt_uint64_t riscv_timer_rdtime(void); +void riscv_timer_set_compare(rt_uint64_t value); + +void riscv_timer_isr(void); + +void riscv_timer_init(void); +void riscv_timer_probe(void *clint_timer_cmp, void *clint_timer_val); + +void riscv_timer_us_delay(rt_uint32_t us); + +#endif /* __RISCV_TIMER_H__ */ diff --git a/libcpu/risc-v/common/include/sbi.h b/libcpu/risc-v/common/include/sbi.h new file mode 100644 index 0000000000..2ed5aa3daa --- /dev/null +++ b/libcpu/risc-v/common/include/sbi.h @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Bernard port from FreeBSD + */ + +/*- + * Copyright (c) 2016-2017 Ruslan Bukin <[email protected]> + * All rights reserved. + * Copyright (c) 2019 Mitchell Horne <[email protected]> + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SBI_H_ +#define _MACHINE_SBI_H_ + +#include <stdint.h> +#include <stdbool.h> +#include <rtdef.h> + +/* SBI Specification Version */ +#define SBI_SPEC_VERS_MAJOR_OFFSET 24 +#define SBI_SPEC_VERS_MAJOR_MASK (0x7F << SBI_SPEC_VERS_MAJOR_OFFSET) +#define SBI_SPEC_VERS_MINOR_OFFSET 0 +#define SBI_SPEC_VERS_MINOR_MASK (0xFFFFFF << SBI_SPEC_VERS_MINOR_OFFSET) + +/* SBI Implementation IDs */ +#define SBI_IMPL_ID_BBL 0 +#define SBI_IMPL_ID_OPENSBI 1 +#define SBI_IMPL_ID_XVISOR 2 +#define SBI_IMPL_ID_KVM 3 +#define SBI_IMPL_ID_RUSTSBI 4 +#define SBI_IMPL_ID_DIOSIX 5 + +/* SBI Error Codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 +#define SBI_ERR_ALREADY_AVAILABLE -6 + +/* SBI Base Extension */ +#define SBI_EXT_ID_BASE 0x10 +#define SBI_BASE_GET_SPEC_VERSION 0 +#define SBI_BASE_GET_IMPL_ID 1 +#define SBI_BASE_GET_IMPL_VERSION 2 +#define SBI_BASE_PROBE_EXTENSION 3 +#define SBI_BASE_GET_MVENDORID 4 +#define SBI_BASE_GET_MARCHID 5 +#define SBI_BASE_GET_MIMPID 6 + +/* Timer (TIME) Extension */ +#define SBI_EXT_ID_TIME 0x54494D45 +#define SBI_TIME_SET_TIMER 0 + +/* IPI (IPI) Extension */ +#define SBI_EXT_ID_IPI 0x735049 +#define SBI_IPI_SEND_IPI 0 + +/* RFENCE (RFNC) Extension */ +#define SBI_EXT_ID_RFNC 0x52464E43 +#define SBI_RFNC_REMOTE_FENCE_I 0 +#define SBI_RFNC_REMOTE_SFENCE_VMA 1 +#define SBI_RFNC_REMOTE_SFENCE_VMA_ASID 2 +#define SBI_RFNC_REMOTE_HFENCE_GVMA_VMID 3 +#define SBI_RFNC_REMOTE_HFENCE_GVMA 4 +#define SBI_RFNC_REMOTE_HFENCE_VVMA_ASID 5 +#define SBI_RFNC_REMOTE_HFENCE_VVMA 6 + +#define SBI_EXT_ID_SRST 0x53525354 +#define SBI_SRST_FID_RESET 0 +#define SBI_SRST_RESET_TYPE_SHUTDOWN 0 +#define SBI_SRST_RESET_TYPE_COLD_REBOOT 1 +#define SBI_SRST_RESET_TYPE_WARM_REBOOT 2 +#define SBI_SRST_RESET_REASON_NONE 0 +#define SBI_SRST_RESET_REASON_SYS_FAILURE 1 + +/* Hart State Management (HSM) Extension */ +#define SBI_EXT_ID_HSM 0x48534D +#define SBI_HSM_HART_START 0 +#define SBI_HSM_HART_STOP 1 +#define SBI_HSM_HART_STATUS 2 +#define SBI_HSM_STATUS_STARTED 0 +#define SBI_HSM_STATUS_STOPPED 1 +#define SBI_HSM_STATUS_START_PENDING 2 +#define SBI_HSM_STATUS_STOP_PENDING 3 + +#define SBI_HART_MASK_BASE_ALL (~0UL) + +/* Legacy Extensions */ +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CALL0(e, f) SBI_CALL5(e, f, 0, 0, 0, 0, 0) +#define SBI_CALL1(e, f, p1) SBI_CALL5(e, f, p1, 0, 0, 0, 0) +#define SBI_CALL2(e, f, p1, p2) SBI_CALL5(e, f, p1, p2, 0, 0, 0) +#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL5(e, f, p1, p2, p3, 0, 0) +#define SBI_CALL4(e, f, p1, p2, p3, p4) SBI_CALL5(e, f, p1, p2, p3, p4, 0) +#define SBI_CALL5(e, f, p1, p2, p3, p4, p5) sbi_call(e, f, p1, p2, p3, p4, p5) + +/* + * Documentation available at + * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc + */ + +struct sbi_ret +{ + long error; + long value; +}; + +rt_inline struct sbi_ret +sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3, uint64_t arg4) +{ + struct sbi_ret ret; + + register uintptr_t a0 __asm("a0") = (uintptr_t)(arg0); + register uintptr_t a1 __asm("a1") = (uintptr_t)(arg1); + register uintptr_t a2 __asm("a2") = (uintptr_t)(arg2); + register uintptr_t a3 __asm("a3") = (uintptr_t)(arg3); + register uintptr_t a4 __asm("a4") = (uintptr_t)(arg4); + register uintptr_t a6 __asm("a6") = (uintptr_t)(arg6); + register uintptr_t a7 __asm("a7") = (uintptr_t)(arg7); + + __asm __volatile(\ + "ecall" \ + : "+r"(a0), "+r"(a1) \ + : "r"(a2), "r"(a3), "r"(a4), "r"(a6), "r"(a7) \ + : "memory"); + + ret.error = a0; + ret.value = a1; + return (ret); +} + +/* Base extension functions and variables. */ +extern unsigned long sbi_spec_version; +extern unsigned long sbi_impl_id; +extern unsigned long sbi_impl_version; + +extern bool has_time_extension; +extern bool has_ipi_extension; +extern bool has_rfnc_extension; +extern bool has_srst_extension; + +static __inline long +sbi_probe_extension(long id) +{ + return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); +} + +/* TIME extension functions. */ +void sbi_set_timer(uint64_t val); + +/* IPI extension functions. */ +void sbi_send_ipi(const unsigned long *cpu_mask); + +/* RFENCE extension functions. */ +void sbi_remote_fence_i(const unsigned long *cpu_mask); +int sbi_remote_sfence_vma(const unsigned long *hart_mask, + const unsigned long hart_mask_base, + unsigned long start, unsigned long size); +void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, + unsigned long size, unsigned long asid); + +/* Hart State Management extension functions. */ + +/* + * Start execution on the specified hart at physical address start_addr. The + * register a0 will contain the hart's ID, and a1 will contain the value of + * priv. + */ +int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv); + +/* + * Stop execution on the current hart. Interrupts should be disabled, or this + * function may return. + */ +void sbi_hsm_hart_stop(void); + +/* + * Get the execution status of the specified hart. The status will be one of: + * - SBI_HSM_STATUS_STARTED + * - SBI_HSM_STATUS_STOPPED + * - SBI_HSM_STATUS_START_PENDING + * - SBI_HSM_STATUS_STOP_PENDING + */ +int sbi_hsm_hart_status(unsigned long hart); + +/* + * Reboot the system. The type will be one of: + * - SBI_SRST_RESET_TYPE_WARM_REBOOT + * - SBI_SRST_RESET_TYPE_COLD_REBOOT + */ +void sbi_srst_reboot(unsigned long reset_type); + +/* + * Power off the system. + */ +void sbi_srst_power_off(void); + +/* Legacy extension functions. */ +static __inline void +sbi_console_putchar(int ch) +{ + (void)SBI_CALL1(SBI_CONSOLE_PUTCHAR, 0, ch); +} + +static __inline int +sbi_console_getchar(void) +{ + /* + * XXX: The "error" is returned here because legacy SBI functions + * continue to return their value in a0. + */ + return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error); +} + +static __inline void +sbi_shutdown(void) +{ + (void)SBI_CALL0(SBI_SHUTDOWN, 0); +} + +void sbi_print_version(void); +void sbi_init(void); + +#endif /* !_MACHINE_SBI_H_ */ diff --git a/libcpu/risc-v/common/include/setup.h b/libcpu/risc-v/common/include/setup.h new file mode 100644 index 0000000000..8f9f432c76 --- /dev/null +++ b/libcpu/risc-v/common/include/setup.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-21 GuEe-GUI first version + */ + +#ifndef __SETUP_H__ +#define __SETUP_H__ + +void rt_hw_fdt_install_early(void *fdt); +void rt_hw_common_setup(void); + +#endif /* __SETUP_H__ */ diff --git a/libcpu/risc-v/common/include/stack.h b/libcpu/risc-v/common/include/stack.h new file mode 100644 index 0000000000..c7d531eea0 --- /dev/null +++ b/libcpu/risc-v/common/include/stack.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2021-11-18 JasonHu add fpu member + * 2022-10-22 Shell Support kernel mode RVV + */ + +#ifndef __STACK_H__ +#define __STACK_H__ + +#include <rtconfig.h> + +#include <context_ext.h> + +#ifndef __ASSEMBLY__ +#include <rtdef.h> +#endif + +#ifdef ARCH_RISCV_FPU + #define K_XSTATUS_EXT SR_FS +#else + #define K_XSTATUS_EXT 0 +#endif + +#ifdef ARCH_RISCV_M_MODE + #define K_XSTATUS_DEFAULT_BASE (SR_PP | SR_PIE | K_XSTATUS_EXT) +#else + #define K_XSTATUS_DEFAULT_BASE (SR_PP | SR_PIE | SR_SUM | K_XSTATUS_EXT) +#endif + +#ifdef ARCH_RISCV_VECTOR + #define K_XSTATUS_DEFAULT (K_XSTATUS_DEFAULT_BASE | SR_VS) +#else + #define K_XSTATUS_DEFAULT K_XSTATUS_DEFAULT_BASE +#endif + +#ifdef ARCH_RISCV_32E + #define CTX_GENERAL_REG_NR 18 + #define FRAME_OFF_SP (17 * SZREG) +#else + #define CTX_GENERAL_REG_NR 34 + #define FRAME_OFF_SP (33 * SZREG) +#endif +#define CTX_ALL_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR + CTX_VECTOR_REG_NR) + +#define FRAME_OFF_XSTATUS (2 * SZREG) +#define FRAME_OFF_XCAUSE (3 * SZREG) +#define FRAME_OFF_GP (4 * SZREG) +#define FRAME_OFF_TP (5 * SZREG) +#define FRAME_OFF_A7 (18 * SZREG) + +/* Switch frame */ +#define RT_HW_SWITCH_CONTEXT_XSTATUS 0 +#define RT_HW_SWITCH_CONTEXT_S1 1 +#define RT_HW_SWITCH_CONTEXT_S0 2 +#define RT_HW_SWITCH_CONTEXT_RA 3 +#define RT_HW_SWITCH_CONTEXT_TP 4 +#ifdef ARCH_RISCV_32E +#define RT_HW_SWITCH_CONTEXT_SIZE 8 /* Padding for alignment */ +#else +#define RT_HW_SWITCH_CONTEXT_S2 5 +#define RT_HW_SWITCH_CONTEXT_S3 6 +#define RT_HW_SWITCH_CONTEXT_S4 7 +#define RT_HW_SWITCH_CONTEXT_S5 8 +#define RT_HW_SWITCH_CONTEXT_S6 9 +#define RT_HW_SWITCH_CONTEXT_S7 10 +#define RT_HW_SWITCH_CONTEXT_S8 11 +#define RT_HW_SWITCH_CONTEXT_S9 12 +#define RT_HW_SWITCH_CONTEXT_S10 13 +#define RT_HW_SWITCH_CONTEXT_S11 14 +#define RT_HW_SWITCH_CONTEXT_SIZE 16 /* Padding for alignment */ +#endif + +#ifndef __ASSEMBLY__ +typedef struct rt_hw_switch_frame +{ + rt_ubase_t regs[RT_HW_SWITCH_CONTEXT_SIZE]; +} *rt_hw_switch_frame_t; + +RT_STATIC_ASSERT(riscv_switch_frame_size, + sizeof(struct rt_hw_switch_frame) == RT_HW_SWITCH_CONTEXT_SIZE * sizeof(rt_ubase_t)); + +#ifdef ARCH_RISCV_USING_IRQ_STACK +void riscv_irq_stack_init(void); +void *riscv_irq_stack_top(void); +#endif + +struct rt_hw_stack_frame +{ + rt_ubase_t epc; /* epc - epc - program counter */ + rt_ubase_t ra; /* x1 - ra - return address for jumps */ + rt_ubase_t xstatus; /* - supervisor/machine status register */ + rt_ubase_t xcause; /* - supervisor/machine cause register */ + rt_ubase_t gp; /* x3 - gp - global pointer */ + rt_ubase_t tp; /* x4 - tp - thread pointer */ + rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ + rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ + rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ + rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ + rt_ubase_t s1; /* x9 - s1 - saved register 1 */ + rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ + rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ + rt_ubase_t a2; /* x12 - a2 - function argument 2 */ + rt_ubase_t a3; /* x13 - a3 - function argument 3 */ + rt_ubase_t a4; /* x14 - a4 - function argument 4 */ + rt_ubase_t a5; /* x15 - a5 - function argument 5 */ +#ifndef ARCH_RISCV_32E + rt_ubase_t a6; /* x16 - a6 - function argument 6 */ + rt_ubase_t a7; /* x17 - s7 - function argument 7 */ + rt_ubase_t s2; /* x18 - s2 - saved register 2 */ + rt_ubase_t s3; /* x19 - s3 - saved register 3 */ + rt_ubase_t s4; /* x20 - s4 - saved register 4 */ + rt_ubase_t s5; /* x21 - s5 - saved register 5 */ + rt_ubase_t s6; /* x22 - s6 - saved register 6 */ + rt_ubase_t s7; /* x23 - s7 - saved register 7 */ + rt_ubase_t s8; /* x24 - s8 - saved register 8 */ + rt_ubase_t s9; /* x25 - s9 - saved register 9 */ + rt_ubase_t s10; /* x26 - s10 - saved register 10 */ + rt_ubase_t s11; /* x27 - s11 - saved register 11 */ + rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ + rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ + rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ + rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ +#endif /* !ARCH_RISCV_32E */ + + rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */ + +#ifdef ARCH_RISCV_FPU + rt_ubase_t f[CTX_FPU_REG_NR]; /* f0~f31 */ +#endif +#ifdef ARCH_RISCV_VECTOR + rt_ubase_t v[CTX_VECTOR_REG_NR]; +#endif +}; + +RT_STATIC_ASSERT(riscv_trap_frame_size, + sizeof(struct rt_hw_stack_frame) == CTX_ALL_REG_NR * sizeof(rt_ubase_t)); +#endif /* __ASSEMBLY__ */ + +#endif /* __STACK_H__ */ diff --git a/libcpu/risc-v/common/include/tlb.h b/libcpu/risc-v/common/include/tlb.h new file mode 100644 index 0000000000..72e3029e08 --- /dev/null +++ b/libcpu/risc-v/common/include/tlb.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-28 WangXiaoyao the first version + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __TLB_H__ +#define __TLB_H__ + +#include <rtthread.h> + +#include <csr.h> +#include <sbi.h> +#include <page_def.h> +#include <mm_aspace.h> + +#ifdef ARCH_USING_ASID +/* Implemented ASID bits, discovered before secondary CPUs are started. */ +extern rt_ubase_t riscv_asid_mask; +#endif + +#define SFENCE_VMA_ASID(asid) \ + __asm__ volatile ("sfence.vma x0, %0"::"r"(asid) : "memory"); + +#define SFENCE_VMA_ADDR_INV(start) \ + __asm__ volatile ("sfence.vma %0, zero" ::"r"(start) : "memory"); + +rt_inline void rt_hw_tlb_invalidate_all(void) +{ +#ifdef RT_USING_SMP + unsigned long mask = 0; +#endif + + __asm__ volatile ("sfence.vma" ::: "memory"); +#ifdef RT_USING_SMP + /* RFENCE completes on all target harts before returning. */ + if (sbi_remote_sfence_vma(&mask, SBI_HART_MASK_BASE_ALL, 0, -1UL) != SBI_SUCCESS) + { + /* Continuing could reuse memory still reachable through a stale TLB. */ + RT_ASSERT(0); + while (1) + { + } + } +#endif +} + +rt_inline void rt_hw_tlb_invalidate_all_local(void) +{ + __asm__ volatile ("sfence.vma" ::: "memory"); +} + +rt_inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace) +{ +#if defined(RT_USING_SMP) + rt_hw_tlb_invalidate_all(); +#elif defined(ARCH_RISCV_DISABLE_SFENCE_VMA_ASID) || !defined(ARCH_USING_ASID) + rt_hw_tlb_invalidate_all_local(); +#else + if (riscv_asid_mask) + { + rt_ubase_t asid_value = aspace->asid & riscv_asid_mask; + + SFENCE_VMA_ASID(asid_value); + } + else + { + rt_hw_tlb_invalidate_all_local(); + } +#endif +} + +rt_inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start) +{ + RT_UNUSED(aspace); +#ifdef RT_USING_SMP + RT_UNUSED(start); + rt_hw_tlb_invalidate_all(); +#else + SFENCE_VMA_ADDR_INV(start); +#endif +} + +rt_inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start, + size_t size, size_t stride) +{ + /* huge page is taking as normal page */ + if (size <= ARCH_PAGE_SIZE) + { + rt_hw_tlb_invalidate_page(aspace, start); + } + else + { + rt_hw_tlb_invalidate_aspace(aspace); + } +} + +#endif /* __TLB_H__ */ |
