xref: /netbsd-src/sys/arch/riscv/include/sysreg.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* $NetBSD: sysreg.h,v 1.13 2021/05/01 07:09:55 skrll 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_SV39		8
257 #define  SATP_MODE_SV48		9
258 #define SATP_ASID		__BITS(59,44)
259 #define SATP_PPN		__BITS(43,0)
260 #else
261 #define SATP_MODE		__BIT(31)
262 #define  SATP_MODE_SV32		1
263 #define SATP_ASID		__BITS(30,22)
264 #define SATP_PPN		__BITS(21,0)
265 #endif
266 
267 static inline uintptr_t
268 riscvreg_satp_read(void)
269 {
270 	uintptr_t satp;
271 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
272 	return satp;
273 }
274 
275 static inline void
276 riscvreg_satp_write(uintptr_t satp)
277 {
278 	__asm __volatile("csrw	satp, %0" :: "r" (satp));
279 }
280 
281 static inline uint32_t
282 riscvreg_asid_read(void)
283 {
284 	uintptr_t satp;
285 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
286 	return __SHIFTOUT(satp, SATP_ASID);
287 }
288 
289 static inline void
290 riscvreg_asid_write(uint32_t asid)
291 {
292 	uintptr_t satp;
293 	__asm __volatile("csrr	%0, satp" : "=r" (satp));
294 	satp &= ~SATP_ASID;
295 	satp |= __SHIFTIN((uintptr_t)asid, SATP_ASID);
296 	__asm __volatile("csrw	satp, %0" :: "r" (satp));
297 }
298 
299 #endif /* _RISCV_SYSREG_H_ */
300