1.. _syscalls:
2
3System Calls
4############
5User threads run with a reduced set of privileges than supervisor threads:
6certain CPU instructions may not be used, and they have access to only a
7limited part of the memory map. System calls (may) allow user threads to
8perform operations not directly available to them.
9
10When defining system calls, it is very important to ensure that access to the
11API's private data is done exclusively through system call interfaces.
12Private kernel data should never be made available to user mode threads
13directly. For example, the ``k_queue`` APIs were intentionally not made
14available as they store bookkeeping information about the queue directly
15in the queue buffers which are visible from user mode.
16
17APIs that allow the user to register callback functions that run in
18supervisor mode should never be exposed as system calls. Reserve these
19for supervisor-mode access only.
20
21This section describes how to declare new system calls and discusses a few
22implementation details relevant to them.
23
24Components
25**********
26
27All system calls have the following components:
28
29* A **C prototype** prefixed with :c:macro:`__syscall` for the API. It
30  will be declared in some header under ``include/`` or in another
31  ``SYSCALL_INCLUDE_DIRS`` directory. This prototype is never implemented
32  manually, instead it gets created by the :ref:`gen_syscalls.py` script.
33  What gets generated is an inline function which either calls the
34  implementation function directly (if called from supervisor mode) or goes
35  through privilege elevation and validation steps (if called from user
36  mode).
37
38* An **implementation function**, which is the real implementation of the
39  system call. The implementation function may assume that all parameters
40  passed in have been validated if it was invoked from user mode.
41
42* A **verification function**, which wraps the implementation function
43  and does validation of all the arguments passed in.
44
45* An **unmarshalling function**, which is an automatically generated
46  handler that must be included by user source code.
47
48C Prototype
49***********
50
51The C prototype represents how the API is invoked from either user or
52supervisor mode. For example, to initialize a semaphore:
53
54.. code-block:: c
55
56    __syscall void k_sem_init(struct k_sem *sem, unsigned int initial_count,
57                              unsigned int limit);
58
59The :c:macro:`__syscall` attribute is very special. To the C compiler, it
60simply expands to 'static inline'. However to the post-build
61:ref:`parse_syscalls.py` script, it indicates that this API is a system call.
62The :ref:`parse_syscalls.py` script does some parsing of the function prototype,
63to determine the data types of its return value and arguments, and has some
64limitations:
65
66* Array arguments must be passed in as pointers, not arrays. For example,
67  ``int foo[]`` or ``int foo[12]`` is not allowed, but should instead be
68  expressed as ``int *foo``.
69
70* Function pointers horribly confuse the limited parser. The workaround is
71  to typedef them first, and then express in the argument list in terms
72  of that typedef.
73
74* :c:macro:`__syscall` must be the first thing in the prototype.
75
76The preprocessor is intentionally not used when determining the set of system
77calls to generate. However, any generated system calls that don't actually have
78a verification function defined (because the related feature is not enabled in
79the kernel configuration) will instead point to a special verification for
80unimplemented system calls. Data type definitions for APIs should not have
81conditional visibility to the compiler.
82
83Any header file that declares system calls must include a special generated
84header at the very bottom of the header file. This header follows the
85naming convention ``syscalls/<name of header file>``. For example, at the
86bottom of :zephyr_file:`include/zephyr/drivers/sensor.h`:
87
88.. code-block:: c
89
90    #include <zephyr/syscalls/sensor.h>
91
92C prototype functions must be declared in one of the directories
93listed in the CMake variable ``SYSCALL_INCLUDE_DIRS``. This list
94always contains ``APPLICATION_SOURCE_DIR`` when
95``CONFIG_APPLICATION_DEFINED_SYSCALL`` is set, or
96``${ZEPHYR_BASE}/subsys/testsuite/ztest/include`` when
97``CONFIG_ZTEST`` is set. Additional paths can be added to the list
98through the CMake command line or in CMake code that is run before
99``find_package(Zephyr ...)`` is run. ``${ZEPHYR_BASE}/include``
100is always scanned for potential syscall prototypes.
101
102Note that not all syscalls will be included in the final binaries.
103CMake functions ``zephyr_syscall_header`` and
104``zephyr_syscall_header_ifdef`` are used to specify which header
105files contain syscall prototypes where those syscalls must be
106present in the final binaries. Note that header files inside
107directories listed in CMake variable ``SYSCALL_INCLUDE_DIRS``
108will always have their syscalls present in final binaries.
109To force all syscalls to be included in the final binaries,
110turn on :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS`.
111
112Invocation Context
113==================
114
115Source code that uses system call APIs can be made more efficient if it is
116known that all the code inside a particular C file runs exclusively in
117user mode, or exclusively in supervisor mode. The system will look for
118the definition of macros :c:macro:`__ZEPHYR_SUPERVISOR__` or
119:c:macro:`__ZEPHYR_USER__`, typically these will be added to the compiler
120flags in the build system for the related files.
121
122* If :kconfig:option:`CONFIG_USERSPACE` is not enabled, all APIs just directly call
123  the implementation function.
124
125* Otherwise, the default case is to make a runtime check to see if the
126  processor is currently running in user mode, and either make the system call
127  or directly call the implementation function as appropriate.
128
129* If :c:macro:`__ZEPHYR_SUPERVISOR__` is defined, then it is assumed that
130  all the code runs in supervisor mode and all APIs just directly call the
131  implementation function. If the code was actually running in user mode,
132  there will be a CPU exception as soon as it tries to do something it isn't
133  allowed to do.
134
135* If :c:macro:`__ZEPHYR_USER__` is defined, then it is assumed that all the
136  code runs in user mode and system calls are unconditionally made.
137
138Implementation Details
139======================
140
141Declaring an API with :c:macro:`__syscall` causes some code to be generated in
142C and header files by the :ref:`gen_syscalls.py` script, all of which can be found in
143the project out directory under ``include/generated/``:
144
145* The system call is added to the enumerated type of system call IDs,
146  which is expressed in ``include/generated/zephyr/syscall_list.h``. It is the name
147  of the API in uppercase, prefixed with ``K_SYSCALL_``.
148
149* An entry for the system call is created in the dispatch table
150  ``_k_syscall_table``, expressed in ``include/generated/zephyr/syscall_dispatch.c``
151
152  * This table only contains syscalls where their corresponding
153    prototypes are declared in header files when
154    :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS` is enabled:
155
156    * Indicated by CMake functions ``zephyr_syscall_header`` and
157      ``zephyr_syscall_header_ifdef``, or
158
159    * Under directories specified in CMake variable
160      ``SYSCALL_INCLUDE_DIRS``.
161
162* A weak verification function is declared, which is just an alias of the
163  'unimplemented system call' verifier. This is necessary since the real
164  verification function may or may not be built depending on the kernel
165  configuration. For example, if a user thread makes a sensor subsystem
166  API call, but the sensor subsystem is not enabled, the weak verifier
167  will be invoked instead.
168
169* An unmarshalling function is defined in ``include/generated/<name>_mrsh.c``
170
171The body of the API is created in the generated system header. Using the
172example of :c:func:`k_sem_init()`, this API is declared in
173:zephyr_file:`include/zephyr/kernel.h`. At the bottom of
174:zephyr_file:`include/zephyr/kernel.h` is::
175
176    #include <zephyr/syscalls/kernel.h>
177
178Inside this header is the body of :c:func:`k_sem_init()`::
179
180    static inline void k_sem_init(struct k_sem * sem, unsigned int initial_count, unsigned int limit)
181    {
182    #ifdef CONFIG_USERSPACE
183            if (z_syscall_trap()) {
184                    arch_syscall_invoke3(*(uintptr_t *)&sem, *(uintptr_t *)&initial_count, *(uintptr_t *)&limit, K_SYSCALL_K_SEM_INIT);
185                    return;
186            }
187            compiler_barrier();
188    #endif
189            z_impl_k_sem_init(sem, initial_count, limit);
190    }
191
192This generates an inline function that takes three arguments with void
193return value. Depending on context it will either directly call the
194implementation function or go through a system call elevation. A
195prototype for the implementation function is also automatically generated.
196
197The final layer is the invocation of the system call itself. All architectures
198implementing system calls must implement the seven inline functions
199:c:func:`_arch_syscall_invoke0` through :c:func:`_arch_syscall_invoke6`. These
200functions marshal arguments into designated CPU registers and perform the
201necessary privilege elevation. Parameters of API inline function, before being
202passed as arguments to system call, are C casted to ``uintptr_t`` which matches
203size of register.
204Exception to above is passing 64-bit parameters on 32-bit systems, in which case
20564-bit parameters are split into lower and higher part and passed as two consecutive
206arguments.
207There is always a ``uintptr_t`` type return value, which may be neglected if
208not needed.
209
210.. figure:: syscall_flow.png
211   :alt: System Call execution flow
212   :width: 80%
213   :align: center
214
215   System Call execution flow
216
217Some system calls may have more than six arguments, but number of arguments
218passed via registers is limited to six for all architectures.
219Additional arguments will need to be passed in an array in the source memory
220space, which needs to be treated as untrusted memory in the verification
221function. This code (packing, unpacking and validation) is generated
222automatically as needed in the stub above and in the unmarshalling function.
223
224System calls return ``uintptr_t`` type value that is C casted, by wrapper, to
225a return type of API prototype declaration. This means that 64-bit value may
226not be directly returned, from a system call to its wrapper, on 32-bit systems.
227To solve the problem the automatically generated wrapper function defines 64-bit
228intermediate variable, which is considered **untrusted** buffer, on its stack
229and passes pointer to that variable to the system call, as a final argument.
230Upon return from the system call the value written to that buffer will be
231returned by the wrapper function.
232The problem does not exist on 64-bit systems which are able to return 64-bit
233values directly.
234
235Implementation Function
236***********************
237
238The implementation function is what actually does the work for the API.
239Zephyr normally does little to no error checking of arguments, or does this
240kind of checking with assertions. When writing the implementation function,
241validation of any parameters is optional and should be done with assertions.
242
243All implementation functions must follow the naming convention, which is the
244name of the API prefixed with ``z_impl_``. Implementation functions may be
245declared in the same header as the API as a static inline function or
246declared in some C file. There is no prototype needed for implementation
247functions, these are automatically generated.
248
249Verification Function
250*********************
251
252The verification function runs on the kernel side when a user thread makes
253a system call. When the user thread makes a software interrupt to elevate to
254supervisor mode, the common system call entry point uses the system call ID
255provided by the user to look up the appropriate unmarshalling function for that
256system call and jump into it. This in turn calls the verification function.
257
258Verification and unmarshalling functions only run when system call APIs are
259invoked from user mode. If an API is invoked from supervisor mode, the
260implementation is simply called and there is no software trap.
261
262The purpose of the verification function is to validate all the arguments
263passed in.  This includes:
264
265* Any kernel object pointers provided. For example, the semaphore APIs must
266  ensure that the semaphore object passed in is a valid semaphore and that
267  the calling thread has permission on it.
268
269* Any memory buffers passed in from user mode. Checks must be made that the
270  calling thread has read or write permissions on the provided buffer.
271
272* Any other arguments that have a limited range of valid values.
273
274Verification functions involve a great deal of boilerplate code which has been
275made simpler by some macros in :zephyr_file:`include/zephyr/internal/syscall_handler.h`.
276Verification functions should be declared using these macros.
277
278Argument Validation
279===================
280
281Several macros exist to validate arguments:
282
283* :c:macro:`K_SYSCALL_OBJ()` Checks a memory address to assert that it is
284  a valid kernel object of the expected type, that the calling thread
285  has permissions on it, and that the object is initialized.
286
287* :c:macro:`K_SYSCALL_OBJ_INIT()` is the same as
288  :c:macro:`K_SYSCALL_OBJ()`, except that the provided object may be
289  uninitialized. This is useful for verifiers of object init functions.
290
291* :c:macro:`K_SYSCALL_OBJ_NEVER_INIT()` is the same as
292  :c:macro:`K_SYSCALL_OBJ()`, except that the provided object must be
293  uninitialized. This is not used very often, currently only for
294  :c:func:`k_thread_create()`.
295
296* :c:macro:`K_SYSCALL_MEMORY_READ()` validates a memory buffer of a particular
297  size. The calling thread must have read permissions on the entire buffer.
298
299* :c:macro:`K_SYSCALL_MEMORY_WRITE()` is the same as
300  :c:macro:`K_SYSCALL_MEMORY_READ()` but the calling thread must additionally
301  have write permissions.
302
303* :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()` validates an array whose total size
304  is expressed as separate arguments for the number of elements and the
305  element size. This macro correctly accounts for multiplication overflow
306  when computing the total size. The calling thread must have read permissions
307  on the total size.
308
309* :c:macro:`K_SYSCALL_MEMORY_ARRAY_WRITE()` is the same as
310  :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()` but the calling thread must
311  additionally have write permissions.
312
313* :c:macro:`K_SYSCALL_VERIFY_MSG()` does a runtime check of some boolean
314  expression which must evaluate to true otherwise the check will fail.
315  A variant :c:macro:`K_SYSCALL_VERIFY` exists which does not take
316  a message parameter, instead printing the expression tested if it
317  fails. The latter should only be used for the most obvious of tests.
318
319* :c:macro:`K_SYSCALL_DRIVER_OP()` checks at runtime if a driver
320  instance is capable of performing a particular operation.  While this
321  macro can be used by itself, it's mostly a building block for macros
322  that are automatically generated for every driver subsystem.  For
323  instance, to validate the GPIO driver, one could use the
324  :c:macro:`K_SYSCALL_DRIVER_GPIO()` macro.
325
326* :c:macro:`K_SYSCALL_SPECIFIC_DRIVER()` is a runtime check to verify that
327  a provided pointer is a valid instance of a specific device driver, that
328  the calling thread has permissions on it, and that the driver has been
329  initialized. It does this by checking the API structure pointer that
330  is stored within the driver instance and ensuring that it matches the
331  provided value, which should be the address of the specific driver's
332  API structure.
333
334If any check fails, the macros will return a nonzero value. The macro
335:c:macro:`K_OOPS()` can be used to induce a kernel oops which will kill the
336calling thread. This is done instead of returning some error condition to
337keep the APIs the same when calling from supervisor mode.
338
339.. _syscall_verification:
340
341Verifier Definition
342===================
343
344All system calls are dispatched to a verifier function with a prefixed
345``z_vrfy_`` name based on the system call.  They have exactly the same
346return type and argument types as the wrapped system call.  Their job
347is to execute the system call (generally by calling the implementation
348function) after having validated all arguments.
349
350The verifier is itself invoked by an automatically generated
351unmarshaller function which takes care of unpacking the register
352arguments from the architecture layer and casting them to the correct
353type.  This is defined in a header file that must be included from
354user code, generally somewhere after the definition of the verifier in
355a translation unit (so that it can be inlined).
356
357For example:
358
359.. code-block:: c
360
361    static int z_vrfy_k_sem_take(struct k_sem *sem, int32_t timeout)
362    {
363        K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM));
364        return z_impl_k_sem_take(sem, timeout);
365    }
366    #include <zephyr/syscalls/k_sem_take_mrsh.c>
367
368
369Verification Memory Access Policies
370===================================
371
372Parameters passed to system calls by reference require special handling,
373because the value of these parameters can be changed at any time by any
374user thread that has access to the memory that parameter points to. If the
375kernel makes any logical decisions based on the contents of this memory, this
376can open up the kernel to attacks even if checking is done. This is a class
377of exploits known as TOCTOU (Time Of Check to Time Of Use).
378
379The proper procedure to mitigate these attacks is to make a copies in the
380verification function, and only perform parameter checks on the copies, which
381user threads will never have access to. The implementation functions get passed
382the copy and not the original data sent by the user. The
383:c:func:`k_usermode_to_copy()` and :c:func:`k_usermode_from_copy()` APIs exist for
384this purpose.
385
386There is one exception in place, with respect to large data buffers which are
387only used to provide a memory area that is either only written to, or whose
388contents are never used for any validation or control flow. Further
389discussion of this later in this section.
390
391As a first example, consider a parameter which is used as an output parameter
392for some integral value:
393
394
395.. code-block:: c
396
397    int z_vrfy_some_syscall(int *out_param)
398    {
399        int local_out_param;
400        int ret;
401
402        ret = z_impl_some_syscall(&local_out_param);
403        K_OOPS(k_usermode_to_copy(out_param, &local_out_param, sizeof(*out_param)));
404        return ret;
405    }
406
407Here we have allocated ``local_out_param`` on the stack, passed its address to
408the implementation function, and then used :c:func:`k_usermode_to_copy()` to fill
409in the memory passed in by the caller.
410
411It might be tempting to do something more concise:
412
413.. code-block:: c
414
415    int z_vrfy_some_syscall(int *out_param)
416    {
417        K_OOPS(K_SYSCALL_MEMORY_WRITE(out_param, sizeof(*out_param)));
418        return z_impl_some_syscall(out_param);
419    }
420
421However, this is unsafe if the implementation ever does any reads to this
422memory as part of its logic. For example, it could be used to store some
423counter value, and this could be meddled with by user threads that have access
424to its memory. It is by far safest for small integral values to do the copying
425as shown in the first example.
426
427Some parameters may be input/output. For instance, it's not uncommon to see APIs
428which pass in a pointer to some ``size_t`` which is a maximum allowable size,
429which is then updated by the implementation to reflect the actual number of
430bytes processed. This too should use a stack copy:
431
432.. code-block:: c
433
434    int z_vrfy_in_out_syscall(size_t *size_ptr)
435    {
436        size_t size;
437        int ret;
438
439        K_OOPS(k_usermode_from_copy(&size, size_ptr, sizeof(size));
440        ret = z_impl_in_out_syscall(&size);
441        K_OOPS(k_usermode_to_copy(size_ptr, &size, sizeof(size)));
442        return ret;
443    }
444
445Many system calls pass in structures or even linked data structures. All should
446be copied. Typically this is done by allocating copies on the stack:
447
448.. code-block:: c
449
450    struct bar {
451        ...
452    };
453
454    struct foo {
455        ...
456        struct bar *bar_left;
457        struct bar *bar_right;
458    };
459
460    int z_vrfy_must_alloc(struct foo *foo)
461    {
462        int ret;
463        struct foo foo_copy;
464        struct bar bar_right_copy;
465        struct bar bar_left_copy;
466
467        K_OOPS(k_usermode_from_copy(&foo_copy, foo, sizeof(*foo)));
468        K_OOPS(k_usermode_from_copy(&bar_right_copy, foo_copy.bar_right,
469                                sizeof(struct bar)));
470        foo_copy.bar_right = &bar_right_copy;
471        K_OOPS(k_usermode_from_copy(&bar_left_copy, foo_copy.bar_left,
472                                sizeof(struct bar)));
473        foo_copy.bar_left = &bar_left_copy;
474
475        return z_impl_must_alloc(&foo_copy);
476    }
477
478In some cases the amount of data isn't known at compile time or may be too
479large to allocate on the stack. In this scenario, it may be necessary to draw
480memory from the caller's resource pool via :c:func:`z_thread_malloc()`. This
481should always be considered last resort. Functional safety programming
482guidelines heavily discourage usage of heap and the fact that a resource pool is
483used must be clearly documented. Any issues with allocation must be
484reported, to a caller, with returning the ``-ENOMEM`` . The ``K_OOPS()``
485should never be used to verify if resource allocation has been successful.
486
487.. code-block:: c
488
489    struct bar {
490        ...
491    };
492
493    struct foo {
494        size_t count;
495        struct bar *bar_list; /* array of struct bar of size count */
496    };
497
498    int z_vrfy_must_alloc(struct foo *foo)
499    {
500        int ret;
501        struct foo foo_copy;
502        struct bar *bar_list_copy;
503        size_t bar_list_bytes;
504
505        /* Safely copy foo into foo_copy */
506        K_OOPS(k_usermode_from_copy(&foo_copy, foo, sizeof(*foo)));
507
508        /* Bounds check the count member, in the copy we made */
509        if (foo_copy.count > 32) {
510            return -EINVAL;
511        }
512
513        /* Allocate RAM for the bar_list, replace the pointer in
514         * foo_copy */
515        bar_list_bytes = foo_copy.count * sizeof(struct_bar);
516        bar_list_copy = z_thread_malloc(bar_list_bytes);
517        if (bar_list_copy == NULL) {
518            return -ENOMEM;
519        }
520        K_OOPS(k_usermode_from_copy(bar_list_copy, foo_copy.bar_list,
521                                bar_list_bytes));
522        foo_copy.bar_list = bar_list_copy;
523
524        ret = z_impl_must_alloc(&foo_copy);
525
526        /* All done with the memory, free it and return */
527        k_free(foo_copy.bar_list_copy);
528        return ret;
529    }
530
531Finally, we must consider large data buffers. These represent areas of user
532memory which either have data copied out of, or copied into. It is permitted
533to pass these pointers to the implementation function directly. The caller's
534access to the buffer still must be validated with ``K_SYSCALL_MEMORY`` APIs.
535The following constraints need to be met:
536
537 * If the buffer is used by the implementation function to write data, such
538   as data captured from some MMIO region, the implementation function must
539   only write this data, and never read it.
540
541 * If the buffer is used by the implementation function to read data, such
542   as a block of memory to write to some hardware destination, this data
543   must be read without any processing. No conditional logic can be implemented
544   due to the data buffer's contents. If such logic is required a copy must be
545   made.
546
547 * The buffer must only be used synchronously with the call. The implementation
548   must not ever save the buffer address and use it asynchronously, such as
549   when an interrupt fires.
550
551.. code-block:: c
552
553    int z_vrfy_get_data_from_kernel(void *buf, size_t size)
554    {
555        K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, size));
556        return z_impl_get_data_from_kernel(buf, size);
557    }
558
559Verification Return Value Policies
560==================================
561
562When verifying system calls, it's important to note which kinds of verification
563failures should propagate a return value to the caller, and which should
564simply invoke :c:macro:`K_OOPS()` which kills the calling thread. The current
565conventions are as follows:
566
567#. For system calls that are defined but not compiled, invocations of these
568   missing system calls are routed to :c:func:`handler_no_syscall()` which
569   invokes :c:macro:`K_OOPS()`.
570
571#. Any invalid access to memory found by the set of ``K_SYSCALL_MEMORY`` APIs,
572   :c:func:`k_usermode_from_copy()`, :c:func:`k_usermode_to_copy()`
573   should trigger a :c:macro:`K_OOPS`. This happens when the caller doesn't have
574   appropriate permissions on the memory buffer or some size calculation
575   overflowed.
576
577#. Most system calls take kernel object pointers as an argument, checked either
578   with one of the ``K_SYSCALL_OBJ`` functions,  ``K_SYSCALL_DRIVER_nnnnn``, or
579   manually using :c:func:`k_object_validate()`. These can fail for a variety
580   of reasons: missing driver API, bad kernel object pointer, wrong kernel
581   object type, or improper initialization state. These issues should always
582   invoke :c:macro:`K_OOPS()`.
583
584#. Any error resulting from a failed memory heap allocation, often from
585   invoking :c:func:`z_thread_malloc()`, should propagate ``-ENOMEM`` to the
586   caller.
587
588#. General parameter checks should be done in the implementation function,
589   in most cases using ``CHECKIF()``.
590
591   * The behavior of ``CHECKIF()`` depends on the kernel configuration, but if
592     user mode is enabled, :kconfig:option:`CONFIG_RUNTIME_ERROR_CHECKS` is enforced,
593     which guarantees that these checks will be made and a return value
594     propagated.
595
596#. It is totally forbidden for any kind of kernel mode callback function to
597   be registered from user mode. APIs which simply install callbacks shall not
598   be exposed as system calls. Some driver subsystem APIs may take optional
599   function callback pointers. User mode verification functions for these APIs
600   must enforce that these are NULL and should invoke :c:macro:`K_OOPS()` if
601   not.
602
603#. Some parameter checks are enforced only from user mode. These should be
604   checked in the verification function and propagate a return value to the
605   caller if possible.
606
607There are some known exceptions to these policies currently in Zephyr:
608
609* :c:func:`k_thread_join()` and :c:func:`k_thread_abort()` are no-ops if
610  the thread object isn't initialized. This is because for threads, the
611  initialization bit pulls double-duty to indicate whether a thread is
612  running, cleared upon exit. See #23030.
613
614* :c:func:`k_thread_create()` invokes :c:macro:`K_OOPS()` for parameter
615  checks, due to a great deal of existing code ignoring the return value.
616  This will also be addressed by #23030.
617
618* :c:func:`k_thread_abort()` invokes :c:macro:`K_OOPS()` if an essential
619  thread is aborted, as the function has no return value.
620
621* Various system calls related to logging invoke :c:macro:`K_OOPS()`
622  when bad parameters are passed in as they do not propagate errors.
623
624Configuration Options
625*********************
626
627Related configuration options:
628
629* :kconfig:option:`CONFIG_USERSPACE`
630* :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS`
631
632APIs
633****
634
635Helper macros for creating system call verification functions are provided in
636:zephyr_file:`include/zephyr/internal/syscall_handler.h`:
637
638* :c:macro:`K_SYSCALL_OBJ()`
639* :c:macro:`K_SYSCALL_OBJ_INIT()`
640* :c:macro:`K_SYSCALL_OBJ_NEVER_INIT()`
641* :c:macro:`K_OOPS()`
642* :c:macro:`K_SYSCALL_MEMORY_READ()`
643* :c:macro:`K_SYSCALL_MEMORY_WRITE()`
644* :c:macro:`K_SYSCALL_MEMORY_ARRAY_READ()`
645* :c:macro:`K_SYSCALL_MEMORY_ARRAY_WRITE()`
646* :c:macro:`K_SYSCALL_VERIFY_MSG()`
647* :c:macro:`K_SYSCALL_VERIFY`
648
649Functions for invoking system calls are defined in
650:zephyr_file:`include/zephyr/syscall.h`:
651
652* :c:func:`_arch_syscall_invoke0`
653* :c:func:`_arch_syscall_invoke1`
654* :c:func:`_arch_syscall_invoke2`
655* :c:func:`_arch_syscall_invoke3`
656* :c:func:`_arch_syscall_invoke4`
657* :c:func:`_arch_syscall_invoke5`
658* :c:func:`_arch_syscall_invoke6`
659