kernel: allow up to 6 arguments for system calls

A quick look at "man syscall" shows that in Linux, all architectures
support at least 6 argument system calls, with a few supporting 7. We
can at least do 6 in Zephyr.

x86 port modified to use EBP register to carry the 6th system call
argument.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-09-19 09:59:42 -07:00 committed by Andrew Boie
commit 1956f09590
5 changed files with 43 additions and 14 deletions

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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_ */

View file

@ -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);