Home | History | Annotate | Line # | Download | only in include
sysreg.h revision 1.17
      1 /* $NetBSD: sysreg.h,v 1.17 2022/10/15 06:52:35 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 /* Supervisor Status Register */
    108 #ifdef _LP64
    109 #define	SR_WPRI		__BITS(62, 34) | __BITS(31,20) | __BIT(17) | \
    110 			    __BITS(12,9) | __BITS(7,6) | __BITS(3,2)
    111 #define	SR_SD		__BIT(63)
    112 			/* Bits 62-34 are WPRI */
    113 #define	SR_UXL		__BITS(33,32)
    114 #define	 SR_UXL_32	1
    115 #define	 SR_UXL_64	2
    116 #define	 SR_UXL_128	3
    117 			/* Bits 31-20 are WPRI*/
    118 #else
    119 #define	SR_WPRI		__BITS(30,20) | __BIT(17) | __BITS(12,9) | \
    120 			    __BITS(7,6) | __BITS(3,2)
    121 #define	SR_SD		__BIT(31)
    122 			/* Bits 30-20 are WPRI*/
    123 #endif /* _LP64 */
    124 
    125 /* Both RV32 and RV64 have the bottom 20 bits shared */
    126 #define	SR_MXR		__BIT(19)
    127 #define	SR_SUM		__BIT(18)
    128 			/* Bit 17 is WPRI */
    129 #define	SR_XS		__BITS(16,15)
    130 #define	SR_FS		__BITS(14,13)
    131 #define	 SR_FS_OFF	0
    132 #define	 SR_FS_INITIAL	1
    133 #define	 SR_FS_CLEAN	2
    134 #define	 SR_FS_DIRTY	3
    135 
    136 			/* Bits 12-9 are WPRI */
    137 #define	SR_SPP		__BIT(8)
    138 			/* Bits 7-6 are WPRI */
    139 #define	SR_SPIE		__BIT(5)
    140 #define	SR_UPIE		__BIT(4)
    141 			/* Bits 3-2 are WPRI */
    142 #define	SR_SIE		__BIT(1)
    143 #define	SR_UIE		__BIT(0)
    144 
    145 /* Supervisor interrupt registers */
    146 /* ... interrupt pending register (sip) */
    147 			/* Bit (XLEN-1)-10 is WIRI */
    148 #define	SIP_SEIP	__BIT(9)
    149 #define	SIP_UEIP	__BIT(8)
    150 			/* Bit 7-6 is WIRI */
    151 #define	SIP_STIP	__BIT(5)
    152 #define	SIP_UTIP	__BIT(4)
    153 			/* Bit 3-2 is WIRI */
    154 #define	SIP_SSIP	__BIT(1)
    155 #define	SIP_USIP	__BIT(0)
    156 
    157 /* ... interrupt-enable register (sie) */
    158 			/* Bit (XLEN-1) - 10 is WIRI */
    159 #define	SIE_SEIE	__BIT(9)
    160 #define	SIE_UEIE	__BIT(8)
    161 			/* Bit 7-6 is WIRI */
    162 #define	SIE_STIE	__BIT(5)
    163 #define	SIE_UTIE	__BIT(4)
    164 			/* Bit 3-2 is WIRI */
    165 #define	SIE_SSIE	__BIT(1)
    166 #define	SIE_USIE	__BIT(0)
    167 
    168 /* Mask for all interrupts */
    169 #define	SIE_IM		(SIE_SEI|SIE_UEIE|SIE_STIE|SIE_UTIE|SIE_SSIE|SIE_USIE)
    170 
    171 #ifdef _LP64
    172 #define	SR_USER		(SR_UIE)
    173 #define	SR_USER32	(SR_USER)
    174 #define	SR_KERNEL	(SR_SIE | SR_UIE)
    175 #else
    176 #define	SR_USER		(SR_UIE)
    177 #define	SR_KERNEL	(SR_SIE | SR_UIE)
    178 #endif
    179 
    180 static inline uint32_t
    181 riscvreg_status_read(void)
    182 {
    183 	uint32_t __sr;
    184 	__asm("csrr\t%0, sstatus" : "=r"(__sr));
    185 	return __sr;
    186 }
    187 
    188 static inline uint32_t
    189 riscvreg_status_clear(uint32_t __mask)
    190 {
    191 	uint32_t __sr;
    192 	if (__builtin_constant_p(__mask) && __mask < 0x20) {
    193 		__asm("csrrci\t%0, sstatus, %1" : "=r"(__sr) : "i"(__mask));
    194 	} else {
    195 		__asm("csrrc\t%0, sstatus, %1" : "=r"(__sr) : "r"(__mask));
    196 	}
    197 	return __sr;
    198 }
    199 
    200 static inline uint32_t
    201 riscvreg_status_set(uint32_t __mask)
    202 {
    203 	uint32_t __sr;
    204 	if (__builtin_constant_p(__mask) && __mask < 0x20) {
    205 		__asm("csrrsi\t%0, sstatus, %1" : "=r"(__sr) : "i"(__mask));
    206 	} else {
    207 		__asm("csrrs\t%0, sstatus, %1" : "=r"(__sr) : "r"(__mask));
    208 	}
    209 	return __sr;
    210 }
    211 
    212 // Cause register
    213 #define	CAUSE_FETCH_MISALIGNED		0
    214 #define	CAUSE_FETCH_ACCESS		1
    215 #define	CAUSE_ILLEGAL_INSTRUCTION	2
    216 #define	CAUSE_BREAKPOINT		3
    217 #define	CAUSE_LOAD_MISALIGNED		4
    218 #define	CAUSE_LOAD_ACCESS		5
    219 #define	CAUSE_STORE_MISALIGNED		6
    220 #define	CAUSE_STORE_ACCESS		7
    221 #define	CAUSE_SYSCALL			8
    222 #define	CAUSE_USER_ECALL		8
    223 #define	CAUSE_SUPERVISOR_ECALL		9
    224 /* 10 is reserved */
    225 #define	CAUSE_MACHINE_ECALL		11
    226 #define	CAUSE_FETCH_PAGE_FAULT		12
    227 #define	CAUSE_LOAD_PAGE_FAULT		13
    228 /* 14 is Reserved */
    229 #define	CAUSE_STORE_PAGE_FAULT		15
    230 /* >= 16 is reserved */
    231 
    232 static inline uint64_t
    233 riscvreg_cycle_read(void)
    234 {
    235 #ifdef _LP64
    236 	uint64_t __lo;
    237 	__asm __volatile("csrr\t%0, cycle" : "=r"(__lo));
    238 	return __lo;
    239 #else
    240 	uint32_t __hi0, __hi1, __lo0;
    241 	do {
    242 		__asm __volatile(
    243 			"csrr\t%[__hi0], cycleh"
    244 		"\n\t"	"csrr\t%[__lo0], cycle"
    245 		"\n\t"	"csrr\t%[__hi1], cycleh"
    246 		   :	[__hi0] "=r"(__hi0),
    247 			[__lo0] "=r"(__lo0),
    248 			[__hi1] "=r"(__hi1));
    249 	} while (__hi0 != __hi1);
    250 	return ((uint64_t)__hi0 << 32) | (uint64_t)__lo0;
    251 #endif
    252 }
    253 
    254 #ifdef _LP64
    255 #define	SATP_MODE		__BITS(63,60)
    256 #define	 SATP_MODE_BARE		0
    257 #define	 SATP_MODE_SV39		8
    258 #define	 SATP_MODE_SV48		9
    259 #define	 SATP_MODE_SV57		10
    260 #define	 SATP_MODE_SV64		10
    261 #define	SATP_ASID		__BITS(59,44)
    262 #define	SATP_PPN		__BITS(43,0)
    263 #else
    264 #define	SATP_MODE		__BIT(31)
    265 #define	 SATP_MODE_BARE		0
    266 #define	 SATP_MODE_SV32		1
    267 #define	SATP_ASID		__BITS(30,22)
    268 #define	SATP_PPN		__BITS(21,0)
    269 #endif
    270 
    271 static inline uintptr_t
    272 riscvreg_satp_read(void)
    273 {
    274 	uintptr_t satp;
    275 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
    276 	return satp;
    277 }
    278 
    279 static inline void
    280 riscvreg_satp_write(uintptr_t satp)
    281 {
    282 	__asm __volatile("csrw	satp, %0" :: "r" (satp));
    283 }
    284 
    285 static inline uint32_t
    286 riscvreg_asid_read(void)
    287 {
    288 	uintptr_t satp;
    289 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
    290 	return __SHIFTOUT(satp, SATP_ASID);
    291 }
    292 
    293 static inline void
    294 riscvreg_asid_write(uint32_t asid)
    295 {
    296 	uintptr_t satp;
    297 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
    298 	satp &= ~SATP_ASID;
    299 	satp |= __SHIFTIN(asid, SATP_ASID);
    300 	__asm __volatile("csrw	satp, %0" :: "r" (satp));
    301 }
    302 
    303 #endif /* _RISCV_SYSREG_H_ */
    304