1 /* $NetBSD: sbi.h,v 1.1 2023/05/07 12:41:48 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2023 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nick Hudson
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_SBI_H_
33 #define _RISCV_SBI_H_
34
35 #include <sys/types.h>
36
37 struct sbiret {
38 long error;
39 long value;
40 };
41
42 #define SBI_SUCCESS 0
43 #define SBI_ERR_FAILED -1
44 #define SBI_ERR_NOT_SUPPORTED -2
45 #define SBI_ERR_INVALID_PARAM -3
46 #define SBI_ERR_DENIED -4
47 #define SBI_ERR_INVALID_ADDRESS -5
48 #define SBI_ERR_ALREADY_AVAILABLE -6
49 #define SBI_ERR_ALREADY_STARTED -7
50 #define SBI_ERR_ALREADY_STOPPED -8
51
52 #define SBI_EID_BASE 0x10
53 #define SBI_EID_TIMER 0x54494D45 // "TIME"
54 #define SBI_EID_IPI 0x00735049 // "sPI"
55 #define SBI_EID_RFENCE 0x52464E43 // "RFNC"
56 #define SBI_EID_HSM 0x0048534D // "HSM"
57 #define SBI_EID_SRST 0x53525354 // "SRST"
58 #define SBI_EID_PMU 0x00504D55 // "PMU"
59
60 /*
61 | Function Name | SBI Version | FID | EID
62 | sbi_get_sbi_spec_version | 0.2 | 0 | 0x10
63 | sbi_get_sbi_impl_id | 0.2 | 1 | 0x10
64 | sbi_get_sbi_impl_version | 0.2 | 2 | 0x10
65 | sbi_probe_extension | 0.2 | 3 | 0x10
66 | sbi_get_mvendorid | 0.2 | 4 | 0x10
67 | sbi_get_marchid | 0.2 | 5 | 0x10
68 | sbi_get_mimpid | 0.2 | 6 | 0x10
69 */
70
71 #define SBI_FID_BASE_GETSPECVERSION 0
72 #define SBI_FID_BASE_GETIMPLID 1
73 #define SBI_FID_BASE_GETIMPLVERSION 2
74 #define SBI_FID_BASE_PROBEEXTENTION 3
75 #define SBI_FID_BASE_GETMVENDORID 4
76 #define SBI_FID_BASE_GETMARCHID 5
77 #define SBI_FID_BASE_GETMIMPID 6
78
79 struct sbiret sbi_get_spec_version(void);
80 struct sbiret sbi_get_impl_id(void);
81 struct sbiret sbi_get_impl_version(void);
82 struct sbiret sbi_probe_extension(long extension_id);
83 struct sbiret sbi_get_mvendorid(void);
84 struct sbiret sbi_get_marchid(void);
85 struct sbiret sbi_get_mimpid(void);
86
87
88 /*
89 | Implementation ID | Name
90 | 0 | Berkeley Boot Loader (BBL)
91 | 1 | OpenSBI
92 | 2 | Xvisor
93 | 3 | KVM
94 | 4 | RustSBI
95 | 5 | Diosix
96 */
97
98 #define SBI_IMPLID_BERKELEY 0
99 #define SBI_IMPLID_OPENSBI 1
100 #define SBI_IMPLID_XVISOR 2
101 #define SBI_IMPLID_KVM 3
102 #define SBI_IMPLID_RUSTSBI 4
103 #define SBI_IMPLID_DIOSIX 5
104
105
106 #define SBI_FID_TIMER_SET 0
107 struct sbiret sbi_set_timer(uint64_t stime_value);
108
109 #define SBI_FID_IPI_SEND 0
110 struct sbiret sbi_send_ipi(unsigned long hart_mask,
111 unsigned long hart_mask_base);
112
113 #define SBI_FID_RFENCE_FENCEI 0
114 #define SBI_FID_RFENCE_SFENCEVMA 1
115 #define SBI_FID_RFENCE_SFENCEVMAASID 2
116 #define SBI_FID_RFENCE_HFENCEGVMAVMID 3
117 #define SBI_FID_RFENCE_HFENCEGVMA 4
118 #define SBI_FID_RFENCE_HFENCEVVMAASID 5
119 #define SBI_FID_RFENCE_HFENCEVVMA 6
120
121
122 struct sbiret sbi_remote_fence_i(unsigned long hart_mask,
123 unsigned long hart_mask_base);
124 struct sbiret sbi_remote_sfence_vma(unsigned long hart_mask,
125 unsigned long hart_mask_base,
126 unsigned long start_addr,
127 unsigned long size);
128 struct sbiret sbi_remote_sfence_vma_asid(unsigned long hart_mask,
129 unsigned long hart_mask_base,
130 unsigned long start_addr,
131 unsigned long size,
132 unsigned long asid);
133 struct sbiret sbi_remote_hfence_gvma_vmid(unsigned long hart_mask,
134 unsigned long hart_mask_base,
135 unsigned long start_addr,
136 unsigned long size,
137 unsigned long vmid);
138 struct sbiret sbi_remote_hfence_gvma(unsigned long hart_mask,
139 unsigned long hart_mask_base,
140 unsigned long start_addr,
141 unsigned long size);
142 struct sbiret sbi_remote_hfence_vvma_asid(unsigned long hart_mask,
143 unsigned long hart_mask_base,
144 unsigned long start_addr,
145 unsigned long size,
146 unsigned long asid);
147 struct sbiret sbi_remote_hfence_vvma(unsigned long hart_mask,
148 unsigned long hart_mask_base,
149 unsigned long start_addr,
150 unsigned long size);
151
152 #define SBI_FID_HSM_START 0
153 #define SBI_FID_HSM_STOP 1
154 #define SBI_FID_HSM_GETSTATUS 2
155 #define SBI_FID_HSM_SUSPEND 3
156
157 struct sbiret sbi_hart_start(unsigned long hartid,
158 unsigned long start_addr,
159 unsigned long opaque);
160 struct sbiret sbi_hart_stop(void);
161 struct sbiret sbi_hart_get_status(unsigned long hartid);
162 struct sbiret sbi_hart_suspend(uint32_t suspend_type,
163 unsigned long resume_addr,
164 unsigned long opaque);
165
166 #define SBI_HART_STARTED 0
167 #define SBI_HART_STOPPED 1
168 #define SBI_HART_STARTPENDING 2
169 #define SBI_HART_STOPPENDING 3
170 #define SBI_HART_SUSPENDED 4
171 #define SBI_HART_SUSPENDPENDING 5
172 #define SBI_HART_RESUMEPENDING 6
173
174
175 #define SBI_FID_SRST_SYSTEMRESET 0
176 struct sbiret sbi_system_reset(uint32_t reset_type, uint32_t reset_reason);
177
178 #define SBI_RESET_TYPE_SHUTDOWN 0
179 #define SBI_RESET_TYPE_COLDREBOOT 1
180 #define SBI_RESET_TYPE_WARNREBOOT 2
181
182 #define SBI_RESET_REASON_NONE 0
183 #define SBI_RESET_REASON_FAILURE 1
184
185
186
187 #define SBU_FID_PMU_GETCOUNTERS 0
188 #define SBU_FID_PMU_COUNTERDETAILS 1
189 #define SBU_FID_PMU_CONFIGCOUNTER 2
190 #define SBU_FID_PMU_STARTCOUNTERS 3
191 #define SBU_FID_PMU_STOPCOUNTERS 4
192 #define SBU_FID_PMU_READCOUNTER 5
193
194 #define SBI_PMU_HW_NO_EVENT 0 // Unused event because
195 // ...`event_idx` cannot be zero
196 #define SBI_PMU_HW_CPU_CYCLES 1 // Event for each CPU cycle
197 #define SBI_PMU_HW_INSTRUCTIONS 2 // Event for each completed
198 // ... instruction
199 #define SBI_PMU_HW_CACHE_REFERENCES 3 // Event for cache hit
200 #define SBI_PMU_HW_CACHE_MISSES 4 // Event for cache miss
201 #define SBI_PMU_HW_BRANCH_INSTRUCTIONS 5 // Event for a branch instruction
202 #define SBI_PMU_HW_BRANCH_MISSES 6 // Event for a branch misprediction
203 #define SBI_PMU_HW_BUS_CYCLES 7 // Event for each BUS cycle
204 #define SBI_PMU_HW_STALLED_CYCLES_FRONTEND 8 // Event for a stalled cycle in
205 // ... microarchitecture frontend
206 #define SBI_PMU_HW_STALLED_CYCLES_BACKEND 9 // Event for a stalled cycle in
207 // ... microarchitecture backend
208 #define SBI_PMU_HW_REF_CPU_CYCLES 10 // Event for each reference
209 // ... CPU cycle
210
211 #define SBI_PMU_HW_CACHE_L1D 0 // Level1 data cache event
212 #define SBI_PMU_HW_CACHE_L1I 1 // Level1 instruction cache event
213 #define SBI_PMU_HW_CACHE_LL 2 // Last level cache event
214 #define SBI_PMU_HW_CACHE_DTLB 3 // Data TLB event
215 #define SBI_PMU_HW_CACHE_ITLB 4 // Instruction TLB event
216 #define SBI_PMU_HW_CACHE_BPU 5 // Branch predictor unit event
217 #define SBI_PMU_HW_CACHE_NODE 6 // NUMA node cache event
218
219 #define SBI_PMU_HW_CACHE_OP_READ 0 // Read cache line
220 #define SBI_PMU_HW_CACHE_OP_WRITE 1 // Write cache line
221 #define SBI_PMU_HW_CACHE_OP_PREFETCH 2 // Prefetch cache line
222
223 #define SBI_PMU_HW_CACHE_RESULT_ACCESS 0 // Cache access
224 #define SBI_PMU_HW_CACHE_RESULT_MISS 1 // Cache miss
225
226 #define SBI_PMU_FW_MISALIGNED_LOAD 0 // Misaligned load trap event
227 #define SBI_PMU_FW_MISALIGNED_STORE 1 // Misaligned store trap event
228 #define SBI_PMU_FW_ACCESS_LOAD 2 // Load access trap event
229 #define SBI_PMU_FW_ACCESS_STORE 3 // Store access trap event
230 #define SBI_PMU_FW_ILLEGAL_INSN 4 // Illegal instruction trap event
231 #define SBI_PMU_FW_SET_TIMER 5 // Set timer event
232 #define SBI_PMU_FW_IPI_SENT 6 // Sent IPI to other HART event
233 #define SBI_PMU_FW_IPI_RECEIVED 7 // Received IPI from other
234 // ... HART event
235 #define SBI_PMU_FW_FENCE_I_SENT 8 // Sent FENCE.I request to
236 // ... other HART event
237 #define SBI_PMU_FW_FENCE_I_RECEIVED 9 // Received FENCE.I request
238 // ... from other HART event
239 #define SBI_PMU_FW_SFENCE_VMA_SENT 10 // Sent SFENCE.VMA request
240 // ... to other HART event
241 #define SBI_PMU_FW_SFENCE_VMA_RECEIVED 11 // Received SFENCE.VMA request
242 // ... from other HART event
243 #define SBI_PMU_FW_SFENCE_VMA_ASID_SENT 12 // Sent SFENCE.VMA with ASID
244 // ... request to other HART event
245 #define SBI_PMU_FW_SFENCE_VMA_ASID_RECEIVED 13 // Received SFENCE.VMA with ASID
246 // ... request from other HART event
247 #define SBI_PMU_FW_HFENCE_GVMA_SENT 14 // Sent HFENCE.GVMA request to
248 // ... other HART event
249 #define SBI_PMU_FW_HFENCE_GVMA_RECEIVED 15 // Received HFENCE.GVMA request
250 // ... from other HART event
251 #define SBI_PMU_FW_HFENCE_GVMA_VMID_SENT 16 // Sent HFENCE.GVMA with VMID
252 // ... request to other HART event
253 #define SBI_PMU_FW_HFENCE_GVMA_VMID_RECEIVED 17 // Received HFENCE.GVMA with VMID
254 // ... request from other HART event
255 #define SBI_PMU_FW_HFENCE_VVMA_SENT 18 // Sent HFENCE.VVMA request to
256 // ... other HART event
257 #define SBI_PMU_FW_HFENCE_VVMA_RECEIVED 19 // Received HFENCE.VVMA request
258 // ... from other HART event
259 #define SBI_PMU_FW_HFENCE_VVMA_ASID_SENT 20 // Sent HFENCE.VVMA with ASID
260 // ... request to other HART event
261 #define SBI_PMU_FW_HFENCE_VVMA_ASID_RECEIVED 21 // Received HFENCE.VVMA with ASID
262 // ... request from other HART event
263
264
265 struct sbiret sbi_pmu_num_counters(void);
266 struct sbiret sbi_pmu_counter_get_info(unsigned long counter_idx);
267
268 struct sbiret sbi_pmu_counter_config_matching(unsigned long counter_idx_base,
269 unsigned long counter_idx_mask,
270 unsigned long config_flags,
271 unsigned long event_idx,
272 uint64_t event_data);
273 struct sbiret sbi_pmu_counter_start(unsigned long counter_idx_base,
274 unsigned long counter_idx_mask,
275 unsigned long start_flags,
276 uint64_t initial_value);
277 struct sbiret sbi_pmu_counter_stop(unsigned long counter_idx_base,
278 unsigned long counter_idx_mask,
279 unsigned long stop_flags);
280 struct sbiret sbi_pmu_counter_fw_read(unsigned long counter_idx);
281
282
283
284 static inline struct sbiret
sbi_call(int eid,int fid,unsigned long arg0,unsigned long arg1,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)285 sbi_call(int eid, int fid,
286 unsigned long arg0, unsigned long arg1, unsigned long arg2,
287 unsigned long arg3, unsigned long arg4, unsigned long arg5)
288 {
289 struct sbiret ret;
290
291 register register_t _a7 __asm ("a7") = eid;
292 register register_t _a6 __asm ("a6") = fid;
293
294 register register_t _a0 __asm ("a0") = arg0;
295 register register_t _a1 __asm ("a1") = arg1;
296 register register_t _a2 __asm ("a2") = arg2;
297 register register_t _a3 __asm ("a3") = arg3;
298 register register_t _a4 __asm ("a4") = arg4;
299 register register_t _a5 __asm ("a5") = arg5;
300
301 __asm __volatile (
302 "ecall"
303 : "+r" (_a0), "+r" (_a1)
304 : "r" (_a2), "r" (_a3), "r" (_a4), "r" (_a5), "r" (_a6), "r" (_a7)
305 : "memory");
306 ret.error = _a0;
307 ret.value = _a1;
308
309 return ret;
310 }
311
312
313 #define SBI_CALL0(eid, fid) sbi_call(eid, fid, 0, 0, 0, 0, 0, 0)
314 #define SBI_CALL1(eid, fid, a0) sbi_call(eid, fid, a0, 0, 0, 0, 0, 0)
315 #define SBI_CALL2(eid, fid, a0, a1) sbi_call(eid, fid, a0, a1, 0, 0, 0, 0)
316 #define SBI_CALL3(eid, fid, a0, a1, a2) sbi_call(eid, fid, a0, a1, a2, 0, 0, 0)
317 #define SBI_CALL4(eid, fid, a0, a1, a2, a3) sbi_call(eid, fid, a0, a1, a2, a3, 0, 0)
318 #define SBI_CALL5(eid, fid, a0, a1, a2, a3, a4) sbi_call(eid, fid, a0, a1, a2, a3, a4, 0)
319 #define SBI_CALL6(eid, fid, a0, a1, a2, a3, a4, a5) sbi_call(eid, fid, a0, a1, a2, a3, a4, a5)
320
321
322
323 #if defined(__RVSBI_LEGACY)
324
325 #define SBI_LEGACY_SET_TIMER 0
326 #define SBI_LEGACY_CONSOLE_PUTCHAR 1
327 #define SBI_LEGACY_CONSOLE_GETCHAR 2
328 #define SBI_LEGACY_CLEAR_IPI 3
329 #define SBI_LEGACY_SEND_IPI 4
330 #define SBI_LEGACY_REMOTE_FENCE_I 5
331 #define SBI_LEGACY_REMOTE_SFENCE_VMA 6
332 #define SBI_LEGACY_REMOTE_SFENCE_VMA_ASID 7
333 #define SBI_LEGACY_SHUTDOWN 8
334
335 #define SBI_LEGACY_CALL0(eid) sbi_call(eid, 0, 0, 0, 0, 0, 0, 0)
336 #define SBI_LEGACY_CALL1(eid, a0) sbi_call(eid, 0, a0, 0, 0, 0, 0, 0)
337 #define SBI_LEGACY_CALL2(eid, a0, a1) sbi_call(eid, 0, a0, a1, 0, 0, 0, 0)
338 #define SBI_LEGACY_CALL3(eid, a0, a1, a2) sbi_call(eid, 0, a0, a1, a2, 0, 0, 0)
339 #define SBI_LEGACY_CALL4(eid, a0, a1, a2, a3) sbi_call(eid, 0, a0, a1, a2, a3, 0, 0)
340 #define SBI_LEGACY_CALL5(eid, a0, a1, a2, a3, a4) sbi_call(eid, 0, a0, a1, a2, a3, a4, 0)
341
342
343 /*
344 * void sbi_set_timer(uint64_t stime_value)
345 */
346
347 static inline long
sbi_legacy_set_timer(uint64_t stime_value)348 sbi_legacy_set_timer(uint64_t stime_value)
349 {
350 #ifdef _LP64
351 struct sbiret ret = SBI_LEGACY_CALL1(SBI_LEGACY_SET_TIMER, stime_value);
352 #else
353 struct sbiret ret = SBI_LEGACY_CALL2(SBI_LEGACY_SET_TIMER,
354 stime_value, stime_value >> 32);
355 #endif
356 return ret.error;
357 }
358
359 /*
360 * void sbi_console_putchar(int ch)
361 */
362
363 static inline long
sbi_legacy_console_putchar(int c)364 sbi_legacy_console_putchar(int c) {
365 struct sbiret ret = SBI_LEGACY_CALL1(SBI_LEGACY_CONSOLE_PUTCHAR, c);
366
367 return ret.error;
368 }
369
370 /*
371 * long sbi_console_getchar(void)
372 */
373 static inline long
sbi_legacy_console_getchar(void)374 sbi_legacy_console_getchar(void) {
375 struct sbiret ret = SBI_LEGACY_CALL0(SBI_LEGACY_CONSOLE_GETCHAR);
376
377 return ret.error;
378 }
379
380 /*
381 * long sbi_clear_ipi(void)
382 */
383 static inline long
sbi_legacy_clear_ipi(void)384 sbi_legacy_clear_ipi(void) {
385 struct sbiret ret = SBI_LEGACY_CALL0(SBI_LEGACY_CLEAR_IPI);
386
387 return ret.error;
388 }
389
390
391 /*
392 * hart_mask is a virtual address that points to a bit-vector of harts. The
393 * bit vector is represented as a sequence of unsigned longs whose length
394 * equals the number of harts in the system divided by the number of bits
395 * in an unsigned long, rounded up to the next integer.
396 */
397
398 /*
399 * void sbi_send_ipi(const unsigned long *hart_mask)
400 */
401 static inline long
sbi_legacy_send_ipi(const unsigned long * hart_mask)402 sbi_legacy_send_ipi(const unsigned long *hart_mask) {
403 struct sbiret ret = SBI_LEGACY_CALL1(SBI_LEGACY_SEND_IPI,
404 (unsigned long)hart_mask);
405
406 return ret.error;
407 }
408
409 /*
410 * long sbi_remote_fence_i(const unsigned long *hart_mask)
411 */
412 static inline long
sbi_legacy_remote_fence_i(const unsigned long * hart_mask)413 sbi_legacy_remote_fence_i(const unsigned long *hart_mask) {
414 struct sbiret ret = SBI_LEGACY_CALL1(SBI_LEGACY_REMOTE_FENCE_I,
415 (unsigned long)hart_mask);
416
417 return ret.error;
418 }
419
420 /*
421 * long sbi_remote_sfence_vma(const unsigned long *hart_mask,
422 * unsigned long start,
423 * unsigned long size)
424 */
425 static inline long
sbi_legacy_remote_sfence_vma(const unsigned long * hart_mask,unsigned long start,unsigned long size)426 sbi_legacy_remote_sfence_vma(const unsigned long *hart_mask,
427 unsigned long start, unsigned long size)
428 {
429 struct sbiret ret = SBI_LEGACY_CALL3(SBI_LEGACY_REMOTE_SFENCE_VMA,
430 (unsigned long)hart_mask, start, size);
431
432 return ret.error;
433 }
434
435 /*
436 * long sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
437 * unsigned long start,
438 * unsigned long size,
439 * unsigned long asid)
440 */
441 static inline long
sbi_legacy_remote_sfence_vma_asid(const unsigned long * hart_mask,unsigned long start,unsigned long size,unsigned long asid)442 sbi_legacy_remote_sfence_vma_asid(const unsigned long *hart_mask,
443 unsigned long start, unsigned long size, unsigned long asid)
444 {
445 struct sbiret ret = SBI_LEGACY_CALL4(SBI_LEGACY_REMOTE_SFENCE_VMA_ASID,
446 (unsigned long)hart_mask, start, size, asid);
447
448 return ret.error;
449 }
450
451 /*
452 * void sbi_shutdown(void)
453 */
454 static inline void
sbi_legacy_shutdown(void)455 sbi_legacy_shutdown(void) {
456 SBI_LEGACY_CALL0(SBI_LEGACY_SHUTDOWN);
457 }
458
459 #endif
460
461
462 #endif /* _RISCV_SBI_H_ */
463