-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsyscall.h
168 lines (145 loc) · 4.92 KB
/
syscall.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
* Copyright (c) 2017, Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SYSCALL_H_
#define ZEPHYR_INCLUDE_SYSCALL_H_
#include <syscall_list.h>
#include <arch/syscall.h>
#include <stdbool.h>
#ifndef _ASMLANGUAGE
#include <zephyr/types.h>
#include <syscall_macros.h>
#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 verifier 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_vrfy_k_foo(). Handler
* functions have the same type signature as the wrapped call,
* 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.
*/
/**
* @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
* 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
* @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
/*
* Interfaces for invoking system calls
*/
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);
#endif /* CONFIG_USERSPACE */
/**
* Indicate whether we are currently running in user mode
*
* @return true if the CPU is currently running with user permissions
*/
#ifdef CONFIG_USERSPACE
static inline bool z_arch_is_user_context(void);
#else
#define z_arch_is_user_context() (true)
#endif
/* True if a syscall function must trap to the kernel, usually a
* compile-time decision.
*/
static ALWAYS_INLINE bool z_syscall_trap(void)
{
bool ret = false;
#ifdef CONFIG_USERSPACE
#if defined(__ZEPHYR_SUPERVISOR__)
ret = false;
#elif defined(__ZEPHYR_USER__)
ret = true;
#else
ret = z_arch_is_user_context();
#endif
#endif
return ret;
}
/**
* Indicate whether the CPU is currently in user mode
*
* @return true if the CPU is currently running with user permissions
*/
static inline bool _is_user_context(void)
{
#ifdef CONFIG_USERSPACE
return z_arch_is_user_context();
#else
return false;
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* _ASMLANGUAGE */
#endif