diff options
Diffstat (limited to 'roms/opensbi/include/sbi')
39 files changed, 4363 insertions, 0 deletions
diff --git a/roms/opensbi/include/sbi/fw_dynamic.h b/roms/opensbi/include/sbi/fw_dynamic.h new file mode 100644 index 000000000..3c088311f --- /dev/null +++ b/roms/opensbi/include/sbi/fw_dynamic.h @@ -0,0 +1,79 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __FW_DYNAMIC_H__ +#define __FW_DYNAMIC_H__ + +#include <sbi/riscv_asm.h> + +/* clang-format off */ + +/** Offset of magic member in fw_dynamic_info */ +#define FW_DYNAMIC_INFO_MAGIC_OFFSET (0 * __SIZEOF_POINTER__) +/** Offset of version member in fw_dynamic_info */ +#define FW_DYNAMIC_INFO_VERSION_OFFSET (1 * __SIZEOF_POINTER__) +/** Offset of next_addr member in fw_dynamic_info (version >= 1) */ +#define FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET (2 * __SIZEOF_POINTER__) +/** Offset of next_mode member in fw_dynamic_info (version >= 1) */ +#define FW_DYNAMIC_INFO_NEXT_MODE_OFFSET (3 * __SIZEOF_POINTER__) +/** Offset of options member in fw_dynamic_info (version >= 1) */ +#define FW_DYNAMIC_INFO_OPTIONS_OFFSET (4 * __SIZEOF_POINTER__) +/** Offset of boot_hart member in fw_dynamic_info (version >= 2) */ +#define FW_DYNAMIC_INFO_BOOT_HART_OFFSET (5 * __SIZEOF_POINTER__) + +/** Expected value of info magic ('OSBI' ascii string in hex) */ +#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f + +/** Maximum supported info version */ +#define FW_DYNAMIC_INFO_VERSION_MAX 0x2 + +/** Possible next mode values */ +#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0 +#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1 +#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3 + +/* clang-format on */ + +#ifndef __ASSEMBLY__ + +#include <sbi/sbi_types.h> + +/** Representation dynamic info passed by previous booting stage */ +struct fw_dynamic_info { + /** Info magic */ + unsigned long magic; + /** Info version */ + unsigned long version; + /** Next booting stage address */ + unsigned long next_addr; + /** Next booting stage mode */ + unsigned long next_mode; + /** Options for OpenSBI library */ + unsigned long options; + /** + * Preferred boot HART id + * + * It is possible that the previous booting stage uses same link + * address as the FW_DYNAMIC firmware. In this case, the relocation + * lottery mechanism can potentially overwrite the previous booting + * stage while other HARTs are still running in the previous booting + * stage leading to boot-time crash. To avoid this boot-time crash, + * the previous booting stage can specify last HART that will jump + * to the FW_DYNAMIC firmware as the preferred boot HART. + * + * To avoid specifying a preferred boot HART, the previous booting + * stage can set it to -1UL which will force the FW_DYNAMIC firmware + * to use the relocation lottery mechanism. + */ + unsigned long boot_hart; +} __packed; + +#endif + +#endif diff --git a/roms/opensbi/include/sbi/riscv_asm.h b/roms/opensbi/include/sbi/riscv_asm.h new file mode 100644 index 000000000..10f31a7fc --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_asm.h @@ -0,0 +1,187 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_ASM_H__ +#define __RISCV_ASM_H__ + +#include <sbi/riscv_encoding.h> + +/* clang-format off */ + +#ifdef __ASSEMBLY__ +#define __ASM_STR(x) x +#else +#define __ASM_STR(x) #x +#endif + +#if __riscv_xlen == 64 +#define __REG_SEL(a, b) __ASM_STR(a) +#elif __riscv_xlen == 32 +#define __REG_SEL(a, b) __ASM_STR(b) +#else +#error "Unexpected __riscv_xlen" +#endif + +#define PAGE_SHIFT (12) +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +#define REG_L __REG_SEL(ld, lw) +#define REG_S __REG_SEL(sd, sw) +#define SZREG __REG_SEL(8, 4) +#define LGREG __REG_SEL(3, 2) + +#if __SIZEOF_POINTER__ == 8 +#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 __SIZEOF_POINTER__ == 4 +#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 __SIZEOF_POINTER__" +#endif + +#if (__SIZEOF_INT__ == 4) +#define RISCV_INT __ASM_STR(.word) +#define RISCV_SZINT __ASM_STR(4) +#define RISCV_LGINT __ASM_STR(2) +#else +#error "Unexpected __SIZEOF_INT__" +#endif + +#if (__SIZEOF_SHORT__ == 2) +#define RISCV_SHORT __ASM_STR(.half) +#define RISCV_SZSHORT __ASM_STR(2) +#define RISCV_LGSHORT __ASM_STR(1) +#else +#error "Unexpected __SIZEOF_SHORT__" +#endif + +/* clang-format on */ + +#ifndef __ASSEMBLY__ + +#define csr_swap(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrrw %0, " __ASM_STR(csr) ", %1" \ + : "=r"(__v) \ + : "rK"(__v) \ + : "memory"); \ + __v; \ + }) + +#define csr_read(csr) \ + ({ \ + register unsigned long __v; \ + __asm__ __volatile__("csrr %0, " __ASM_STR(csr) \ + : "=r"(__v) \ + : \ + : "memory"); \ + __v; \ + }) + +#define csr_write(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +#define csr_read_set(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \ + : "=r"(__v) \ + : "rK"(__v) \ + : "memory"); \ + __v; \ + }) + +#define csr_set(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +#define csr_read_clear(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \ + : "=r"(__v) \ + : "rK"(__v) \ + : "memory"); \ + __v; \ + }) + +#define csr_clear(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrc " __ASM_STR(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +unsigned long csr_read_num(int csr_num); + +void csr_write_num(int csr_num, unsigned long val); + +#define wfi() \ + do { \ + __asm__ __volatile__("wfi" ::: "memory"); \ + } while (0) + +/* Get current HART id */ +#define current_hartid() ((unsigned int)csr_read(CSR_MHARTID)) + +/* determine CPU extension, return non-zero support */ +int misa_extension_imp(char ext); + +#define misa_extension(c)\ +({\ + _Static_assert(((c >= 'A') && (c <= 'Z')),\ + "The parameter of misa_extension must be [A-Z]");\ + misa_extension_imp(c);\ +}) + +/* Get MXL field of misa, return -1 on error */ +int misa_xlen(void); + +/* Get RISC-V ISA string representation */ +void misa_string(int xlen, char *out, unsigned int out_sz); + +int pmp_set(unsigned int n, unsigned long prot, unsigned long addr, + unsigned long log2len); + +int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, + unsigned long *log2len); + +#endif /* !__ASSEMBLY__ */ + +#endif diff --git a/roms/opensbi/include/sbi/riscv_atomic.h b/roms/opensbi/include/sbi/riscv_atomic.h new file mode 100644 index 000000000..3972e0b72 --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_atomic.h @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_ATOMIC_H__ +#define __RISCV_ATOMIC_H__ + +typedef struct { + volatile long counter; +} atomic_t; + +#define ATOMIC_INIT(_lptr, val) (_lptr)->counter = (val) + +#define ATOMIC_INITIALIZER(val) \ + { \ + .counter = (val), \ + } + +long atomic_read(atomic_t *atom); + +void atomic_write(atomic_t *atom, long value); + +long atomic_add_return(atomic_t *atom, long value); + +long atomic_sub_return(atomic_t *atom, long value); + +long atomic_cmpxchg(atomic_t *atom, long oldval, long newval); + +long atomic_xchg(atomic_t *atom, long newval); + +unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr, + unsigned int newval); + +unsigned long atomic_raw_xchg_ulong(volatile unsigned long *ptr, + unsigned long newval); +/** + * Set a bit in an atomic variable and return the new value. + * @nr : Bit to set. + * @atom: atomic variable to modify + */ +int atomic_set_bit(int nr, atomic_t *atom); + +/** + * Clear a bit in an atomic variable and return the new value. + * @nr : Bit to set. + * @atom: atomic variable to modify + */ + +int atomic_clear_bit(int nr, atomic_t *atom); + +/** + * Set a bit in any address and return the new value . + * @nr : Bit to set. + * @addr: Address to modify + */ +int atomic_raw_set_bit(int nr, volatile unsigned long *addr); + +/** + * Clear a bit in any address and return the new value . + * @nr : Bit to set. + * @addr: Address to modify + */ +int atomic_raw_clear_bit(int nr, volatile unsigned long *addr); + +#endif diff --git a/roms/opensbi/include/sbi/riscv_barrier.h b/roms/opensbi/include/sbi/riscv_barrier.h new file mode 100644 index 000000000..905ecb40f --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_barrier.h @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_BARRIER_H__ +#define __RISCV_BARRIER_H__ + +/* clang-format off */ + +#define RISCV_ACQUIRE_BARRIER "\tfence r , rw\n" +#define RISCV_RELEASE_BARRIER "\tfence rw, w\n" + +#define RISCV_FENCE(p, s) \ + __asm__ __volatile__ ("fence " #p "," #s : : : "memory") + +/* Read & Write Memory barrier */ +#define mb() RISCV_FENCE(iorw,iorw) + +/* Read Memory barrier */ +#define rmb() RISCV_FENCE(ir,ir) + +/* Write Memory barrier */ +#define wmb() RISCV_FENCE(ow,ow) + +/* SMP Read & Write Memory barrier */ +#define smp_mb() RISCV_FENCE(rw,rw) + +/* SMP Read Memory barrier */ +#define smp_rmb() RISCV_FENCE(r,r) + +/* SMP Write Memory barrier */ +#define smp_wmb() RISCV_FENCE(w,w) + +/* CPU relax for busy loop */ +#define cpu_relax() asm volatile ("" : : : "memory") + +/* clang-format on */ + +#define __smp_store_release(p, v) \ + do { \ + RISCV_FENCE(rw, w); \ + *(p) = (v); \ + } while (0) + +#define __smp_load_acquire(p) \ + ({ \ + typeof(*p) ___p1 = *(p); \ + RISCV_FENCE(r, rw); \ + ___p1; \ + }) + +#endif diff --git a/roms/opensbi/include/sbi/riscv_encoding.h b/roms/opensbi/include/sbi/riscv_encoding.h new file mode 100644 index 000000000..e1d0b463c --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_encoding.h @@ -0,0 +1,699 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_ENCODING_H__ +#define __RISCV_ENCODING_H__ + +#include <sbi/sbi_const.h> + +/* clang-format off */ +#define MSTATUS_SIE _UL(0x00000002) +#define MSTATUS_MIE _UL(0x00000008) +#define MSTATUS_SPIE_SHIFT 5 +#define MSTATUS_SPIE (_UL(1) << MSTATUS_SPIE_SHIFT) +#define MSTATUS_UBE _UL(0x00000040) +#define MSTATUS_MPIE _UL(0x00000080) +#define MSTATUS_SPP_SHIFT 8 +#define MSTATUS_SPP (_UL(1) << MSTATUS_SPP_SHIFT) +#define MSTATUS_MPP_SHIFT 11 +#define MSTATUS_MPP (_UL(3) << MSTATUS_MPP_SHIFT) +#define MSTATUS_FS _UL(0x00006000) +#define MSTATUS_XS _UL(0x00018000) +#define MSTATUS_VS _UL(0x01800000) +#define MSTATUS_MPRV _UL(0x00020000) +#define MSTATUS_SUM _UL(0x00040000) +#define MSTATUS_MXR _UL(0x00080000) +#define MSTATUS_TVM _UL(0x00100000) +#define MSTATUS_TW _UL(0x00200000) +#define MSTATUS_TSR _UL(0x00400000) +#define MSTATUS32_SD _UL(0x80000000) +#if __riscv_xlen == 64 +#define MSTATUS_UXL _ULL(0x0000000300000000) +#define MSTATUS_SXL _ULL(0x0000000C00000000) +#define MSTATUS_SBE _ULL(0x0000001000000000) +#define MSTATUS_MBE _ULL(0x0000002000000000) +#define MSTATUS_MPV _ULL(0x0000008000000000) +#else +#define MSTATUSH_SBE _UL(0x00000010) +#define MSTATUSH_MBE _UL(0x00000020) +#define MSTATUSH_MPV _UL(0x00000080) +#endif +#define MSTATUS32_SD _UL(0x80000000) +#define MSTATUS64_SD _ULL(0x8000000000000000) + +#define SSTATUS_SIE MSTATUS_SIE +#define SSTATUS_SPIE_SHIFT MSTATUS_SPIE_SHIFT +#define SSTATUS_SPIE MSTATUS_SPIE +#define SSTATUS_SPP_SHIFT MSTATUS_SPP_SHIFT +#define SSTATUS_SPP MSTATUS_SPP +#define SSTATUS_FS MSTATUS_FS +#define SSTATUS_XS MSTATUS_XS +#define SSTATUS_VS MSTATUS_VS +#define SSTATUS_SUM MSTATUS_SUM +#define SSTATUS_MXR MSTATUS_MXR +#define SSTATUS32_SD MSTATUS32_SD +#define SSTATUS64_UXL MSTATUS_UXL +#define SSTATUS64_SD MSTATUS64_SD + +#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) + +#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 MIP_SSIP (_UL(1) << IRQ_S_SOFT) +#define MIP_VSSIP (_UL(1) << IRQ_VS_SOFT) +#define MIP_MSIP (_UL(1) << IRQ_M_SOFT) +#define MIP_STIP (_UL(1) << IRQ_S_TIMER) +#define MIP_VSTIP (_UL(1) << IRQ_VS_TIMER) +#define MIP_MTIP (_UL(1) << IRQ_M_TIMER) +#define MIP_SEIP (_UL(1) << IRQ_S_EXT) +#define MIP_VSEIP (_UL(1) << IRQ_VS_EXT) +#define MIP_MEIP (_UL(1) << IRQ_M_EXT) +#define MIP_SGEIP (_UL(1) << IRQ_S_GEXT) + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U _UL(0) +#define PRV_S _UL(1) +#define PRV_M _UL(3) + +#define SATP32_MODE _UL(0x80000000) +#define SATP32_ASID _UL(0x7FC00000) +#define SATP32_PPN _UL(0x003FFFFF) +#define SATP64_MODE _ULL(0xF000000000000000) +#define SATP64_ASID _ULL(0x0FFFF00000000000) +#define SATP64_PPN _ULL(0x00000FFFFFFFFFFF) + +#define SATP_MODE_OFF _UL(0) +#define SATP_MODE_SV32 _UL(1) +#define SATP_MODE_SV39 _UL(8) +#define SATP_MODE_SV48 _UL(9) +#define SATP_MODE_SV57 _UL(10) +#define SATP_MODE_SV64 _UL(11) + +#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 HGATP32_MODE_SHIFT 31 +#define HGATP32_VMID_SHIFT 22 +#define HGATP32_VMID_MASK _UL(0x1FC00000) +#define HGATP32_PPN _UL(0x003FFFFF) + +#define HGATP64_MODE_SHIFT 60 +#define HGATP64_VMID_SHIFT 44 +#define HGATP64_VMID_MASK _ULL(0x03FFF00000000000) +#define HGATP64_PPN _ULL(0x00000FFFFFFFFFFF) + +#define PMP_R _UL(0x01) +#define PMP_W _UL(0x02) +#define PMP_X _UL(0x04) +#define PMP_A _UL(0x18) +#define PMP_A_TOR _UL(0x08) +#define PMP_A_NA4 _UL(0x10) +#define PMP_A_NAPOT _UL(0x18) +#define PMP_L _UL(0x80) + +#define PMP_SHIFT 2 +#define PMP_COUNT 64 +#if __riscv_xlen == 64 +#define PMP_ADDR_MASK ((_ULL(0x1) << 54) - 1) +#else +#define PMP_ADDR_MASK _UL(0xFFFFFFFF) +#endif + +#if __riscv_xlen == 64 +#define MSTATUS_SD MSTATUS64_SD +#define SSTATUS_SD SSTATUS64_SD +#define SATP_MODE SATP64_MODE + +#define HGATP_PPN HGATP64_PPN +#define HGATP_VMID_SHIFT HGATP64_VMID_SHIFT +#define HGATP_VMID_MASK HGATP64_VMID_MASK +#define HGATP_MODE_SHIFT HGATP64_MODE_SHIFT +#else +#define MSTATUS_SD MSTATUS32_SD +#define SSTATUS_SD SSTATUS32_SD +#define SATP_MODE SATP32_MODE + +#define HGATP_PPN HGATP32_PPN +#define HGATP_VMID_SHIFT HGATP32_VMID_SHIFT +#define HGATP_VMID_MASK HGATP32_VMID_MASK +#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT +#endif + +/* ===== User-level CSRs ===== */ + +/* User Trap Setup (N-extension) */ +#define CSR_USTATUS 0x000 +#define CSR_UIE 0x004 +#define CSR_UTVEC 0x005 + +/* User Trap Handling (N-extension) */ +#define CSR_USCRATCH 0x040 +#define CSR_UEPC 0x041 +#define CSR_UCAUSE 0x042 +#define CSR_UTVAL 0x043 +#define CSR_UIP 0x044 + +/* User Floating-point CSRs */ +#define CSR_FFLAGS 0x001 +#define CSR_FRM 0x002 +#define CSR_FCSR 0x003 + +/* User Counters/Timers */ +#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 + +/* ===== Supervisor-level CSRs ===== */ + +/* Supervisor Trap Setup */ +#define CSR_SSTATUS 0x100 +#define CSR_SEDELEG 0x102 +#define CSR_SIDELEG 0x103 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 + +/* Supervisor Trap Handling */ +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 + +/* Supervisor Protection and Translation */ +#define CSR_SATP 0x180 + +/* ===== Hypervisor-level CSRs ===== */ + +/* Hypervisor Trap Setup (H-extension) */ +#define CSR_HSTATUS 0x600 +#define CSR_HEDELEG 0x602 +#define CSR_HIDELEG 0x603 +#define CSR_HIE 0x604 +#define CSR_HCOUNTEREN 0x606 +#define CSR_HGEIE 0x607 + +/* Hypervisor Trap Handling (H-extension) */ +#define CSR_HTVAL 0x643 +#define CSR_HIP 0x644 +#define CSR_HVIP 0x645 +#define CSR_HTINST 0x64a +#define CSR_HGEIP 0xe12 + +/* Hypervisor Protection and Translation (H-extension) */ +#define CSR_HGATP 0x680 + +/* Hypervisor Counter/Timer Virtualization Registers (H-extension) */ +#define CSR_HTIMEDELTA 0x605 +#define CSR_HTIMEDELTAH 0x615 + +/* Virtual Supervisor Registers (H-extension) */ +#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 + +/* ===== Machine-level CSRs ===== */ + +/* Machine Information Registers */ +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 + +/* Machine Trap Setup */ +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 +#define CSR_MSTATUSH 0x310 + +/* Machine Trap Handling */ +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_MTINST 0x34a +#define CSR_MTVAL2 0x34b + +/* Machine Memory Protection */ +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#define CSR_PMPCFG4 0x3a4 +#define CSR_PMPCFG5 0x3a5 +#define CSR_PMPCFG6 0x3a6 +#define CSR_PMPCFG7 0x3a7 +#define CSR_PMPCFG8 0x3a8 +#define CSR_PMPCFG9 0x3a9 +#define CSR_PMPCFG10 0x3aa +#define CSR_PMPCFG11 0x3ab +#define CSR_PMPCFG12 0x3ac +#define CSR_PMPCFG13 0x3ad +#define CSR_PMPCFG14 0x3ae +#define CSR_PMPCFG15 0x3af +#define CSR_PMPADDR0 0x3b0 +#define CSR_PMPADDR1 0x3b1 +#define CSR_PMPADDR2 0x3b2 +#define CSR_PMPADDR3 0x3b3 +#define CSR_PMPADDR4 0x3b4 +#define CSR_PMPADDR5 0x3b5 +#define CSR_PMPADDR6 0x3b6 +#define CSR_PMPADDR7 0x3b7 +#define CSR_PMPADDR8 0x3b8 +#define CSR_PMPADDR9 0x3b9 +#define CSR_PMPADDR10 0x3ba +#define CSR_PMPADDR11 0x3bb +#define CSR_PMPADDR12 0x3bc +#define CSR_PMPADDR13 0x3bd +#define CSR_PMPADDR14 0x3be +#define CSR_PMPADDR15 0x3bf +#define CSR_PMPADDR16 0x3c0 +#define CSR_PMPADDR17 0x3c1 +#define CSR_PMPADDR18 0x3c2 +#define CSR_PMPADDR19 0x3c3 +#define CSR_PMPADDR20 0x3c4 +#define CSR_PMPADDR21 0x3c5 +#define CSR_PMPADDR22 0x3c6 +#define CSR_PMPADDR23 0x3c7 +#define CSR_PMPADDR24 0x3c8 +#define CSR_PMPADDR25 0x3c9 +#define CSR_PMPADDR26 0x3ca +#define CSR_PMPADDR27 0x3cb +#define CSR_PMPADDR28 0x3cc +#define CSR_PMPADDR29 0x3cd +#define CSR_PMPADDR30 0x3ce +#define CSR_PMPADDR31 0x3cf +#define CSR_PMPADDR32 0x3d0 +#define CSR_PMPADDR33 0x3d1 +#define CSR_PMPADDR34 0x3d2 +#define CSR_PMPADDR35 0x3d3 +#define CSR_PMPADDR36 0x3d4 +#define CSR_PMPADDR37 0x3d5 +#define CSR_PMPADDR38 0x3d6 +#define CSR_PMPADDR39 0x3d7 +#define CSR_PMPADDR40 0x3d8 +#define CSR_PMPADDR41 0x3d9 +#define CSR_PMPADDR42 0x3da +#define CSR_PMPADDR43 0x3db +#define CSR_PMPADDR44 0x3dc +#define CSR_PMPADDR45 0x3dd +#define CSR_PMPADDR46 0x3de +#define CSR_PMPADDR47 0x3df +#define CSR_PMPADDR48 0x3e0 +#define CSR_PMPADDR49 0x3e1 +#define CSR_PMPADDR50 0x3e2 +#define CSR_PMPADDR51 0x3e3 +#define CSR_PMPADDR52 0x3e4 +#define CSR_PMPADDR53 0x3e5 +#define CSR_PMPADDR54 0x3e6 +#define CSR_PMPADDR55 0x3e7 +#define CSR_PMPADDR56 0x3e8 +#define CSR_PMPADDR57 0x3e9 +#define CSR_PMPADDR58 0x3ea +#define CSR_PMPADDR59 0x3eb +#define CSR_PMPADDR60 0x3ec +#define CSR_PMPADDR61 0x3ed +#define CSR_PMPADDR62 0x3ee +#define CSR_PMPADDR63 0x3ef + +/* Machine Counters/Timers */ +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f + +/* Machine Counter Setup */ +#define CSR_MCOUNTINHIBIT 0x320 +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f + +/* Debug/Trace Registers */ +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 + +/* Debug Mode Registers */ +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH0 0x7b2 +#define CSR_DSCRATCH1 0x7b3 + +/* ===== Trap/Exception Causes ===== */ + +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FETCH_ACCESS 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_LOAD_ACCESS 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_STORE_ACCESS 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#define CAUSE_FETCH_PAGE_FAULT 0xc +#define CAUSE_LOAD_PAGE_FAULT 0xd +#define CAUSE_STORE_PAGE_FAULT 0xf +#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14 +#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15 +#define CAUSE_VIRTUAL_INST_FAULT 0x16 +#define CAUSE_STORE_GUEST_PAGE_FAULT 0x17 + +/* ===== Instruction Encodings ===== */ + +#define INSN_MATCH_LB 0x3 +#define INSN_MASK_LB 0x707f +#define INSN_MATCH_LH 0x1003 +#define INSN_MASK_LH 0x707f +#define INSN_MATCH_LW 0x2003 +#define INSN_MASK_LW 0x707f +#define INSN_MATCH_LD 0x3003 +#define INSN_MASK_LD 0x707f +#define INSN_MATCH_LBU 0x4003 +#define INSN_MASK_LBU 0x707f +#define INSN_MATCH_LHU 0x5003 +#define INSN_MASK_LHU 0x707f +#define INSN_MATCH_LWU 0x6003 +#define INSN_MASK_LWU 0x707f +#define INSN_MATCH_SB 0x23 +#define INSN_MASK_SB 0x707f +#define INSN_MATCH_SH 0x1023 +#define INSN_MASK_SH 0x707f +#define INSN_MATCH_SW 0x2023 +#define INSN_MASK_SW 0x707f +#define INSN_MATCH_SD 0x3023 +#define INSN_MASK_SD 0x707f + +#define INSN_MATCH_FLW 0x2007 +#define INSN_MASK_FLW 0x707f +#define INSN_MATCH_FLD 0x3007 +#define INSN_MASK_FLD 0x707f +#define INSN_MATCH_FLQ 0x4007 +#define INSN_MASK_FLQ 0x707f +#define INSN_MATCH_FSW 0x2027 +#define INSN_MASK_FSW 0x707f +#define INSN_MATCH_FSD 0x3027 +#define INSN_MASK_FSD 0x707f +#define INSN_MATCH_FSQ 0x4027 +#define INSN_MASK_FSQ 0x707f + +#define INSN_MATCH_C_LD 0x6000 +#define INSN_MASK_C_LD 0xe003 +#define INSN_MATCH_C_SD 0xe000 +#define INSN_MASK_C_SD 0xe003 +#define INSN_MATCH_C_LW 0x4000 +#define INSN_MASK_C_LW 0xe003 +#define INSN_MATCH_C_SW 0xc000 +#define INSN_MASK_C_SW 0xe003 +#define INSN_MATCH_C_LDSP 0x6002 +#define INSN_MASK_C_LDSP 0xe003 +#define INSN_MATCH_C_SDSP 0xe002 +#define INSN_MASK_C_SDSP 0xe003 +#define INSN_MATCH_C_LWSP 0x4002 +#define INSN_MASK_C_LWSP 0xe003 +#define INSN_MATCH_C_SWSP 0xc002 +#define INSN_MASK_C_SWSP 0xe003 + +#define INSN_MATCH_C_FLD 0x2000 +#define INSN_MASK_C_FLD 0xe003 +#define INSN_MATCH_C_FLW 0x6000 +#define INSN_MASK_C_FLW 0xe003 +#define INSN_MATCH_C_FSD 0xa000 +#define INSN_MASK_C_FSD 0xe003 +#define INSN_MATCH_C_FSW 0xe000 +#define INSN_MASK_C_FSW 0xe003 +#define INSN_MATCH_C_FLDSP 0x2002 +#define INSN_MASK_C_FLDSP 0xe003 +#define INSN_MATCH_C_FSDSP 0xa002 +#define INSN_MASK_C_FSDSP 0xe003 +#define INSN_MATCH_C_FLWSP 0x6002 +#define INSN_MASK_C_FLWSP 0xe003 +#define INSN_MATCH_C_FSWSP 0xe002 +#define INSN_MASK_C_FSWSP 0xe003 + +#define INSN_MASK_WFI 0xffffff00 +#define INSN_MATCH_WFI 0x10500000 + +#define INSN_16BIT_MASK 0x3 +#define INSN_32BIT_MASK 0x1c + +#define INSN_IS_16BIT(insn) \ + (((insn) & INSN_16BIT_MASK) != INSN_16BIT_MASK) +#define INSN_IS_32BIT(insn) \ + (((insn) & INSN_16BIT_MASK) == INSN_16BIT_MASK && \ + ((insn) & INSN_32BIT_MASK) != INSN_32BIT_MASK) + +#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_RD 7 +#define SH_RS1 15 +#define SH_RS2 20 +#define SH_RS2C 2 + +#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1)) +#define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | \ + (RV_X(x, 10, 3) << 3) | \ + (RV_X(x, 5, 1) << 6)) +#define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | \ + (RV_X(x, 5, 2) << 6)) +#define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | \ + (RV_X(x, 12, 1) << 5) | \ + (RV_X(x, 2, 2) << 6)) +#define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | \ + (RV_X(x, 12, 1) << 5) | \ + (RV_X(x, 2, 3) << 6)) +#define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | \ + (RV_X(x, 7, 2) << 6)) +#define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \ + (RV_X(x, 7, 3) << 6)) +#define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3)) +#define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3)) +#define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5) + +#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_RM(insn) (((insn) >> 12) & 7) + +#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)) +#define MASK_FUNCT3 0x7000 + +/* clang-format on */ + +#endif diff --git a/roms/opensbi/include/sbi/riscv_fp.h b/roms/opensbi/include/sbi/riscv_fp.h new file mode 100644 index 000000000..a685884a5 --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_fp.h @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_FP_H__ +#define __RISCV_FP_H__ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_types.h> + +#define GET_PRECISION(insn) (((insn) >> 25) & 3) +#define GET_RM(insn) (((insn) >> 12) & 7) +#define PRECISION_S 0 +#define PRECISION_D 1 + +#ifdef __riscv_flen + +#define GET_F32_REG(insn, pos, regs) \ + ({ \ + register s32 value asm("a0") = \ + SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ + ulong tmp; \ + asm("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" \ + : "=&r"(tmp), "+&r"(value)::"t0"); \ + value; \ + }) +#define SET_F32_REG(insn, pos, regs, val) \ + ({ \ + register u32 value asm("a0") = (val); \ + ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ + ulong tmp; \ + asm volatile( \ + "1: auipc %0, %%pcrel_hi(put_f32_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" \ + : "=&r"(tmp) \ + : "r"(value), "r"(offset) \ + : "t0"); \ + }) +#define init_fp_reg(i) SET_F32_REG((i) << 3, 3, 0, 0) +#define GET_F64_REG(insn, pos, regs) \ + ({ \ + register ulong value asm("a0") = \ + SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ + ulong tmp; \ + asm("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" \ + : "=&r"(tmp), "+&r"(value)::"t0"); \ + sizeof(ulong) == 4 ? *(int64_t *)value : (int64_t)value; \ + }) +#define SET_F64_REG(insn, pos, regs, val) \ + ({ \ + uint64_t __val = (val); \ + register ulong value asm("a0") = \ + sizeof(ulong) == 4 ? (ulong)&__val : (ulong)__val; \ + ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ + ulong tmp; \ + asm volatile( \ + "1: auipc %0, %%pcrel_hi(put_f64_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" \ + : "=&r"(tmp) \ + : "r"(value), "r"(offset) \ + : "t0"); \ + }) +#define GET_FCSR() csr_read(CSR_FCSR) +#define SET_FCSR(value) csr_write(CSR_FCSR, (value)) +#define GET_FRM() csr_read(CSR_FRM) +#define SET_FRM(value) csr_write(CSR_FRM, (value)) +#define GET_FFLAGS() csr_read(CSR_FFLAGS) +#define SET_FFLAGS(value) csr_write(CSR_FFLAGS, (value)) + +#define SET_FS_DIRTY() ((void)0) + +#define GET_F32_RS1(insn, regs) (GET_F32_REG(insn, 15, regs)) +#define GET_F32_RS2(insn, regs) (GET_F32_REG(insn, 20, regs)) +#define GET_F32_RS3(insn, regs) (GET_F32_REG(insn, 27, regs)) +#define GET_F64_RS1(insn, regs) (GET_F64_REG(insn, 15, regs)) +#define GET_F64_RS2(insn, regs) (GET_F64_REG(insn, 20, regs)) +#define GET_F64_RS3(insn, regs) (GET_F64_REG(insn, 27, regs)) +#define SET_F32_RD(insn, regs, val) \ + (SET_F32_REG(insn, 7, regs, val), SET_FS_DIRTY()) +#define SET_F64_RD(insn, regs, val) \ + (SET_F64_REG(insn, 7, regs, val), SET_FS_DIRTY()) + +#define GET_F32_RS2C(insn, regs) (GET_F32_REG(insn, 2, regs)) +#define GET_F32_RS2S(insn, regs) (GET_F32_REG(RVC_RS2S(insn), 0, regs)) +#define GET_F64_RS2C(insn, regs) (GET_F64_REG(insn, 2, regs)) +#define GET_F64_RS2S(insn, regs) (GET_F64_REG(RVC_RS2S(insn), 0, regs)) + +#endif + +#endif diff --git a/roms/opensbi/include/sbi/riscv_io.h b/roms/opensbi/include/sbi/riscv_io.h new file mode 100644 index 000000000..491323283 --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_io.h @@ -0,0 +1,114 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_IO_H__ +#define __RISCV_IO_H__ + +#include <sbi/riscv_barrier.h> +#include <sbi/sbi_types.h> + +static inline void __raw_writeb(u8 val, volatile void *addr) +{ + asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +static inline void __raw_writew(u16 val, volatile void *addr) +{ + asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +static inline void __raw_writel(u32 val, volatile void *addr) +{ + asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +#if __riscv_xlen != 32 +static inline void __raw_writeq(u64 val, volatile void *addr) +{ + asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr)); +} +#endif + +static inline u8 __raw_readb(const volatile void *addr) +{ + u8 val; + + asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +static inline u16 __raw_readw(const volatile void *addr) +{ + u16 val; + + asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +static inline u32 __raw_readl(const volatile void *addr) +{ + u32 val; + + asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +#if __riscv_xlen != 32 +static inline u64 __raw_readq(const volatile void *addr) +{ + u64 val; + + asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} +#endif + +/* FIXME: These are now the same as asm-generic */ + +/* clang-format off */ + +#define __io_rbr() do {} while (0) +#define __io_rar() do {} while (0) +#define __io_rbw() do {} while (0) +#define __io_raw() do {} while (0) + +#define readb_relaxed(c) ({ u8 __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) +#define readw_relaxed(c) ({ u16 __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) +#define readl_relaxed(c) ({ u32 __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) + +#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) +#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) +#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) + +#if __riscv_xlen != 32 +#define readq_relaxed(c) ({ u64 __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) +#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) +#endif + +#define __io_br() do {} while (0) +#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); +#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); +#define __io_aw() do {} while (0) + +#define readb(c) ({ u8 __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) +#define readw(c) ({ u16 __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) +#define readl(c) ({ u32 __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) + +#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) +#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) +#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) + +#if __riscv_xlen != 32 +#define readq(c) ({ u64 __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) +#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) +#endif + +/* clang-format on */ + +#endif diff --git a/roms/opensbi/include/sbi/riscv_locks.h b/roms/opensbi/include/sbi/riscv_locks.h new file mode 100644 index 000000000..55da7c01c --- /dev/null +++ b/roms/opensbi/include/sbi/riscv_locks.h @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __RISCV_LOCKS_H__ +#define __RISCV_LOCKS_H__ + +typedef struct { + volatile long lock; +} spinlock_t; + +#define __RISCV_SPIN_UNLOCKED 0 + +#define SPIN_LOCK_INIT(_lptr) (_lptr)->lock = __RISCV_SPIN_UNLOCKED + +#define SPIN_LOCK_INITIALIZER \ + { \ + .lock = __RISCV_SPIN_UNLOCKED, \ + } + +int spin_lock_check(spinlock_t *lock); + +int spin_trylock(spinlock_t *lock); + +void spin_lock(spinlock_t *lock); + +void spin_unlock(spinlock_t *lock); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_bitmap.h b/roms/opensbi/include/sbi/sbi_bitmap.h new file mode 100644 index 000000000..4f0ebb63a --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_bitmap.h @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_BITMAP_H__ +#define __SBI_BITMAP_H__ + +#include <sbi/sbi_bitops.h> + +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) +#define BITMAP_LAST_WORD_MASK(nbits) \ +( \ + ((nbits) % BITS_PER_LONG) ? \ + ((1UL << ((nbits) % BITS_PER_LONG)) - 1) : ~0UL \ +) + +#define small_const_nbits(nbits) \ + (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) + +#define DECLARE_BITMAP(name, nbits) unsigned long name[BITS_TO_LONGS(nbits)] +#define DEFINE_BITMAP(name) extern unsigned long name[] + +static inline unsigned long bitmap_estimate_size(int nbits) +{ + return (BITS_TO_LONGS(nbits) * sizeof(unsigned long)); +} + +void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); + +static inline void bitmap_set(unsigned long *bmap, int start, int len) +{ + int bit; + for (bit = start; bit < (start + len); bit++) + bmap[BIT_WORD(bit)] |= (0x1UL << BIT_WORD_OFFSET(bit)); +} + +static inline void bitmap_clear(unsigned long *bmap, int start, int len) +{ + int bit; + for (bit = start; bit < (start + len); bit++) + bmap[BIT_WORD(bit)] &= ~(0x1UL << BIT_WORD_OFFSET(bit)); +} + +static inline void bitmap_zero(unsigned long *dst, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = 0UL; + else { + size_t i, len = BITS_TO_LONGS(nbits); + for (i = 0; i < len; i++) + dst[i] = 0; + } +} + +static inline void bitmap_zero_except(unsigned long *dst, + int exception, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = 0UL; + else { + size_t i, len = BITS_TO_LONGS(nbits); + for (i = 0; i < len; i++) + dst[i] = 0; + } + if (exception < nbits) + __set_bit(exception, dst); +} + +static inline void bitmap_fill(unsigned long *dst, int nbits) +{ + size_t i, nlongs = BITS_TO_LONGS(nbits); + if (!small_const_nbits(nbits)) { + for (i = 0; i < (nlongs - 1); i++) + dst[i] = -1UL; + } + dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); +} + +static inline void bitmap_copy(unsigned long *dst, + const unsigned long *src, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = *src; + else { + size_t i, len = BITS_TO_LONGS(nbits); + for (i = 0; i < len; i++) + dst[i] = src[i]; + } +} + +static inline void bitmap_and(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = *src1 & *src2; + else + __bitmap_and(dst, src1, src2, nbits); +} + +static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = *src1 | *src2; + else + __bitmap_or(dst, src1, src2, nbits); +} + +static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = *src1 ^ *src2; + else + __bitmap_xor(dst, src1, src2, nbits); +} + +#endif diff --git a/roms/opensbi/include/sbi/sbi_bitops.h b/roms/opensbi/include/sbi/sbi_bitops.h new file mode 100644 index 000000000..879430d4b --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_bitops.h @@ -0,0 +1,320 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#ifndef __SBI_BITOPS_H__ +#define __SBI_BITOPS_H__ + +#include <sbi/sbi_types.h> + +#if __SIZEOF_POINTER__ == 8 +#define BITS_PER_LONG 64 +#elif __SIZEOF_POINTER__ == 4 +#define BITS_PER_LONG 32 +#else +#error "Unexpected __SIZEOF_POINTER__" +#endif + +#define EXTRACT_FIELD(val, which) \ + (((val) & (which)) / ((which) & ~((which)-1))) +#define INSERT_FIELD(val, which, fieldval) \ + (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#define BITS_TO_LONGS(nbits) (((nbits) + BITS_PER_LONG - 1) / \ + BITS_PER_LONG) + +#define BIT(nr) (1UL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(bit) ((bit) / BITS_PER_LONG) +#define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1)) + +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +/** + * ffs - Find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static inline int ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) + r += 1; + return r; +} + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline int __ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +#define ffz(x) __ffs(~(x)) + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ + +static inline int fls(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000u)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) + r -= 1; + return r; +} + +/** + * __fls - find last (most-significant) set bit in a long word + * @word: the word to search + * + * Undefined if no set bit exists, so code should check against 0 first. + */ +static inline unsigned long __fls(unsigned long word) +{ + int num = BITS_PER_LONG - 1; + +#if BITS_PER_LONG == 64 + if (!(word & (~0ul << 32))) { + num -= 32; + word <<= 32; + } +#endif + if (!(word & (~0ul << (BITS_PER_LONG-16)))) { + num -= 16; + word <<= 16; + } + if (!(word & (~0ul << (BITS_PER_LONG-8)))) { + num -= 8; + word <<= 8; + } + if (!(word & (~0ul << (BITS_PER_LONG-4)))) { + num -= 4; + word <<= 4; + } + if (!(word & (~0ul << (BITS_PER_LONG-2)))) { + num -= 2; + word <<= 2; + } + if (!(word & (~0ul << (BITS_PER_LONG-1)))) + num -= 1; + return num; +} + +#define for_each_set_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + +/* same as for_each_set_bit() but use bit as value to start with */ +#define for_each_set_bit_from(bit, addr, size) \ + for ((bit) = find_next_bit((addr), (size), (bit)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + +#define for_each_clear_bit(bit, addr, size) \ + for ((bit) = find_first_zero_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) + +/* same as for_each_clear_bit() but use bit as value to start with */ +#define for_each_clear_bit_from(bit, addr, size) \ + for ((bit) = find_next_zero_bit((addr), (size), (bit)); \ + (bit) < (size); \ + (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) + +unsigned long find_first_bit(const unsigned long *addr, + unsigned long size); + +unsigned long find_first_zero_bit(const unsigned long *addr, + unsigned long size); + +unsigned long find_last_bit(const unsigned long *addr, + unsigned long size); + +unsigned long find_next_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset); + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is non-atomic and may be reordered. + */ +static inline void __set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p |= mask; +} + +/** + * __clear_bit - Clear a bit in memory + * @nr: the bit to clear + * @addr: the address to start counting from + * + * This function is non-atomic and may be reordered. + */ +static inline void __clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p &= ~mask; +} + +/** + * __change_bit - Toggle a bit in memory + * @nr: the bit to change + * @addr: the address to start counting from + * + * This function is non-atomic and may be reordered. + */ +static inline void __change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p ^= mask; +} + +/** + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + */ +static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old = *p; + + *p = old | mask; + return (old & mask) != 0; +} + +/** + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + */ +static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old = *p; + + *p = old & ~mask; + return (old & mask) != 0; +} + +/** + * __test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + * + * This operation is non-atomic and can be reordered. + */ +static inline int __test_bit(int nr, const volatile unsigned long *addr) +{ + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +#endif diff --git a/roms/opensbi/include/sbi/sbi_console.h b/roms/opensbi/include/sbi/sbi_console.h new file mode 100644 index 000000000..7d648f0b5 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_console.h @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_CONSOLE_H__ +#define __SBI_CONSOLE_H__ + +#include <sbi/sbi_types.h> + +#define __printf(a, b) __attribute__((format(printf, a, b))) + +bool sbi_isprintable(char ch); + +int sbi_getc(void); + +void sbi_putc(char ch); + +void sbi_puts(const char *str); + +void sbi_gets(char *s, int maxwidth, char endchar); + +int __printf(2, 3) sbi_sprintf(char *out, const char *format, ...); + +int __printf(3, 4) sbi_snprintf(char *out, u32 out_sz, const char *format, ...); + +int __printf(1, 2) sbi_printf(const char *format, ...); + +int __printf(1, 2) sbi_dprintf(const char *format, ...); + +struct sbi_scratch; + +int sbi_console_init(struct sbi_scratch *scratch); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_const.h b/roms/opensbi/include/sbi/sbi_const.h new file mode 100644 index 000000000..37866546a --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_const.h @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_CONST_H__ +#define __SBI_CONST_H__ + +/* + * Some constant macros are used in both assembler and + * C code. Therefore we cannot annotate them always with + * 'UL' and other type specifiers unilaterally. We + * use the following macros to deal with this. + * + * Similarly, _AT() will cast an expression with a type in C, but + * leave it unchanged in asm. + */ + +/* clang-format off */ + +#ifdef __ASSEMBLY__ +#define _AC(X,Y) X +#define _AT(T,X) X +#else +#define __AC(X,Y) (X##Y) +#define _AC(X,Y) __AC(X,Y) +#define _AT(T,X) ((T)(X)) +#endif + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) + +#define UL(x) (_UL(x)) +#define ULL(x) (_ULL(x)) + +#define __STR(s) #s +#define STRINGIFY(s) __STR(s) + +/* clang-format on */ + +#endif diff --git a/roms/opensbi/include/sbi/sbi_csr_detect.h b/roms/opensbi/include/sbi/sbi_csr_detect.h new file mode 100644 index 000000000..f29488845 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_csr_detect.h @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#ifndef __SBI_CSR_DETECT__H +#define __SBI_CSR_DETECT__H + +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_hart.h> + +#define csr_read_allowed(csr_num, trap) \ + ({ \ + register ulong tinfo asm("a3") = (ulong)trap; \ + register ulong ttmp asm("a4"); \ + register ulong mtvec = sbi_hart_expected_trap_addr(); \ + register ulong ret = 0; \ + asm volatile( \ + "add %[ttmp], %[tinfo], zero\n" \ + "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \ + "csrr %[ret], %[csr]\n" \ + "csrw " STR(CSR_MTVEC) ", %[mtvec]" \ + : [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo), \ + [ttmp] "+&r"(ttmp), [ret] "=&r" (ret) \ + : [csr] "i" (csr_num) \ + : "memory"); \ + ret; \ + }) \ + +#define csr_write_allowed(csr_num, trap, value) \ + ({ \ + register ulong tinfo asm("a3") = (ulong)trap; \ + register ulong ttmp asm("a4"); \ + register ulong mtvec = sbi_hart_expected_trap_addr(); \ + asm volatile( \ + "add %[ttmp], %[tinfo], zero\n" \ + "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \ + "csrw %[csr], %[val]\n" \ + "csrw " STR(CSR_MTVEC) ", %[mtvec]" \ + : [mtvec] "+&r"(mtvec), \ + [tinfo] "+&r"(tinfo), [ttmp] "+&r"(ttmp) \ + : [csr] "i" (csr_num), [val] "r" (value) \ + : "memory"); \ + }) \ + +#endif diff --git a/roms/opensbi/include/sbi/sbi_domain.h b/roms/opensbi/include/sbi/sbi_domain.h new file mode 100644 index 000000000..1f8b942c4 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_domain.h @@ -0,0 +1,165 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_DOMAIN_H__ +#define __SBI_DOMAIN_H__ + +#include <sbi/sbi_types.h> +#include <sbi/sbi_hartmask.h> + +struct sbi_scratch; + +/** Domain access types */ +enum sbi_domain_access { + SBI_DOMAIN_READ = (1UL << 0), + SBI_DOMAIN_WRITE = (1UL << 1), + SBI_DOMAIN_EXECUTE = (1UL << 2), + SBI_DOMAIN_MMIO = (1UL << 3) +}; + +/** Representation of OpenSBI domain memory region */ +struct sbi_domain_memregion { + /** + * Size of memory region as power of 2 + * It has to be minimum 3 and maximum __riscv_xlen + */ + unsigned long order; + /** + * Base address of memory region + * It must be 2^order aligned address + */ + unsigned long base; + /** Flags representing memory region attributes */ +#define SBI_DOMAIN_MEMREGION_READABLE (1UL << 0) +#define SBI_DOMAIN_MEMREGION_WRITEABLE (1UL << 1) +#define SBI_DOMAIN_MEMREGION_EXECUTABLE (1UL << 2) +#define SBI_DOMAIN_MEMREGION_MMODE (1UL << 3) +#define SBI_DOMAIN_MEMREGION_ACCESS_MASK (0xfUL) + +#define SBI_DOMAIN_MEMREGION_MMIO (1UL << 31) + unsigned long flags; +}; + +/** Maximum number of domains */ +#define SBI_DOMAIN_MAX_INDEX 32 + +/** Representation of OpenSBI domain */ +struct sbi_domain { + /** + * Logical index of this domain + * Note: This set by sbi_domain_finalize() in the coldboot path + */ + u32 index; + /** + * HARTs assigned to this domain + * Note: This set by sbi_domain_init() and sbi_domain_finalize() + * in the coldboot path + */ + struct sbi_hartmask assigned_harts; + /** Name of this domain */ + char name[64]; + /** Possible HARTs in this domain */ + const struct sbi_hartmask *possible_harts; + /** Array of memory regions terminated by a region with order zero */ + struct sbi_domain_memregion *regions; + /** HART id of the HART booting this domain */ + u32 boot_hartid; + /** Arg1 (or 'a1' register) of next booting stage for this domain */ + unsigned long next_arg1; + /** Address of next booting stage for this domain */ + unsigned long next_addr; + /** Privilege mode of next booting stage for this domain */ + unsigned long next_mode; + /** Is domain allowed to reset the system */ + bool system_reset_allowed; +}; + +/** HART id to domain table */ +extern struct sbi_domain *hartid_to_domain_table[]; + +/** Get pointer to sbi_domain from HART id */ +#define sbi_hartid_to_domain(__hartid) \ + hartid_to_domain_table[__hartid] + +/** Get pointer to sbi_domain for current HART */ +#define sbi_domain_thishart_ptr() \ + sbi_hartid_to_domain(current_hartid()) + +/** Index to domain table */ +extern struct sbi_domain *domidx_to_domain_table[]; + +/** Get pointer to sbi_domain from index */ +#define sbi_index_to_domain(__index) \ + domidx_to_domain_table[__index] + +/** Iterate over each domain */ +#define sbi_domain_for_each(__i, __d) \ + for ((__i) = 0; ((__d) = sbi_index_to_domain(__i)); (__i)++) + +/** Iterate over each memory region of a domain */ +#define sbi_domain_for_each_memregion(__d, __r) \ + for ((__r) = (__d)->regions; (__r)->order; (__r)++) + +/** + * Check whether given HART is assigned to specified domain + * @param dom pointer to domain + * @param hartid the HART ID + * @return TRUE if HART is assigned to domain otherwise FALSE + */ +bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid); + +/** + * Get ulong assigned HART mask for given domain and HART base ID + * @param dom pointer to domain + * @param hbase the HART base ID + * @return ulong possible HART mask + * Note: the return ulong mask will be set to zero on failure. + */ +ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, + ulong hbase); + +/** Initialize a domain memory region as firmware region */ +void sbi_domain_memregion_initfw(struct sbi_domain_memregion *reg); + +/** + * Check whether we can access specified address for given mode and + * memory region flags under a domain + * @param dom pointer to domain + * @param addr the address to be checked + * @param mode the privilege mode of access + * @param access_flags bitmask of domain access types (enum sbi_domain_access) + * @return TRUE if access allowed otherwise FALSE + */ +bool sbi_domain_check_addr(const struct sbi_domain *dom, + unsigned long addr, unsigned long mode, + unsigned long access_flags); + +/** Dump domain details on the console */ +void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); + +/** Dump all domain details on the console */ +void sbi_domain_dump_all(const char *suffix); + +/** + * Register a new domain + * @param dom pointer to domain + * @param assign_mask pointer to HART mask of HARTs assigned to the domain + * + * @return 0 on success and negative error code on failure + */ +int sbi_domain_register(struct sbi_domain *dom, + const struct sbi_hartmask *assign_mask); + +/** Finalize domain tables and startup non-root domains */ +int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid); + +/** Initialize domains */ +int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_ecall.h b/roms/opensbi/include/sbi/sbi_ecall.h new file mode 100644 index 000000000..d35708544 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_ecall.h @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_ECALL_H__ +#define __SBI_ECALL_H__ + +#include <sbi/sbi_types.h> +#include <sbi/sbi_list.h> + +#define SBI_ECALL_VERSION_MAJOR 0 +#define SBI_ECALL_VERSION_MINOR 2 +#define SBI_OPENSBI_IMPID 1 + +struct sbi_trap_regs; +struct sbi_trap_info; + +struct sbi_ecall_extension { + struct sbi_dlist head; + unsigned long extid_start; + unsigned long extid_end; + int (* probe)(unsigned long extid, unsigned long *out_val); + int (* handle)(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap); +}; + +extern struct sbi_ecall_extension ecall_base; +extern struct sbi_ecall_extension ecall_legacy; +extern struct sbi_ecall_extension ecall_time; +extern struct sbi_ecall_extension ecall_rfence; +extern struct sbi_ecall_extension ecall_ipi; +extern struct sbi_ecall_extension ecall_vendor; +extern struct sbi_ecall_extension ecall_hsm; +extern struct sbi_ecall_extension ecall_srst; + +u16 sbi_ecall_version_major(void); + +u16 sbi_ecall_version_minor(void); + +unsigned long sbi_ecall_get_impid(void); + +void sbi_ecall_set_impid(unsigned long impid); + +struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid); + +int sbi_ecall_register_extension(struct sbi_ecall_extension *ext); + +void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext); + +int sbi_ecall_handler(struct sbi_trap_regs *regs); + +int sbi_ecall_init(void); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_ecall_interface.h b/roms/opensbi/include/sbi/sbi_ecall_interface.h new file mode 100644 index 000000000..002c6f9cb --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_ecall_interface.h @@ -0,0 +1,98 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_ECALL_INTERFACE_H__ +#define __SBI_ECALL_INTERFACE_H__ + +/* clang-format off */ + +/* SBI Extension IDs */ +#define SBI_EXT_0_1_SET_TIMER 0x0 +#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 +#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 +#define SBI_EXT_0_1_CLEAR_IPI 0x3 +#define SBI_EXT_0_1_SEND_IPI 0x4 +#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7 +#define SBI_EXT_0_1_SHUTDOWN 0x8 +#define SBI_EXT_BASE 0x10 +#define SBI_EXT_TIME 0x54494D45 +#define SBI_EXT_IPI 0x735049 +#define SBI_EXT_RFENCE 0x52464E43 +#define SBI_EXT_HSM 0x48534D +#define SBI_EXT_SRST 0x53525354 + +/* SBI function IDs for BASE extension*/ +#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0 +#define SBI_EXT_BASE_GET_IMP_ID 0x1 +#define SBI_EXT_BASE_GET_IMP_VERSION 0x2 +#define SBI_EXT_BASE_PROBE_EXT 0x3 +#define SBI_EXT_BASE_GET_MVENDORID 0x4 +#define SBI_EXT_BASE_GET_MARCHID 0x5 +#define SBI_EXT_BASE_GET_MIMPID 0x6 + +/* SBI function IDs for TIME extension*/ +#define SBI_EXT_TIME_SET_TIMER 0x0 + +/* SBI function IDs for IPI extension*/ +#define SBI_EXT_IPI_SEND_IPI 0x0 + +/* SBI function IDs for RFENCE extension*/ +#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x3 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x4 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x5 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x6 + +/* SBI function IDs for HSM extension */ +#define SBI_EXT_HSM_HART_START 0x0 +#define SBI_EXT_HSM_HART_STOP 0x1 +#define SBI_EXT_HSM_HART_GET_STATUS 0x2 + +#define SBI_HSM_HART_STATUS_STARTED 0x0 +#define SBI_HSM_HART_STATUS_STOPPED 0x1 +#define SBI_HSM_HART_STATUS_START_PENDING 0x2 +#define SBI_HSM_HART_STATUS_STOP_PENDING 0x3 + +/* SBI function IDs for SRST extension */ +#define SBI_EXT_SRST_RESET 0x0 + +#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0 +#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1 +#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2 +#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT + +#define SBI_SRST_RESET_REASON_NONE 0x0 +#define SBI_SRST_RESET_REASON_SYSFAIL 0x1 + +#define SBI_SPEC_VERSION_MAJOR_OFFSET 24 +#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f +#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff +#define SBI_EXT_VENDOR_START 0x09000000 +#define SBI_EXT_VENDOR_END 0x09FFFFFF +#define SBI_EXT_FIRMWARE_START 0x0A000000 +#define SBI_EXT_FIRMWARE_END 0x0AFFFFFF + +/* SBI return error codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILED -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 + +#define SBI_LAST_ERR SBI_ERR_ALREADY_AVAILABLE + +/* clang-format on */ + +#endif diff --git a/roms/opensbi/include/sbi/sbi_emulate_csr.h b/roms/opensbi/include/sbi/sbi_emulate_csr.h new file mode 100644 index 000000000..548056a11 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_emulate_csr.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_EMULATE_CSR_H__ +#define __SBI_EMULATE_CSR_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs; + +int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs, + ulong *csr_val); + +int sbi_emulate_csr_write(int csr_num, struct sbi_trap_regs *regs, + ulong csr_val); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_error.h b/roms/opensbi/include/sbi/sbi_error.h new file mode 100644 index 000000000..3655d1220 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_error.h @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_ERROR_H__ +#define __SBI_ERROR_H__ + +#include <sbi/sbi_ecall_interface.h> + +/* clang-format off */ + +#define SBI_OK 0 +#define SBI_EFAIL SBI_ERR_FAILED +#define SBI_ENOTSUPP SBI_ERR_NOT_SUPPORTED +#define SBI_EINVAL SBI_ERR_INVALID_PARAM +#define SBI_EDENIED SBI_ERR_DENIED +#define SBI_EINVALID_ADDR SBI_ERR_INVALID_ADDRESS +#define SBI_EALREADY SBI_ERR_ALREADY_AVAILABLE + +#define SBI_ENODEV -1000 +#define SBI_ENOSYS -1001 +#define SBI_ETIMEDOUT -1002 +#define SBI_EIO -1003 +#define SBI_EILL -1004 +#define SBI_ENOSPC -1005 +#define SBI_ENOMEM -1006 +#define SBI_ETRAP -1007 +#define SBI_EUNKNOWN -1008 +#define SBI_ENOENT -1009 + +/* clang-format on */ + +#endif diff --git a/roms/opensbi/include/sbi/sbi_fifo.h b/roms/opensbi/include/sbi/sbi_fifo.h new file mode 100644 index 000000000..bc8f8f600 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_fifo.h @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra<atish.patra@wdc.com> + * + */ + +#ifndef __SBI_FIFO_H__ +#define __SBI_FIFO_H__ + +#include <sbi/riscv_locks.h> +#include <sbi/sbi_types.h> + +struct sbi_fifo { + void *queue; + spinlock_t qlock; + u16 entry_size; + u16 num_entries; + u16 avail; + u16 tail; +}; + +enum sbi_fifo_inplace_update_types { + SBI_FIFO_SKIP, + SBI_FIFO_UPDATED, + SBI_FIFO_UNCHANGED, +}; + +int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data); +int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data); +void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries, + u16 entry_size); +bool sbi_fifo_is_empty(struct sbi_fifo *fifo); +bool sbi_fifo_is_full(struct sbi_fifo *fifo); +int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in, + int (*fptr)(void *in, void *data)); +u16 sbi_fifo_avail(struct sbi_fifo *fifo); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_hart.h b/roms/opensbi/include/sbi/sbi_hart.h new file mode 100644 index 000000000..ec9e30f91 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_hart.h @@ -0,0 +1,56 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_HART_H__ +#define __SBI_HART_H__ + +#include <sbi/sbi_types.h> + +/** Possible feature flags of a hart */ +enum sbi_hart_features { + /** Hart has S-mode counter enable */ + SBI_HART_HAS_SCOUNTEREN = (1 << 0), + /** Hart has M-mode counter enable */ + SBI_HART_HAS_MCOUNTEREN = (1 << 1), + /** HART has timer csr implementation in hardware */ + SBI_HART_HAS_TIME = (1 << 2), + + /** Last index of Hart features*/ + SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_TIME, +}; + +struct sbi_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_count(struct sbi_scratch *scratch); +void sbi_hart_delegation_dump(struct sbi_scratch *scratch, + const char *prefix, const char *suffix); +unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch); +unsigned long sbi_hart_pmp_granularity(struct sbi_scratch *scratch); +unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch); +int sbi_hart_pmp_configure(struct sbi_scratch *scratch); +bool sbi_hart_has_feature(struct sbi_scratch *scratch, unsigned long feature); +void sbi_hart_get_features_str(struct sbi_scratch *scratch, + char *features_str, int nfstr); + +void __attribute__((noreturn)) sbi_hart_hang(void); + +void __attribute__((noreturn)) +sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1, + unsigned long next_addr, unsigned long next_mode, + bool next_virt); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_hartmask.h b/roms/opensbi/include/sbi/sbi_hartmask.h new file mode 100644 index 000000000..f1cef0c2a --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_hartmask.h @@ -0,0 +1,141 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_HARTMASK_H__ +#define __SBI_HARTMASK_H__ + +#include <sbi/sbi_bitmap.h> + +/** + * Maximum number of bits in a hartmask + * + * The hartmask is indexed using physical HART id so this define + * also represents the maximum number of HART ids generic OpenSBI + * can handle. + */ +#define SBI_HARTMASK_MAX_BITS 128 + +/** Representation of hartmask */ +struct sbi_hartmask { + DECLARE_BITMAP(bits, SBI_HARTMASK_MAX_BITS); +}; + +/** Initialize hartmask to zero */ +#define SBI_HARTMASK_INIT(__m) \ + bitmap_zero(((__m)->bits), SBI_HARTMASK_MAX_BITS) + +/** Initialize hartmask to zero except a particular HART id */ +#define SBI_HARTMASK_INIT_EXCEPT(__m, __h) \ + bitmap_zero_except(((__m)->bits), (__h), SBI_HARTMASK_MAX_BITS) + +/** + * Get underlying bitmap of hartmask + * @param m the hartmask pointer + */ +#define sbi_hartmask_bits(__m) ((__m)->bits) + +/** + * Set a HART in hartmask + * @param h HART id to set + * @param m the hartmask pointer + */ +static inline void sbi_hartmask_set_hart(u32 h, struct sbi_hartmask *m) +{ + if (h < SBI_HARTMASK_MAX_BITS) + __set_bit(h, m->bits); +} + +/** + * Clear a HART in hartmask + * @param h HART id to clear + * @param m the hartmask pointer + */ +static inline void sbi_hartmask_clear_hart(u32 h, struct sbi_hartmask *m) +{ + if (h < SBI_HARTMASK_MAX_BITS) + __clear_bit(h, m->bits); +} + +/** + * Test a HART in hartmask + * @param h HART id to test + * @param m the hartmask pointer + */ +static inline int sbi_hartmask_test_hart(u32 h, const struct sbi_hartmask *m) +{ + if (h < SBI_HARTMASK_MAX_BITS) + return __test_bit(h, m->bits); + return 0; +} + +/** + * Set all HARTs in a hartmask + * @param dstp the hartmask pointer + */ +static inline void sbi_hartmask_set_all(struct sbi_hartmask *dstp) +{ + bitmap_fill(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS); +} + +/** + * Clear all HARTs in a hartmask + * @param dstp the hartmask pointer + */ +static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp) +{ + bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS); +} + +/** + * *dstp = *src1p & *src2p + * @param dstp the hartmask result + * @param src1p the first input + * @param src2p the second input + */ +static inline void sbi_hartmask_and(struct sbi_hartmask *dstp, + const struct sbi_hartmask *src1p, + const struct sbi_hartmask *src2p) +{ + bitmap_and(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p), + sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS); +} + +/** + * *dstp = *src1p | *src2p + * @param dstp the hartmask result + * @param src1p the first input + * @param src2p the second input + */ +static inline void sbi_hartmask_or(struct sbi_hartmask *dstp, + const struct sbi_hartmask *src1p, + const struct sbi_hartmask *src2p) +{ + bitmap_or(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p), + sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS); +} + +/** + * *dstp = *src1p ^ *src2p + * @param dstp the hartmask result + * @param src1p the first input + * @param src2p the second input + */ +static inline void sbi_hartmask_xor(struct sbi_hartmask *dstp, + const struct sbi_hartmask *src1p, + const struct sbi_hartmask *src2p) +{ + bitmap_xor(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p), + sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS); +} + +/** Iterate over each HART in hartmask */ +#define sbi_hartmask_for_each_hart(__h, __m) \ + for_each_set_bit(__h, (__m)->bits, SBI_HARTMASK_MAX_BITS) + +#endif diff --git a/roms/opensbi/include/sbi/sbi_hfence.h b/roms/opensbi/include/sbi/sbi_hfence.h new file mode 100644 index 000000000..4420f2793 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_hfence.h @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_FENCE_H__ +#define __SBI_FENCE_H__ + +/** Invalidate Stage2 TLBs for given VMID and guest physical address */ +void __sbi_hfence_gvma_vmid_gpa(unsigned long gpa, unsigned long vmid); + +/** Invalidate Stage2 TLBs for given VMID */ +void __sbi_hfence_gvma_vmid(unsigned long vmid); + +/** Invalidate Stage2 TLBs for given guest physical address */ +void __sbi_hfence_gvma_gpa(unsigned long gpa); + +/** Invalidate all possible Stage2 TLBs */ +void __sbi_hfence_gvma_all(void); + +/** Invalidate unified TLB entries for given asid and guest virtual address */ +void __sbi_hfence_vvma_asid_va(unsigned long va, unsigned long asid); + +/** Invalidate unified TLB entries for given ASID for a guest*/ +void __sbi_hfence_vvma_asid(unsigned long asid); + +/** Invalidate unified TLB entries for a given guest virtual address */ +void __sbi_hfence_vvma_va(unsigned long va); + +/** Invalidate all possible Stage2 TLBs */ +void __sbi_hfence_vvma_all(void); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_hsm.h b/roms/opensbi/include/sbi/sbi_hsm.h new file mode 100644 index 000000000..482338309 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_hsm.h @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#ifndef __SBI_HSM_H__ +#define __SBI_HSM_H__ + +#include <sbi/sbi_types.h> + +/** Hart state values **/ +#define SBI_HART_STOPPED 0 +#define SBI_HART_STOPPING 1 +#define SBI_HART_STARTING 2 +#define SBI_HART_STARTED 3 +#define SBI_HART_UNKNOWN 4 + +struct sbi_domain; +struct sbi_scratch; + +int sbi_hsm_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot); +void __noreturn sbi_hsm_exit(struct sbi_scratch *scratch); + +int sbi_hsm_hart_start(struct sbi_scratch *scratch, + const struct sbi_domain *dom, + u32 hartid, ulong saddr, ulong smode, ulong priv); +int sbi_hsm_hart_stop(struct sbi_scratch *scratch, bool exitnow); +int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid); +int sbi_hsm_hart_state_to_status(int state); +int sbi_hsm_hart_started_mask(const struct sbi_domain *dom, + ulong hbase, ulong *out_hmask); +void sbi_hsm_prepare_next_jump(struct sbi_scratch *scratch, u32 hartid); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_illegal_insn.h b/roms/opensbi/include/sbi/sbi_illegal_insn.h new file mode 100644 index 000000000..0397935e2 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_illegal_insn.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_ILLEGAl_INSN_H__ +#define __SBI_ILLEGAl_INSN_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs; + +int sbi_illegal_insn_handler(ulong insn, struct sbi_trap_regs *regs); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_init.h b/roms/opensbi/include/sbi/sbi_init.h new file mode 100644 index 000000000..74eb1c075 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_init.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_INIT_H__ +#define __SBI_INIT_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +void __noreturn sbi_init(struct sbi_scratch *scratch); + +unsigned long sbi_init_count(u32 hartid); + +void __noreturn sbi_exit(struct sbi_scratch *scratch); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_ipi.h b/roms/opensbi/include/sbi/sbi_ipi.h new file mode 100644 index 000000000..617872c1b --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_ipi.h @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_IPI_H__ +#define __SBI_IPI_H__ + +#include <sbi/sbi_types.h> + +/* clang-format off */ + +#define SBI_IPI_EVENT_MAX __riscv_xlen + +/* clang-format on */ + +struct sbi_scratch; + +/** IPI event operations or callbacks */ +struct sbi_ipi_event_ops { + /** Name of the IPI event operations */ + char name[32]; + + /** + * Update callback to save/enqueue data for remote HART + * Note: This is an optional callback and it is called just before + * triggering IPI to remote HART. + */ + int (* update)(struct sbi_scratch *scratch, + struct sbi_scratch *remote_scratch, + u32 remote_hartid, void *data); + + /** + * Sync callback to wait for remote HART + * Note: This is an optional callback and it is called just after + * triggering IPI to remote HART. + */ + void (* sync)(struct sbi_scratch *scratch); + + /** + * Process callback to handle IPI event + * Note: This is a mandatory callback and it is called on the + * remote HART after IPI is triggered. + */ + void (* process)(struct sbi_scratch *scratch); +}; + +int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data); + +int sbi_ipi_event_create(const struct sbi_ipi_event_ops *ops); + +void sbi_ipi_event_destroy(u32 event); + +int sbi_ipi_send_smode(ulong hmask, ulong hbase); + +void sbi_ipi_clear_smode(void); + +int sbi_ipi_send_halt(ulong hmask, ulong hbase); + +void sbi_ipi_process(void); + +int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot); + +void sbi_ipi_exit(struct sbi_scratch *scratch); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_list.h b/roms/opensbi/include/sbi/sbi_list.h new file mode 100644 index 000000000..1174ad274 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_list.h @@ -0,0 +1,152 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Simple doubly-linked list library. + * + * Adapted from Xvisor source file libs/include/libs/list.h + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_LIST_H__ +#define __SBI_LIST_H__ + +#include <sbi/sbi_types.h> + +#define SBI_LIST_POISON_PREV 0xDEADBEEF +#define SBI_LIST_POISON_NEXT 0xFADEBABE + +struct sbi_dlist { + struct sbi_dlist *next, *prev; +}; + +#define SBI_LIST_HEAD_INIT(__lname) { &(__lname), &(__lname) } + +#define SBI_LIST_HEAD(_lname) \ +struct sbi_dlist _lname = SBI_LIST_HEAD_INIT(_lname) + +#define SBI_INIT_LIST_HEAD(ptr) \ +do { \ + (ptr)->next = ptr; (ptr)->prev = ptr; \ +} while (0); + +static inline void __sbi_list_add(struct sbi_dlist *new, + struct sbi_dlist *prev, + struct sbi_dlist *next) +{ + new->prev = prev; + new->next = next; + prev->next = new; + next->prev = new; +} + +/** + * Adds the new node after the given head. + * @param new New node that needs to be added to list. + * @param head List head after which the "new" node should be added. + * Note: the new node is added after the head. + */ +static inline void sbi_list_add(struct sbi_dlist *new, struct sbi_dlist *head) +{ + __sbi_list_add(new, head, head->next); +} + +/** + * Adds a node at the tail where tnode points to tail node. + * @param new The new node to be added before tail. + * @param tnode The current tail node. + * Note: the new node is added before tail node. + */ +static inline void sbi_list_add_tail(struct sbi_dlist *new, + struct sbi_dlist *tnode) +{ + __sbi_list_add(new, tnode->prev, tnode); +} + +static inline void __sbi_list_del(struct sbi_dlist *prev, + struct sbi_dlist *next) +{ + prev->next = next; + next->prev = prev; +} + +static inline void __sbi_list_del_entry(struct sbi_dlist *entry) +{ + __sbi_list_del(entry->prev, entry->next); +} + +/** + * Deletes a given entry from list. + * @param node Node to be deleted. + */ +static inline void sbi_list_del(struct sbi_dlist *entry) +{ + __sbi_list_del(entry->prev, entry->next); + entry->next = (void *)SBI_LIST_POISON_NEXT; + entry->prev = (void *)SBI_LIST_POISON_PREV; +} + +/** + * Deletes entry from list and reinitialize it. + * @param entry the element to delete from the list. + */ +static inline void sbi_list_del_init(struct sbi_dlist *entry) +{ + __sbi_list_del_entry(entry); + SBI_INIT_LIST_HEAD(entry); +} + +/** + * Get the struct for this entry + * @param ptr the &struct list_head pointer. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_struct within the struct. + */ +#define sbi_list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * Get the first element from a list + * @param ptr the list head to take the element from. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_struct within the struct. + * + * Note: that list is expected to be not empty. + */ +#define sbi_list_first_entry(ptr, type, member) \ + sbi_list_entry((ptr)->next, type, member) + +/** + * Get the last element from a list + * @param ptr the list head to take the element from. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_head within the struct. + * + * Note: that list is expected to be not empty. + */ +#define sbi_list_last_entry(ptr, type, member) \ + sbi_list_entry((ptr)->prev, type, member) + +/** + * Iterate over a list + * @param pos the &struct list_head to use as a loop cursor. + * @param head the head for your list. + */ +#define sbi_list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * Iterate over list of given type + * @param pos the type * to use as a loop cursor. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + */ +#define sbi_list_for_each_entry(pos, head, member) \ + for (pos = sbi_list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = sbi_list_entry(pos->member.next, typeof(*pos), member)) + +#endif diff --git a/roms/opensbi/include/sbi/sbi_math.h b/roms/opensbi/include/sbi/sbi_math.h new file mode 100644 index 000000000..564fd585c --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_math.h @@ -0,0 +1,15 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#ifndef __SBI_MATH_H__ +#define __SBI_MATH_H__ + +unsigned long log2roundup(unsigned long x); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_misaligned_ldst.h b/roms/opensbi/include/sbi/sbi_misaligned_ldst.h new file mode 100644 index 000000000..ab27eb422 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_misaligned_ldst.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_MISALIGNED_LDST_H__ +#define __SBI_MISALIGNED_LDST_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs; + +int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst, + struct sbi_trap_regs *regs); + +int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst, + struct sbi_trap_regs *regs); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_platform.h b/roms/opensbi/include/sbi/sbi_platform.h new file mode 100644 index 000000000..cc7e3ff99 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_platform.h @@ -0,0 +1,757 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_PLATFORM_H__ +#define __SBI_PLATFORM_H__ + +/** + * OpenSBI 32-bit platform version with: + * 1. upper 16-bits as major number + * 2. lower 16-bits as minor number + */ +#define SBI_PLATFORM_VERSION(Major, Minor) ((Major << 16) | Minor) + +/** Offset of opensbi_version in struct sbi_platform */ +#define SBI_PLATFORM_OPENSBI_VERSION_OFFSET (0x00) +/** Offset of platform_version in struct sbi_platform */ +#define SBI_PLATFORM_VERSION_OFFSET (0x04) +/** Offset of name in struct sbi_platform */ +#define SBI_PLATFORM_NAME_OFFSET (0x08) +/** Offset of features in struct sbi_platform */ +#define SBI_PLATFORM_FEATURES_OFFSET (0x48) +/** Offset of hart_count in struct sbi_platform */ +#define SBI_PLATFORM_HART_COUNT_OFFSET (0x50) +/** Offset of hart_stack_size in struct sbi_platform */ +#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54) +/** Offset of platform_ops_addr in struct sbi_platform */ +#define SBI_PLATFORM_OPS_OFFSET (0x58) +/** Offset of firmware_context in struct sbi_platform */ +#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x58 + __SIZEOF_POINTER__) +/** Offset of hart_index2id in struct sbi_platform */ +#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x58 + (__SIZEOF_POINTER__ * 2)) + +#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12) + +#ifndef __ASSEMBLY__ + +#include <sbi/sbi_ecall_interface.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_scratch.h> +#include <sbi/sbi_version.h> + +struct sbi_domain_memregion; +struct sbi_trap_info; +struct sbi_trap_regs; + +/** Possible feature flags of a platform */ +enum sbi_platform_features { + /** Platform has timer value */ + SBI_PLATFORM_HAS_TIMER_VALUE = (1 << 0), + /** Platform has HART hotplug support */ + SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1), + /** Platform has fault delegation support */ + SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 2), + /** Platform has custom secondary hart booting support */ + SBI_PLATFORM_HAS_HART_SECONDARY_BOOT = (1 << 3), + + /** Last index of Platform features*/ + SBI_PLATFORM_HAS_LAST_FEATURE = SBI_PLATFORM_HAS_HART_SECONDARY_BOOT, +}; + +/** Default feature set for a platform */ +#define SBI_PLATFORM_DEFAULT_FEATURES \ + (SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_MFAULTS_DELEGATION) + +/** Platform functions */ +struct sbi_platform_operations { + /** Platform early initialization */ + int (*early_init)(bool cold_boot); + /** Platform final initialization */ + int (*final_init)(bool cold_boot); + + /** Platform early exit */ + void (*early_exit)(void); + /** Platform final exit */ + void (*final_exit)(void); + + /** + * For platforms that do not implement misa, non-standard + * methods are needed to determine cpu extension. + */ + int (*misa_check_extension)(char ext); + + /** + * For platforms that do not implement misa, non-standard + * methods are needed to get MXL field of misa. + */ + int (*misa_get_xlen)(void); + + /** Get platform specific root domain memory regions */ + struct sbi_domain_memregion *(*domains_root_regions)(void); + /** Initialize (or populate) domains for the platform */ + int (*domains_init)(void); + + /** Write a character to the platform console output */ + void (*console_putc)(char ch); + /** Read a character from the platform console input */ + int (*console_getc)(void); + /** Initialize the platform console */ + int (*console_init)(void); + + /** Initialize the platform interrupt controller for current HART */ + int (*irqchip_init)(bool cold_boot); + /** Exit the platform interrupt controller for current HART */ + void (*irqchip_exit)(void); + + /** Send IPI to a target HART */ + void (*ipi_send)(u32 target_hart); + /** Clear IPI for a target HART */ + void (*ipi_clear)(u32 target_hart); + /** Initialize IPI for current HART */ + int (*ipi_init)(bool cold_boot); + /** Exit IPI for current HART */ + void (*ipi_exit)(void); + + /** Get tlb flush limit value **/ + u64 (*get_tlbr_flush_limit)(void); + + /** Get platform timer value */ + u64 (*timer_value)(void); + /** Start platform timer event for current HART */ + void (*timer_event_start)(u64 next_event); + /** Stop platform timer event for current HART */ + void (*timer_event_stop)(void); + /** Initialize platform timer for current HART */ + int (*timer_init)(bool cold_boot); + /** Exit platform timer for current HART */ + void (*timer_exit)(void); + + /** Bringup the given hart */ + int (*hart_start)(u32 hartid, ulong saddr); + /** + * Stop the current hart from running. This call doesn't expect to + * return if success. + */ + int (*hart_stop)(void); + + /* Check whether reset type and reason supported by the platform */ + int (*system_reset_check)(u32 reset_type, u32 reset_reason); + /** Reset the platform */ + void (*system_reset)(u32 reset_type, u32 reset_reason); + + /** platform specific SBI extension implementation probe function */ + int (*vendor_ext_check)(long extid); + /** platform specific SBI extension implementation provider */ + int (*vendor_ext_provider)(long extid, long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_value, + struct sbi_trap_info *out_trap); +}; + +/** Platform default per-HART stack size for exception/interrupt handling */ +#define SBI_PLATFORM_DEFAULT_HART_STACK_SIZE 8192 + +/** Representation of a platform */ +struct sbi_platform { + /** + * OpenSBI version this sbi_platform is based on. + * It's a 32-bit value where upper 16-bits are major number + * and lower 16-bits are minor number + */ + u32 opensbi_version; + /** + * OpenSBI platform version released by vendor. + * It's a 32-bit value where upper 16-bits are major number + * and lower 16-bits are minor number + */ + u32 platform_version; + /** Name of the platform */ + char name[64]; + /** Supported features */ + u64 features; + /** Total number of HARTs */ + u32 hart_count; + /** Per-HART stack size for exception/interrupt handling */ + u32 hart_stack_size; + /** Pointer to sbi platform operations */ + unsigned long platform_ops_addr; + /** Pointer to system firmware specific context */ + unsigned long firmware_context; + /** + * HART index to HART id table + * + * For used HART index <abc>: + * hart_index2id[<abc>] = some HART id + * For unused HART index <abc>: + * hart_index2id[<abc>] = -1U + * + * If hart_index2id == NULL then we assume identity mapping + * hart_index2id[<abc>] = <abc> + * + * We have only two restrictions: + * 1. HART index < sbi_platform hart_count + * 2. HART id < SBI_HARTMASK_MAX_BITS + */ + const u32 *hart_index2id; +}; + +/** Get pointer to sbi_platform for sbi_scratch pointer */ +#define sbi_platform_ptr(__s) \ + ((const struct sbi_platform *)((__s)->platform_addr)) +/** Get pointer to sbi_platform for current HART */ +#define sbi_platform_thishart_ptr() ((const struct sbi_platform *) \ + (sbi_scratch_thishart_ptr()->platform_addr)) +/** Get pointer to platform_ops_addr from platform pointer **/ +#define sbi_platform_ops(__p) \ + ((const struct sbi_platform_operations *)(__p)->platform_ops_addr) + +/** Check whether the platform supports timer value */ +#define sbi_platform_has_timer_value(__p) \ + ((__p)->features & SBI_PLATFORM_HAS_TIMER_VALUE) +/** Check whether the platform supports HART hotplug */ +#define sbi_platform_has_hart_hotplug(__p) \ + ((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG) +/** Check whether the platform supports fault delegation */ +#define sbi_platform_has_mfaults_delegation(__p) \ + ((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION) +/** Check whether the platform supports custom secondary hart booting support */ +#define sbi_platform_has_hart_secondary_boot(__p) \ + ((__p)->features & SBI_PLATFORM_HAS_HART_SECONDARY_BOOT) + +/** + * Get HART index for the given HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * + * @return 0 <= value < hart_count for valid HART otherwise -1U + */ +u32 sbi_platform_hart_index(const struct sbi_platform *plat, u32 hartid); + +/** + * Get the platform features in string format + * + * @param plat pointer to struct sbi_platform + * @param features_str pointer to a char array where the features string will be + * updated + * @param nfstr length of the features_str. The feature string will be truncated + * if nfstr is not long enough. + */ +void sbi_platform_get_features_str(const struct sbi_platform *plat, + char *features_str, int nfstr); + +/** + * Get name of the platform + * + * @param plat pointer to struct sbi_platform + * + * @return pointer to platform name on success and "Unknown" on failure + */ +static inline const char *sbi_platform_name(const struct sbi_platform *plat) +{ + if (plat) + return plat->name; + return "Unknown"; +} + +/** + * Get the platform features + * + * @param plat pointer to struct sbi_platform + * + * @return the features value currently set for the given platform + */ +static inline unsigned long sbi_platform_get_features( + const struct sbi_platform *plat) +{ + if (plat) + return plat->features; + return 0; +} + +/** + * Get platform specific tlb range flush maximum value. Any request with size + * higher than this is upgraded to a full flush. + * + * @param plat pointer to struct sbi_platform + * + * @return tlb range flush limit value. Returns a default (page size) if not + * defined by platform. + */ +static inline u64 sbi_platform_tlbr_flush_limit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->get_tlbr_flush_limit) + return sbi_platform_ops(plat)->get_tlbr_flush_limit(); + return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT; +} + +/** + * Get total number of HARTs supported by the platform + * + * @param plat pointer to struct sbi_platform + * + * @return total number of HARTs + */ +static inline u32 sbi_platform_hart_count(const struct sbi_platform *plat) +{ + if (plat) + return plat->hart_count; + return 0; +} + +/** + * Get per-HART stack size for exception/interrupt handling + * + * @param plat pointer to struct sbi_platform + * + * @return stack size in bytes + */ +static inline u32 sbi_platform_hart_stack_size(const struct sbi_platform *plat) +{ + if (plat) + return plat->hart_stack_size; + return 0; +} + +/** + * Check whether given HART is invalid + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * + * @return TRUE if HART is invalid and FALSE otherwise + */ +static inline bool sbi_platform_hart_invalid(const struct sbi_platform *plat, + u32 hartid) +{ + if (!plat) + return TRUE; + if (plat->hart_count <= sbi_platform_hart_index(plat, hartid)) + return TRUE; + return FALSE; +} + +/** + * Bringup a given hart from previous stage. Platform should implement this + * operation if they support a custom mechanism to start a hart. Otherwise, + * a generic WFI based approach will be used to start/stop a hart in OpenSBI. + * + * @param plat pointer to struct sbi_platform + * @param hartid HART id + * @param saddr M-mode start physical address for the HART + * + * @return 0 if sucessful and negative error code on failure + */ +static inline int sbi_platform_hart_start(const struct sbi_platform *plat, + u32 hartid, ulong saddr) +{ + if (plat && sbi_platform_ops(plat)->hart_start) + return sbi_platform_ops(plat)->hart_start(hartid, saddr); + return SBI_ENOTSUPP; +} + +/** + * Stop the current hart in OpenSBI. + * + * @param plat pointer to struct sbi_platform + * + * @return Negative error code on failure. It doesn't return on success. + */ +static inline int sbi_platform_hart_stop(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->hart_stop) + return sbi_platform_ops(plat)->hart_stop(); + return SBI_ENOTSUPP; +} + +/** + * Early initialization for current HART + * + * @param plat pointer to struct sbi_platform + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_early_init(const struct sbi_platform *plat, + bool cold_boot) +{ + if (plat && sbi_platform_ops(plat)->early_init) + return sbi_platform_ops(plat)->early_init(cold_boot); + return 0; +} + +/** + * Final initialization for current HART + * + * @param plat pointer to struct sbi_platform + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_final_init(const struct sbi_platform *plat, + bool cold_boot) +{ + if (plat && sbi_platform_ops(plat)->final_init) + return sbi_platform_ops(plat)->final_init(cold_boot); + return 0; +} + +/** + * Early exit for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void sbi_platform_early_exit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->early_exit) + sbi_platform_ops(plat)->early_exit(); +} + +/** + * Final exit for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void sbi_platform_final_exit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->final_exit) + sbi_platform_ops(plat)->final_exit(); +} + +/** + * Check CPU extension in MISA + * + * @param plat pointer to struct sbi_platform + * @param ext shorthand letter for CPU extensions + * + * @return zero for not-supported and non-zero for supported + */ +static inline int sbi_platform_misa_extension(const struct sbi_platform *plat, + char ext) +{ + if (plat && sbi_platform_ops(plat)->misa_check_extension) + return sbi_platform_ops(plat)->misa_check_extension(ext); + return 0; +} + +/** + * Get MXL field of MISA + * + * @param plat pointer to struct sbi_platform + * + * @return 1/2/3 on success and error code on failure + */ +static inline int sbi_platform_misa_xlen(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->misa_get_xlen) + return sbi_platform_ops(plat)->misa_get_xlen(); + return -1; +} + +/** + * Get platform specific root domain memory regions + * + * @param plat pointer to struct sbi_platform + * + * @return an array of memory regions terminated by a region with order zero + * or NULL for no memory regions + */ +static inline struct sbi_domain_memregion * +sbi_platform_domains_root_regions(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->domains_root_regions) + return sbi_platform_ops(plat)->domains_root_regions(); + return NULL; +} + +/** + * Initialize (or populate) domains for the platform + * + * @param plat pointer to struct sbi_platform + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_domains_init(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->domains_init) + return sbi_platform_ops(plat)->domains_init(); + return 0; +} + +/** + * Write a character to the platform console output + * + * @param plat pointer to struct sbi_platform + * @param ch character to write + */ +static inline void sbi_platform_console_putc(const struct sbi_platform *plat, + char ch) +{ + if (plat && sbi_platform_ops(plat)->console_putc) + sbi_platform_ops(plat)->console_putc(ch); +} + +/** + * Read a character from the platform console input + * + * @param plat pointer to struct sbi_platform + * + * @return character read from console input + */ +static inline int sbi_platform_console_getc(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->console_getc) + return sbi_platform_ops(plat)->console_getc(); + return -1; +} + +/** + * Initialize the platform console + * + * @param plat pointer to struct sbi_platform + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_console_init(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->console_init) + return sbi_platform_ops(plat)->console_init(); + return 0; +} + +/** + * Initialize the platform interrupt controller for current HART + * + * @param plat pointer to struct sbi_platform + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat, + bool cold_boot) +{ + if (plat && sbi_platform_ops(plat)->irqchip_init) + return sbi_platform_ops(plat)->irqchip_init(cold_boot); + return 0; +} + +/** + * Exit the platform interrupt controller for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void sbi_platform_irqchip_exit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->irqchip_exit) + sbi_platform_ops(plat)->irqchip_exit(); +} + +/** + * Send IPI to a target HART + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of IPI target + */ +static inline void sbi_platform_ipi_send(const struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && sbi_platform_ops(plat)->ipi_send) + sbi_platform_ops(plat)->ipi_send(target_hart); +} + +/** + * Clear IPI for a target HART + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of IPI target + */ +static inline void sbi_platform_ipi_clear(const struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && sbi_platform_ops(plat)->ipi_clear) + sbi_platform_ops(plat)->ipi_clear(target_hart); +} + +/** + * Initialize the platform IPI support for current HART + * + * @param plat pointer to struct sbi_platform + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_ipi_init(const struct sbi_platform *plat, + bool cold_boot) +{ + if (plat && sbi_platform_ops(plat)->ipi_init) + return sbi_platform_ops(plat)->ipi_init(cold_boot); + return 0; +} + +/** + * Exit the platform IPI support for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void sbi_platform_ipi_exit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->ipi_exit) + sbi_platform_ops(plat)->ipi_exit(); +} + +/** + * Get platform timer value + * + * @param plat pointer to struct sbi_platform + * + * @return 64-bit timer value + */ +static inline u64 sbi_platform_timer_value(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->timer_value) + return sbi_platform_ops(plat)->timer_value(); + return 0; +} + +/** + * Start platform timer event for current HART + * + * @param plat pointer to struct struct sbi_platform + * @param next_event timer value when timer event will happen + */ +static inline void +sbi_platform_timer_event_start(const struct sbi_platform *plat, u64 next_event) +{ + if (plat && sbi_platform_ops(plat)->timer_event_start) + sbi_platform_ops(plat)->timer_event_start(next_event); +} + +/** + * Stop platform timer event for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void +sbi_platform_timer_event_stop(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->timer_event_stop) + sbi_platform_ops(plat)->timer_event_stop(); +} + +/** + * Initialize the platform timer for current HART + * + * @param plat pointer to struct sbi_platform + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_timer_init(const struct sbi_platform *plat, + bool cold_boot) +{ + if (plat && sbi_platform_ops(plat)->timer_init) + return sbi_platform_ops(plat)->timer_init(cold_boot); + return 0; +} + +/** + * Exit the platform timer for current HART + * + * @param plat pointer to struct sbi_platform + */ +static inline void sbi_platform_timer_exit(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->timer_exit) + sbi_platform_ops(plat)->timer_exit(); +} + +/** + * Check whether reset type and reason supported by the platform + * + * @param plat pointer to struct sbi_platform + * @param reset_type type of reset + * @param reset_reason reason for reset + * + * @return 0 if reset type and reason not supported and 1 if supported + */ +static inline int sbi_platform_system_reset_check( + const struct sbi_platform *plat, + u32 reset_type, u32 reset_reason) +{ + if (plat && sbi_platform_ops(plat)->system_reset_check) + return sbi_platform_ops(plat)->system_reset_check(reset_type, + reset_reason); + return 0; +} + +/** + * Reset the platform + * + * This function will not return for supported reset type and reset reason + * + * @param plat pointer to struct sbi_platform + * @param reset_type type of reset + * @param reset_reason reason for reset + */ +static inline void sbi_platform_system_reset(const struct sbi_platform *plat, + u32 reset_type, u32 reset_reason) +{ + if (plat && sbi_platform_ops(plat)->system_reset) + sbi_platform_ops(plat)->system_reset(reset_type, reset_reason); +} + +/** + * Check if a vendor extension is implemented or not. + * + * @param plat pointer to struct sbi_platform + * @param extid vendor SBI extension id + * + * @return 0 if extid is not implemented and 1 if implemented + */ +static inline int sbi_platform_vendor_ext_check(const struct sbi_platform *plat, + long extid) +{ + if (plat && sbi_platform_ops(plat)->vendor_ext_check) + return sbi_platform_ops(plat)->vendor_ext_check(extid); + + return 0; +} + +/** + * Invoke platform specific vendor SBI extension implementation. + * + * @param plat pointer to struct sbi_platform + * @param extid vendor SBI extension id + * @param funcid SBI function id within the extension id + * @param regs pointer to trap registers passed by the caller + * @param out_value output value that can be filled by the callee + * @param out_trap trap info that can be filled by the callee + * + * @return 0 on success and negative error code on failure + */ +static inline int sbi_platform_vendor_ext_provider( + const struct sbi_platform *plat, + long extid, long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_value, + struct sbi_trap_info *out_trap) +{ + if (plat && sbi_platform_ops(plat)->vendor_ext_provider) { + return sbi_platform_ops(plat)->vendor_ext_provider(extid, + funcid, regs, + out_value, + out_trap); + } + + return SBI_ENOTSUPP; +} + +#endif + +#endif diff --git a/roms/opensbi/include/sbi/sbi_scratch.h b/roms/opensbi/include/sbi/sbi_scratch.h new file mode 100644 index 000000000..e35122bed --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_scratch.h @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_SCRATCH_H__ +#define __SBI_SCRATCH_H__ + +#include <sbi/riscv_asm.h> + +/* clang-format off */ + +/** Offset of fw_start member in sbi_scratch */ +#define SBI_SCRATCH_FW_START_OFFSET (0 * __SIZEOF_POINTER__) +/** Offset of fw_size member in sbi_scratch */ +#define SBI_SCRATCH_FW_SIZE_OFFSET (1 * __SIZEOF_POINTER__) +/** Offset of next_arg1 member in sbi_scratch */ +#define SBI_SCRATCH_NEXT_ARG1_OFFSET (2 * __SIZEOF_POINTER__) +/** Offset of next_addr member in sbi_scratch */ +#define SBI_SCRATCH_NEXT_ADDR_OFFSET (3 * __SIZEOF_POINTER__) +/** Offset of next_mode member in sbi_scratch */ +#define SBI_SCRATCH_NEXT_MODE_OFFSET (4 * __SIZEOF_POINTER__) +/** Offset of warmboot_addr member in sbi_scratch */ +#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET (5 * __SIZEOF_POINTER__) +/** Offset of platform_addr member in sbi_scratch */ +#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET (6 * __SIZEOF_POINTER__) +/** Offset of hartid_to_scratch member in sbi_scratch */ +#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__) +/** Offset of trap_exit member in sbi_scratch */ +#define SBI_SCRATCH_TRAP_EXIT_OFFSET (8 * __SIZEOF_POINTER__) +/** Offset of tmp0 member in sbi_scratch */ +#define SBI_SCRATCH_TMP0_OFFSET (9 * __SIZEOF_POINTER__) +/** Offset of options member in sbi_scratch */ +#define SBI_SCRATCH_OPTIONS_OFFSET (10 * __SIZEOF_POINTER__) +/** Offset of extra space in sbi_scratch */ +#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (11 * __SIZEOF_POINTER__) +/** Maximum size of sbi_scratch (4KB) */ +#define SBI_SCRATCH_SIZE (0x1000) + +/* clang-format on */ + +#ifndef __ASSEMBLY__ + +#include <sbi/sbi_types.h> + +/** Representation of per-HART scratch space */ +struct sbi_scratch { + /** Start (or base) address of firmware linked to OpenSBI library */ + unsigned long fw_start; + /** Size (in bytes) of firmware linked to OpenSBI library */ + unsigned long fw_size; + /** Arg1 (or 'a1' register) of next booting stage for this HART */ + unsigned long next_arg1; + /** Address of next booting stage for this HART */ + unsigned long next_addr; + /** Priviledge mode of next booting stage for this HART */ + unsigned long next_mode; + /** Warm boot entry point address for this HART */ + unsigned long warmboot_addr; + /** Address of sbi_platform */ + unsigned long platform_addr; + /** Address of HART ID to sbi_scratch conversion function */ + unsigned long hartid_to_scratch; + /** Address of trap exit function */ + unsigned long trap_exit; + /** Temporary storage */ + unsigned long tmp0; + /** Options for OpenSBI library */ + unsigned long options; +}; + +/** Possible options for OpenSBI library */ +enum sbi_scratch_options { + /** Disable prints during boot */ + SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0), + /** Enable runtime debug prints */ + SBI_SCRATCH_DEBUG_PRINTS = (1 << 1), +}; + +/** Get pointer to sbi_scratch for current HART */ +#define sbi_scratch_thishart_ptr() \ + ((struct sbi_scratch *)csr_read(CSR_MSCRATCH)) + +/** Get Arg1 of next booting stage for current HART */ +#define sbi_scratch_thishart_arg1_ptr() \ + ((void *)(sbi_scratch_thishart_ptr()->next_arg1)) + +/** Initialize scratch table and allocator */ +int sbi_scratch_init(struct sbi_scratch *scratch); + +/** + * Allocate from extra space in sbi_scratch + * + * @return zero on failure and non-zero (>= SBI_SCRATCH_EXTRA_SPACE_OFFSET) + * on success + */ +unsigned long sbi_scratch_alloc_offset(unsigned long size, const char *owner); + +/** Free-up extra space in sbi_scratch */ +void sbi_scratch_free_offset(unsigned long offset); + +/** Get pointer from offset in sbi_scratch */ +#define sbi_scratch_offset_ptr(scratch, offset) ((void *)scratch + (offset)) + +/** Get pointer from offset in sbi_scratch for current HART */ +#define sbi_scratch_thishart_offset_ptr(offset) \ + ((void *)sbi_scratch_thishart_ptr() + (offset)) + +/** HART id to scratch table */ +extern struct sbi_scratch *hartid_to_scratch_table[]; + +/** Get sbi_scratch from HART id */ +#define sbi_hartid_to_scratch(__hartid) \ + hartid_to_scratch_table[__hartid] + +/** Last HART id having a sbi_scratch pointer */ +extern u32 last_hartid_having_scratch; + +/** Get last HART id having a sbi_scratch pointer */ +#define sbi_scratch_last_hartid() last_hartid_having_scratch + +#endif + +#endif diff --git a/roms/opensbi/include/sbi/sbi_string.h b/roms/opensbi/include/sbi/sbi_string.h new file mode 100644 index 000000000..b7c2bc22a --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_string.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#ifndef __STRING_H__ +#define __STRING_H__ + +#include <sbi/sbi_types.h> + +/* + Provides sbi_strcmp for the completeness of supporting string functions. + it is not recommended to use sbi_strcmp() but use sbi_strncmp instead. +*/ + +int sbi_strcmp(const char *a, const char *b); + +int sbi_strncmp(const char *a, const char *b, size_t count); + +size_t sbi_strlen(const char *str); + +size_t sbi_strnlen(const char *str, size_t count); + +char *sbi_strcpy(char *dest, const char *src); + +char *sbi_strncpy(char *dest, const char *src, size_t count); + +char *sbi_strchr(const char *s, int c); + +char *sbi_strrchr(const char *s, int c); + +void *sbi_memset(void *s, int c, size_t count); + +void *sbi_memcpy(void *dest, const void *src, size_t count); + +void *sbi_memmove(void *dest, const void *src, size_t count); + +int sbi_memcmp(const void *s1, const void *s2, size_t count); + +void *sbi_memchr(const void *s, int c, size_t count); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_system.h b/roms/opensbi/include/sbi/sbi_system.h new file mode 100644 index 000000000..34ba7669a --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_system.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_SYSTEM_H__ +#define __SBI_SYSTEM_H__ + +#include <sbi/sbi_types.h> + +bool sbi_system_reset_supported(u32 reset_type, u32 reset_reason); + +void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_timer.h b/roms/opensbi/include/sbi/sbi_timer.h new file mode 100644 index 000000000..87bbdbfa0 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_timer.h @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_TIMER_H__ +#define __SBI_TIMER_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +/** Get timer value for current HART */ +u64 sbi_timer_value(void); + +/** Get virtualized timer value for current HART */ +u64 sbi_timer_virt_value(void); + +/** Get timer delta value for current HART */ +u64 sbi_timer_get_delta(void); + +/** Set timer delta value for current HART */ +void sbi_timer_set_delta(ulong delta); + +/** Set upper 32-bits of timer delta value for current HART */ +void sbi_timer_set_delta_upper(ulong delta_upper); + +/** Start timer event for current HART */ +void sbi_timer_event_start(u64 next_event); + +/** Process timer event for current HART */ +void sbi_timer_process(void); + +/* Initialize timer */ +int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot); + +/* Exit timer */ +void sbi_timer_exit(struct sbi_scratch *scratch); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_tlb.h b/roms/opensbi/include/sbi/sbi_tlb.h new file mode 100644 index 000000000..48f1962d7 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_tlb.h @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_TLB_H__ +#define __SBI_TLB_H__ + +#include <sbi/sbi_types.h> +#include <sbi/sbi_hartmask.h> + +/* clang-format off */ + +#define SBI_TLB_FLUSH_ALL ((unsigned long)-1) + +/* clang-format on */ + +#define SBI_TLB_FIFO_NUM_ENTRIES 8 + +struct sbi_scratch; + +struct sbi_tlb_info { + unsigned long start; + unsigned long size; + unsigned long asid; + unsigned long vmid; + void (*local_fn)(struct sbi_tlb_info *tinfo); + struct sbi_hartmask smask; +}; + +void sbi_tlb_local_hfence_vvma(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_hfence_vvma_asid(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_hfence_gvma_vmid(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo); +void sbi_tlb_local_fence_i(struct sbi_tlb_info *tinfo); + +#define SBI_TLB_INFO_INIT(__p, __start, __size, __asid, __vmid, __lfn, __src) \ +do { \ + (__p)->start = (__start); \ + (__p)->size = (__size); \ + (__p)->asid = (__asid); \ + (__p)->vmid = (__vmid); \ + (__p)->local_fn = (__lfn); \ + SBI_HARTMASK_INIT_EXCEPT(&(__p)->smask, (__src)); \ +} while (0) + +#define SBI_TLB_INFO_SIZE sizeof(struct sbi_tlb_info) + +int sbi_tlb_request(ulong hmask, ulong hbase, struct sbi_tlb_info *tinfo); + +int sbi_tlb_init(struct sbi_scratch *scratch, bool cold_boot); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_trap.h b/roms/opensbi/include/sbi/sbi_trap.h new file mode 100644 index 000000000..5fb94f980 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_trap.h @@ -0,0 +1,214 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_TRAP_H__ +#define __SBI_TRAP_H__ + +/* clang-format off */ + +/** Index of zero member in sbi_trap_regs */ +#define SBI_TRAP_REGS_zero 0 +/** Index of ra member in sbi_trap_regs */ +#define SBI_TRAP_REGS_ra 1 +/** Index of sp member in sbi_trap_regs */ +#define SBI_TRAP_REGS_sp 2 +/** Index of gp member in sbi_trap_regs */ +#define SBI_TRAP_REGS_gp 3 +/** Index of tp member in sbi_trap_regs */ +#define SBI_TRAP_REGS_tp 4 +/** Index of t0 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t0 5 +/** Index of t1 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t1 6 +/** Index of t2 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t2 7 +/** Index of s0 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s0 8 +/** Index of s1 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s1 9 +/** Index of a0 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a0 10 +/** Index of a1 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a1 11 +/** Index of a2 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a2 12 +/** Index of a3 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a3 13 +/** Index of a4 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a4 14 +/** Index of a5 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a5 15 +/** Index of a6 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a6 16 +/** Index of a7 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_a7 17 +/** Index of s2 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s2 18 +/** Index of s3 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s3 19 +/** Index of s4 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s4 20 +/** Index of s5 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s5 21 +/** Index of s6 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s6 22 +/** Index of s7 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s7 23 +/** Index of s8 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s8 24 +/** Index of s9 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s9 25 +/** Index of s10 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s10 26 +/** Index of s11 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_s11 27 +/** Index of t3 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t3 28 +/** Index of t4 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t4 29 +/** Index of t5 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t5 30 +/** Index of t6 member in sbi_trap_regs */ +#define SBI_TRAP_REGS_t6 31 +/** Index of mepc member in sbi_trap_regs */ +#define SBI_TRAP_REGS_mepc 32 +/** Index of mstatus member in sbi_trap_regs */ +#define SBI_TRAP_REGS_mstatus 33 +/** Index of mstatusH member in sbi_trap_regs */ +#define SBI_TRAP_REGS_mstatusH 34 +/** Last member index in sbi_trap_regs */ +#define SBI_TRAP_REGS_last 35 + +/** Index of epc member in sbi_trap_info */ +#define SBI_TRAP_INFO_epc 0 +/** Index of cause member in sbi_trap_info */ +#define SBI_TRAP_INFO_cause 1 +/** Index of tval member in sbi_trap_info */ +#define SBI_TRAP_INFO_tval 2 +/** Index of tval2 member in sbi_trap_info */ +#define SBI_TRAP_INFO_tval2 3 +/** Index of tinst member in sbi_trap_info */ +#define SBI_TRAP_INFO_tinst 4 +/** Last member index in sbi_trap_info */ +#define SBI_TRAP_INFO_last 5 + +/* clang-format on */ + +/** Get offset of member with name 'x' in sbi_trap_regs */ +#define SBI_TRAP_REGS_OFFSET(x) ((SBI_TRAP_REGS_##x) * __SIZEOF_POINTER__) +/** Size (in bytes) of sbi_trap_regs */ +#define SBI_TRAP_REGS_SIZE SBI_TRAP_REGS_OFFSET(last) + +/** Get offset of member with name 'x' in sbi_trap_info */ +#define SBI_TRAP_INFO_OFFSET(x) ((SBI_TRAP_INFO_##x) * __SIZEOF_POINTER__) +/** Size (in bytes) of sbi_trap_info */ +#define SBI_TRAP_INFO_SIZE SBI_TRAP_INFO_OFFSET(last) + +#ifndef __ASSEMBLY__ + +#include <sbi/sbi_types.h> + +/** 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; + /** mepc register state */ + unsigned long mepc; + /** mstatus register state */ + unsigned long mstatus; + /** mstatusH register state (only for 32-bit) */ + unsigned long mstatusH; +}; + +/** Representation of trap details */ +struct sbi_trap_info { + /** epc Trap program counter */ + unsigned long epc; + /** cause Trap exception cause */ + unsigned long cause; + /** tval Trap value */ + unsigned long tval; + /** tval2 Trap value 2 */ + unsigned long tval2; + /** tinst Trap instruction */ + unsigned long tinst; +}; + +int sbi_trap_redirect(struct sbi_trap_regs *regs, + struct sbi_trap_info *trap); + +void sbi_trap_handler(struct sbi_trap_regs *regs); + +void __noreturn sbi_trap_exit(const struct sbi_trap_regs *regs); + +#endif + +#endif diff --git a/roms/opensbi/include/sbi/sbi_types.h b/roms/opensbi/include/sbi/sbi_types.h new file mode 100644 index 000000000..0952d5c82 --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_types.h @@ -0,0 +1,109 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_TYPES_H__ +#define __SBI_TYPES_H__ + +#ifndef OPENSBI_EXTERNAL_SBI_TYPES + +/* clang-format off */ + +typedef char s8; +typedef unsigned char u8; +typedef unsigned char uint8_t; + +typedef short s16; +typedef unsigned short u16; +typedef short int16_t; +typedef unsigned short uint16_t; + +typedef int s32; +typedef unsigned int u32; +typedef int int32_t; +typedef unsigned int uint32_t; + +#if __riscv_xlen == 64 +typedef long s64; +typedef unsigned long u64; +typedef long int64_t; +typedef unsigned long uint64_t; +#define PRILX "016lx" +#elif __riscv_xlen == 32 +typedef long long s64; +typedef unsigned long long u64; +typedef long long int64_t; +typedef unsigned long long uint64_t; +#define PRILX "08lx" +#else +#error "Unexpected __riscv_xlen" +#endif + +typedef int bool; +typedef unsigned long ulong; +typedef unsigned long uintptr_t; +typedef unsigned long size_t; +typedef long ssize_t; +typedef unsigned long virtual_addr_t; +typedef unsigned long virtual_size_t; +typedef unsigned long physical_addr_t; +typedef unsigned long physical_size_t; + +#define TRUE 1 +#define FALSE 0 +#define true TRUE +#define false FALSE + +#define NULL ((void *)0) + +#define __packed __attribute__((packed)) +#define __noreturn __attribute__((noreturn)) + +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) + +#undef offsetof +#ifdef __compiler_offsetof +#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER) +#else +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) * __mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) + +#define array_size(x) (sizeof(x) / sizeof((x)[0])) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) + +#define STR(x) XSTR(x) +#define XSTR(x) #x + +#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b)) +#define ROUNDDOWN(a, b) ((a) / (b) * (b)) + +/* clang-format on */ + +#else +/* + * OPENSBI_EXTERNAL_SBI_TYPES could be defined in CFLAGS for using the + * external definitions of data types and common macros. + * OPENSBI_EXTERNAL_SBI_TYPES is the file name to external header file, + * the external build system should address the additional include + * directory ccordingly. + */ + +#define XSTR(x) #x +#define STR(x) XSTR(x) +#include STR(OPENSBI_EXTERNAL_SBI_TYPES) +#endif + +#endif diff --git a/roms/opensbi/include/sbi/sbi_unpriv.h b/roms/opensbi/include/sbi/sbi_unpriv.h new file mode 100644 index 000000000..8cbd3de0c --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_unpriv.h @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_UNPRIV_H__ +#define __SBI_UNPRIV_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; +struct sbi_trap_info; + +#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type) \ + type sbi_load_##type(const type *addr, \ + struct sbi_trap_info *trap); + +#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type) \ + void sbi_store_##type(type *addr, type val, \ + struct sbi_trap_info *trap); + +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s8) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s16) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s32) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u8) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u16) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u32) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong) + +ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap); + +#endif diff --git a/roms/opensbi/include/sbi/sbi_version.h b/roms/opensbi/include/sbi/sbi_version.h new file mode 100644 index 000000000..3f734fe9d --- /dev/null +++ b/roms/opensbi/include/sbi/sbi_version.h @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __SBI_VERSION_H__ +#define __SBI_VERSION_H__ + +#define OPENSBI_VERSION_MAJOR 0 +#define OPENSBI_VERSION_MINOR 9 + +/** + * OpenSBI 32-bit version with: + * 1. upper 16-bits as major number + * 2. lower 16-bits as minor number + */ +#define OPENSBI_VERSION ((OPENSBI_VERSION_MAJOR << 16) | \ + (OPENSBI_VERSION_MINOR)) + +#endif |