-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Description
Got some interesting code as below which is running on Cortex-M7 with user space enabled, the tool-chain is Zephyr SDK 0.10.3(somehow it's not easy to update it to latest one) and the code base is 1.14 branch.
The code from 60005bfc to 60005c1e is doing arguments preparation to call api->chnl_read_async((uint32_t)&(((struct adc_driver_api *)0)->chnl_read_async) = 36), but the code located at 60005c08 (strd r2, r1, [sp, #52]) which is trying to put margs->arg6 at [sp, #52] and put margs->arg7 at [sp, #56] will cause the stack (before calling this function) overflow 4 bytes(it may be easily understood with below layout of the privileged stack of the calling thread). So the unprivileged SP will be wrong when back to original function that called SVC.
And I made a patch temporally(if more arguments, need push more. It's not solution) as below to workaround it and it will work as expected. But we need find out why compiler behaves like this, currently IMHO it's most probably a bug of compiler, welcome any idea. Maybe we also need add some test cases to cover more than 6 arguments syscall.
* | ... |
* | ... |
* |---------------------- <---- Stack Ptr when PC at 0x60005bcc (sp = Stack Ptr before calling z_hdlr_adc_chnl_read_async - 48)
* | ... |
* | ... |
* | ... |
* |---------------------- <---- Stack Ptr before calling z_hdlr_adc_chnl_read_async
* | r4 |
* |-----------------------
* | r5 |
* |-----------------------
* | unprivileged SP |
* |-----------------------
* | LR |
* |-----------------------
* | ... |
* | ... |
--- a/arch/arm/core/userspace.S
+++ b/arch/arm/core/userspace.S
@@ -233,7 +233,7 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
valid_syscall:
/* push args to complete stack frame */
- push {r4,r5}
+ push {r4,r5,r6}
dispatch_syscall:
ldr ip, =_k_syscall_table
@@ -244,7 +244,7 @@ dispatch_syscall:
blx ip
/* restore LR */
- ldr lr, [sp,#12]
+ ldr lr, [sp, #16]
#if defined(CONFIG_BUILTIN_STACK_GUARD)
/* clear stack limit (stack protection not required in user mode) */
@@ -253,7 +253,7 @@ dispatch_syscall:
#endif
/* set stack back to unprivileged stack */
- ldr ip, [sp,#8]
+ ldr ip, [sp, #12]
msr PSP, ip
push {r0, r1}Z_SYSCALL_HANDLER(adc_chnl_read_async, dev, channel_id, buffer, usr_buff_size,
ts_buff, more_args_ptr)
{
volatile struct _syscall_7_args *margs =
(struct _syscall_7_args *)more_args_ptr;
Z_OOPS(Z_SYSCALL_MEMORY_READ(margs, sizeof(*margs)));
Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, chnl_read_async));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, usr_buff_size));
Z_OOPS(Z_SYSCALL_OBJ_INIT(margs->arg7, K_OBJ_POLL_SIGNAL));
return z_impl_adc_chnl_read_async((struct device *)dev,
(u8_t) channel_id, (u16_t *)buffer,
(size_t) usr_buff_size, (u64_t *)ts_buff,
margs->arg6, margs->arg7);
}
static inline int z_impl_adc_chnl_read_async(struct device *dev,
const u8_t channel_id, u16_t *buffer,
size_t usr_buff_size, u64_t *ts_buff,
const u32_t sample_count,
struct k_poll_signal *async)
{
const struct adc_driver_api *api = dev->driver_api;
return api->chnl_read_async(dev, channel_id, buffer, usr_buff_size,
ts_buff, sample_count, async);
}
Z_SYSCALL_HANDLER(adc_chnl_read_async, dev, channel_id, buffer, usr_buff_size,
ts_buff, more_args_ptr)
{
60005bc8: e92d 4ff7 stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr}
60005bcc: e9dd b40c ldrd fp, r4, [sp, #48] ; 0x30
60005bd0: 4605 mov r5, r0
60005bd2: 468a mov sl, r1
60005bd4: 4617 mov r7, r2
volatile struct _syscall_7_args *margs =
(struct _syscall_7_args *)more_args_ptr;
Z_OOPS(Z_SYSCALL_MEMORY_READ(margs, sizeof(*margs)));
60005bd6: 2108 movs r1, #8
60005bd8: 2200 movs r2, #0
60005bda: 4620 mov r0, r4
{
60005bdc: 4698 mov r8, r3
60005bde: 9e0e ldr r6, [sp, #56] ; 0x38
Z_OOPS(Z_SYSCALL_MEMORY_READ(margs, sizeof(*margs)));
60005be0: f009 f92b bl 6000ee3a <z_arch_buffer_validate>
60005be4: 4681 mov r9, r0
60005be6: 2800 cmp r0, #0
60005be8: d035 beq.n 60005c56 <z_hdlr_adc_chnl_read_async+0x8e>
60005bea: 4b26 ldr r3, [pc, #152] ; (60005c84 <z_hdlr_adc_chnl_read_async+0xbc>)
60005bec: 4622 mov r2, r4
60005bee: 9300 str r3, [sp, #0]
60005bf0: 2308 movs r3, #8
Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, chnl_read_async));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, usr_buff_size));
60005bf2: 4925 ldr r1, [pc, #148] ; (60005c88 <z_hdlr_adc_chnl_read_async+0xc0>)
60005bf4: 4825 ldr r0, [pc, #148] ; (60005c8c <z_hdlr_adc_chnl_read_async+0xc4>)
60005bf6: f7fb fc17 bl 60001428 <printk>
60005bfa: e03f b.n 60005c7c <z_hdlr_adc_chnl_read_async+0xb4>
Z_OOPS(Z_SYSCALL_OBJ_INIT(margs->arg7, K_OBJ_POLL_SIGNAL));
return z_impl_adc_chnl_read_async((struct device *)dev,
60005bfc: 6822 ldr r2, [r4, #0]
return api->chnl_read_async(dev, channel_id, buffer, usr_buff_size,
60005bfe: 4628 mov r0, r5
(u8_t) channel_id, (u16_t *)buffer,
(size_t) usr_buff_size, (u64_t *)ts_buff,
margs->arg6, margs->arg7);
60005c00: 6861 ldr r1, [r4, #4]
60005c02: 686b ldr r3, [r5, #4]
60005c04: f8cd b030 str.w fp, [sp, #48] ; 0x30
60005c08: e9cd 210d strd r2, r1, [sp, #52] ; 0x34
60005c0c: 6a5c ldr r4, [r3, #36] ; 0x24
60005c0e: 463a mov r2, r7
60005c10: 4643 mov r3, r8
60005c12: fa5f f18a uxtb.w r1, sl
60005c16: 46a4 mov ip, r4
}
60005c18: b003 add sp, #12
60005c1a: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
60005c1e: 4760 bx ip
Z_OOPS(Z_SYSCALL_OBJ_INIT(margs->arg7, K_OBJ_POLL_SIGNAL));
60005c20: 6860 ldr r0, [r4, #4]
60005c22: f7fa fb61 bl 600002e8 <z_object_find>
60005c26: 6861 ldr r1, [r4, #4]
60005c28: 2301 movs r3, #1
60005c2a: 2206 movs r2, #6
60005c2c: f009 f91c bl 6000ee68 <z_obj_validation_check>
60005c30: 2800 cmp r0, #0
60005c32: d0e3 beq.n 60005bfc <z_hdlr_adc_chnl_read_async+0x34>
60005c34: 4914 ldr r1, [pc, #80] ; (60005c88 <z_hdlr_adc_chnl_read_async+0xc0>)
60005c36: 4816 ldr r0, [pc, #88] ; (60005c90 <z_hdlr_adc_chnl_read_async+0xc8>)
60005c38: f7fb fbf6 bl 60001428 <printk>
60005c3c: e01e b.n 60005c7c <z_hdlr_adc_chnl_read_async+0xb4>
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, usr_buff_size));
60005c3e: 2201 movs r2, #1
60005c40: 4641 mov r1, r8
60005c42: 4638 mov r0, r7
60005c44: f009 f8f9 bl 6000ee3a <z_arch_buffer_validate>
60005c48: 2800 cmp r0, #0
60005c4a: d0e9 beq.n 60005c20 <z_hdlr_adc_chnl_read_async+0x58>
60005c4c: 4b11 ldr r3, [pc, #68] ; (60005c94 <z_hdlr_adc_chnl_read_async+0xcc>)
60005c4e: 463a mov r2, r7
60005c50: 9300 str r3, [sp, #0]
60005c52: 4643 mov r3, r8
60005c54: e7cd b.n 60005bf2 <z_hdlr_adc_chnl_read_async+0x2a>
Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, chnl_read_async));
60005c56: 4628 mov r0, r5
60005c58: f7fa fb46 bl 600002e8 <z_object_find>
60005c5c: 464b mov r3, r9
60005c5e: 220d movs r2, #13
60005c60: 4629 mov r1, r5
60005c62: f009 f901 bl 6000ee68 <z_obj_validation_check>
60005c66: 2800 cmp r0, #0
60005c68: d1e4 bne.n 60005c34 <z_hdlr_adc_chnl_read_async+0x6c>
60005c6a: 686b ldr r3, [r5, #4]
60005c6c: 6a5a ldr r2, [r3, #36] ; 0x24
60005c6e: 2a00 cmp r2, #0
60005c70: d1e5 bne.n 60005c3e <z_hdlr_adc_chnl_read_async+0x76>
60005c72: 4a09 ldr r2, [pc, #36] ; (60005c98 <z_hdlr_adc_chnl_read_async+0xd0>)
60005c74: 4904 ldr r1, [pc, #16] ; (60005c88 <z_hdlr_adc_chnl_read_async+0xc0>)
60005c76: 4809 ldr r0, [pc, #36] ; (60005c9c <z_hdlr_adc_chnl_read_async+0xd4>)
60005c78: f7fb fbd6 bl 60001428 <printk>
Z_OOPS(Z_SYSCALL_OBJ_INIT(margs->arg7, K_OBJ_POLL_SIGNAL));
60005c7c: 4630 mov r0, r6
60005c7e: f7ff f933 bl 60004ee8 <z_arch_syscall_oops>
60005c82: bf00 nop
60005c84: 60011b3d .word 0x60011b3d
60005c88: 60011aae .word 0x60011aae
60005c8c: 6001116e .word 0x6001116e
60005c90: 6001139c .word 0x6001139c
60005c94: 600111c9 .word 0x600111c9
60005c98: 60011b42 .word 0x60011b42
60005c9c: 600113c4 .word 0x600113c4