1 /*
2  * Copyright (c) 2017, Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #ifndef ZEPHYR_INCLUDE_SYSCALL_H_
9 #define ZEPHYR_INCLUDE_SYSCALL_H_
10 
11 #include <zephyr/syscall_list.h>
12 #include <zephyr/arch/syscall.h>
13 #include <stdbool.h>
14 
15 #ifndef _ASMLANGUAGE
16 #include <zephyr/types.h>
17 #include <zephyr/linker/sections.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /*
24  * System Call Declaration macros
25  *
26  * These macros are used in public header files to declare system calls.
27  * They generate inline functions which have different implementations
28  * depending on the current compilation context:
29  *
30  * - Kernel-only code, or CONFIG_USERSPACE disabled, these inlines will
31  *   directly call the implementation
32  * - User-only code, these inlines will marshal parameters and elevate
33  *   privileges
34  * - Mixed or indeterminate code, these inlines will do a runtime check
35  *   to determine what course of action is needed.
36  *
37  * All system calls require a verifier function and an implementation
38  * function.  These must follow a naming convention. For a system call
39  * named k_foo():
40  *
41  * - The handler function will be named z_vrfy_k_foo(). Handler
42  *   functions have the same type signature as the wrapped call,
43  *   verify arguments passed up from userspace, and call the
44  *   implementation function. See documentation for that typedef for
45  *   more information.  - The implementation function will be named
46  *   z_impl_k_foo(). This is the actual implementation of the system
47  *   call.
48  */
49 
50 /**
51  * @typedef _k_syscall_handler_t
52  * @brief System call handler function type
53  *
54  * These are kernel-side skeleton functions for system calls. They are
55  * necessary to sanitize the arguments passed into the system call:
56  *
57  * - Any kernel object or device pointers are validated with _SYSCALL_IS_OBJ()
58  * - Any memory buffers passed in are checked to ensure that the calling thread
59  *   actually has access to them
60  * - Many kernel calls do no sanity checking of parameters other than
61  *   assertions. The handler must check all of these conditions using
62  *   _SYSCALL_ASSERT()
63  * - If the system call has more than 6 arguments, then arg6 will be a pointer
64  *   to some struct containing arguments 6+. The struct itself needs to be
65  *   validated like any other buffer passed in from userspace, and its members
66  *   individually validated (if necessary) and then passed to the real
67  *   implementation like normal arguments
68  *
69  * Even if the system call implementation has no return value, these always
70  * return something, even 0, to prevent register leakage to userspace.
71  *
72  * Once everything has been validated, the real implementation will be executed.
73  *
74  * @param arg1 system call argument 1
75  * @param arg2 system call argument 2
76  * @param arg3 system call argument 3
77  * @param arg4 system call argument 4
78  * @param arg5 system call argument 5
79  * @param arg6 system call argument 6
80  * @param ssf System call stack frame pointer. Used to generate kernel oops
81  *            via _arch_syscall_oops_at(). Contents are arch-specific.
82  * @return system call return value, or 0 if the system call implementation
83  *         return void
84  *
85  */
86 typedef uintptr_t (*_k_syscall_handler_t)(uintptr_t arg1, uintptr_t arg2,
87 					  uintptr_t arg3, uintptr_t arg4,
88 					  uintptr_t arg5, uintptr_t arg6,
89 					  void *ssf);
90 
91 /* True if a syscall function must trap to the kernel, usually a
92  * compile-time decision.
93  */
z_syscall_trap(void)94 static ALWAYS_INLINE bool z_syscall_trap(void)
95 {
96 	bool ret = false;
97 #ifdef CONFIG_USERSPACE
98 #if defined(__ZEPHYR_SUPERVISOR__)
99 	ret = false;
100 #elif defined(__ZEPHYR_USER__)
101 	ret = true;
102 #else
103 	ret = arch_is_user_context();
104 #endif
105 #endif
106 	return ret;
107 }
108 
109 /**
110  * Indicate whether the CPU is currently in user mode
111  *
112  * @return true if the CPU is currently running with user permissions
113  */
114 __pinned_func
k_is_user_context(void)115 static inline bool k_is_user_context(void)
116 {
117 #ifdef CONFIG_USERSPACE
118 	return arch_is_user_context();
119 #else
120 	return false;
121 #endif
122 }
123 
124 #ifdef __cplusplus
125 }
126 #endif
127 
128 #endif /* _ASMLANGUAGE */
129 
130 #endif
131