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