1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com>
4 * Copyright 2021, HENSOLDT Cyber
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 */
8
9 #pragma once
10
11 #ifndef __ASSEMBLER__
12 #include <arch/types.h>
13 #include <arch/object/structures.h>
14 #include <arch/machine/hardware.h>
15 #include <arch/model/statedata.h>
16 #include <arch/sbi.h>
17 #include <mode/machine.h>
18
19 /* Bit flags in CSR MIP/SIP (interrupt pending). */
20 /* Bit 0 was SIP_USIP, but the N extension will be dropped in v1.12 */
21 #define SIP_SSIP 1 /* S-Mode software interrupt pending. */
22 /* Bit 2 was SIP_HSIP in v1.9, but the H extension was reworked afterwards. */
23 #define SIP_MSIP 3 /* M-Mode software interrupt pending (MIP only). */
24 /* Bit 4 was SIP_UTIP, but the N extension will be dropped in v1.12 */
25 #define SIP_STIP 5 /* S-Mode timer interrupt pending. */
26 /* Bit 6 was SIP_HTIP in v1.9, but the H extension was reworked afterwards. */
27 #define SIP_MTIP 7 /* M-Mode timer interrupt pending (MIP only). */
28 /* Bit 8 was SIP_UEIP, but the N extension will be dropped in v1.12 */
29 #define SIP_SEIP 9 /* S-Mode external interrupt pending. */
30 /* Bit 10 was SIP_HEIP in v1.9, but the H extension was reworked afterwards. */
31 #define SIP_MEIP 11 /* M-Mode external interrupt pending (MIP only). */
32 /* Bit 12 and above are reserved. */
33
34 /* Bit flags in CSR MIE/SIE (interrupt enable). */
35 /* Bit 0 was SIE_USIE, but the N extension will be dropped in v1.12 */
36 #define SIE_SSIE 1 /* S-Mode software interrupt enable. */
37 /* Bit 2 was SIE_HSIE in v1.9, but the H extension was reworked afterwards. */
38 #define SIE_MSIE 3 /* M-Mode software interrupt enable (MIP only). */
39 /* Bit 4 was SIE_UTIE, but the N extension will be dropped in v1.12 */
40 #define SIE_STIE 5 /* S-Mode timer interrupt enable. */
41 /* Bit 6 was SIE_HTIE in v1.9, but the H extension was reworked afterwards. */
42 #define SIE_MTIE 7 /* M-Mode timer interrupt enable (MIP only). */
43 /* Bit 8 was SIE_UEIE, but the N extension will be dropped in v1.12 */
44 #define SIE_SEIE 9 /* S-Mode external interrupt enable. */
45 /* Bit 10 was SIE_HEIE in v1.9, but the H extension was reworked afterwards. */
46 #define SIE_MEIE 11 /* M-Mode external interrupt enable (MIP only). */
47 /* Bit 12 and above are reserved. */
48
49 #ifdef ENABLE_SMP_SUPPORT
50
fence_rw_rw(void)51 static inline void fence_rw_rw(void)
52 {
53 asm volatile("fence rw, rw" ::: "memory");
54 }
55
fence_w_rw(void)56 static inline void fence_w_rw(void)
57 {
58 asm volatile("fence w, rw" ::: "memory");
59 }
60
fence_r_rw(void)61 static inline void fence_r_rw(void)
62 {
63 asm volatile("fence r,rw" ::: "memory");
64 }
65
fence_w_r(void)66 static inline void fence_w_r(void)
67 {
68 asm volatile("fence w,r" ::: "memory");
69 }
70
ifence_local(void)71 static inline void ifence_local(void)
72 {
73 asm volatile("fence.i":::"memory");
74 }
75
sfence_local(void)76 static inline void sfence_local(void)
77 {
78 asm volatile("sfence.vma" ::: "memory");
79 }
80
ifence(void)81 static inline void ifence(void)
82 {
83 ifence_local();
84
85 unsigned long mask = 0;
86 for (int i = 0; i < CONFIG_MAX_NUM_NODES; i++) {
87 if (i != getCurrentCPUIndex()) {
88 mask |= BIT(cpuIndexToID(i));
89 }
90 }
91 sbi_remote_fence_i(&mask);
92 }
93
sfence(void)94 static inline void sfence(void)
95 {
96 fence_w_rw();
97 sfence_local();
98
99 unsigned long mask = 0;
100 for (int i = 0; i < CONFIG_MAX_NUM_NODES; i++) {
101 if (i != getCurrentCPUIndex()) {
102 mask |= BIT(cpuIndexToID(i));
103 }
104 }
105 sbi_remote_sfence_vma(&mask, 0, 0);
106 }
107
hwASIDFlushLocal(asid_t asid)108 static inline void hwASIDFlushLocal(asid_t asid)
109 {
110 asm volatile("sfence.vma x0, %0" :: "r"(asid): "memory");
111 }
112
hwASIDFlush(asid_t asid)113 static inline void hwASIDFlush(asid_t asid)
114 {
115 hwASIDFlushLocal(asid);
116
117 unsigned long mask = 0;
118 for (int i = 0; i < CONFIG_MAX_NUM_NODES; i++) {
119 if (i != getCurrentCPUIndex()) {
120 mask |= BIT(cpuIndexToID(i));
121 }
122 }
123 sbi_remote_sfence_vma_asid(&mask, 0, 0, asid);
124 }
125
126 #else
127
sfence(void)128 static inline void sfence(void)
129 {
130 asm volatile("sfence.vma" ::: "memory");
131 }
132
hwASIDFlush(asid_t asid)133 static inline void hwASIDFlush(asid_t asid)
134 {
135 asm volatile("sfence.vma x0, %0" :: "r"(asid): "memory");
136 }
137
138 #endif /* end of !ENABLE_SMP_SUPPORT */
139
140 word_t PURE getRestartPC(tcb_t *thread);
141 void setNextPC(tcb_t *thread, word_t v);
142
143 /* Cleaning memory before user-level access */
clearMemory(void * ptr,unsigned int bits)144 static inline void clearMemory(void *ptr, unsigned int bits)
145 {
146 memzero(ptr, BIT(bits));
147 }
148
write_satp(word_t value)149 static inline void write_satp(word_t value)
150 {
151 asm volatile("csrw satp, %0" :: "rK"(value));
152 }
153
write_stvec(word_t value)154 static inline void write_stvec(word_t value)
155 {
156 asm volatile("csrw stvec, %0" :: "rK"(value));
157 }
158
read_stval(void)159 static inline word_t read_stval(void)
160 {
161 word_t temp;
162 asm volatile("csrr %0, stval" : "=r"(temp));
163 return temp;
164 }
165
read_scause(void)166 static inline word_t read_scause(void)
167 {
168 word_t temp;
169 asm volatile("csrr %0, scause" : "=r"(temp));
170 return temp;
171 }
172
read_sepc(void)173 static inline word_t read_sepc(void)
174 {
175 word_t temp;
176 asm volatile("csrr %0, sepc" : "=r"(temp));
177 return temp;
178 }
179
read_sstatus(void)180 static inline word_t read_sstatus(void)
181 {
182 word_t temp;
183 asm volatile("csrr %0, sstatus" : "=r"(temp));
184 return temp;
185 }
186
read_sip(void)187 static inline word_t read_sip(void)
188 {
189 word_t temp;
190 asm volatile("csrr %0, sip" : "=r"(temp));
191 return temp;
192 }
193
write_sie(word_t value)194 static inline void write_sie(word_t value)
195 {
196 asm volatile("csrw sie, %0" :: "r"(value));
197 }
198
read_sie(void)199 static inline word_t read_sie(void)
200 {
201 word_t temp;
202 asm volatile("csrr %0, sie" : "=r"(temp));
203 return temp;
204 }
205
set_sie_mask(word_t mask_high)206 static inline void set_sie_mask(word_t mask_high)
207 {
208 word_t temp;
209 asm volatile("csrrs %0, sie, %1" : "=r"(temp) : "rK"(mask_high));
210 }
211
clear_sie_mask(word_t mask_low)212 static inline void clear_sie_mask(word_t mask_low)
213 {
214 word_t temp;
215 asm volatile("csrrc %0, sie, %1" : "=r"(temp) : "rK"(mask_low));
216 }
217
218 #ifdef CONFIG_HAVE_FPU
read_fcsr(void)219 static inline uint32_t read_fcsr(void)
220 {
221 uint32_t fcsr;
222 asm volatile("csrr %0, fcsr" : "=r"(fcsr));
223 return fcsr;
224 }
225
write_fcsr(uint32_t value)226 static inline void write_fcsr(uint32_t value)
227 {
228 asm volatile("csrw fcsr, %0" :: "rK"(value));
229 }
230 #endif
231
232 #if CONFIG_PT_LEVELS == 2
233 #define SATP_MODE SATP_MODE_SV32
234 #elif CONFIG_PT_LEVELS == 3
235 #define SATP_MODE SATP_MODE_SV39
236 #elif CONFIG_PT_LEVELS == 4
237 #define SATP_MODE SATP_MODE_SV48
238 #else
239 #error "Unsupported PT levels"
240 #endif
setVSpaceRoot(paddr_t addr,asid_t asid)241 static inline void setVSpaceRoot(paddr_t addr, asid_t asid)
242 {
243 satp_t satp = satp_new(SATP_MODE, /* mode */
244 asid, /* asid */
245 addr >> seL4_PageBits); /* PPN */
246
247 write_satp(satp.words[0]);
248
249 /* Order read/write operations */
250 #ifdef ENABLE_SMP_SUPPORT
251 sfence_local();
252 #else
253 sfence();
254 #endif
255 }
256
257 void map_kernel_devices(void);
258
259 /** MODIFIES: [*] */
260 void initTimer(void);
261 void initLocalIRQController(void);
262 void initIRQController(void);
263 void setIRQTrigger(irq_t irq, bool_t trigger);
264
265 #ifdef ENABLE_SMP_SUPPORT
266 #define irq_remote_call_ipi (INTERRUPT_IPI_0)
267 #define irq_reschedule_ipi (INTERRUPT_IPI_1)
268
arch_pause(void)269 static inline void arch_pause(void)
270 {
271 // use a memory fence to delay a bit.
272 // other alternatives?
273 fence_rw_rw();
274 }
275
276 #endif
277
278 /* Update the value of the actual register to hold the expected value */
Arch_setTLSRegister(word_t tls_base)279 static inline exception_t Arch_setTLSRegister(word_t tls_base)
280 {
281 /* The register is always reloaded upon return from kernel. */
282 setRegister(NODE_STATE(ksCurThread), TLS_BASE, tls_base);
283 return EXCEPTION_NONE;
284 }
285
286 #endif // __ASSEMBLER__
287