Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | # Copyright (c) 2017 Intel Corporation |
| 4 | # |
| 5 | # SPDX-License-Identifier: Apache-2.0 |
| 6 | |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 7 | """ |
| 8 | Script to generate system call invocation macros |
| 9 | |
| 10 | This script parses the system call metadata JSON file emitted by |
| 11 | parse_syscalls.py to create several files: |
| 12 | |
| 13 | - A file containing weak aliases of any potentially unimplemented system calls, |
| 14 | as well as the system call dispatch table, which maps system call type IDs |
| 15 | to their handler functions. |
| 16 | |
Ruslan Mstoi | 84822e3 | 2020-05-26 16:10:21 +0300 | [diff] [blame] | 17 | - A header file defining the system call type IDs, as well as function |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 18 | prototypes for all system call handler functions. |
| 19 | |
| 20 | - A directory containing header files. Each header corresponds to a header |
| 21 | that was identified as containing system call declarations. These |
| 22 | generated headers contain the inline invocation functions for each system |
| 23 | call in that header. |
| 24 | """ |
| 25 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 26 | import sys |
| 27 | import re |
| 28 | import argparse |
| 29 | import os |
Sebastian Bøe | 13a6840 | 2017-11-20 13:03:55 +0100 | [diff] [blame] | 30 | import json |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 31 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 32 | types64 = ["int64_t", "uint64_t"] |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 33 | |
| 34 | # The kernel linkage is complicated. These functions from |
| 35 | # userspace_handlers.c are present in the kernel .a library after |
| 36 | # userspace.c, which contains the weak fallbacks defined here. So the |
| 37 | # linker finds the weak one first and stops searching, and thus won't |
| 38 | # see the real implementation which should override. Yet changing the |
| 39 | # order runs afoul of a comment in CMakeLists.txt that the order is |
| 40 | # critical. These are core syscalls that won't ever be unconfigured, |
| 41 | # just disable the fallback mechanism as a simple workaround. |
Marc Herbert | f987029 | 2019-09-19 10:30:43 -0700 | [diff] [blame] | 42 | noweak = ["z_mrsh_k_object_release", |
| 43 | "z_mrsh_k_object_access_grant", |
| 44 | "z_mrsh_k_object_alloc"] |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 45 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 46 | table_template = """/* auto-generated by gen_syscalls.py, don't edit */ |
| 47 | |
Paul Sokolovsky | 94620bd | 2017-10-01 23:47:43 +0300 | [diff] [blame] | 48 | /* Weak handler functions that get replaced by the real ones unless a system |
| 49 | * call is not implemented due to kernel configuration. |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 50 | */ |
| 51 | %s |
| 52 | |
| 53 | const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = { |
| 54 | \t%s |
| 55 | }; |
| 56 | """ |
| 57 | |
| 58 | list_template = """ |
| 59 | /* auto-generated by gen_syscalls.py, don't edit */ |
Flavio Ceolin | a7fffa9 | 2018-09-13 15:06:35 -0700 | [diff] [blame] | 60 | #ifndef ZEPHYR_SYSCALL_LIST_H |
| 61 | #define ZEPHYR_SYSCALL_LIST_H |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 62 | |
Sebastian Bøe | 1a40990 | 2018-08-10 15:23:00 +0200 | [diff] [blame] | 63 | %s |
| 64 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 65 | #ifndef _ASMLANGUAGE |
| 66 | |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 67 | #include <stdint.h> |
Andrew Boie | c67eb56 | 2018-03-26 13:44:44 -0700 | [diff] [blame] | 68 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 69 | #endif /* _ASMLANGUAGE */ |
| 70 | |
Flavio Ceolin | a7fffa9 | 2018-09-13 15:06:35 -0700 | [diff] [blame] | 71 | #endif /* ZEPHYR_SYSCALL_LIST_H */ |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 72 | """ |
| 73 | |
| 74 | syscall_template = """ |
| 75 | /* auto-generated by gen_syscalls.py, don't edit */ |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 76 | %s |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 77 | |
| 78 | #ifndef _ASMLANGUAGE |
| 79 | |
| 80 | #include <syscall_list.h> |
Flavio Ceolin | f4adf10 | 2019-12-03 09:09:07 -0800 | [diff] [blame] | 81 | #include <syscall.h> |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 82 | |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 83 | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 84 | #pragma GCC diagnostic push |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 85 | #endif |
| 86 | |
| 87 | #ifdef __GNUC__ |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 88 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" |
Daniel Leung | 82ec1c0 | 2021-06-01 13:19:51 -0700 | [diff] [blame] | 89 | #pragma GCC diagnostic ignored "-Warray-bounds" |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 90 | #endif |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 91 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 92 | #ifdef __cplusplus |
| 93 | extern "C" { |
| 94 | #endif |
| 95 | |
| 96 | %s |
| 97 | |
| 98 | #ifdef __cplusplus |
| 99 | } |
| 100 | #endif |
| 101 | |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 102 | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 103 | #pragma GCC diagnostic pop |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 104 | #endif |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 105 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 106 | #endif |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 107 | #endif /* include guard */ |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 108 | """ |
| 109 | |
| 110 | handler_template = """ |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 111 | extern uintptr_t z_hdlr_%s(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, |
| 112 | uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf); |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 113 | """ |
| 114 | |
| 115 | weak_template = """ |
Leandro Pereira | a1ae845 | 2018-03-06 15:08:55 -0800 | [diff] [blame] | 116 | __weak ALIAS_OF(handler_no_syscall) |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 117 | uintptr_t %s(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, |
| 118 | uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf); |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 119 | """ |
| 120 | |
| 121 | |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 122 | typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$') |
| 123 | |
| 124 | |
| 125 | class SyscallParseException(Exception): |
| 126 | pass |
| 127 | |
| 128 | |
| 129 | def typename_split(item): |
| 130 | if "[" in item: |
| 131 | raise SyscallParseException( |
| 132 | "Please pass arrays to syscalls as pointers, unable to process '%s'" % |
| 133 | item) |
| 134 | |
| 135 | if "(" in item: |
| 136 | raise SyscallParseException( |
| 137 | "Please use typedefs for function pointers") |
| 138 | |
| 139 | mo = typename_regex.match(item) |
| 140 | if not mo: |
| 141 | raise SyscallParseException("Malformed system call invocation") |
| 142 | |
| 143 | m = mo.groups() |
| 144 | return (m[0].strip(), m[1]) |
| 145 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 146 | def need_split(argtype): |
Andrew Boie | 9ff64bb | 2019-11-05 09:39:05 -0800 | [diff] [blame] | 147 | return (not args.long_registers) and (argtype in types64) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 148 | |
| 149 | # Note: "lo" and "hi" are named in little endian conventions, |
| 150 | # but it doesn't matter as long as they are consistently |
| 151 | # generated. |
| 152 | def union_decl(type): |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 153 | return "union { struct { uintptr_t lo, hi; } split; %s val; }" % type |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 154 | |
| 155 | def wrapper_defs(func_name, func_type, args): |
Andrew Boie | 9ff64bb | 2019-11-05 09:39:05 -0800 | [diff] [blame] | 156 | ret64 = need_split(func_type) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 157 | mrsh_args = [] # List of rvalue expressions for the marshalled invocation |
| 158 | split_args = [] |
| 159 | nsplit = 0 |
Ulf Magnusson | a0136b9 | 2019-09-13 15:47:16 +0200 | [diff] [blame] | 160 | for argtype, argname in args: |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 161 | if need_split(argtype): |
| 162 | split_args.append((argtype, argname)) |
| 163 | mrsh_args.append("parm%d.split.lo" % nsplit) |
| 164 | mrsh_args.append("parm%d.split.hi" % nsplit) |
| 165 | nsplit += 1 |
| 166 | else: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 167 | mrsh_args.append("*(uintptr_t *)&" + argname) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 168 | |
| 169 | if ret64: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 170 | mrsh_args.append("(uintptr_t)&ret64") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 171 | |
James Harris | 074dbb9 | 2021-03-04 08:21:14 -0800 | [diff] [blame] | 172 | decl_arglist = ", ".join([" ".join(argrec) for argrec in args]) or "void" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 173 | |
| 174 | wrap = "extern %s z_impl_%s(%s);\n" % (func_type, func_name, decl_arglist) |
| 175 | wrap += "static inline %s %s(%s)\n" % (func_type, func_name, decl_arglist) |
| 176 | wrap += "{\n" |
| 177 | wrap += "#ifdef CONFIG_USERSPACE\n" |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 178 | wrap += ("\t" + "uint64_t ret64;\n") if ret64 else "" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 179 | wrap += "\t" + "if (z_syscall_trap()) {\n" |
| 180 | |
| 181 | for parmnum, rec in enumerate(split_args): |
| 182 | (argtype, argname) = rec |
| 183 | wrap += "\t\t%s parm%d;\n" % (union_decl(argtype), parmnum) |
| 184 | wrap += "\t\t" + "parm%d.val = %s;\n" % (parmnum, argname) |
| 185 | |
| 186 | if len(mrsh_args) > 6: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 187 | wrap += "\t\t" + "uintptr_t more[] = {\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 188 | wrap += "\t\t\t" + (",\n\t\t\t".join(mrsh_args[5:])) + "\n" |
| 189 | wrap += "\t\t" + "};\n" |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 190 | mrsh_args[5:] = ["(uintptr_t) &more"] |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 191 | |
| 192 | syscall_id = "K_SYSCALL_" + func_name.upper() |
Andrew Boie | 4f77c2a | 2019-11-07 12:43:29 -0800 | [diff] [blame] | 193 | invoke = ("arch_syscall_invoke%d(%s)" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 194 | % (len(mrsh_args), |
| 195 | ", ".join(mrsh_args + [syscall_id]))) |
| 196 | |
Daniel Leung | 4725db8 | 2021-05-26 10:26:51 -0700 | [diff] [blame] | 197 | # Coverity does not understand syscall mechanism |
| 198 | # and will already complain when any function argument |
| 199 | # is not of exact size as uintptr_t. So tell Coverity |
| 200 | # to ignore this particular rule here. |
| 201 | wrap += "\t\t/* coverity[OVERRUN] */\n" |
| 202 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 203 | if ret64: |
| 204 | wrap += "\t\t" + "(void)%s;\n" % invoke |
| 205 | wrap += "\t\t" + "return (%s)ret64;\n" % func_type |
| 206 | elif func_type == "void": |
| 207 | wrap += "\t\t" + "%s;\n" % invoke |
Ulf Magnusson | a0136b9 | 2019-09-13 15:47:16 +0200 | [diff] [blame] | 208 | wrap += "\t\t" + "return;\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 209 | else: |
| 210 | wrap += "\t\t" + "return (%s) %s;\n" % (func_type, invoke) |
| 211 | |
| 212 | wrap += "\t" + "}\n" |
| 213 | wrap += "#endif\n" |
| 214 | |
| 215 | # Otherwise fall through to direct invocation of the impl func. |
| 216 | # Note the compiler barrier: that is required to prevent code from |
| 217 | # the impl call from being hoisted above the check for user |
| 218 | # context. |
| 219 | impl_arglist = ", ".join([argrec[1] for argrec in args]) |
| 220 | impl_call = "z_impl_%s(%s)" % (func_name, impl_arglist) |
| 221 | wrap += "\t" + "compiler_barrier();\n" |
| 222 | wrap += "\t" + "%s%s;\n" % ("return " if func_type != "void" else "", |
| 223 | impl_call) |
| 224 | |
| 225 | wrap += "}\n" |
| 226 | |
| 227 | return wrap |
| 228 | |
| 229 | # Returns an expression for the specified (zero-indexed!) marshalled |
| 230 | # parameter to a syscall, with handling for a final "more" parameter. |
| 231 | def mrsh_rval(mrsh_num, total): |
| 232 | if mrsh_num < 5 or total <= 6: |
| 233 | return "arg%d" % mrsh_num |
| 234 | else: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 235 | return "(((uintptr_t *)more)[%d])" % (mrsh_num - 5) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 236 | |
| 237 | def marshall_defs(func_name, func_type, args): |
| 238 | mrsh_name = "z_mrsh_" + func_name |
| 239 | |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 240 | nmrsh = 0 # number of marshalled uintptr_t parameter |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 241 | vrfy_parms = [] # list of (arg_num, mrsh_or_parm_num, bool_is_split) |
| 242 | split_parms = [] # list of a (arg_num, mrsh_num) for each split |
Ulf Magnusson | a0136b9 | 2019-09-13 15:47:16 +0200 | [diff] [blame] | 243 | for i, (argtype, _) in enumerate(args): |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 244 | if need_split(argtype): |
| 245 | vrfy_parms.append((i, len(split_parms), True)) |
| 246 | split_parms.append((i, nmrsh)) |
| 247 | nmrsh += 2 |
| 248 | else: |
| 249 | vrfy_parms.append((i, nmrsh, False)) |
| 250 | nmrsh += 1 |
| 251 | |
| 252 | # Final argument for a 64 bit return value? |
Andrew Boie | 9ff64bb | 2019-11-05 09:39:05 -0800 | [diff] [blame] | 253 | if need_split(func_type): |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 254 | nmrsh += 1 |
| 255 | |
| 256 | decl_arglist = ", ".join([" ".join(argrec) for argrec in args]) |
| 257 | mrsh = "extern %s z_vrfy_%s(%s);\n" % (func_type, func_name, decl_arglist) |
| 258 | |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 259 | mrsh += "uintptr_t %s(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,\n" % mrsh_name |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 260 | if nmrsh <= 6: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 261 | mrsh += "\t\t" + "uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, void *ssf)\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 262 | else: |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 263 | mrsh += "\t\t" + "uintptr_t arg3, uintptr_t arg4, void *more, void *ssf)\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 264 | mrsh += "{\n" |
Andy Ross | 7353c7f | 2020-02-06 13:39:03 -0800 | [diff] [blame] | 265 | mrsh += "\t" + "_current->syscall_frame = ssf;\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 266 | |
| 267 | for unused_arg in range(nmrsh, 6): |
| 268 | mrsh += "\t(void) arg%d;\t/* unused */\n" % unused_arg |
| 269 | |
| 270 | if nmrsh > 6: |
| 271 | mrsh += ("\tZ_OOPS(Z_SYSCALL_MEMORY_READ(more, " |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 272 | + str(nmrsh - 6) + " * sizeof(uintptr_t)));\n") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 273 | |
| 274 | for i, split_rec in enumerate(split_parms): |
| 275 | arg_num, mrsh_num = split_rec |
Ulf Magnusson | a0136b9 | 2019-09-13 15:47:16 +0200 | [diff] [blame] | 276 | arg_type = args[arg_num][0] |
| 277 | mrsh += "\t%s parm%d;\n" % (union_decl(arg_type), i) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 278 | mrsh += "\t" + "parm%d.split.lo = %s;\n" % (i, mrsh_rval(mrsh_num, |
| 279 | nmrsh)) |
| 280 | mrsh += "\t" + "parm%d.split.hi = %s;\n" % (i, mrsh_rval(mrsh_num + 1, |
| 281 | nmrsh)) |
| 282 | # Finally, invoke the verify function |
| 283 | out_args = [] |
| 284 | for i, argn, is_split in vrfy_parms: |
| 285 | if is_split: |
| 286 | out_args.append("parm%d.val" % argn) |
| 287 | else: |
| 288 | out_args.append("*(%s*)&%s" % (args[i][0], mrsh_rval(argn, nmrsh))) |
| 289 | |
| 290 | vrfy_call = "z_vrfy_%s(%s)\n" % (func_name, ", ".join(out_args)) |
| 291 | |
| 292 | if func_type == "void": |
| 293 | mrsh += "\t" + "%s;\n" % vrfy_call |
Andrew Boie | 378024c | 2020-05-28 11:48:54 -0700 | [diff] [blame] | 294 | mrsh += "\t" + "_current->syscall_frame = NULL;\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 295 | mrsh += "\t" + "return 0;\n" |
| 296 | else: |
| 297 | mrsh += "\t" + "%s ret = %s;\n" % (func_type, vrfy_call) |
Andrew Boie | 378024c | 2020-05-28 11:48:54 -0700 | [diff] [blame] | 298 | |
Andrew Boie | 9ff64bb | 2019-11-05 09:39:05 -0800 | [diff] [blame] | 299 | if need_split(func_type): |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 300 | ptr = "((uint64_t *)%s)" % mrsh_rval(nmrsh - 1, nmrsh) |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 301 | mrsh += "\t" + "Z_OOPS(Z_SYSCALL_MEMORY_WRITE(%s, 8));\n" % ptr |
| 302 | mrsh += "\t" + "*%s = ret;\n" % ptr |
Andrew Boie | 378024c | 2020-05-28 11:48:54 -0700 | [diff] [blame] | 303 | mrsh += "\t" + "_current->syscall_frame = NULL;\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 304 | mrsh += "\t" + "return 0;\n" |
| 305 | else: |
Andrew Boie | 378024c | 2020-05-28 11:48:54 -0700 | [diff] [blame] | 306 | mrsh += "\t" + "_current->syscall_frame = NULL;\n" |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 307 | mrsh += "\t" + "return (uintptr_t) ret;\n" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 308 | |
| 309 | mrsh += "}\n" |
| 310 | |
| 311 | return mrsh, mrsh_name |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 312 | |
| 313 | def analyze_fn(match_group): |
| 314 | func, args = match_group |
| 315 | |
| 316 | try: |
| 317 | if args == "void": |
| 318 | args = [] |
| 319 | else: |
| 320 | args = [typename_split(a.strip()) for a in args.split(",")] |
| 321 | |
| 322 | func_type, func_name = typename_split(func) |
| 323 | except SyscallParseException: |
| 324 | sys.stderr.write("In declaration of %s\n" % func) |
| 325 | raise |
| 326 | |
| 327 | sys_id = "K_SYSCALL_" + func_name.upper() |
| 328 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 329 | marshaller = None |
| 330 | marshaller, handler = marshall_defs(func_name, func_type, args) |
| 331 | invocation = wrapper_defs(func_name, func_type, args) |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 332 | |
| 333 | # Entry in _k_syscall_table |
| 334 | table_entry = "[%s] = %s" % (sys_id, handler) |
| 335 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 336 | return (handler, invocation, marshaller, sys_id, table_entry) |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 337 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 338 | def parse_args(): |
| 339 | global args |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 340 | parser = argparse.ArgumentParser( |
| 341 | description=__doc__, |
| 342 | formatter_class=argparse.RawDescriptionHelpFormatter) |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 343 | |
Sebastian Bøe | 13a6840 | 2017-11-20 13:03:55 +0100 | [diff] [blame] | 344 | parser.add_argument("-i", "--json-file", required=True, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 345 | help="Read syscall information from json file") |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 346 | parser.add_argument("-d", "--syscall-dispatch", required=True, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 347 | help="output C system call dispatch table file") |
Andrew Boie | 353acf4 | 2018-07-23 18:10:15 -0700 | [diff] [blame] | 348 | parser.add_argument("-l", "--syscall-list", required=True, |
| 349 | help="output C system call list header") |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 350 | parser.add_argument("-o", "--base-output", required=True, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 351 | help="Base output directory for syscall macro headers") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 352 | parser.add_argument("-s", "--split-type", action="append", |
Andrew Boie | 9ff64bb | 2019-11-05 09:39:05 -0800 | [diff] [blame] | 353 | help="A long type that must be split/marshalled on 32-bit systems") |
| 354 | parser.add_argument("-x", "--long-registers", action="store_true", |
| 355 | help="Indicates we are on system with 64-bit registers") |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 356 | args = parser.parse_args() |
| 357 | |
| 358 | |
| 359 | def main(): |
| 360 | parse_args() |
| 361 | |
Ulf Magnusson | a0136b9 | 2019-09-13 15:47:16 +0200 | [diff] [blame] | 362 | if args.split_type is not None: |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 363 | for t in args.split_type: |
| 364 | types64.append(t) |
| 365 | |
Sebastian Bøe | 13a6840 | 2017-11-20 13:03:55 +0100 | [diff] [blame] | 366 | with open(args.json_file, 'r') as fd: |
| 367 | syscalls = json.load(fd) |
| 368 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 369 | invocations = {} |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 370 | mrsh_defs = {} |
| 371 | mrsh_includes = {} |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 372 | ids = [] |
| 373 | table_entries = [] |
| 374 | handlers = [] |
| 375 | |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 376 | for match_group, fn in syscalls: |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 377 | handler, inv, mrsh, sys_id, entry = analyze_fn(match_group) |
Andrew Boie | a698e84 | 2018-07-23 17:27:57 -0700 | [diff] [blame] | 378 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 379 | if fn not in invocations: |
| 380 | invocations[fn] = [] |
| 381 | |
| 382 | invocations[fn].append(inv) |
| 383 | ids.append(sys_id) |
| 384 | table_entries.append(entry) |
| 385 | handlers.append(handler) |
| 386 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 387 | if mrsh: |
| 388 | syscall = typename_split(match_group[0])[1] |
| 389 | mrsh_defs[syscall] = mrsh |
| 390 | mrsh_includes[syscall] = "#include <syscalls/%s>" % fn |
| 391 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 392 | with open(args.syscall_dispatch, "w") as fp: |
Leandro Pereira | a1ae845 | 2018-03-06 15:08:55 -0800 | [diff] [blame] | 393 | table_entries.append("[K_SYSCALL_BAD] = handler_bad_syscall") |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 394 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 395 | weak_defines = "".join([weak_template % name |
| 396 | for name in handlers |
| 397 | if not name in noweak]) |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 398 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 399 | # The "noweak" ones just get a regular declaration |
Andrew Boie | 800b35f | 2019-11-05 09:27:18 -0800 | [diff] [blame] | 400 | weak_defines += "\n".join(["extern uintptr_t %s(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf);" |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 401 | % s for s in noweak]) |
| 402 | |
| 403 | fp.write(table_template % (weak_defines, |
| 404 | ",\n\t".join(table_entries))) |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 405 | |
| 406 | # Listing header emitted to stdout |
| 407 | ids.sort() |
| 408 | ids.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"]) |
Sebastian Bøe | 1a40990 | 2018-08-10 15:23:00 +0200 | [diff] [blame] | 409 | |
| 410 | ids_as_defines = "" |
| 411 | for i, item in enumerate(ids): |
| 412 | ids_as_defines += "#define {} {}\n".format(item, i) |
| 413 | |
Andrew Boie | 353acf4 | 2018-07-23 18:10:15 -0700 | [diff] [blame] | 414 | with open(args.syscall_list, "w") as fp: |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 415 | fp.write(list_template % ids_as_defines) |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 416 | |
| 417 | os.makedirs(args.base_output, exist_ok=True) |
| 418 | for fn, invo_list in invocations.items(): |
| 419 | out_fn = os.path.join(args.base_output, fn) |
| 420 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 421 | ig = re.sub("[^a-zA-Z0-9]", "_", "Z_INCLUDE_SYSCALLS_" + fn).upper() |
| 422 | include_guard = "#ifndef %s\n#define %s\n" % (ig, ig) |
| 423 | header = syscall_template % (include_guard, "\n\n".join(invo_list)) |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 424 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 425 | with open(out_fn, "w") as fp: |
| 426 | fp.write(header) |
| 427 | |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 428 | # Likewise emit _mrsh.c files for syscall inclusion |
| 429 | for fn in mrsh_defs: |
| 430 | mrsh_fn = os.path.join(args.base_output, fn + "_mrsh.c") |
| 431 | |
| 432 | with open(mrsh_fn, "w") as fp: |
| 433 | fp.write("/* auto-generated by gen_syscalls.py, don't edit */\n") |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 434 | fp.write("#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)\n") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 435 | fp.write("#pragma GCC diagnostic push\n") |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 436 | fp.write("#endif\n") |
| 437 | fp.write("#ifdef __GNUC__\n") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 438 | fp.write("#pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n") |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 439 | fp.write("#endif\n") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 440 | fp.write(mrsh_includes[fn] + "\n") |
| 441 | fp.write("\n") |
| 442 | fp.write(mrsh_defs[fn] + "\n") |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 443 | fp.write("#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)\n") |
Andy Ross | 6564974 | 2019-08-06 13:34:31 -0700 | [diff] [blame] | 444 | fp.write("#pragma GCC diagnostic pop\n") |
Stephanos Ioannidis | 2a1c625 | 2019-09-26 13:57:59 +0900 | [diff] [blame] | 445 | fp.write("#endif\n") |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 446 | |
Andrew Boie | fa94ee7 | 2017-09-28 16:54:35 -0700 | [diff] [blame] | 447 | if __name__ == "__main__": |
| 448 | main() |