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