xref: /netbsd-src/sys/arch/riscv/include/sysreg.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* $NetBSD: sysreg.h,v 1.3 2015/03/31 01:14:02 matt Exp $ */
2 /*-
3  * Copyright (c) 2014 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Matt Thomas of 3am Software Foundry.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef _RISCV_SYSREG_H_
32 #define _RISCV_SYSREG_H_
33 
34 #ifndef _KERNEL
35 #include <sys/param.h>
36 #endif
37 
38 #define FCSR_FMASK	0	// no exception bits
39 #define FCSR_FRM	__BITS(7,5)
40 #define FCSR_FRM_RNE	0b000	// Round Nearest, ties to Even
41 #define FCSR_FRM_RTZ	0b001	// Round Towards Zero
42 #define FCSR_FRM_RDN	0b010	// Round DowN (-infinity)
43 #define FCSR_FRM_RUP	0b011	// Round UP (+infinity)
44 #define FCSR_FRM_RMM	0b100	// Round to nearest, ties to Max Magnitude
45 #define FCSR_FFLAGS	__BITS(4,0)	// Sticky bits
46 #define FCSR_NV		__BIT(4)	// iNValid operation
47 #define FCSR_DZ		__BIT(3)	// Divide by Zero
48 #define FCSR_OF		__BIT(2)	// OverFlow
49 #define FCSR_UF		__BIT(1)	// UnderFlow
50 #define FCSR_NX		__BIT(0)	// iNeXact
51 
52 static inline uint32_t
53 riscvreg_fcsr_read(void)
54 {
55 	uint32_t __fcsr;
56 	__asm("frcsr %0" : "=r"(__fcsr));
57 	return __fcsr;
58 }
59 
60 
61 static inline uint32_t
62 riscvreg_fcsr_write(uint32_t __new)
63 {
64 	uint32_t __old;
65 	__asm("fscsr %0, %1" : "=r"(__old) : "r"(__new));
66 	return __old;
67 }
68 
69 static inline uint32_t
70 riscvreg_fcsr_read_fflags(void)
71 {
72 	uint32_t __old;
73 	__asm("frflags %0" : "=r"(__old));
74 	return __SHIFTOUT(__old, FCSR_FFLAGS);
75 }
76 
77 static inline uint32_t
78 riscvreg_fcsr_write_fflags(uint32_t __new)
79 {
80 	uint32_t __old;
81 	__new = __SHIFTIN(__new, FCSR_FFLAGS);
82 	__asm("fsflags %0, %1" : "=r"(__old) : "r"(__new));
83 	return __SHIFTOUT(__old, FCSR_FFLAGS);
84 }
85 
86 static inline uint32_t
87 riscvreg_fcsr_read_frm(void)
88 {
89 	uint32_t __old;
90 	__asm("frrm\t%0" : "=r"(__old));
91 	return __SHIFTOUT(__old, FCSR_FRM);
92 }
93 
94 static inline uint32_t
95 riscvreg_fcsr_write_frm(uint32_t __new)
96 {
97 	uint32_t __old;
98 	__new = __SHIFTIN(__new, FCSR_FRM);
99 	__asm volatile("fsrm\t%0, %1" : "=r"(__old) : "r"(__new));
100 	return __SHIFTOUT(__old, FCSR_FRM);
101 }
102 
103 // Status Register
104 #define SR_IP		__BITS(31,24)	// Pending interrupts
105 #define SR_IM		__BITS(23,16)	// Interrupt Mask
106 #define SR_VM		__BIT(7)	// MMU On
107 #define SR_S64		__BIT(6)	// RV64 supervisor mode
108 #define SR_U64		__BIT(5)	// RV64 user mode
109 #define SR_EF		__BIT(4)	// Enable Floating Point
110 #define SR_PEI		__BIT(3)	// Previous EI setting
111 #define SR_EI		__BIT(2)	// Enable interrupts
112 #define SR_PS		__BIT(1)	// Previous (S) supervisor setting
113 #define SR_S		__BIT(0)	// Supervisor
114 
115 #ifdef _LP64
116 #define	SR_USER		(SR_EI|SR_U64|SR_S64|SR_VM|SR_IM)
117 #define	SR_USER32	(SR_USER & ~SR_U64)
118 #define	SR_KERNEL	(SR_S|SR_EI|SR_U64|SR_S64|SR_VM)
119 #else
120 #define	SR_USER		(SR_EI|SR_VM|SR_IM)
121 #define	SR_KERNEL	(SR_S|SR_EI|SR_VM)
122 #endif
123 
124 static inline uint32_t
125 riscvreg_status_read(void)
126 {
127 	uint32_t __sr;
128 	__asm("csrr\t%0, sstatus" : "=r"(__sr));
129 	return __sr;
130 }
131 
132 static inline uint32_t
133 riscvreg_status_clear(uint32_t __mask)
134 {
135 	uint32_t __sr;
136 	if (__builtin_constant_p(__mask) && __mask < 0x20) {
137 		__asm("csrrci\t%0, sstatus, %1" : "=r"(__sr) : "i"(__mask));
138 	} else {
139 		__asm("csrrc\t%0, sstatus, %1" : "=r"(__sr) : "r"(__mask));
140 	}
141 	return __sr;
142 }
143 
144 static inline uint32_t
145 riscvreg_status_set(uint32_t __mask)
146 {
147 	uint32_t __sr;
148 	if (__builtin_constant_p(__mask) && __mask < 0x20) {
149 		__asm("csrrsi\t%0, sstatus, %1" : "=r"(__sr) : "i"(__mask));
150 	} else {
151 		__asm("csrrs\t%0, sstatus, %1" : "=r"(__sr) : "r"(__mask));
152 	}
153 	return __sr;
154 }
155 
156 // Cause register
157 #define CAUSE_MISALIGNED_FETCH		0
158 #define CAUSE_FAULT_FETCH		1
159 #define CAUSE_ILLEGAL_INSTRUCTION	2
160 #define CAUSE_PRIVILEGED_INSTRUCTION	3
161 #define CAUSE_MISALIGNED_LOAD		4
162 #define CAUSE_FAULT_LOAD		5
163 #define CAUSE_MISALIGNED_STORE		6
164 #define CAUSE_FAULT_STORE		7
165 #define CAUSE_SYSCALL			8
166 #define CAUSE_BREAKPOINT		9
167 #define CAUSE_FP_DISABLED		10
168 #define CAUSE_ACCELERATOR_DISABLED	12
169 
170 static inline uint64_t
171 riscvreg_cycle_read(void)
172 {
173 #ifdef _LP64
174 	uint64_t __lo;
175 	__asm __volatile("csrr\t%0, cycle" : "=r"(__lo));
176 	return __lo;
177 #else
178 	uint32_t __hi0, __hi1, __lo0;
179 	do {
180 		__asm __volatile(
181 			"csrr\t%[__hi0], cycleh"
182 		"\n\t"	"csrr\t%[__lo0], cycle"
183 		"\n\t"	"csrr\t%[__hi1], cycleh"
184 		   :	[__hi0] "=r"(__hi0),
185 			[__lo0] "=r"(__lo0),
186 			[__hi1] "=r"(__hi1));
187 	} while (__hi0 != __hi1);
188 	return ((uint64_t)__hi0 << 32) | (uint64_t)__lo0;
189 #endif
190 }
191 
192 static inline uintptr_t
193 riscvreg_ptbr_read(void)
194 {
195 	uintptr_t __ptbr;
196 	__asm("csrr\t%0, sptbr" : "=r"(__ptbr));
197 	return __ptbr;
198 }
199 
200 static inline void
201 riscvreg_ptbr_write(uint32_t __ptbr)
202 {
203 	__asm("csrw\tsptbr, %0" :: "r"(__ptbr));
204 }
205 
206 static inline uint32_t
207 riscvreg_asid_read(void)
208 {
209 	uint32_t __asid;
210 	__asm __volatile("csrr\t%0, sasid" : "=r"(__asid));
211 	return __asid;
212 }
213 
214 static inline void
215 riscvreg_asid_write(uint32_t __asid)
216 {
217 	__asm __volatile("csrw\tsasid, %0" :: "r"(__asid));
218 }
219 
220 #endif /* _RISCV_SYSREG_H_ */
221