Skip to content

Commit bf32fc5

Browse files
committed
arc: add user mode support. fix the issue in the memory_protection example
there was an issue caused by stack checking when switch from kernel mode to user mode. The issue is solved by disable stack checking. Signed-off-by: Yuguo Zou <yuguo.zou@synopsys.com>
1 parent 1e2487d commit bf32fc5

File tree

4 files changed

+150
-24
lines changed

4 files changed

+150
-24
lines changed

arc/arc_util.s

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,60 @@
3434

3535
.file "arc_utils.s"
3636

37-
.text
38-
.global arc_in_user_mode
39-
.align 4
40-
arc_in_user_mode:
41-
lr r0, [AUX_STATUS32]
42-
bbit1 r0, 20, 1f
43-
bset r1, r0, 20
44-
bclr r1, r1, 31
45-
kflag r1
46-
lr r1, [AUX_STATUS32]
47-
bbit0 r1, 20, 2f
48-
kflag r0
49-
1:
50-
j_s.d [blink]
51-
mov r0, 0
52-
2:
53-
j_s.d [blink]
54-
mov r0, 1
37+
/**
38+
* @brief Go to user mode
39+
*
40+
* @param target Target address to run in user mode, 0 means next
41+
* line of code
42+
* @param sp Stack where the target address runs, 0 means using
43+
* current stack
44+
*/
45+
.text
46+
.global arc_goto_usermode
47+
.align 4
48+
arc_goto_usermode:
49+
cmp r0, 0
50+
mov.z r0, blink
51+
cmp r1, 0
52+
mov.nz sp, r1
53+
#if defined(ARC_FEATURE_SEC_PRESENT)
54+
sr (1 << AUX_ERSEC_STAT_BIT_ERM), [AUX_ERSEC_STAT]
55+
sr sp, [AUX_SEC_U_SP]
56+
#else
57+
sr sp, [AUX_USER_SP]
58+
#endif
59+
lr r1, [AUX_STATUS32]
60+
bset r1, r1, AUX_STATUS_BIT_U
61+
sr r1, [AUX_ERSTATUS]
62+
lr r1, [AUX_STATUS32]
63+
bset r1, r1, AUX_STATUS_BIT_AE
64+
kflag r1
65+
sr r0, [AUX_ERRET]
66+
rtie
67+
68+
/**
69+
* @brief go to kernel mode
70+
* this function uses trap exception to do switch from user mode to kernel mode,
71+
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
72+
* function
73+
* @param target, the target address to run in kernel mode, 0 means next line of code
74+
* @param sp, the stack where the target address runs, 0 means using current stack
75+
*/
76+
.text
77+
.global arc_goto_kernelmode
78+
.global exc_entry_arc_goto_kernelmode
79+
.align 4
80+
arc_goto_kernelmode:
81+
cmp r0, 0
82+
mov.z r0, blink
83+
cmp r1, 0
84+
mov.z r1, sp
85+
trap_s 0
86+
.align 4
87+
exc_entry_arc_goto_kernelmode:
88+
mov sp, r1
89+
sr r0, [AUX_ERRET]
90+
lr r0, [AUX_ERSTATUS]
91+
bclr r0, r0, AUX_STATUS_BIT_U
92+
sr r0, [AUX_ERSTATUS]
93+
rtie

example/baremetal/arc_feature/memory_protection/main.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static void user_mode_func(void)
9292
arc_kflag(0);
9393
arc_goto_kernelmode(0, 0);
9494

95-
EMBARC_PRINTF("end of program\r\n");
95+
EMBARC_PRINTF("Memory Protection Test Done\n");
9696
while (1) {
9797
;
9898
}
@@ -292,7 +292,12 @@ int main(void)
292292
EMBARC_PRINTF("raise violation of execute in RAM \r\n");
293293
trigger_execute_violation((uint32_t)_f_data);
294294
EMBARC_PRINTF("go to user mode \r\n");
295+
#if ARC_FEATURE_STACK_CHECK
296+
// disable stack check
297+
arc_stack_check_disable();
298+
#endif
295299
arc_goto_usermode(user_mode_func, &user_mode_stack[512]);
300+
// arc_goto_usermode() does NOT return
296301
#else /* ARC_FEATURE_MPU_PRESENT */
297302
EMBARC_PRINTF("This example is not supported under current configurations \r\n");
298303
#endif /* ARC_FEATURE_MPU_PRESENT */

include/arc/arc.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -560,11 +560,6 @@ extern "C" {
560560
#endif
561561

562562
/* add type definition and function declaration here */
563-
/**
564-
* \brief check whether process is in user mode
565-
* \retval 0 kernel mode, 1 user mode
566-
*/
567-
extern unsigned int arc_in_user_mode(void);
568563

569564
#ifdef __cplusplus
570565
}

include/arc/arc_builtin.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,93 @@ Inline uint32_t arc_core_id(void)
379379
return ret;
380380
}
381381

382+
/**
383+
* @fn void arc_stack_check_disable(void)
384+
* @brief Disable hardware stack checking
385+
*/
386+
Inline void arc_stack_check_disable(void)
387+
{
388+
#if ARC_FEATURE_SEC_PRESENT
389+
Asm(
390+
"bclr %0, %0, %1\n"
391+
"sflag %%r0\n"
392+
:
393+
: "r" (arc_aux_read(AUX_SEC_STAT)), "i" (AUX_SEC_STAT_BIT_SSC));
394+
#else
395+
Asm(
396+
"bclr %0, %0, %1\n"
397+
"kflag %%r0\n"
398+
:
399+
: "r" (arc_aux_read(AUX_STATUS32)), "i" (AUX_STATUS_BIT_SC));
400+
#endif
401+
}
402+
403+
/**
404+
* @fn void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
405+
* @brief Configure stack checking in kernel mode
406+
*
407+
* @param top Top of stack
408+
* @param base Base of stack
409+
*/
410+
Inline void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
411+
{
412+
#if ARC_FEATURE_SEC_PRESENT
413+
arc_aux_write(AUX_S_KSTACK_TOP, top);
414+
arc_aux_write(AUX_S_KSTACK_BASE, base);
415+
#else
416+
arc_aux_write(AUX_KSTACK_TOP, top);
417+
arc_aux_write(AUX_KSTACK_BASE, base);
418+
#endif
419+
}
420+
421+
/**
422+
* @fn uint32_t arc_is_user_mode(void)
423+
* @brief Check whether processor is in user mode
424+
* this function relies on AUX_STATUS_BIT_US set in privileged mode first
425+
* @return 1 user mode, 0 privileged mode
426+
*/
427+
Inline uint32_t arc_in_user_mode(void)
428+
{
429+
uint32_t status;
430+
431+
Asm(
432+
"lr %0, [%1]\n"
433+
: "=r" (status)
434+
: "i" (AUX_STATUS32)
435+
: "memory");
436+
437+
return !(status & AUX_STATUS_MASK_US) ? 1 : 0;
438+
}
439+
440+
/**
441+
* @brief Go to user mode
442+
* It's suggested to disable interrupt before call this function especially
443+
* when using current stack, i.e., sp == 0. Because interrupt handling requires
444+
* kernel mode stack which is different with user mode stack.
445+
* @param target Target address to run in user mode, 0 means next
446+
* line of code
447+
* @param sp Stack where the target address runs, 0 means using
448+
* current stack
449+
*/
450+
extern void arc_goto_usermode(void *target, uint32_t *sp);
451+
452+
/**
453+
* @brief Go to kernel mode
454+
* this function uses trap exception to do switch from user mode to kernel mode,
455+
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
456+
* function
457+
* @param target Target address to run in kernel mode, 0 means next line of code
458+
* @param sp Stack where the target address runs, 0 means using current stack
459+
*/
460+
extern void arc_goto_kernelmode(void *target, uint32_t *sp);
461+
462+
/**
463+
* @brief Trap exception entry used for arc_goto_kernelmode
464+
*
465+
* install this entry for trap exception before call arc_goto_kernelmode
466+
*/
467+
extern void exc_entry_arc_goto_kernelmode(void);
468+
382469
#ifdef __cplusplus
383470
}
384471
#endif

0 commit comments

Comments
 (0)