xref: /haiku/headers/private/system/arch/riscv64/arch_cpu_defs.h (revision 4a32f48e70297d9a634646f01e08c2f451ecd6bd)
1 /*
2  * Copyright 2021, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _SYSTEM_ARCH_RISCV64_DEFS_H
6 #define _SYSTEM_ARCH_RISCV64_DEFS_H
7 
8 
9 #include <SupportDefs.h>
10 
11 
12 enum {
13 	modeU = 0,
14 	modeS = 1,
15 	modeM = 3,
16 };
17 
18 // fs, xs
19 enum {
20 	extStatusOff     = 0,
21 	extStatusInitial = 1,
22 	extStatusClean   = 2,
23 	extStatusDirty   = 3,
24 };
25 
26 struct MstatusReg {
27 	union {
28 		struct {
29 			uint64 ie:      4; // interrupt enable
30 			uint64 pie:     4; // previous interrupt enable
31 			uint64 spp:     1; // previous mode (supervisor)
32 			uint64 unused1: 2;
33 			uint64 mpp:     2; // previous mode (machine)
34 			uint64 fs:      2; // FPU status
35 			uint64 xs:      2; // extensions status
36 			uint64 mprv:    1; // modify privelege
37 			uint64 sum:     1; // permit supervisor user memory access
38 			uint64 mxr:     1; // make executable readable
39 			uint64 tvm:     1; // trap virtual memory
40 			uint64 tw:      1; // timeout wait (trap WFI)
41 			uint64 tsr:     1; // trap SRET
42 			uint64 unused2: 9;
43 			uint64 uxl:     2; // U-mode XLEN
44 			uint64 sxl:     2; // S-mode XLEN
45 			uint64 unused3: 27;
46 			uint64 sd:      1; // status dirty
47 		};
48 		uint64 val;
49 	};
50 
51 	MstatusReg() {}
52 	MstatusReg(uint64 val): val(val) {}
53 };
54 
55 struct SstatusReg {
56 	union {
57 		struct {
58 			uint64 ie:      2; // interrupt enable
59 			uint64 unused1: 2;
60 			uint64 pie:     2; // previous interrupt enable
61 			uint64 unused2: 2;
62 			uint64 spp:     1; // previous mode (supervisor)
63 			uint64 unused3: 4;
64 			uint64 fs:      2; // FPU status
65 			uint64 xs:      2; // extensions status
66 			uint64 unused4: 1;
67 			uint64 sum:     1; // permit supervisor user memory access
68 			uint64 mxr:     1; // make executable readable
69 			uint64 unused5: 12;
70 			uint64 uxl:     2; // U-mode XLEN
71 			uint64 unused6: 29;
72 			uint64 sd:      1; // status dirty
73 		};
74 		uint64 val;
75 	};
76 
77 	SstatusReg() {}
78 	SstatusReg(uint64 val): val(val) {}
79 };
80 
81 enum {
82 	softInt    = 0,
83 	uSoftInt   = softInt + modeU,
84 	sSoftInt   = softInt + modeS,
85 	mSoftInt   = softInt + modeM,
86 	timerInt   = 4,
87 	uTimerInt  = timerInt + modeU,
88 	sTimerInt  = timerInt + modeS,
89 	mTimerInt  = timerInt + modeM,
90 	externInt  = 8,
91 	uExternInt = externInt + modeU,
92 	sExternInt = externInt + modeS,
93 	mExternInt = externInt + modeM,
94 };
95 
96 enum {
97 	causeInterrupt        = 1ULL << 63, // rest bits are interrupt number
98 	causeExecMisalign     = 0,
99 	causeExecAccessFault  = 1,
100 	causeIllegalInst      = 2,
101 	causeBreakpoint       = 3,
102 	causeLoadMisalign     = 4,
103 	causeLoadAccessFault  = 5,
104 	causeStoreMisalign    = 6,
105 	causeStoreAccessFault = 7,
106 	causeECall            = 8,
107 	causeUEcall           = causeECall + modeU,
108 	causeSEcall           = causeECall + modeS,
109 	causeMEcall           = causeECall + modeM,
110 	causeExecPageFault    = 12,
111 	causeLoadPageFault    = 13,
112 	causeStorePageFault   = 15,
113 };
114 
115 enum {
116 	pageSize = 4096,
117 	pageBits = 12,
118 	pteCount = 512,
119 	pteIdxBits = 9,
120 };
121 
122 enum {
123 	pteValid    = 0,
124 	pteRead     = 1,
125 	pteWrite    = 2,
126 	pteExec     = 3,
127 	pteUser     = 4,
128 	pteGlobal   = 5,
129 	pteAccessed = 6,
130 	pteDirty    = 7,
131 };
132 
133 struct Pte {
134 	union {
135 		struct {
136 			uint64 flags:     8;
137 			uint64 rsw:       2;
138 			uint64 ppn:      44;
139 			uint64 reserved: 10;
140 		};
141 		uint64 val;
142 	};
143 
144 	Pte() {}
145 	Pte(uint64 val): val(val) {}
146 };
147 
148 enum {
149 	satpModeBare =  0,
150 	satpModeSv39 =  8,
151 	satpModeSv48 =  9,
152 	satpModeSv57 = 10,
153 	satpModeSv64 = 11,
154 };
155 
156 struct SatpReg {
157 	union {
158 		struct {
159 			uint64 ppn:  44;
160 			uint64 asid: 16;
161 			uint64 mode:  4;
162 		};
163 		uint64 val;
164 	};
165 
166 	SatpReg() {}
167 	SatpReg(uint64 val): val(val) {}
168 };
169 
170 static B_ALWAYS_INLINE uint64 PhysAdrPte(uint64 physAdr, uint32 level)
171 {
172 	return (physAdr >> (pageBits + pteIdxBits*level)) % (1 << pteIdxBits);
173 }
174 
175 static B_ALWAYS_INLINE uint64 PhysAdrOfs(uint64 physAdr)
176 {
177 	return physAdr % pageSize;
178 }
179 
180 // CPU core ID
181 static B_ALWAYS_INLINE uint64 Mhartid() {
182 	uint64 x; asm volatile("csrr %0, mhartid" : "=r" (x)); return x;}
183 
184 // status register
185 static B_ALWAYS_INLINE uint64 Mstatus() {
186 	uint64 x; asm volatile("csrr %0, mstatus" : "=r" (x)); return x;}
187 static B_ALWAYS_INLINE void SetMstatus(uint64 x) {
188 	asm volatile("csrw mstatus, %0" : : "r" (x));}
189 static B_ALWAYS_INLINE uint64 Sstatus() {
190 	uint64 x; asm volatile("csrr %0, sstatus" : "=r" (x)); return x;}
191 static B_ALWAYS_INLINE void SetSstatus(uint64 x) {
192 	asm volatile("csrw sstatus, %0" : : "r" (x));}
193 
194 // exception program counter
195 static B_ALWAYS_INLINE uint64 Mepc() {
196 	uint64 x; asm volatile("csrr %0, mepc" : "=r" (x)); return x;}
197 static B_ALWAYS_INLINE void SetMepc(uint64 x) {
198 	asm volatile("csrw mepc, %0" : : "r" (x));}
199 static B_ALWAYS_INLINE uint64 Sepc() {
200 	uint64 x; asm volatile("csrr %0, sepc" : "=r" (x)); return x;}
201 static B_ALWAYS_INLINE void SetSepc(uint64 x) {
202 	asm volatile("csrw sepc, %0" : : "r" (x));}
203 
204 // interrupt pending
205 static B_ALWAYS_INLINE uint64 Mip() {
206 	uint64 x; asm volatile("csrr %0, mip" : "=r" (x)); return x;}
207 static B_ALWAYS_INLINE void SetMip(uint64 x) {
208 	asm volatile("csrw mip, %0" : : "r" (x));}
209 static B_ALWAYS_INLINE uint64 Sip() {
210 	uint64 x; asm volatile("csrr %0, sip" : "=r" (x)); return x;}
211 static B_ALWAYS_INLINE void SetSip(uint64 x) {
212 	asm volatile("csrw sip, %0" : : "r" (x));}
213 
214 // interrupt enable
215 static B_ALWAYS_INLINE uint64 Sie() {
216 	uint64 x; asm volatile("csrr %0, sie" : "=r" (x)); return x;}
217 static B_ALWAYS_INLINE void SetSie(uint64 x) {
218 	asm volatile("csrw sie, %0" : : "r" (x));}
219 static B_ALWAYS_INLINE uint64 Mie() {
220 	uint64 x; asm volatile("csrr %0, mie" : "=r" (x)); return x;}
221 static B_ALWAYS_INLINE void SetMie(uint64 x) {
222 	asm volatile("csrw mie, %0" : : "r" (x));}
223 
224 // exception delegation
225 static B_ALWAYS_INLINE uint64 Medeleg() {
226 	uint64 x; asm volatile("csrr %0, medeleg" : "=r" (x)); return x;}
227 static B_ALWAYS_INLINE void SetMedeleg(uint64 x) {
228 	asm volatile("csrw medeleg, %0" : : "r" (x));}
229 // interrupt delegation
230 static B_ALWAYS_INLINE uint64 Mideleg() {
231 	uint64 x; asm volatile("csrr %0, mideleg" : "=r" (x)); return x;}
232 static B_ALWAYS_INLINE void SetMideleg(uint64 x) {
233 	asm volatile("csrw mideleg, %0" : : "r" (x));}
234 
235 // trap vector, 2 low bits: mode
236 static B_ALWAYS_INLINE uint64 Mtvec() {
237 	uint64 x; asm volatile("csrr %0, mtvec" : "=r" (x)); return x;}
238 static B_ALWAYS_INLINE void SetMtvec(uint64 x) {
239 	asm volatile("csrw mtvec, %0" : : "r" (x));}
240 static B_ALWAYS_INLINE uint64 Stvec() {
241 	uint64 x; asm volatile("csrr %0, stvec" : "=r" (x)); return x;}
242 static B_ALWAYS_INLINE void SetStvec(uint64 x) {
243 	asm volatile("csrw stvec, %0" : : "r" (x));}
244 
245 // address translation and protection (pointer to page table and flags)
246 static B_ALWAYS_INLINE uint64 Satp() {
247 	uint64 x; asm volatile("csrr %0, satp" : "=r" (x)); return x;}
248 static B_ALWAYS_INLINE void SetSatp(uint64 x) {
249 	asm volatile("csrw satp, %0" : : "r" (x));}
250 
251 // scratch register
252 static B_ALWAYS_INLINE uint64 Mscratch() {
253 	uint64 x; asm volatile("csrr %0, mscratch" : "=r" (x)); return x;}
254 static B_ALWAYS_INLINE void SetMscratch(uint64 x) {
255 	asm volatile("csrw mscratch, %0" : : "r" (x));}
256 static B_ALWAYS_INLINE uint64 Sscratch() {
257 	uint64 x; asm volatile("csrr %0, sscratch" : "=r" (x)); return x;}
258 static B_ALWAYS_INLINE void SetSscratch(uint64 x) {
259 	asm volatile("csrw sscratch, %0" : : "r" (x));}
260 
261 // trap cause
262 static B_ALWAYS_INLINE uint64 Mcause() {
263 	uint64 x; asm volatile("csrr %0, mcause" : "=r" (x)); return x;}
264 static B_ALWAYS_INLINE void SetMcause(uint64 x) {
265 	asm volatile("csrw mcause, %0" : : "r" (x));}
266 static B_ALWAYS_INLINE uint64 Scause() {
267 	uint64 x; asm volatile("csrr %0, scause" : "=r" (x)); return x;}
268 static B_ALWAYS_INLINE void SetScause(uint64 x) {
269 	asm volatile("csrw scause, %0" : : "r" (x));}
270 
271 // trap value
272 static B_ALWAYS_INLINE uint64 Mtval() {
273 	uint64 x; asm volatile("csrr %0, mtval" : "=r" (x)); return x;}
274 static B_ALWAYS_INLINE void SetMtval(uint64 x) {
275 	asm volatile("csrw mtval, %0" : : "r" (x));}
276 static B_ALWAYS_INLINE uint64 Stval() {
277 	uint64 x; asm volatile("csrr %0, stval" : "=r" (x)); return x;}
278 static B_ALWAYS_INLINE void SetStval(uint64 x) {
279 	asm volatile("csrw stval, %0" : : "r" (x));}
280 
281 // machine-mode counter enable
282 static B_ALWAYS_INLINE uint64 Mcounteren() {
283 	uint64 x; asm volatile("csrr %0, mcounteren" : "=r" (x)); return x;}
284 static B_ALWAYS_INLINE void SetMcounteren(uint64 x) {
285 	asm volatile("csrw mcounteren, %0" : : "r" (x));}
286 
287 // machine-mode cycle counter
288 static B_ALWAYS_INLINE uint64 Mcycle() {
289 	uint64 x; asm volatile("csrr %0, mcycle" : "=r" (x)); return x;}
290 // monotonic timer
291 static B_ALWAYS_INLINE uint64 CpuTime() {
292 	uint64 x; asm volatile("csrr %0, time" : "=r" (x)); return x;}
293 
294 // flush the TLB
295 static B_ALWAYS_INLINE void FlushTlbAll() {
296 	asm volatile("sfence.vma" : : : "memory");}
297 static B_ALWAYS_INLINE void FlushTlbPage(uint64 x) {
298 	asm volatile("sfence.vma %0" : : "r" (x) : "memory");}
299 
300 static B_ALWAYS_INLINE uint64 Sp() {
301 	uint64 x; asm volatile("mv %0, sp" : "=r" (x)); return x;}
302 static B_ALWAYS_INLINE void SetSp(uint64 x) {
303 	asm volatile("mv sp, %0" : : "r" (x));}
304 static B_ALWAYS_INLINE uint64 Fp() {
305 	uint64 x; asm volatile("mv %0, fp" : "=r" (x)); return x;}
306 static B_ALWAYS_INLINE void SetFp(uint64 x) {
307 	asm volatile("mv fp, %0" : : "r" (x));}
308 static B_ALWAYS_INLINE uint64 Tp() {
309 	uint64 x; asm volatile("mv %0, tp" : "=r" (x)); return x;}
310 static B_ALWAYS_INLINE void SetTp(uint64 x) {
311 	asm volatile("mv tp, %0" : : "r" (x));}
312 static B_ALWAYS_INLINE uint64 Ra() {
313 	uint64 x; asm volatile("mv %0, ra" : "=r" (x)); return x;}
314 static B_ALWAYS_INLINE void SetRa(uint64 x) {
315 	asm volatile("mv ra, %0" : : "r" (x));}
316 
317 static B_ALWAYS_INLINE void Ecall() {asm volatile("ecall");}
318 
319 // Wait for interrupts, reduce CPU load when inactive.
320 static B_ALWAYS_INLINE void Wfi() {asm volatile("wfi");}
321 
322 static B_ALWAYS_INLINE void Mret() {asm volatile("mret");}
323 static B_ALWAYS_INLINE void Sret() {asm volatile("sret");}
324 
325 
326 #define SPINLOCK_PAUSE()	do {} while (false)
327 
328 
329 #endif	/* _SYSTEM_ARCH_RISCV64_DEFS_H */
330 
331