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