diff options
Diffstat (limited to 'include/sbi')
-rw-r--r-- | include/sbi/riscv_asm.h | 244 | ||||
-rw-r--r-- | include/sbi/riscv_atomic.h | 38 | ||||
-rw-r--r-- | include/sbi/riscv_barrier.h | 53 | ||||
-rw-r--r-- | include/sbi/riscv_encoding.h | 423 | ||||
-rw-r--r-- | include/sbi/riscv_io.h | 109 | ||||
-rw-r--r-- | include/sbi/riscv_locks.h | 33 | ||||
-rw-r--r-- | include/sbi/sbi_bits.h | 44 | ||||
-rw-r--r-- | include/sbi/sbi_console.h | 37 | ||||
-rw-r--r-- | include/sbi/sbi_const.h | 43 | ||||
-rw-r--r-- | include/sbi/sbi_ecall.h | 26 | ||||
-rw-r--r-- | include/sbi/sbi_emulate_csr.h | 27 | ||||
-rw-r--r-- | include/sbi/sbi_error.h | 25 | ||||
-rw-r--r-- | include/sbi/sbi_hart.h | 41 | ||||
-rw-r--r-- | include/sbi/sbi_illegal_insn.h | 22 | ||||
-rw-r--r-- | include/sbi/sbi_init.h | 19 | ||||
-rw-r--r-- | include/sbi/sbi_ipi.h | 33 | ||||
-rw-r--r-- | include/sbi/sbi_platform.h | 258 | ||||
-rw-r--r-- | include/sbi/sbi_scratch.h | 35 | ||||
-rw-r--r-- | include/sbi/sbi_system.h | 31 | ||||
-rw-r--r-- | include/sbi/sbi_timer.h | 30 | ||||
-rw-r--r-- | include/sbi/sbi_trap.h | 57 | ||||
-rw-r--r-- | include/sbi/sbi_types.h | 57 | ||||
-rw-r--r-- | include/sbi/sbi_unpriv.h | 111 |
23 files changed, 1796 insertions, 0 deletions
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h new file mode 100644 index 0000000..516bf6f --- /dev/null +++ b/include/sbi/riscv_asm.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __RISCV_ASM_H__ +#define __RISCV_ASM_H__ + +#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 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 + +#define RISCV_SCRATCH_TMP0_OFFSET (0 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_FW_START_OFFSET (1 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_FW_SIZE_OFFSET (2 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_NEXT_ARG1_OFFSET (3 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_NEXT_ADDR_OFFSET (4 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_NEXT_MODE_OFFSET (5 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_WARMBOOT_ADDR_OFFSET (6 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_PLATFORM_ADDR_OFFSET (7 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_HARTID_TO_SCRATCH_OFFSET (8 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_IPI_TYPE_OFFSET (9 * __SIZEOF_POINTER__) +#define RISCV_SCRATCH_SIZE 256 + +#define RISCV_TRAP_REGS_zero 0 +#define RISCV_TRAP_REGS_ra 1 +#define RISCV_TRAP_REGS_sp 2 +#define RISCV_TRAP_REGS_gp 3 +#define RISCV_TRAP_REGS_tp 4 +#define RISCV_TRAP_REGS_t0 5 +#define RISCV_TRAP_REGS_t1 6 +#define RISCV_TRAP_REGS_t2 7 +#define RISCV_TRAP_REGS_s0 8 +#define RISCV_TRAP_REGS_s1 9 +#define RISCV_TRAP_REGS_a0 10 +#define RISCV_TRAP_REGS_a1 11 +#define RISCV_TRAP_REGS_a2 12 +#define RISCV_TRAP_REGS_a3 13 +#define RISCV_TRAP_REGS_a4 14 +#define RISCV_TRAP_REGS_a5 15 +#define RISCV_TRAP_REGS_a6 16 +#define RISCV_TRAP_REGS_a7 17 +#define RISCV_TRAP_REGS_s2 18 +#define RISCV_TRAP_REGS_s3 19 +#define RISCV_TRAP_REGS_s4 20 +#define RISCV_TRAP_REGS_s5 21 +#define RISCV_TRAP_REGS_s6 22 +#define RISCV_TRAP_REGS_s7 23 +#define RISCV_TRAP_REGS_s8 24 +#define RISCV_TRAP_REGS_s9 25 +#define RISCV_TRAP_REGS_s10 26 +#define RISCV_TRAP_REGS_s11 27 +#define RISCV_TRAP_REGS_t3 28 +#define RISCV_TRAP_REGS_t4 29 +#define RISCV_TRAP_REGS_t5 30 +#define RISCV_TRAP_REGS_t6 31 +#define RISCV_TRAP_REGS_mepc 32 +#define RISCV_TRAP_REGS_mstatus 33 +#define RISCV_TRAP_REGS_last 34 + +#define RISCV_TRAP_REGS_OFFSET(x) \ + ((RISCV_TRAP_REGS_##x) * __SIZEOF_POINTER__) +#define RISCV_TRAP_REGS_SIZE RISCV_TRAP_REGS_OFFSET(last) + +#ifndef __ASSEMBLY__ + +#define csr_swap(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrrw %0, " #csr ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_read(csr) \ +({ \ + register unsigned long __v; \ + __asm__ __volatile__ ("csrr %0, " #csr \ + : "=r" (__v) : \ + : "memory"); \ + __v; \ +}) + +#define csr_read_n(csr_num) \ +({ \ + register unsigned long __v; \ + __asm__ __volatile__ ("csrr %0, " __ASM_STR(csr_num) \ + : "=r" (__v) : \ + : "memory"); \ + __v; \ +}) + +#define csr_write(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrw " #csr ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_write_n(csr_num, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrw " __ASM_STR(csr_num) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_set(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrrs %0, " #csr ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_set(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrs " #csr ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_clear(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrrc %0, " #csr ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_clear(csr, val) \ +({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__ ("csrc " #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) + +static inline int misa_extension(char ext) +{ + return csr_read(misa) & (1 << (ext - 'A')); +} + +static inline int misa_xlen(void) +{ + return ((long)csr_read(misa) < 0) ? 64 : 32; +} + +static inline void misa_string(char *out, unsigned int out_sz) +{ + unsigned long i, val = csr_read(misa); + + for (i = 0; i < 26; i++) { + if (val & (1 << i)) { + *out = 'A' + i; + out++; + } + } + *out = '\0'; + out++; +} + +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_out); + +#endif /* !__ASSEMBLY__ */ + +#endif diff --git a/include/sbi/riscv_atomic.h b/include/sbi/riscv_atomic.h new file mode 100644 index 0000000..775cd6f --- /dev/null +++ b/include/sbi/riscv_atomic.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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 arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval); + +long arch_atomic_xchg(atomic_t *atom, long newval); + +unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr, + unsigned int newval); + +#endif diff --git a/include/sbi/riscv_barrier.h b/include/sbi/riscv_barrier.h new file mode 100644 index 0000000..993cbda --- /dev/null +++ b/include/sbi/riscv_barrier.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __RISCV_BARRIER_H__ +#define __RISCV_BARRIER_H__ + +#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") + +#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/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h new file mode 100644 index 0000000..a4407d2 --- /dev/null +++ b/include/sbi/riscv_encoding.h @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __RISCV_ENCODING_H__ +#define __RISCV_ENCODING_H__ + +#include <sbi/sbi_const.h> + +/* TODO: Make constants usable in assembly with _AC() macro */ + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_HPP 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_SUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_TVM 0x00100000 +#define MSTATUS_TW 0x00200000 +#define MSTATUS_TSR 0x00400000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS_UXL 0x0000000300000000 +#define MSTATUS_SXL 0x0000000C00000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_SUM 0x00040000 +#define SSTATUS_MXR 0x00080000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS_UXL 0x0000000300000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define SATP32_MODE 0x80000000 +#define SATP32_ASID 0x7FC00000 +#define SATP32_PPN 0x003FFFFF +#define SATP64_MODE 0xF000000000000000 +#define SATP64_ASID 0x0FFFF00000000000 +#define SATP64_PPN 0x00000FFFFFFFFFFF + +#define SATP_MODE_OFF 0 +#define SATP_MODE_SV32 1 +#define SATP_MODE_SV39 8 +#define SATP_MODE_SV48 9 +#define SATP_MODE_SV57 10 +#define SATP_MODE_SV64 11 + +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_A_TOR 0x08 +#define PMP_A_NA4 0x10 +#define PMP_A_NAPOT 0x18 +#define PMP_L 0x80 + +#define PMP_SHIFT 2 +#define PMP_COUNT 16 + +/* page table entry (PTE) fields */ +#define PTE_V 0x001 /* Valid */ +#define PTE_R 0x002 /* Read */ +#define PTE_W 0x004 /* Write */ +#define PTE_X 0x008 /* Execute */ +#define PTE_U 0x010 /* User */ +#define PTE_G 0x020 /* Global */ +#define PTE_A 0x040 /* Accessed */ +#define PTE_D 0x080 /* Dirty */ +#define PTE_SOFT 0x300 /* Reserved for Software */ + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) \ + (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#if __riscv_xlen == 64 +#define MSTATUS_SD MSTATUS64_SD +#define SSTATUS_SD SSTATUS64_SD +#define RISCV_PGLEVEL_BITS 9 +#define SATP_MODE SATP64_MODE +#else +#define MSTATUS_SD MSTATUS32_SD +#define SSTATUS_SD SSTATUS32_SD +#define RISCV_PGLEVEL_BITS 10 +#define SATP_MODE SATP32_MODE +#endif +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#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_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 +#define CSR_SATP 0x180 +#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_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#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_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH 0x7b2 +#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_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 +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f +#define CSR_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 + +#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_HYPERVISOR_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 + +#endif diff --git a/include/sbi/riscv_io.h b/include/sbi/riscv_io.h new file mode 100644 index 0000000..08f1a2f --- /dev/null +++ b/include/sbi/riscv_io.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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 */ +#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 + +#endif diff --git a/include/sbi/riscv_locks.h b/include/sbi/riscv_locks.h new file mode 100644 index 0000000..4a683d9 --- /dev/null +++ b/include/sbi/riscv_locks.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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/include/sbi/sbi_bits.h b/include/sbi/sbi_bits.h new file mode 100644 index 0000000..118fab2 --- /dev/null +++ b/include/sbi/sbi_bits.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_BITS_H__ +#define __SBI_BITS_H__ + +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) + +#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) +#define ROUNDDOWN(a, b) ((a)/(b)*(b)) + +#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 EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) +#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#define STR(x) XSTR(x) +#define XSTR(x) #x + +#if __riscv_xlen == 64 +#define SLL32 sllw +#define STORE sd +#define LOAD ld +#define LWU lwu +#define LOG_REGBYTES 3 +#else +#define SLL32 sll +#define STORE sw +#define LOAD lw +#define LWU lw +#define LOG_REGBYTES 2 +#endif +#define REGBYTES (1 << LOG_REGBYTES) + +#endif diff --git a/include/sbi/sbi_console.h b/include/sbi/sbi_console.h new file mode 100644 index 0000000..df258ba --- /dev/null +++ b/include/sbi/sbi_console.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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); + +char 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, ...); + +struct sbi_scratch; +int sbi_console_init(struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_const.h b/include/sbi/sbi_const.h new file mode 100644 index 0000000..3071094 --- /dev/null +++ b/include/sbi/sbi_const.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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. + */ + +#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) + +#endif diff --git a/include/sbi/sbi_ecall.h b/include/sbi/sbi_ecall.h new file mode 100644 index 0000000..4f39329 --- /dev/null +++ b/include/sbi/sbi_ecall.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_ECALL_H__ +#define __SBI_ECALL_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs; +struct sbi_scratch; + +u16 sbi_ecall_version_major(void); + +u16 sbi_ecall_version_minor(void); + +int sbi_ecall_handler(u32 hartid, ulong mcause, + struct sbi_trap_regs *regs, + struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_emulate_csr.h b/include/sbi/sbi_emulate_csr.h new file mode 100644 index 0000000..c6fe419 --- /dev/null +++ b/include/sbi/sbi_emulate_csr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_EMULATE_CSR_H__ +#define __SBI_EMULATE_CSR_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +int sbi_emulate_csr_read(int csr_num, + u32 hartid, ulong mstatus, + struct sbi_scratch *scratch, + ulong *csr_val); + +int sbi_emulate_csr_write(int csr_num, + u32 hartid, ulong mstatus, + struct sbi_scratch *scratch, + ulong csr_val); + +#endif diff --git a/include/sbi/sbi_error.h b/include/sbi/sbi_error.h new file mode 100644 index 0000000..955674e --- /dev/null +++ b/include/sbi/sbi_error.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_ERROR_H__ +#define __SBI_ERROR_H__ + +#define SBI_OK 0 +#define SBI_EUNKNOWN -1 +#define SBI_EFAIL -2 +#define SBI_EINVAL -3 +#define SBI_ENOENT -4 +#define SBI_ENOTSUPP -5 +#define SBI_ENODEV -6 +#define SBI_ENOSYS -7 +#define SBI_ETIMEDOUT -8 +#define SBI_EIO -9 +#define SBI_EILL -10 + +#endif diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h new file mode 100644 index 0000000..38032ed --- /dev/null +++ b/include/sbi/sbi_hart.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_HART_H__ +#define __SBI_HART_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid); + +void sbi_hart_pmp_dump(void); + +void __attribute__((noreturn)) sbi_hart_hang(void); + +void __attribute__((noreturn)) sbi_hart_boot_next(unsigned long arg0, + unsigned long arg1, + unsigned long next_addr, + unsigned long next_mode); + +void sbi_hart_mark_available(u32 hartid); + +ulong sbi_hart_available_mask(void); + +void sbi_hart_unmark_available(u32 hartid); + +struct sbi_scratch *sbi_hart_id_to_scratch(struct sbi_scratch *scratch, + u32 hartid); + +void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid); + +void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_illegal_insn.h b/include/sbi/sbi_illegal_insn.h new file mode 100644 index 0000000..1b8837f --- /dev/null +++ b/include/sbi/sbi_illegal_insn.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_ILLEGAl_INSN_H__ +#define __SBI_ILLEGAl_INSN_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs; +struct sbi_scratch; + +int sbi_illegal_insn_handler(u32 hartid, ulong mcause, + struct sbi_trap_regs *regs, + struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_init.h b/include/sbi/sbi_init.h new file mode 100644 index 0000000..b3aafdc --- /dev/null +++ b/include/sbi/sbi_init.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_INIT_H__ +#define __SBI_INIT_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +void __attribute__((noreturn)) sbi_init(struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_ipi.h b/include/sbi/sbi_ipi.h new file mode 100644 index 0000000..4058194 --- /dev/null +++ b/include/sbi/sbi_ipi.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_IPI_H__ +#define __SBI_IPI_H__ + +#include <sbi/sbi_types.h> + +#define SBI_IPI_EVENT_SOFT 0x1 +#define SBI_IPI_EVENT_FENCE_I 0x2 +#define SBI_IPI_EVENT_SFENCE_VMA 0x4 +#define SBI_IPI_EVENT_HALT 0x8 + +struct sbi_scratch; + +int sbi_ipi_send_many(struct sbi_scratch *scratch, + u32 hartid, ulong *pmask, u32 event); + +void sbi_ipi_clear_smode(struct sbi_scratch *scratch, u32 hartid); + +void sbi_ipi_process(struct sbi_scratch *scratch, u32 hartid); + +int sbi_ipi_warm_init(struct sbi_scratch *scratch, u32 hartid); + +int sbi_ipi_cold_init(struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h new file mode 100644 index 0000000..57b8e6b --- /dev/null +++ b/include/sbi/sbi_platform.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_PLATFORM_H__ +#define __SBI_PLATFORM_H__ + +#include <sbi/sbi_scratch.h> + +enum sbi_platform_features { + SBI_PLATFORM_HAS_MMIO_TIMER_VALUE = (1 << 0), + SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1), +}; + +struct sbi_platform { + char name[64]; + u64 features; + u32 hart_count; + u32 hart_stack_size; + int (*cold_early_init)(void); + int (*cold_final_init)(void); + int (*warm_early_init)(u32 target_hart); + int (*warm_final_init)(u32 target_hart); + u32 (*pmp_region_count)(u32 target_hart); + int (*pmp_region_info)(u32 target_hart, u32 index, + ulong *prot, ulong *addr, ulong *log2size); + void (*console_putc)(char ch); + char (*console_getc)(void); + int (*console_init)(void); + int (*cold_irqchip_init)(void); + int (*warm_irqchip_init)(u32 target_hart); + void (*ipi_inject)(u32 target_hart, u32 source_hart); + void (*ipi_sync)(u32 target_hart, u32 source_hart); + void (*ipi_clear)(u32 target_hart); + int (*cold_ipi_init)(void); + int (*warm_ipi_init)(u32 target_hart); + u64 (*timer_value)(void); + void (*timer_event_stop)(u32 target_hart); + void (*timer_event_start)(u32 target_hart, u64 next_event); + int (*cold_timer_init)(void); + int (*warm_timer_init)(u32 target_hart); + int (*system_reboot)(u32 type); + int (*system_shutdown)(u32 type); +} __attribute__((packed)); + +#define sbi_platform_ptr(__s) \ +((struct sbi_platform *)((__s)->platform_addr)) + +#define sbi_platform_thishart_ptr() \ +((struct sbi_platform *)(sbi_scratch_thishart_ptr()->platform_addr)) + +#define sbi_platform_has_mmio_timer_value(__p) \ +((__p)->features & SBI_PLATFORM_HAS_MMIO_TIMER_VALUE) + +#define sbi_platform_has_hart_hotplug(__p) \ +((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG) + +static inline const char *sbi_platform_name(struct sbi_platform *plat) +{ + if (plat) + return plat->name; + return NULL; +} + +static inline u32 sbi_platform_hart_count(struct sbi_platform *plat) +{ + if (plat) + return plat->hart_count; + return 0; +} + +static inline u32 sbi_platform_hart_stack_size(struct sbi_platform *plat) +{ + if (plat) + return plat->hart_stack_size; + return 0; +} + +static inline int sbi_platform_cold_early_init(struct sbi_platform *plat) +{ + if (plat && plat->cold_early_init) + return plat->cold_early_init(); + return 0; +} + +static inline int sbi_platform_cold_final_init(struct sbi_platform *plat) +{ + if (plat && plat->cold_final_init) + return plat->cold_final_init(); + return 0; +} + +static inline int sbi_platform_warm_early_init(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->warm_early_init) + return plat->warm_early_init(target_hart); + return 0; +} + +static inline int sbi_platform_warm_final_init(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->warm_final_init) + return plat->warm_final_init(target_hart); + return 0; +} + +static inline u32 sbi_platform_pmp_region_count(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->pmp_region_count) + return plat->pmp_region_count(target_hart); + return 0; +} + +static inline int sbi_platform_pmp_region_info(struct sbi_platform *plat, + u32 target_hart, u32 index, + ulong *prot, ulong *addr, + ulong *log2size) +{ + if (plat && plat->pmp_region_info) + return plat->pmp_region_info(target_hart, index, + prot, addr, log2size); + return 0; +} + +static inline void sbi_platform_console_putc(struct sbi_platform *plat, + char ch) +{ + if (plat && plat->console_putc) + plat->console_putc(ch); +} + +static inline char sbi_platform_console_getc(struct sbi_platform *plat) +{ + if (plat && plat->console_getc) + return plat->console_getc(); + return 0; +} + +static inline int sbi_platform_console_init(struct sbi_platform *plat) +{ + if (plat && plat->console_init) + return plat->console_init(); + return 0; +} + +static inline int sbi_platform_warm_irqchip_init(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->warm_irqchip_init) + return plat->warm_irqchip_init(target_hart); + return 0; +} + +static inline int sbi_platform_cold_irqchip_init(struct sbi_platform *plat) +{ + if (plat && plat->cold_irqchip_init) + return plat->cold_irqchip_init(); + return 0; +} + +static inline void sbi_platform_ipi_inject(struct sbi_platform *plat, + u32 target_hart, u32 source_hart) +{ + if (plat && plat->ipi_inject) + plat->ipi_inject(target_hart, source_hart); +} + +static inline void sbi_platform_ipi_sync(struct sbi_platform *plat, + u32 target_hart, u32 source_hart) +{ + if (plat && plat->ipi_sync) + plat->ipi_sync(target_hart, source_hart); +} + +static inline void sbi_platform_ipi_clear(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->ipi_clear) + plat->ipi_clear(target_hart); +} + +static inline int sbi_platform_warm_ipi_init(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->warm_ipi_init) + return plat->warm_ipi_init(target_hart); + return 0; +} + +static inline int sbi_platform_cold_ipi_init(struct sbi_platform *plat) +{ + if (plat && plat->cold_ipi_init) + return plat->cold_ipi_init(); + return 0; +} + +static inline u64 sbi_platform_timer_value(struct sbi_platform *plat) +{ + if (plat && plat->timer_value) + return plat->timer_value(); + return 0; +} + +static inline void sbi_platform_timer_event_stop(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->timer_event_stop) + plat->timer_event_stop(target_hart); +} + +static inline void sbi_platform_timer_event_start(struct sbi_platform *plat, + u32 target_hart, + u64 next_event) +{ + if (plat && plat->timer_event_start) + plat->timer_event_start(target_hart, next_event); +} + +static inline int sbi_platform_warm_timer_init(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->warm_timer_init) + return plat->warm_timer_init(target_hart); + return 0; +} + +static inline int sbi_platform_cold_timer_init(struct sbi_platform *plat) +{ + if (plat && plat->cold_timer_init) + return plat->cold_timer_init(); + return 0; +} + +static inline int sbi_platform_system_reboot(struct sbi_platform *plat, + u32 type) +{ + if (plat && plat->system_reboot) + return plat->system_reboot(type); + return 0; +} + +static inline int sbi_platform_system_shutdown(struct sbi_platform *plat, + u32 type) +{ + if (plat && plat->system_shutdown) + return plat->system_shutdown(type); + return 0; +} + +#endif diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h new file mode 100644 index 0000000..d5c6f35 --- /dev/null +++ b/include/sbi/sbi_scratch.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_SCRATCH_H__ +#define __SBI_SCRATCH_H__ + +#include <sbi/riscv_asm.h> +#include <sbi/sbi_types.h> + +struct sbi_scratch { + unsigned long tmp0; + unsigned long fw_start; + unsigned long fw_size; + unsigned long next_arg1; + unsigned long next_addr; + unsigned long next_mode; + unsigned long warmboot_addr; + unsigned long platform_addr; + unsigned long hartid_to_scratch; + unsigned long ipi_type; +} __attribute__((packed)); + +#define sbi_scratch_thishart_ptr() \ +((struct sbi_scratch *)csr_read(mscratch)) + +#define sbi_scratch_thishart_arg1_ptr() \ +((void *)(sbi_scratch_thishart_ptr()->next_arg1)) + +#endif diff --git a/include/sbi/sbi_system.h b/include/sbi/sbi_system.h new file mode 100644 index 0000000..ac1fb36 --- /dev/null +++ b/include/sbi/sbi_system.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_SYSTEM_H__ +#define __SBI_SYSTEM_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +int sbi_system_warm_early_init(struct sbi_scratch *scratch, u32 hartid); + +int sbi_system_warm_final_init(struct sbi_scratch *scratch, u32 hartid); + +int sbi_system_cold_early_init(struct sbi_scratch *scratch); + +int sbi_system_cold_final_init(struct sbi_scratch *scratch); + +void __attribute__((noreturn)) sbi_system_reboot(struct sbi_scratch *scratch, + u32 type); + +void __attribute__((noreturn)) sbi_system_shutdown(struct sbi_scratch *scratch, + u32 type); + +#endif diff --git a/include/sbi/sbi_timer.h b/include/sbi/sbi_timer.h new file mode 100644 index 0000000..914e9c0 --- /dev/null +++ b/include/sbi/sbi_timer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_TIMER_H__ +#define __SBI_TIMER_H__ + +#include <sbi/sbi_types.h> + +struct sbi_scratch; + +u64 sbi_timer_value(struct sbi_scratch *scratch); + +void sbi_timer_event_stop(struct sbi_scratch *scratch, u32 hartid); + +void sbi_timer_event_start(struct sbi_scratch *scratch, u32 hartid, + u64 next_event); + +void sbi_timer_process(struct sbi_scratch *scratch, u32 hartid); + +int sbi_timer_warm_init(struct sbi_scratch *scratch, u32 hartid); + +int sbi_timer_cold_init(struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h new file mode 100644 index 0000000..a6b22e4 --- /dev/null +++ b/include/sbi/sbi_trap.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_TRAP_H__ +#define __SBI_TRAP_H__ + +#include <sbi/sbi_types.h> + +struct sbi_trap_regs { + unsigned long zero; + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; + unsigned long mepc; + unsigned long mstatus; +} __attribute__((packed)); + +struct sbi_scratch; + +void sbi_trap_handler(struct sbi_trap_regs *regs, + struct sbi_scratch *scratch); + +#endif diff --git a/include/sbi/sbi_types.h b/include/sbi/sbi_types.h new file mode 100644 index 0000000..ddcdea2 --- /dev/null +++ b/include/sbi/sbi_types.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_TYPES_H__ +#define __SBI_TYPES_H__ + +typedef char s8; +typedef unsigned char u8; +typedef char int8_t; +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; +#elif __riscv_xlen == 32 +typedef long long s64; +typedef unsigned long long u64; +typedef long long int64_t; +typedef unsigned long long uint64_t; +#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 NULL ((void *)0) + +#endif diff --git a/include/sbi/sbi_unpriv.h b/include/sbi/sbi_unpriv.h new file mode 100644 index 0000000..2b925c5 --- /dev/null +++ b/include/sbi/sbi_unpriv.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_UNPRIV_H__ +#define __SBI_UNPRIV_H__ + +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_bits.h> +#include <sbi/sbi_types.h> + +#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ +static inline type load_##type(const type *addr, ulong mepc) \ +{ \ + register ulong __mepc asm ("a2") = mepc; \ + register ulong __mstatus asm ("a3"); \ + type val; \ + asm ("csrrs %0, mstatus, %3\n" \ + #insn " %1, %2\n" \ + "csrw mstatus, %0" \ + : "+&r" (__mstatus), "=&r" (val) \ + : "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \ + return val; \ +} + +#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \ +static inline void store_##type(type *addr, type val, ulong mepc) \ +{ \ + register ulong __mepc asm ("a2") = mepc; \ + register ulong __mstatus asm ("a3"); \ + asm volatile ("csrrs %0, mstatus, %3\n" \ + #insn " %1, %2\n" \ + "csrw mstatus, %0" \ + : "+&r" (__mstatus) \ + : "r" (val), "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \ +} + +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8, lbu) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16, lhu) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s8, lb) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s16, lh) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s32, lw) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u8, sb) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u16, sh) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u32, sw) +#if __riscv_xlen == 64 +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lwu) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64, ld) +DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64, sd) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld) +#else +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw) + +static inline u64 load_u64(const u64 *addr, ulong mepc) +{ + return load_u32((u32 *)addr, mepc) + + ((u64)load_u32((u32 *)addr + 1, mepc) << 32); +} + +static inline void store_u64(u64 *addr, u64 val, ulong mepc) +{ + store_u32((u32 *)addr, val, mepc); + store_u32((u32 *)addr + 1, val >> 32, mepc); +} +#endif + +static inline ulong get_insn(ulong mepc, ulong *mstatus) +{ + register ulong __mepc asm ("a2") = mepc; + register ulong __mstatus asm ("a3"); + ulong val; +#ifndef __riscv_compressed + asm ("csrrs %[mstatus], mstatus, %[mprv]\n" + STR(LWU) " %[insn], (%[addr])\n" + "csrw mstatus, %[mstatus]" + : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val) + : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc)); +#else + ulong rvc_mask = 3, tmp; + asm ("csrrs %[mstatus], mstatus, %[mprv]\n" + "and %[tmp], %[addr], 2\n" + "bnez %[tmp], 1f\n" + STR(LWU) " %[insn], (%[addr])\n" + "and %[tmp], %[insn], %[rvc_mask]\n" + "beq %[tmp], %[rvc_mask], 2f\n" + "sll %[insn], %[insn], %[xlen_minus_16]\n" + "srl %[insn], %[insn], %[xlen_minus_16]\n" + "j 2f\n" + "1:\n" + "lhu %[insn], (%[addr])\n" + "and %[tmp], %[insn], %[rvc_mask]\n" + "bne %[tmp], %[rvc_mask], 2f\n" + "lhu %[tmp], 2(%[addr])\n" + "sll %[tmp], %[tmp], 16\n" + "add %[insn], %[insn], %[tmp]\n" + "2: csrw mstatus, %[mstatus]" + : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp) + : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc), + [rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16)); +#endif + *mstatus = __mstatus; + return val; +} + +#endif |