#ifndef _RISCV_SYSREG_H_
#define _RISCV_SYSREG_H_
#ifndef _KERNEL
#include <sys/param.h>
#endif
#include <riscv/reg.h>
#define CPU_VENDOR_SIFIVE 0x489
#define CPU_SIFIVE_ARCH_7SERIES 0x8000000000000007
#define CPU_VENDOR_THEAD 0x5b7
#define FCSR_FMASK 0
#define FCSR_FRM __BITS(7, 5)
#define FCSR_FRM_RNE 0b000
#define FCSR_FRM_RTZ 0b001
#define FCSR_FRM_RDN 0b010
#define FCSR_FRM_RUP 0b011
#define FCSR_FRM_RMM 0b100
#define FCSR_FRM_DYN 0b111
#define FCSR_FFLAGS __BITS(4, 0)
#define FCSR_NV __BIT(4)
#define FCSR_DZ __BIT(3)
#define FCSR_OF __BIT(2)
#define FCSR_UF __BIT(1)
#define FCSR_NX __BIT(0)
static inline uint32_t
fcsr_read(void)
{
uint32_t __fcsr;
asm("frcsr %0" : "=r"(__fcsr) :: "memory");
return __fcsr;
}
static inline uint32_t
fcsr_write(uint32_t __new)
{
uint32_t __old;
asm volatile("fscsr %0, %1" : "=r"(__old) : "r"(__new) : "memory");
return __old;
}
static inline uint32_t
fcsr_fflags_read(void)
{
uint32_t __old;
asm("frflags %0" : "=r"(__old) :: "memory");
return __old;
}
static inline uint32_t
fcsr_fflags_write(uint32_t __new)
{
uint32_t __old;
asm volatile("fsflags %0, %1" : "=r"(__old) : "r"(__new) : "memory");
return __old;
}
static inline uint32_t
fcsr_frm_read(void)
{
uint32_t __old;
asm("frrm\t%0" : "=r"(__old) :: "memory");
return __old;
}
static inline uint32_t
fcsr_frm_write(uint32_t __new)
{
uint32_t __old;
asm volatile("fsrm\t%0, %1" : "=r"(__old) : "r"(__new) : "memory");
return __old;
}
#define RISCVREG_READ_INLINE(regname) \
static inline uintptr_t \
csr_##regname##_read(void) \
{ \
uintptr_t __rv; \
asm volatile("csrr %0, " #regname : "=r"(__rv) :: "memory"); \
return __rv; \
}
#define RISCVREG_WRITE_INLINE(regname) \
static inline void \
csr_##regname##_write(uintptr_t __val) \
{ \
asm volatile("csrw " #regname ", %0" :: "r"(__val) : "memory"); \
}
#define RISCVREG_SET_INLINE(regname) \
static inline void \
csr_##regname##_set(uintptr_t __mask) \
{ \
if (__builtin_constant_p(__mask) && __mask < 0x20) { \
asm volatile("csrsi " #regname ", %0" :: "i"(__mask) : \
"memory"); \
} else { \
asm volatile("csrs " #regname ", %0" :: "r"(__mask) : \
"memory"); \
} \
}
#define RISCVREG_CLEAR_INLINE(regname) \
static inline void \
csr_##regname##_clear(uintptr_t __mask) \
{ \
if (__builtin_constant_p(__mask) && __mask < 0x20) { \
asm volatile("csrci " #regname ", %0" :: "i"(__mask) : \
"memory"); \
} else { \
asm volatile("csrc " #regname ", %0" :: "r"(__mask) : \
"memory"); \
} \
}
#define RISCVREG_READ_WRITE_INLINE(regname) \
RISCVREG_READ_INLINE(regname) \
RISCVREG_WRITE_INLINE(regname)
#define RISCVREG_SET_CLEAR_INLINE(regname) \
RISCVREG_SET_INLINE(regname) \
RISCVREG_CLEAR_INLINE(regname)
#define RISCVREG_READ_SET_CLEAR_INLINE(regname) \
RISCVREG_READ_INLINE(regname) \
RISCVREG_SET_CLEAR_INLINE(regname)
#define RISCVREG_READ_WRITE_SET_CLEAR_INLINE(regname) \
RISCVREG_READ_WRITE_INLINE(regname) \
RISCVREG_SET_CLEAR_INLINE(regname)
RISCVREG_READ_SET_CLEAR_INLINE(sstatus)
#ifdef _LP64
#define SR_WPRI __BITS(62, 34) | __BITS(31, 20) | \
__BIT(17) | __BITS(12, 11) | __BIT(7) | __BITS(4, 2) | \
__BIT(0)
#define SR_SD __BIT(63)
#define SR_UXL __BITS(33, 32)
#define SR_UXL_32 1
#define SR_UXL_64 2
#define SR_UXL_128 3
#else
#define SR_WPRI __BITS(30, 20) | \
__BIT(17) | __BITS(12, 11) | __BIT(7) | __BITS(4, 2) | \
__BIT(0)
#define SR_SD __BIT(31)
#endif
#define SR_MXR __BIT(19)
#define SR_SUM __BIT(18)
#define SR_XS __BITS(16, 15)
#define SR_XS_OFF 0
#define SR_XS_SOME_ON 1
#define SR_XS_SOME_CLEAN 2
#define SR_XS_SOME_DIRTY 3
#define SR_FS __BITS(14, 13)
#define SR_FS_OFF 0
#define SR_FS_INITIAL 1
#define SR_FS_CLEAN 2
#define SR_FS_DIRTY 3
#define SR_VS __BITS(10, 9)
#define SR_VS_OFF SR_FS_OFF
#define SR_VS_INITIAL SR_FS_INITIAL
#define SR_VS_CLEAN SR_FS_CLEAN
#define SR_VS_DIRTY SR_FS_DIRTY
#define SR_SPP __BIT(8)
#define SR_UBE __BIT(6)
#define SR_SPIE __BIT(5)
#define SR_SIE __BIT(1)
RISCVREG_READ_SET_CLEAR_INLINE(sip)
#define SIP_SEIP __BIT(9)
#define SIP_STIP __BIT(5)
#define SIP_SSIP __BIT(1)
RISCVREG_READ_SET_CLEAR_INLINE(sie)
#define SIE_SEIE __BIT(9)
#define SIE_STIE __BIT(5)
#define SIE_SSIE __BIT(1)
#ifdef _LP64
#define SR_USER64 (SR_SPIE | __SHIFTIN(SR_UXL_64, SR_UXL))
#define SR_USER32 (SR_SPIE | __SHIFTIN(SR_UXL_32, SR_UXL))
#else
#define SR_USER (SR_SPIE)
#endif
#define CAUSE_INTERRUPT_P(cause) ((cause) & __BIT(XLEN - 1))
#define CAUSE_CODE(cause) ((cause) & __BITS(XLEN - 2, 0))
#define CAUSE_FETCH_MISALIGNED 0
#define CAUSE_FETCH_ACCESS 1
#define CAUSE_ILLEGAL_INSTRUCTION 2
#define CAUSE_BREAKPOINT 3
#define CAUSE_LOAD_MISALIGNED 4
#define CAUSE_LOAD_ACCESS 5
#define CAUSE_STORE_MISALIGNED 6
#define CAUSE_STORE_ACCESS 7
#define CAUSE_USER_ECALL 8
#define CAUSE_SYSCALL CAUSE_USER_ECALL
#define CAUSE_SUPERVISOR_ECALL 9
#define CAUSE_MACHINE_ECALL 11
#define CAUSE_FETCH_PAGE_FAULT 12
#define CAUSE_LOAD_PAGE_FAULT 13
#define CAUSE_STORE_PAGE_FAULT 15
#define IRQ_SUPERVISOR_SOFTWARE 1
#define IRQ_VIRTUAL_SUPERVISOR_SOFTWARE 2
#define IRQ_MACHINE_SOFTWARE 3
#define IRQ_SUPERVISOR_TIMER 5
#define IRQ_VIRTUAL_SUPERVISOR_TIMER 6
#define IRQ_MACHINE_TIMER 7
#define IRQ_SUPERVISOR_EXTERNAL 9
#define IRQ_VIRTUAL_SUPERVISOR_EXTERNAL 10
#define IRQ_MACHINE_EXTERNAL 11
#define IRQ_SUPERVISOR_GUEST_EXTERNAL 12
#define IRQ_NSOURCES 16
RISCVREG_READ_INLINE(time)
#ifdef _LP64
RISCVREG_READ_INLINE(cycle)
#else
static inline uint64_t
csr_cycle_read(void)
{
uint32_t __hi0, __hi1, __lo0;
do {
asm volatile(
"csrr\t%[__hi0], cycleh"
"\n\t" "csrr\t%[__lo0], cycle"
"\n\t" "csrr\t%[__hi1], cycleh"
: [__hi0] "=r"(__hi0),
[__lo0] "=r"(__lo0),
[__hi1] "=r"(__hi1));
} while (__hi0 != __hi1);
return
__SHIFTIN(__hi0, __BITS(63, 32)) |
__SHIFTIN(__lo0, __BITS(31, 0));
}
#endif
#ifdef _LP64
#define SATP_MODE __BITS(63, 60)
#define SATP_MODE_BARE 0
#define SATP_MODE_SV39 8
#define SATP_MODE_SV48 9
#define SATP_MODE_SV57 10
#define SATP_MODE_SV64 11
#define SATP_ASID __BITS(59, 44)
#define SATP_PPN __BITS(43, 0)
#else
#define SATP_MODE __BIT(31)
#define SATP_MODE_BARE 0
#define SATP_MODE_SV32 1
#define SATP_ASID __BITS(30, 22)
#define SATP_PPN __BITS(21, 0)
#endif
RISCVREG_READ_WRITE_INLINE(satp)
static inline uint32_t
csr_asid_read(void)
{
uintptr_t satp = csr_satp_read();
return __SHIFTOUT(satp, SATP_ASID);
}
static inline void
csr_asid_write(uint32_t asid)
{
uintptr_t satp = csr_satp_read();
satp &= ~SATP_ASID;
satp |= __SHIFTIN(asid, SATP_ASID);
csr_satp_write(satp);
}
static inline uintptr_t
csr_thead_sxstatus_read(void)
{
uintptr_t __rv;
asm volatile("csrr %0, 0x5c0" : "=r"(__rv) :: "memory");
return __rv;
}
#define TX_SXSTATUS_MAEE __BIT(21)
#define TH_SXSTATUS_THEADISAEE __BIT(22)
#endif