zephyr/include/syscall.h

284 lines
7.9 KiB
C
Raw Normal View History

userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/*
* Copyright (c) 2017, Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
*/
#ifndef ZEPHYR_INCLUDE_SYSCALL_H_
#define ZEPHYR_INCLUDE_SYSCALL_H_
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
#include <syscall_list.h>
#include <arch/syscall.h>
#include <stdbool.h>
#ifndef _ASMLANGUAGE
#include <zephyr/types.h>
#include <syscall_macros.h>
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
#ifdef __cplusplus
extern "C" {
#endif
/*
* System Call Declaration macros
*
* These macros are used in public header files to declare system calls.
* They generate inline functions which have different implementations
* depending on the current compilation context:
*
* - Kernel-only code, or CONFIG_USERSPACE disabled, these inlines will
* directly call the implementation
* - User-only code, these inlines will marshal parameters and elevate
* privileges
* - Mixed or indeterminate code, these inlines will do a runtime check
* to determine what course of action is needed.
*
* All system calls require a handler function and an implementation function.
* These must follow a naming convention. For a system call named k_foo():
*
* - The handler function will be named z_hdlr_k_foo(). Handler functions
* are always of type _k_syscall_handler_t, verify arguments passed up
* from userspace, and call the implementation function. See
* documentation for that typedef for more information.
* - The implementation function will be named z_impl_k_foo(). This is the
* actual implementation of the system call.
*
* The basic declartion macros are as follows. System calls with 0 to 10
* parameters are supported. For a system call with N parameters, that returns
* a value and is* not implemented inline, the macro is as follows (N noted
* as {N} for clarity):
*
* K_SYSCALL_DECLARE{N}(id, name, ret, t0, p0, ... , t{N-1}, p{N-1})
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
* @param id System call ID, one of K_SYSCALL_* defines
* @param name Symbol name of the system call used to invoke it
* @param ret Data type of return value
* @param tX Data type of parameter X
* @param pX Name of parameter x
*
* For system calls that return no value:
*
* K_SYSCALL_DECLARE{n}_VOID(id, name, t0, p0, .... , t{N-1}, p{N-1})
*
* This is identical to above except there is no 'ret' parameter.
*
* For system calls where the implementation is an inline function, we have
*
* K_SYSCALL_DECLARE{n}_INLINE(id, name, ret, t0, p0, ... , t{N-1}, p{N-1})
* K_SYSCALL_DECLARE{n}_VOID_INLINE(id, name, t0, p0, ... , t{N-1}, p{N-1})
*
* These are used in the same way as their non-INLINE counterparts.
*
* These macros are generated by scripts/gen_syscall_header.py and can be
* found in $OUTDIR/include/generated/syscall_macros.h
*/
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/**
* @typedef _k_syscall_handler_t
* @brief System call handler function type
*
* These are kernel-side skeleton functions for system calls. They are
* necessary to sanitize the arguments passed into the system call:
*
* - Any kernel object or device pointers are validated with _SYSCALL_IS_OBJ()
* - Any memory buffers passed in are checked to ensure that the calling thread
* actually has access to them
* - 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 than 6 arguments, then arg6 will be a pointer
* to some struct containing arguments 6+. The struct itself needs to be
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
* 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
*
* Even if the system call implementation has no return value, these always
* return something, even 0, to prevent register leakage to userspace.
*
* Once everything has been validated, the real implementation will be executed.
*
* @param arg1 system call argument 1
* @param arg2 system call argument 2
* @param arg3 system call argument 3
* @param arg4 system call argument 4
* @param arg5 system call argument 5
* @param arg6 system call argument 6
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
* @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
* return void
*
*/
typedef u32_t (*_k_syscall_handler_t)(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5, u32_t arg6,
void *ssf);
#ifdef CONFIG_USERSPACE
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/**
* Indicate whether we are currently running in user mode
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
*
* @return true if the CPU is currently running with user permissions
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
*/
static inline bool z_arch_is_user_context(void);
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/**
* Indicate whether the CPU is currently in user mode
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
*
* @return true if the CPU is currently running with user permissions
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
*/
static inline bool _is_user_context(void)
{
return z_arch_is_user_context();
}
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/*
* Helper data structures for system calls with large argument lists
*/
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
struct _syscall_7_args {
u32_t arg6;
u32_t arg7;
};
struct _syscall_8_args {
u32_t arg6;
u32_t arg7;
u32_t arg8;
};
struct _syscall_9_args {
u32_t arg6;
u32_t arg7;
u32_t arg8;
u32_t arg9;
};
struct _syscall_10_args {
u32_t arg6;
u32_t arg7;
u32_t arg8;
u32_t arg9;
u32_t arg10;
};
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
/*
* Interfaces for invoking system calls
*/
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
static inline u32_t z_arch_syscall_invoke0(u32_t call_id);
static inline u32_t z_arch_syscall_invoke1(u32_t arg1, u32_t call_id);
static inline u32_t z_arch_syscall_invoke2(u32_t arg1, u32_t arg2,
u32_t call_id);
static inline u32_t z_arch_syscall_invoke3(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t call_id);
static inline u32_t z_arch_syscall_invoke4(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t call_id);
static inline u32_t z_arch_syscall_invoke5(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5,
u32_t call_id);
static inline u32_t z_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 z_syscall_invoke7(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5, u32_t arg6,
u32_t arg7, u32_t call_id) {
struct _syscall_7_args args = {
.arg6 = arg6,
.arg7 = arg7,
};
return z_arch_syscall_invoke6(arg1, arg2, arg3, arg4, arg5, (u32_t)&args,
call_id);
}
static inline u32_t z_syscall_invoke8(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5, u32_t arg6,
u32_t arg7, u32_t arg8, u32_t call_id)
{
struct _syscall_8_args args = {
.arg6 = arg6,
.arg7 = arg7,
.arg8 = arg8,
};
return z_arch_syscall_invoke6(arg1, arg2, arg3, arg4, arg5, (u32_t)&args,
call_id);
}
static inline u32_t z_syscall_invoke9(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5, u32_t arg6,
u32_t arg7, u32_t arg8, u32_t arg9,
u32_t call_id)
{
struct _syscall_9_args args = {
.arg6 = arg6,
.arg7 = arg7,
.arg8 = arg8,
.arg9 = arg9,
};
return z_arch_syscall_invoke6(arg1, arg2, arg3, arg4, arg5, (u32_t)&args,
call_id);
}
static inline u32_t z_syscall_invoke10(u32_t arg1, u32_t arg2, u32_t arg3,
u32_t arg4, u32_t arg5, u32_t arg6,
u32_t arg7, u32_t arg8, u32_t arg9,
u32_t arg10, u32_t call_id)
{
struct _syscall_10_args args = {
.arg6 = arg6,
.arg7 = arg7,
.arg8 = arg8,
.arg9 = arg9,
.arg10 = arg10
};
return z_arch_syscall_invoke6(arg1, arg2, arg3, arg4, arg5, (u32_t)&args,
call_id);
}
static inline u64_t z_syscall_ret64_invoke0(u32_t call_id)
{
u64_t ret;
(void)z_arch_syscall_invoke1((u32_t)&ret, call_id);
return ret;
}
static inline u64_t z_syscall_ret64_invoke1(u32_t arg1, u32_t call_id)
{
u64_t ret;
(void)z_arch_syscall_invoke2(arg1, (u32_t)&ret, call_id);
return ret;
}
static inline u64_t z_syscall_ret64_invoke2(u32_t arg1, u32_t arg2,
u32_t call_id)
{
u64_t ret;
(void)z_arch_syscall_invoke3(arg1, arg2, (u32_t)&ret, call_id);
return ret;
}
#endif /* CONFIG_USERSPACE */
#ifdef __cplusplus
}
#endif
userspace: flesh out internal syscall interface * Instead of a common system call entry function, we instead create a table mapping system call ids to handler skeleton functions which are invoked directly by the architecture code which receives the system call. * system call handler prototype specified. All but the most trivial system calls will implement one of these. They validate all the arguments, including verifying kernel/device object pointers, ensuring that the calling thread has appropriate access to any memory buffers passed in, and performing other parameter checks that the base system call implementation does not check, or only checks with __ASSERT(). It's only possible to install a system call implementation directly inside this table if the implementation has a return value and requires no validation of any of its arguments. A sample handler implementation for k_mutex_unlock() might look like: u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, void *ssf) { struct k_mutex *mutex = (struct k_mutex *)mutex_arg; _SYSCALL_ARG1; _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0, ssf); _SYSCALL_VERIFY(mutex->lock_count > 0, ssf); _SYSCALL_VERIFY(mutex->owner == _current, ssf); k_mutex_unlock(mutex); return 0; } * the x86 port modified to work with the system call table instead of calling a common handler function. fixed an issue where registers being changed could confuse the compiler has been fixed; all registers, even ones used for parameters, must be preserved across the system call. * a new arch API for producing a kernel oops when validating system call arguments added. The debug information reported will be from the system call site and not inside the handler function. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-13 18:04:21 -07:00
#endif /* _ASMLANGUAGE */
#endif