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