@@ -23,6 +23,7 @@ GTEXT(__swap)
23
23
GTEXT(__svc)
24
24
GTEXT(__pendsv)
25
25
GTEXT(_do_kernel_oops)
26
+ GTEXT(_arm_do_syscall)
26
27
GDATA(_k_neg_eagain)
27
28
28
29
GDATA(_kernel)
@@ -176,12 +177,24 @@ _thread_irq_disabled:
176
177
#endif / * CONFIG_MPU_STACK_GUARD * /
177
178
178
179
#ifdef CONFIG_USERSPACE
180
+ / * restore mode * /
181
+ ldr r0 , [ r2 , #_thread_offset_to_mode ]
182
+ mrs r3 , CONTROL
183
+ bic r3 , # 1
184
+ orr r3 , r0
185
+ msr CONTROL , r3
186
+
179
187
/ * r2 contains k_thread * /
180
188
add r0 , r2 , # 0
181
189
push {r2 , lr}
182
190
blx configure_mpu_mem_domain
183
191
pop {r2 , lr}
184
- #endif / * CONFIG_USERSPACE * /
192
+
193
+ add r0 , r2 , # 0
194
+ push {r2 , lr}
195
+ blx configure_mpu_user_context
196
+ pop {r2 , lr}
197
+ #endif
185
198
186
199
/ * load callee - saved + psp from thread * /
187
200
add r0 , r2 , #_thread_offset_to_callee_saved
@@ -268,7 +281,6 @@ _oops:
268
281
* /
269
282
270
283
SECTION_FUNC(TEXT , __svc)
271
-
272
284
tst lr , # 0x4 / * did we come from thread mode ? * /
273
285
ite eq / * if zero (equal) , came from handler mode * /
274
286
mrseq r0 , MSP / * handler mode , stack frame is on MSP * /
@@ -283,10 +295,26 @@ SECTION_FUNC(TEXT, __svc)
283
295
* 0 : context switch
284
296
* 1 : irq_offload (if configured)
285
297
* 2 : kernel panic or oops (software generated fatal exception)
298
+ * 3 : System call
286
299
* Planned implementation of system calls for memory protection will
287
300
* expand this case.
288
301
* /
289
302
ands r1 , # 0xff
303
+ #if CONFIG_USERSPACE
304
+ mrs r2 , CONTROL
305
+
306
+ cmp r1 , # 3
307
+ beq _do_syscall
308
+
309
+ / *
310
+ * check th at we are privileged before invoking other SVCs
311
+ * oops if we are unprivileged
312
+ * /
313
+ tst r2 , # 0x1
314
+ bne _oops
315
+
316
+ cmp r1 , # 0
317
+ #endif
290
318
beq _context_switch
291
319
292
320
cmp r1 , # 2
@@ -324,6 +352,46 @@ _oops:
324
352
blx _do_kernel_oops
325
353
pop {pc}
326
354
355
+ #if CONFIG_USERSPACE
356
+ / *
357
+ * System call will setup a jump to the _do_arm_syscall function
358
+ * when the SVC returns via the bx lr.
359
+ *
360
+ * There is some trickery involved here because we have to preserve
361
+ * the original LR value so th at we can return back to the caller of
362
+ * the SVC.
363
+ *
364
+ * On SVC exeption , the stack looks like the following:
365
+ * r0 - r1 - r2 - r3 - r12 - LR - PC - PSR
366
+ * r5 - r6 - call id - saved LR
367
+ *
368
+ * /
369
+ _do_syscall:
370
+ ldr r1 , [ r0 , # 24 ] / * grab address of PC from stack frame * /
371
+ str r1 , [ r0 , # 44 ] / * store address to use for LR after syscall * /
372
+ ldr r1 , =_arm_do_syscall
373
+ str r1 , [ r0 , # 24 ] / * overwrite the LR to point to _arm_do_syscall * /
374
+
375
+ / * validate syscall limit , only set priv mode if valid * /
376
+ ldr ip , =_SYSCALL_LIMIT
377
+ ldr r1 , [ r0 , # 40 ]
378
+ cmp r1 , ip
379
+ blt valid_syscall_id
380
+
381
+ / * bad syscall id. Set arg0 to bad id and set call_id to SYSCALL_BAD * /
382
+ str r1 , [ r0 , # 0 ]
383
+ ldr r1 , =_SYSCALL_BAD
384
+ str r1 , [ r0 , # 40 ]
385
+
386
+ valid_syscall_id:
387
+ / * set mode to privileged , r2 still contains value from CONTROL * /
388
+ bic r2 , # 1
389
+ msr CONTROL , r2
390
+
391
+ / * return from SVC to the modified LR - _arm_do_syscall * /
392
+ bx lr
393
+ #endif
394
+
327
395
#else
328
396
#error Unknown ARM architecture
329
397
#endif / * CONFIG_ARMV6_M_ARMV8_M_BASELINE * /
@@ -381,6 +449,13 @@ SECTION_FUNC(TEXT, __swap)
381
449
ldr r2 , [ r1 , #_kernel_offset_to_current ]
382
450
str r0 , [ r2 , #_thread_offset_to_basepri ]
383
451
452
+ #ifdef CONFIG_USERSPACE
453
+ mrs r0 , CONTROL
454
+ movs r3 , # 1
455
+ ands r0 , r3
456
+ str r0 , [ r2 , #_thread_offset_to_mode ]
457
+ #endif
458
+
384
459
/ *
385
460
* Set __swap()'s default return code to - EAGAIN. This eliminates the need
386
461
* for the timeout code to set it itself.
0 commit comments