Implemented VRQ-wait pseudo instuctions, fixed some more problems in VRQ handling.
@@ -49,6 +49,7 @@ | ||
49 | 49 | #define SB_SYSC_EVENT_WAIT_ALL 10 |
50 | 50 | #define SB_SYSC_EVENT_BROADCAST 11 |
51 | 51 | #define SB_SYSC_LOADELF 12 |
52 | +#define SB_SYSC_VRQ_WAIT 247 | |
52 | 53 | #define SB_SYSC_VRQ_SETWT 248 |
53 | 54 | #define SB_SYSC_VRQ_CLRWT 249 |
54 | 55 | #define SB_SYSC_VRQ_SETEN 250 |
@@ -280,6 +280,10 @@ | ||
280 | 280 | * @brief Mask of pending virtual IRQ flags. |
281 | 281 | */ |
282 | 282 | sb_vrqmask_t vrq_wtmask; |
283 | + /** | |
284 | + * @brief Reference to sh SB thread while waiting for VRQs. | |
285 | + */ | |
286 | + thread_reference_t vrq_trp; | |
283 | 287 | #endif |
284 | 288 | #if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) |
285 | 289 | /** |
@@ -76,6 +76,7 @@ | ||
76 | 76 | * @{ |
77 | 77 | */ |
78 | 78 | #if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__) |
79 | +#define SB_SVC247_HANDLER sb_api_vrq_wait | |
79 | 80 | #define SB_SVC248_HANDLER sb_api_vrq_setwt |
80 | 81 | #define SB_SVC249_HANDLER sb_api_vrq_clrwt |
81 | 82 | #define SB_SVC250_HANDLER sb_api_vrq_seten |
@@ -1219,8 +1220,6 @@ | ||
1219 | 1220 | |
1220 | 1221 | void __sb_abort(msg_t msg) { |
1221 | 1222 | |
1222 | - chSysUnlock(); | |
1223 | - | |
1224 | 1223 | sb_cleanup(); |
1225 | 1224 | |
1226 | 1225 | chSysLock(); |
@@ -52,7 +52,7 @@ | ||
52 | 52 | __STATIC_FORCEINLINE void vrq_makectx(sb_class_t *sbp, |
53 | 53 | struct port_extctx *newctxp, |
54 | 54 | uint32_t active_mask) { |
55 | - uint32_t irqn = 31U - __CLZ(active_mask); | |
55 | + uint32_t irqn = __CLZ(__RBIT(active_mask)); | |
56 | 56 | sbp->vrq_wtmask &= ~(1U << irqn); |
57 | 57 | |
58 | 58 | /* Disabling VRQs globally during processing.*/ |
@@ -67,7 +67,7 @@ | ||
67 | 67 | #endif |
68 | 68 | } |
69 | 69 | |
70 | -static void vrq_check_trigger(sb_class_t *sbp, struct port_extctx *ectxp) { | |
70 | +static void vrq_check_trigger_s(sb_class_t *sbp, struct port_extctx *ectxp) { | |
71 | 71 | |
72 | 72 | /* Triggering the VRQ if required.*/ |
73 | 73 | if ((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 0U) { |
@@ -81,6 +81,7 @@ | ||
81 | 81 | if (!sb_is_valid_write_range(sbp, |
82 | 82 | (void *)ectxp, |
83 | 83 | sizeof (struct port_extctx))) { |
84 | + chSysUnlock(); | |
84 | 85 | __sb_abort(CH_RET_EFAULT); |
85 | 86 | } |
86 | 87 |
@@ -116,6 +117,8 @@ | ||
116 | 117 | |
117 | 118 | chDbgCheckClassS(); |
118 | 119 | |
120 | + chDbgAssert(sbp->tp->state != CH_STATE_CURRENT, "current"); | |
121 | + | |
119 | 122 | /* Adding VRQ mask to the pending mask.*/ |
120 | 123 | sbp->vrq_wtmask |= vmask; |
121 | 124 |
@@ -142,6 +145,8 @@ | ||
142 | 145 | /* Building the return context.*/ |
143 | 146 | vrq_makectx(sbp, newctxp, active_mask); |
144 | 147 | __port_syscall_set_u_psp(sbp->tp, newctxp); |
148 | + | |
149 | + chThdResumeS(&sbp->vrq_trp, MSG_OK); | |
145 | 150 | } |
146 | 151 | } |
147 | 152 | } |
@@ -172,9 +177,20 @@ | ||
172 | 177 | |
173 | 178 | /* This IRQ could have preempted the sandbox itself or some other thread, |
174 | 179 | handling is different.*/ |
175 | - if (sbp->tp->state == CH_STATE_CURRENT) { | |
180 | + if ((sbp->tp->state == CH_STATE_CURRENT)) { | |
176 | 181 | /* Sandbox case, getting the current exception frame.*/ |
177 | - ectxp = (struct port_extctx *)__get_PSP(); | |
182 | + if ((__get_CONTROL() & 1U) == 0U) { | |
183 | + /* If preempted in privileged mode then getting the store U_PSP | |
184 | + value.*/ | |
185 | + ectxp = (struct port_extctx *)sbp->tp->ctx.syscall.u_psp; | |
186 | + } | |
187 | + else { | |
188 | + /* If preempted in unprivileged mode then getting the current PSP | |
189 | + value, it is U_PSP.*/ | |
190 | + ectxp = (struct port_extctx *)__get_PSP(); | |
191 | + } | |
192 | + | |
193 | + /* Creating new context for the VRQ.*/ | |
178 | 194 | newctxp = ectxp - 1; |
179 | 195 | |
180 | 196 | /* Checking if the new frame is within the sandbox else failure.*/ |
@@ -212,20 +228,42 @@ | ||
212 | 228 | } |
213 | 229 | } |
214 | 230 | |
231 | + chThdResumeI(&sbp->vrq_trp, MSG_OK); | |
232 | + | |
215 | 233 | chSysUnlockFromISR(); |
216 | 234 | |
217 | 235 | return; |
218 | 236 | } |
219 | 237 | |
238 | +void sb_api_vrq_wait(struct port_extctx *ectxp) { | |
239 | + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; | |
240 | + sb_vrqmask_t active_mask; | |
241 | + | |
242 | + (void)ectxp; | |
243 | + | |
244 | + chSysLock(); | |
245 | + | |
246 | + active_mask = sbp->vrq_wtmask & sbp->vrq_enmask; | |
247 | + if (active_mask != 0U) { | |
248 | + chThdSuspendS(&sbp->vrq_trp); | |
249 | + } | |
250 | + | |
251 | + chSysUnlock(); | |
252 | +} | |
253 | + | |
220 | 254 | void sb_api_vrq_setwt(struct port_extctx *ectxp) { |
221 | 255 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
222 | 256 | uint32_t m; |
223 | 257 | |
258 | + chSysLock(); | |
259 | + | |
224 | 260 | m = ectxp->r0; |
225 | 261 | ectxp->r0 = sbp->vrq_wtmask; |
226 | 262 | sbp->vrq_wtmask |= m; |
227 | 263 | |
228 | - vrq_check_trigger(sbp, ectxp); | |
264 | + vrq_check_trigger_s(sbp, ectxp); | |
265 | + | |
266 | + chSysUnlock(); | |
229 | 267 | } |
230 | 268 | |
231 | 269 | void sb_api_vrq_clrwt(struct port_extctx *ectxp) { |
@@ -232,9 +270,13 @@ | ||
232 | 270 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
233 | 271 | uint32_t m; |
234 | 272 | |
273 | + chSysLock(); | |
274 | + | |
235 | 275 | m = ectxp->r0; |
236 | 276 | ectxp->r0 = sbp->vrq_wtmask; |
237 | 277 | sbp->vrq_wtmask &= ~m; |
278 | + | |
279 | + chSysUnlock(); | |
238 | 280 | } |
239 | 281 | |
240 | 282 | void sb_api_vrq_seten(struct port_extctx *ectxp) { |
@@ -241,11 +283,15 @@ | ||
241 | 283 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
242 | 284 | uint32_t m; |
243 | 285 | |
286 | + chSysLock(); | |
287 | + | |
244 | 288 | m = ectxp->r0; |
245 | 289 | ectxp->r0 = sbp->vrq_enmask; |
246 | 290 | sbp->vrq_enmask |= m; |
247 | 291 | |
248 | - vrq_check_trigger(sbp, ectxp); | |
292 | + vrq_check_trigger_s(sbp, ectxp); | |
293 | + | |
294 | + chSysUnlock(); | |
249 | 295 | } |
250 | 296 | |
251 | 297 | void sb_api_vrq_clren(struct port_extctx *ectxp) { |
@@ -252,25 +298,37 @@ | ||
252 | 298 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
253 | 299 | uint32_t m; |
254 | 300 | |
301 | + chSysLock(); | |
302 | + | |
255 | 303 | m = ectxp->r0; |
256 | 304 | ectxp->r0 = sbp->vrq_enmask; |
257 | 305 | sbp->vrq_enmask &= ~m; |
306 | + | |
307 | + chSysUnlock(); | |
258 | 308 | } |
259 | 309 | |
260 | 310 | void sb_api_vrq_disable(struct port_extctx *ectxp) { |
261 | 311 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
262 | 312 | |
313 | + chSysLock(); | |
314 | + | |
263 | 315 | ectxp->r0 = sbp->vrq_isr; |
264 | 316 | sbp->vrq_isr |= SB_VRQ_ISR_DISABLED; |
317 | + | |
318 | + chSysUnlock(); | |
265 | 319 | } |
266 | 320 | |
267 | 321 | void sb_api_vrq_enable(struct port_extctx *ectxp) { |
268 | 322 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
269 | 323 | |
324 | + chSysLock(); | |
325 | + | |
270 | 326 | ectxp->r0 = sbp->vrq_isr; |
271 | 327 | sbp->vrq_isr &= ~SB_VRQ_ISR_DISABLED; |
272 | 328 | |
273 | - vrq_check_trigger(sbp, ectxp); | |
329 | + vrq_check_trigger_s(sbp, ectxp); | |
330 | + | |
331 | + chSysUnlock(); | |
274 | 332 | } |
275 | 333 | |
276 | 334 | void sb_api_vrq_getisr(struct port_extctx *ectxp) { |
@@ -283,6 +341,8 @@ | ||
283 | 341 | sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; |
284 | 342 | sb_vrqmask_t active_mask; |
285 | 343 | |
344 | + chSysLock(); | |
345 | + | |
286 | 346 | /* VRQs must be disabled on return, sanity check.*/ |
287 | 347 | if (((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 0U)) { |
288 | 348 | __sb_abort(CH_RET_EFAULT); |
@@ -303,6 +363,8 @@ | ||
303 | 363 | } |
304 | 364 | |
305 | 365 | __port_syscall_set_u_psp(sbp->tp, ectxp); |
366 | + | |
367 | + chSysUnlock(); | |
306 | 368 | } |
307 | 369 | |
308 | 370 | #endif /* SB_CFG_ENABLE_VRQ == TRUE */ |
@@ -66,6 +66,7 @@ | ||
66 | 66 | #endif |
67 | 67 | void sbVRQTriggerS(sb_class_t *sbp, sb_vrqmask_t vmask); |
68 | 68 | void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask); |
69 | + void sb_api_vrq_wait(struct port_extctx *ectxp); | |
69 | 70 | void sb_api_vrq_setwt(struct port_extctx *ectxp); |
70 | 71 | void sb_api_vrq_clrwt(struct port_extctx *ectxp); |
71 | 72 | void sb_api_vrq_seten(struct port_extctx *ectxp); |
@@ -844,6 +844,16 @@ | ||
844 | 844 | } |
845 | 845 | |
846 | 846 | /** |
847 | + * @brief VRQ @p wait pseudo-instruction. | |
848 | + * | |
849 | + * @api | |
850 | + */ | |
851 | +static inline void __sb_vrq_setwt(void) { | |
852 | + | |
853 | + __syscall0(247); | |
854 | +} | |
855 | + | |
856 | +/** | |
847 | 857 | * @brief VRQ @p setwt pseudo-instruction. |
848 | 858 | * |
849 | 859 | * @param[in] m VRQs mask |