diff options
author | Anup Patel <anup.patel@wdc.com> | 2018-12-11 19:24:06 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2018-12-11 19:24:06 +0530 |
commit | 9e8ff05cb61f157fb0bcb6b0071d7b6dc0763faa (patch) | |
tree | b9513a86b3b36e569cb46387846fee9c5544f566 /include/sbi/riscv_asm.h |
Initial commit.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'include/sbi/riscv_asm.h')
-rw-r--r-- | include/sbi/riscv_asm.h | 244 |
1 files changed, 244 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 |