diff --git a/arch/x86/core/userspace.S b/arch/x86/core/userspace.S index 5c42d09df34..ee39507319c 100644 --- a/arch/x86/core/userspace.S +++ b/arch/x86/core/userspace.S @@ -35,6 +35,7 @@ _id_ok: * for _k_syscall_handler_t functions */ push %esp /* ssf */ + push %ebp /* arg6 */ push %edi /* arg5 */ push %ebx /* arg4 */ #ifndef CONFIG_X86_IAMCU @@ -63,11 +64,11 @@ _id_ok: pop %ebx pop %edi #ifndef CONFIG_X86_IAMCU - /* Discard ssf, no free register to pop it into so we add instead */ - add $4, %esp + /* Discard ssf and arg6 */ + add $8, %esp #else - xor %edx, %edx /* Clean EDX */ - pop %ecx /* Clean ECX and get ssf arg off the stack */ + pop %ecx /* Clean ECX and get arg6 off the stack */ + pop %edx /* Clean EDX and get ssf off the stack */ #endif iret diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index cca90b987db..55218930bb6 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -560,6 +560,26 @@ extern struct task_state_segment _main_tss; * the entry stub clobbers EDX and ECX on IAMCU systems */ +static inline u32_t _arch_syscall_invoke6(u32_t arg1, u32_t arg2, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, + u32_t call_id) +{ + u32_t ret; + + __asm__ volatile("push %%ebp\n\t" + "mov %[arg6], %%ebp\n\t" + "int $0x80\n\t" + "pop %%ebp\n\t" + : "=a" (ret) +#ifdef CONFIG_X86_IAMCU + , "=d" (arg2), "=c" (arg3) +#endif + : "S" (call_id), "a" (arg1), "d" (arg2), + "c" (arg3), "b" (arg4), "D" (arg5), + [arg6] "r" (arg6)); + return ret; +} + static inline u32_t _arch_syscall_invoke5(u32_t arg1, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, u32_t call_id) { diff --git a/include/kernel.h b/include/kernel.h index d224e1aa4bf..589315824ce 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -3917,6 +3917,10 @@ static inline int _is_user_context(void) } /* Interfaces for invoking system calls */ +static inline u32_t _arch_syscall_invoke6(u32_t arg1, u32_t arg2, u32_t arg3, + u32_t arg4, u32_t arg5, u32_t arg6, + u32_t call_id); + static inline u32_t _arch_syscall_invoke5(u32_t arg1, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, u32_t call_id); diff --git a/include/syscall.h b/include/syscall.h index d243262fe45..fa23e1844e1 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -31,8 +31,8 @@ * - Many kernel calls do no sanity checking of parameters other than * assertions. The handler must check all of these conditions using * _SYSCALL_ASSERT() - * - If the system call has more then 5 arguments, then arg5 will be a pointer - * to some struct containing arguments 5+. The struct itself needs to be + * - If the system call has more than 6 arguments, then arg6 will be a pointer + * to some struct containing arguments 6+. The struct itself needs to be * validated like any other buffer passed in from userspace, and its members * individually validated (if necessary) and then passed to the real * implementation like normal arguments @@ -47,6 +47,7 @@ * @param arg3 system call argument 3 * @param arg4 system call argument 4 * @param arg5 system call argument 5 + * @param arg6 system call argument 6 * @param ssf System call stack frame pointer. Used to generate kernel oops * via _arch_syscall_oops_at(). Contents are arch-specific. * @return system call return value, or 0 if the system call implementation @@ -54,7 +55,8 @@ * */ typedef u32_t (*_k_syscall_handler_t)(u32_t arg1, u32_t arg2, u32_t arg3, - u32_t arg4, u32_t arg5, void *ssf); + u32_t arg4, u32_t arg5, u32_t arg6, + void *ssf); extern const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT]; @@ -94,18 +96,20 @@ extern const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT]; /* Convenience macros for handler implementations */ #define _SYSCALL_ARG0 ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); \ - ARG_UNUSED(arg4); ARH_UNUSED(arg5) + ARG_UNUSED(arg4); ARH_UNUSED(arg5); ARG_UNUSED(arg6) #define _SYSCALL_ARG1 ARG_UNUSED(arg2); ARG_UNUSED(arg3); ARG_UNUSED(arg4); \ - ARG_UNUSED(arg5) + ARG_UNUSED(arg5); ARG_UNUSED(arg6) -#define _SYSCALL_ARG2 ARG_UNUSED(arg3); ARG_UNUSED(arg4); ARG_UNUSED(arg5) +#define _SYSCALL_ARG2 ARG_UNUSED(arg3); ARG_UNUSED(arg4); ARG_UNUSED(arg5); \ + ARG_UNUSED(arg6) -#define _SYSCALL_ARG3 ARG_UNUSED(arg4); ARG_UNUSED(arg5) - -#define _SYSCALL_ARG4 ARG_UNUSED(arg5) +#define _SYSCALL_ARG3 ARG_UNUSED(arg4); ARG_UNUSED(arg5); ARG_UNUSED(arg6) +#define _SYSCALL_ARG4 ARG_UNUSED(arg5); ARG_UNUSED(arg6) + +#define _SYSCALL_ARG5 ARG_UNUSED(arg6) #endif /* _ASMLANGUAGE */ #endif /* _ZEPHYR_SYSCALL_H_ */ diff --git a/kernel/userspace.c b/kernel/userspace.c index 790f2201186..cd5707b9a57 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -183,7 +183,7 @@ void _k_object_init(void *object) } static u32_t _syscall_bad_handler(u32_t bad_id, u32_t arg2, u32_t arg3, - u32_t arg4, u32_t arg5, void *ssf) + u32_t arg4, u32_t arg5, u32_t arg6, void *ssf) { printk("Bad system call id %u invoked\n", bad_id); _arch_syscall_oops(ssf);