Home | History | Annotate | Line # | Download | only in include
sysreg.h revision 1.27
      1  1.27     skrll  /* $NetBSD: sysreg.h,v 1.27 2022/11/18 06:53:06 skrll Exp $ */
      2   1.4      maxv 
      3   1.4      maxv /*
      4   1.1      matt  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      5   1.1      matt  * All rights reserved.
      6   1.1      matt  *
      7   1.1      matt  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1      matt  * by Matt Thomas of 3am Software Foundry.
      9   1.1      matt  *
     10   1.1      matt  * Redistribution and use in source and binary forms, with or without
     11   1.1      matt  * modification, are permitted provided that the following conditions
     12   1.1      matt  * are met:
     13   1.1      matt  * 1. Redistributions of source code must retain the above copyright
     14   1.1      matt  *    notice, this list of conditions and the following disclaimer.
     15   1.1      matt  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1      matt  *    notice, this list of conditions and the following disclaimer in the
     17   1.1      matt  *    documentation and/or other materials provided with the distribution.
     18   1.1      matt  *
     19   1.1      matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1      matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1      matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1      matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1      matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1      matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1      matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1      matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1      matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1      matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1      matt  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1      matt  */
     31   1.1      matt 
     32   1.1      matt #ifndef _RISCV_SYSREG_H_
     33  1.15    simonb #define	_RISCV_SYSREG_H_
     34   1.1      matt 
     35   1.1      matt #ifndef _KERNEL
     36   1.1      matt #include <sys/param.h>
     37   1.1      matt #endif
     38   1.1      matt 
     39  1.13     skrll #include <riscv/reg.h>
     40  1.13     skrll 
     41  1.15    simonb #define	FCSR_FMASK	0	// no exception bits
     42  1.27     skrll #define	FCSR_FRM	__BITS(7, 5)
     43  1.15    simonb #define	 FCSR_FRM_RNE	0b000	// Round Nearest, ties to Even
     44  1.15    simonb #define	 FCSR_FRM_RTZ	0b001	// Round Towards Zero
     45  1.15    simonb #define	 FCSR_FRM_RDN	0b010	// Round DowN (-infinity)
     46  1.15    simonb #define	 FCSR_FRM_RUP	0b011	// Round UP (+infinity)
     47  1.15    simonb #define	 FCSR_FRM_RMM	0b100	// Round to nearest, ties to Max Magnitude
     48  1.15    simonb #define	 FCSR_FRM_DYN	0b111	// Dynamic rounding
     49  1.27     skrll #define	FCSR_FFLAGS	__BITS(4, 0)	// Sticky bits
     50  1.15    simonb #define	FCSR_NV		__BIT(4)	// iNValid operation
     51  1.15    simonb #define	FCSR_DZ		__BIT(3)	// Divide by Zero
     52  1.15    simonb #define	FCSR_OF		__BIT(2)	// OverFlow
     53  1.15    simonb #define	FCSR_UF		__BIT(1)	// UnderFlow
     54  1.15    simonb #define	FCSR_NX		__BIT(0)	// iNeXact
     55   1.1      matt 
     56   1.1      matt static inline uint32_t
     57   1.1      matt riscvreg_fcsr_read(void)
     58   1.1      matt {
     59   1.1      matt 	uint32_t __fcsr;
     60   1.1      matt 	__asm("frcsr %0" : "=r"(__fcsr));
     61   1.1      matt 	return __fcsr;
     62   1.1      matt }
     63   1.1      matt 
     64   1.1      matt 
     65   1.1      matt static inline uint32_t
     66   1.1      matt riscvreg_fcsr_write(uint32_t __new)
     67   1.1      matt {
     68   1.1      matt 	uint32_t __old;
     69   1.1      matt 	__asm("fscsr %0, %1" : "=r"(__old) : "r"(__new));
     70   1.1      matt 	return __old;
     71   1.1      matt }
     72   1.1      matt 
     73   1.1      matt static inline uint32_t
     74   1.1      matt riscvreg_fcsr_read_fflags(void)
     75   1.1      matt {
     76   1.1      matt 	uint32_t __old;
     77   1.1      matt 	__asm("frflags %0" : "=r"(__old));
     78   1.1      matt 	return __SHIFTOUT(__old, FCSR_FFLAGS);
     79   1.1      matt }
     80   1.1      matt 
     81   1.1      matt static inline uint32_t
     82   1.1      matt riscvreg_fcsr_write_fflags(uint32_t __new)
     83   1.1      matt {
     84   1.1      matt 	uint32_t __old;
     85   1.1      matt 	__new = __SHIFTIN(__new, FCSR_FFLAGS);
     86   1.1      matt 	__asm("fsflags %0, %1" : "=r"(__old) : "r"(__new));
     87   1.1      matt 	return __SHIFTOUT(__old, FCSR_FFLAGS);
     88   1.1      matt }
     89   1.1      matt 
     90   1.1      matt static inline uint32_t
     91   1.1      matt riscvreg_fcsr_read_frm(void)
     92   1.1      matt {
     93   1.1      matt 	uint32_t __old;
     94   1.1      matt 	__asm("frrm\t%0" : "=r"(__old));
     95   1.1      matt 	return __SHIFTOUT(__old, FCSR_FRM);
     96   1.1      matt }
     97   1.1      matt 
     98   1.1      matt static inline uint32_t
     99   1.1      matt riscvreg_fcsr_write_frm(uint32_t __new)
    100   1.1      matt {
    101   1.1      matt 	uint32_t __old;
    102   1.1      matt 	__new = __SHIFTIN(__new, FCSR_FRM);
    103  1.17    simonb 	__asm __volatile("fsrm\t%0, %1" : "=r"(__old) : "r"(__new));
    104   1.1      matt 	return __SHIFTOUT(__old, FCSR_FRM);
    105   1.1      matt }
    106   1.1      matt 
    107  1.25    simonb 
    108  1.25    simonb #define	RISCVREG_READ_INLINE(regname)					\
    109  1.25    simonb static inline uintptr_t							\
    110  1.25    simonb csr_##regname##_read(void)						\
    111  1.25    simonb {									\
    112  1.25    simonb 	uintptr_t __rv;							\
    113  1.25    simonb 	asm volatile("csrr %0, " #regname : "=r"(__rv) :: "memory");	\
    114  1.25    simonb 	return __rv;							\
    115  1.25    simonb }
    116  1.25    simonb 
    117  1.25    simonb #define	RISCVREG_WRITE_INLINE(regname)					\
    118  1.25    simonb static inline void							\
    119  1.25    simonb csr_##regname##_write(uintptr_t __val)					\
    120  1.25    simonb {									\
    121  1.25    simonb 	asm volatile("csrw " #regname ", %0" :: "r"(__val) : "memory");	\
    122  1.25    simonb }
    123  1.25    simonb 
    124  1.25    simonb #define	RISCVREG_SET_INLINE(regname)					\
    125  1.25    simonb static inline void							\
    126  1.25    simonb csr_##regname##_set(uintptr_t __mask)					\
    127  1.25    simonb {									\
    128  1.25    simonb 	if (__builtin_constant_p(__mask) && __mask < 0x20) {		\
    129  1.25    simonb 		asm volatile("csrsi " #regname ", %0" :: "i"(__mask) :	\
    130  1.25    simonb 		    "memory");						\
    131  1.25    simonb 	} else {							\
    132  1.25    simonb 		asm volatile("csrs " #regname ", %0" :: "r"(__mask) :	\
    133  1.25    simonb 		    "memory");						\
    134  1.25    simonb 	}								\
    135  1.25    simonb }
    136  1.25    simonb 
    137  1.25    simonb #define	RISCVREG_CLEAR_INLINE(regname)					\
    138  1.25    simonb static inline void							\
    139  1.25    simonb csr_##regname##_clear(uintptr_t __mask)					\
    140  1.25    simonb {									\
    141  1.25    simonb 	if (__builtin_constant_p(__mask) && __mask < 0x20) {		\
    142  1.25    simonb 		asm volatile("csrci " #regname ", %0" :: "i"(__mask) :	\
    143  1.25    simonb 		    "memory");						\
    144  1.25    simonb 	} else {							\
    145  1.25    simonb 		asm volatile("csrc " #regname ", %0" :: "r"(__mask) :	\
    146  1.25    simonb 		    "memory");						\
    147  1.25    simonb 	}								\
    148  1.25    simonb }
    149  1.25    simonb 
    150  1.25    simonb #define	RISCVREG_READ_WRITE_INLINE(regname)				\
    151  1.25    simonb RISCVREG_READ_INLINE(regname)						\
    152  1.25    simonb RISCVREG_WRITE_INLINE(regname)
    153  1.25    simonb #define	RISCVREG_SET_CLEAR_INLINE(regname)				\
    154  1.25    simonb RISCVREG_SET_INLINE(regname)						\
    155  1.25    simonb RISCVREG_CLEAR_INLINE(regname)
    156  1.25    simonb #define	RISCVREG_READ_SET_CLEAR_INLINE(regname)				\
    157  1.25    simonb RISCVREG_READ_INLINE(regname)						\
    158  1.25    simonb RISCVREG_SET_CLEAR_INLINE(regname)
    159  1.25    simonb #define	RISCVREG_READ_WRITE_SET_CLEAR_INLINE(regname)			\
    160  1.25    simonb RISCVREG_READ_WRITE_INLINE(regname)					\
    161  1.25    simonb RISCVREG_SET_CLEAR_INLINE(regname)
    162  1.25    simonb 
    163   1.9     skrll /* Supervisor Status Register */
    164  1.25    simonb RISCVREG_READ_SET_CLEAR_INLINE(sstatus)		// supervisor status register
    165   1.9     skrll #ifdef _LP64
    166  1.27     skrll #define	SR_WPRI		__BITS(62, 34) | __BITS(31, 20) | \
    167  1.27     skrll 			__BIT(17) | __BITS(12, 11) | __BIT(7) | __BITS(4, 2) | \
    168  1.27     skrll 			__BIT(0)
    169  1.26    simonb #define	SR_SD		__BIT(63)	// any of FS or VS or XS dirty
    170   1.9     skrll 			/* Bits 62-34 are WPRI */
    171  1.27     skrll #define	SR_UXL		__BITS(33, 32)	// U-mode XLEN
    172  1.26    simonb #define	 SR_UXL_32	1		//   XLEN ==  32
    173  1.26    simonb #define	 SR_UXL_64	2		//   XLEN ==  64
    174  1.26    simonb #define	 SR_UXL_128	3		//   XLEN == 128
    175   1.9     skrll 			/* Bits 31-20 are WPRI*/
    176   1.9     skrll #else
    177  1.27     skrll #define	SR_WPRI		__BITS(30, 20) | \
    178  1.27     skrll 			__BIT(17) | __BITS(12, 11) | __BIT(7) | __BITS(4, 2) | \
    179  1.27     skrll 			__BIT(0)
    180  1.26    simonb #define	SR_SD		__BIT(31)	// any of FS or VS or XS dirty
    181   1.9     skrll 			/* Bits 30-20 are WPRI*/
    182   1.9     skrll #endif /* _LP64 */
    183   1.9     skrll 
    184   1.9     skrll /* Both RV32 and RV64 have the bottom 20 bits shared */
    185  1.26    simonb #define	SR_MXR		__BIT(19)	// Make eXecutable Readable
    186  1.26    simonb #define	SR_SUM		__BIT(18)	// permit Supervisor User Memory access
    187   1.9     skrll 			/* Bit 17 is WPRI */
    188  1.27     skrll #define	SR_XS		__BITS(16, 15)	// Vector extension state
    189  1.26    simonb #define	 SR_XS_OFF		0	//   All off
    190  1.26    simonb #define	 SR_XS_SOME_ON		1	//   None dirty or clean, some on
    191  1.26    simonb #define	 SR_XS_SOME_CLEAN	2	//   None dirty, some clean
    192  1.26    simonb #define	 SR_XS_SOME_DIRTY	3	//   Some dirty
    193  1.27     skrll #define	SR_FS		__BITS(14, 13)	// Floating-point unit state
    194  1.26    simonb #define	 SR_FS_OFF	0		//   Off
    195  1.26    simonb #define	 SR_FS_INITIAL	1		//   Initial
    196  1.26    simonb #define	 SR_FS_CLEAN	2		//   Clean
    197  1.26    simonb #define	 SR_FS_DIRTY	3		//   Dirty
    198  1.26    simonb 			/* Bits 12-11 are WPRI */
    199  1.27     skrll #define	SR_VS		__BITS(10, 9)	// User-mode extention state
    200  1.26    simonb #define	 SR_VS_OFF	SR_FS_OFF	//   Off
    201  1.26    simonb #define	 SR_VS_INITIAL	SR_FS_INITIAL	//   Initial
    202  1.26    simonb #define	 SR_VS_CLEAN	SR_FS_CLEAN	//   Clean
    203  1.26    simonb #define	 SR_VS_DIRTY	SR_FS_DIRTY	//   Dirty
    204  1.26    simonb #define	SR_SPP		__BIT(8)	// Priv level before supervisor mode
    205  1.26    simonb 			/* Bit 7 is WPRI */
    206  1.26    simonb #define	SR_UBE		__BIT(6)	// User-mode endianness
    207  1.26    simonb #define	SR_SPIE		__BIT(5)	// S-Mode interrupts enabled before trap
    208  1.26    simonb 			/* Bits 4-2 are WPRI */
    209  1.26    simonb #define	SR_SIE		__BIT(1)	// Supervisor mode interrupt enable
    210  1.26    simonb 			/* Bit 0 is WPRI */
    211   1.9     skrll 
    212   1.9     skrll /* Supervisor interrupt registers */
    213  1.11  christos /* ... interrupt pending register (sip) */
    214  1.25    simonb RISCVREG_READ_SET_CLEAR_INLINE(sip)		// supervisor interrupt pending
    215  1.19     skrll 			/* Bit (XLEN-1) - 10 is WIRI */
    216  1.26    simonb #define	SIP_SEIP	__BIT(9)	// S-mode interrupt pending
    217  1.26    simonb 			/* Bit 8-6 is WIRI */
    218  1.26    simonb #define	SIP_STIP	__BIT(5)	// S-mode timer interrupt pending
    219  1.26    simonb 			/* Bit 4-2 is WIRI */
    220  1.26    simonb #define	SIP_SSIP	__BIT(1)	// S-mode software interrupt pending
    221  1.26    simonb 			/* Bit 0 is WIRI */
    222   1.9     skrll 
    223  1.11  christos /* ... interrupt-enable register (sie) */
    224  1.25    simonb RISCVREG_READ_SET_CLEAR_INLINE(sie)		// supervisor interrupt enable
    225   1.9     skrll 			/* Bit (XLEN-1) - 10 is WIRI */
    226  1.26    simonb #define	SIE_SEIE	__BIT(9)	// S-mode interrupt enable
    227  1.26    simonb 			/* Bit 8-6 is WIRI */
    228  1.26    simonb #define	SIE_STIE	__BIT(5)	// S-mode timer interrupt enable
    229  1.26    simonb 			/* Bit 4-2 is WIRI */
    230  1.26    simonb #define	SIE_SSIE	__BIT(1)	// S-mode software interrupt enable
    231  1.26    simonb 			/* Bit 0 is WIRI */
    232   1.9     skrll 
    233   1.9     skrll /* Mask for all interrupts */
    234  1.27     skrll #define	SIE_IM		(SIE_SEI |SIE_STIE | SIE_SSIE)
    235   1.1      matt 
    236   1.1      matt #ifdef _LP64
    237  1.26    simonb #define	SR_USER64	(SR_SPIE | SR_UXL_64)	// 64-bit U-mode sstatus
    238  1.26    simonb #define	SR_USER32	(SR_SPIE | SR_UXL_32)	// 32-bit U-mode sstatus
    239   1.1      matt #else
    240  1.26    simonb #define	SR_USER		(SR_SPIE)		// U-mode sstatus
    241   1.1      matt #endif
    242   1.1      matt 
    243   1.1      matt // Cause register
    244  1.27     skrll #define	CAUSE_INTERRUPT_P(cause)	((cause) & __BIT(XLEN - 1))
    245  1.27     skrll #define	CAUSE_CODE(cause)		((cause) & __BITS(XLEN - 2, 0))
    246  1.20    simonb 
    247  1.20    simonb // Cause register - exceptions
    248  1.15    simonb #define	CAUSE_FETCH_MISALIGNED		0
    249  1.15    simonb #define	CAUSE_FETCH_ACCESS		1
    250  1.15    simonb #define	CAUSE_ILLEGAL_INSTRUCTION	2
    251  1.15    simonb #define	CAUSE_BREAKPOINT		3
    252  1.15    simonb #define	CAUSE_LOAD_MISALIGNED		4
    253  1.15    simonb #define	CAUSE_LOAD_ACCESS		5
    254  1.15    simonb #define	CAUSE_STORE_MISALIGNED		6
    255  1.15    simonb #define	CAUSE_STORE_ACCESS		7
    256  1.15    simonb #define	CAUSE_USER_ECALL		8
    257  1.20    simonb #define	CAUSE_SYSCALL			CAUSE_USER_ECALL /* convenience alias */
    258  1.15    simonb #define	CAUSE_SUPERVISOR_ECALL		9
    259   1.6     skrll /* 10 is reserved */
    260  1.15    simonb #define	CAUSE_MACHINE_ECALL		11
    261  1.15    simonb #define	CAUSE_FETCH_PAGE_FAULT		12
    262  1.15    simonb #define	CAUSE_LOAD_PAGE_FAULT		13
    263   1.6     skrll /* 14 is Reserved */
    264  1.15    simonb #define	CAUSE_STORE_PAGE_FAULT		15
    265  1.20    simonb /* >= 16 is reserved/custom */
    266  1.20    simonb 
    267  1.24     skrll // Cause register - interrupts
    268  1.20    simonb #define	IRQ_SUPERVISOR_SOFTWARE	1
    269  1.20    simonb #define	IRQ_MACHINE_SOFTWARE	3
    270  1.20    simonb #define	IRQ_SUPERVISOR_TIMER	5
    271  1.20    simonb #define	IRQ_MACHINE_TIMER	7
    272  1.20    simonb #define	IRQ_SUPERVISOR_EXTERNAL	9
    273  1.20    simonb #define	IRQ_MACHINE_EXTERNAL	11
    274   1.1      matt 
    275  1.25    simonb RISCVREG_READ_INLINE(time)
    276  1.25    simonb #ifdef _LP64
    277  1.25    simonb RISCVREG_READ_INLINE(cycle)
    278  1.25    simonb #else /* !_LP64 */
    279   1.1      matt static inline uint64_t
    280  1.25    simonb csr_cycle_read(void)
    281   1.1      matt {
    282   1.1      matt 	uint32_t __hi0, __hi1, __lo0;
    283   1.1      matt 	do {
    284   1.1      matt 		__asm __volatile(
    285   1.5     skrll 			"csrr\t%[__hi0], cycleh"
    286   1.1      matt 		"\n\t"	"csrr\t%[__lo0], cycle"
    287   1.1      matt 		"\n\t"	"csrr\t%[__hi1], cycleh"
    288   1.1      matt 		   :	[__hi0] "=r"(__hi0),
    289   1.1      matt 			[__lo0] "=r"(__lo0),
    290   1.1      matt 			[__hi1] "=r"(__hi1));
    291   1.1      matt 	} while (__hi0 != __hi1);
    292  1.27     skrll 	return
    293  1.27     skrll 	    __SHIFTIN(__hi0, __BITS(63, 32)) |
    294  1.27     skrll 	    __SHIFTIN(__lo0, __BITS(31,  0));
    295   1.1      matt }
    296  1.25    simonb #endif /* !_LP64 */
    297   1.1      matt 
    298   1.4      maxv #ifdef _LP64
    299  1.27     skrll #define	SATP_MODE		__BITS(63, 60)	// Translation mode
    300  1.26    simonb #define	 SATP_MODE_BARE		0		//   No translation or protection
    301  1.26    simonb 				/* modes 1-7 reserved for standard use */
    302  1.26    simonb #define	 SATP_MODE_SV39		8		//   Page-based 39-bit virt addr
    303  1.26    simonb #define	 SATP_MODE_SV48		9		//   Page-based 48-bit virt addr
    304  1.26    simonb #define	 SATP_MODE_SV57		10		//   Page-based 57-bit virt addr
    305  1.26    simonb #define	 SATP_MODE_SV64		11		//   Page-based 64-bit virt addr
    306  1.26    simonb 				/* modes 12-13 reserved for standard use */
    307  1.26    simonb 				/* modes 14-15 designated for custom use */
    308  1.27     skrll #define	SATP_ASID		__BITS(59, 44)	//   Address Space Identifier
    309  1.27     skrll #define	SATP_PPN		__BITS(43, 0)	//   Physical Page Number
    310   1.4      maxv #else
    311  1.26    simonb #define	SATP_MODE		__BIT(31)	// Translation mode
    312  1.26    simonb #define	 SATP_MODE_BARE		0		//   No translation or protection
    313  1.26    simonb #define	 SATP_MODE_SV32		1		//   Page-based 32-bit virt addr
    314  1.27     skrll #define	SATP_ASID		__BITS(30, 22)	//   Address Space Identifier
    315  1.27     skrll #define	SATP_PPN		__BITS(21, 0)	//   Physical Page Number
    316   1.4      maxv #endif
    317   1.2      matt 
    318  1.25    simonb RISCVREG_READ_WRITE_INLINE(satp)
    319  1.13     skrll 
    320  1.25    simonb /* Fake "ASID" CSR (a field of SATP register) functions */
    321   1.2      matt static inline uint32_t
    322  1.25    simonb csr_asid_read(void)
    323   1.2      matt {
    324  1.25    simonb 	uintptr_t satp = csr_satp_read();
    325   1.4      maxv 	return __SHIFTOUT(satp, SATP_ASID);
    326   1.2      matt }
    327   1.2      matt 
    328   1.2      matt static inline void
    329  1.25    simonb csr_asid_write(uint32_t asid)
    330   1.2      matt {
    331  1.27     skrll 	uintptr_t satp = csr_satp_read();
    332   1.4      maxv 	satp &= ~SATP_ASID;
    333  1.14     skrll 	satp |= __SHIFTIN(asid, SATP_ASID);
    334  1.25    simonb 	csr_satp_write(satp);
    335   1.2      matt }
    336   1.2      matt 
    337   1.1      matt #endif /* _RISCV_SYSREG_H_ */
    338