syscall: fix call source detection
This commit is contained in:
parent
aa722fc34f
commit
57fb52dc1e
4 changed files with 14 additions and 12 deletions
arch/at91sam3x8e
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#ifdef CONFIG_CHECK_SYSCALL_SOURCE
|
#ifdef CONFIG_CHECK_SYSCALL_SOURCE
|
||||||
/* syscall.S */
|
/* syscall.S */
|
||||||
extern uintptr_t __syscall_entry_point;
|
extern uint16_t __syscall_return_point;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void arch_enter(void *sp)
|
void arch_enter(void *sp)
|
||||||
|
@ -27,10 +27,11 @@ void arch_enter(void *sp)
|
||||||
# ifdef CONFIG_CHECK_SYSCALL_SOURCE
|
# ifdef CONFIG_CHECK_SYSCALL_SOURCE
|
||||||
/*
|
/*
|
||||||
* We need to ignore the program counter's LSB because the CPU uses
|
* We need to ignore the program counter's LSB because the CPU uses
|
||||||
* that as a flag for whether it's operating in ARM or Thumb mode
|
* that as a flag for whether it's operating in ARM or Thumb mode;
|
||||||
* (1 for Thumb); the instructions are always 2-byte aligned.
|
* the instructions are always 2-byte aligned. Additionally, the PC
|
||||||
|
* points to the instruction *after* the SVC, not SVC itself.
|
||||||
*/
|
*/
|
||||||
if ((regs->hw.pc & 0xfffffffe) != __syscall_entry_point) {
|
if (((uintptr_t)regs->hw.pc & 0xfffffffe) != (uintptr_t)&__syscall_return_point) {
|
||||||
arch_syscall_set_rval(regs, -EACCES);
|
arch_syscall_set_rval(regs, -EACCES);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct reg_sw_snapshot {
|
||||||
* lr is saved by hardware, but we need to store it twice
|
* lr is saved by hardware, but we need to store it twice
|
||||||
* because the IRQ entry overwrites it
|
* because the IRQ entry overwrites it
|
||||||
*/
|
*/
|
||||||
uintptr_t lr; /* alias r14 */
|
void *lr; /* alias r14 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,8 +42,8 @@ struct reg_hw_snapshot {
|
||||||
word_t r2;
|
word_t r2;
|
||||||
word_t r3;
|
word_t r3;
|
||||||
word_t r12;
|
word_t r12;
|
||||||
uintptr_t lr; /* alias r14 */
|
void *lr; /* alias r14 */
|
||||||
uintptr_t pc; /* alias r15 */
|
void *pc; /* alias r15 */
|
||||||
word_t psr;
|
word_t psr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,9 @@ void arch_sched_task_init(struct task *task, void (*entry)(void))
|
||||||
task->sp = regs;
|
task->sp = regs;
|
||||||
|
|
||||||
memset(regs, 0, sizeof(*regs));
|
memset(regs, 0, sizeof(*regs));
|
||||||
regs->hw.pc = (uintptr_t)entry;
|
regs->hw.pc = entry;
|
||||||
regs->hw.psr = 0x01000000U;
|
regs->hw.psr = 0x01000000;
|
||||||
regs->sw.lr = 0xfffffff9U;
|
regs->sw.lr = (void *)0xfffffff9;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield(enum task_state state)
|
void yield(enum task_state state)
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
/* this is only invoked from user space, obviously */
|
/* this is only invoked from user space, obviously */
|
||||||
.section .text.shared
|
.section .text.shared
|
||||||
|
|
||||||
|
.global __syscall_return_point
|
||||||
|
|
||||||
/* int syscall(int number, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); */
|
/* int syscall(int number, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); */
|
||||||
func_begin syscall
|
func_begin syscall
|
||||||
|
|
||||||
|
@ -32,10 +34,9 @@ func_begin syscall
|
||||||
ldr r4, [sp, #16] /* arg5 */
|
ldr r4, [sp, #16] /* arg5 */
|
||||||
ldr r5, [sp, #20] /* arg6 */
|
ldr r5, [sp, #20] /* arg6 */
|
||||||
|
|
||||||
.global __syscall_entry_point
|
|
||||||
__syscall_entry_point:
|
|
||||||
svc #0
|
svc #0
|
||||||
|
|
||||||
|
__syscall_return_point:
|
||||||
pop {r4-r5,r7}
|
pop {r4-r5,r7}
|
||||||
|
|
||||||
/* r0 (return value) is set by the kernel */
|
/* r0 (return value) is set by the kernel */
|
||||||
|
|
Loading…
Reference in a new issue