Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -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 | Generation script for syscall_macros.h |
| 9 | |
| 10 | The generation of macros for invoking system calls of various number |
| 11 | of arguments, in different execution types (supervisor only, user only, |
| 12 | mixed supervisor/user code) is tedious and repetitive. Rather than writing |
| 13 | by hand, this script generates it. |
| 14 | |
| 15 | This script has no inputs, and emits the generated header to stdout. |
| 16 | """ |
| 17 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 18 | import sys |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 19 | from enum import Enum |
| 20 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 21 | |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 22 | class Retval(Enum): |
| 23 | VOID = 0 |
| 24 | U32 = 1 |
| 25 | U64 = 2 |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 26 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 27 | |
Andrew Boie | 990bf16 | 2017-10-03 12:36:49 -0700 | [diff] [blame] | 28 | def gen_macro(ret, argc): |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 29 | if ret == Retval.VOID: |
| 30 | suffix = "_VOID" |
| 31 | elif ret == Retval.U64: |
| 32 | suffix = "_RET64" |
| 33 | else: |
| 34 | suffix = "" |
| 35 | |
| 36 | sys.stdout.write("K_SYSCALL_DECLARE%d%s(id, name" % (argc, suffix)) |
Ulf Magnusson | ba312fe | 2019-03-20 19:30:29 +0100 | [diff] [blame] | 37 | if ret != Retval.VOID: |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 38 | sys.stdout.write(", ret") |
| 39 | for i in range(argc): |
| 40 | sys.stdout.write(", t%d, p%d" % (i, i)) |
| 41 | sys.stdout.write(")") |
| 42 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 43 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 44 | def gen_fn(ret, argc, name, extern=False): |
| 45 | sys.stdout.write("\t%s %s %s(" % |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 46 | (("extern" if extern else "static inline"), |
| 47 | ("ret" if ret != Retval.VOID else "void"), name)) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 48 | if argc == 0: |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 49 | sys.stdout.write("void") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 50 | else: |
| 51 | for i in range(argc): |
| 52 | sys.stdout.write("t%d p%d" % (i, i)) |
| 53 | if i != (argc - 1): |
| 54 | sys.stdout.write(", ") |
| 55 | sys.stdout.write(")") |
| 56 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 57 | |
Andrew Boie | 3ae6444 | 2017-11-28 13:59:15 -0800 | [diff] [blame] | 58 | def tabs(count): |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 59 | sys.stdout.write("\t" * count) |
| 60 | |
Andrew Boie | 3ae6444 | 2017-11-28 13:59:15 -0800 | [diff] [blame] | 61 | |
| 62 | def gen_make_syscall(ret, argc, tabcount): |
| 63 | tabs(tabcount) |
| 64 | |
| 65 | # The core kernel is built with the --no-whole-archive linker option. |
| 66 | # For all the individual .o files which make up the kernel, if there |
| 67 | # are no external references to symbols within these object files, |
| 68 | # everything in the object file is dropped. |
| 69 | # |
| 70 | # This has a subtle interaction with system call handlers. If an object |
| 71 | # file has system call handler inside it, and nothing else in the |
| 72 | # object file is referenced, then the linker will prefer the weak |
| 73 | # version of the handler in the generated syscall_dispatch.c. The |
| 74 | # user will get an "unimplemented system call" error if the associated |
| 75 | # system call for that handler is made. |
| 76 | # |
| 77 | # Fix this by making a fake reference to the handler function at the |
| 78 | # system call site. The address gets stored inside a special section |
| 79 | # "hndlr_ref". This is enough to prevent the handlers from being |
| 80 | # dropped, and the hndlr_ref section is itself dropped from the binary |
| 81 | # from gc-sections; these references will not consume space. |
| 82 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 83 | sys.stdout.write( |
Andrew Boie | 7ea2112 | 2019-03-15 10:47:05 -0700 | [diff] [blame] | 84 | "static Z_GENERIC_SECTION(hndlr_ref) __used void *href = (void *)&z_hdlr_##name; \\\n") |
Andrew Boie | 3ae6444 | 2017-11-28 13:59:15 -0800 | [diff] [blame] | 85 | tabs(tabcount) |
Ulf Magnusson | ba312fe | 2019-03-20 19:30:29 +0100 | [diff] [blame] | 86 | if ret != Retval.VOID: |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 87 | sys.stdout.write("return (ret)") |
Flavio Ceolin | 91b6123 | 2018-09-11 18:05:14 -0700 | [diff] [blame] | 88 | else: |
| 89 | sys.stdout.write("return (void)") |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 90 | if (argc <= 6 and ret != Retval.U64): |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 91 | sys.stdout.write("z_arch_syscall%s_invoke%d(" % |
| 92 | (("_ret64" if ret == Retval.U64 else ""), argc)) |
| 93 | else: |
| 94 | sys.stdout.write("z_syscall%s_invoke%d(" % |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 95 | (("_ret64" if ret == Retval.U64 else ""), argc)) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 96 | for i in range(argc): |
| 97 | sys.stdout.write("(u32_t)p%d, " % (i)) |
| 98 | sys.stdout.write("id); \\\n") |
| 99 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 100 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 101 | def gen_call_impl(ret, argc): |
Ulf Magnusson | ba312fe | 2019-03-20 19:30:29 +0100 | [diff] [blame] | 102 | if ret != Retval.VOID: |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 103 | sys.stdout.write("return ") |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 104 | sys.stdout.write("z_impl_##name(") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 105 | for i in range(argc): |
| 106 | sys.stdout.write("p%d" % (i)) |
| 107 | if i != (argc - 1): |
| 108 | sys.stdout.write(", ") |
| 109 | sys.stdout.write("); \\\n") |
| 110 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 111 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 112 | def newline(): |
| 113 | sys.stdout.write(" \\\n") |
| 114 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 115 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 116 | def gen_defines_inner(ret, argc, kernel_only=False, user_only=False): |
| 117 | sys.stdout.write("#define ") |
Andrew Boie | 990bf16 | 2017-10-03 12:36:49 -0700 | [diff] [blame] | 118 | gen_macro(ret, argc) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 119 | newline() |
| 120 | |
Andrew Boie | 990bf16 | 2017-10-03 12:36:49 -0700 | [diff] [blame] | 121 | if not user_only: |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 122 | gen_fn(ret, argc, "z_impl_##name", extern=True) |
Andrew Boie | 990bf16 | 2017-10-03 12:36:49 -0700 | [diff] [blame] | 123 | sys.stdout.write(";") |
| 124 | newline() |
| 125 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 126 | gen_fn(ret, argc, "name") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 127 | newline() |
| 128 | sys.stdout.write("\t{") |
| 129 | newline() |
| 130 | |
| 131 | if kernel_only: |
| 132 | sys.stdout.write("\t\t") |
| 133 | gen_call_impl(ret, argc) |
| 134 | elif user_only: |
Andrew Boie | 3ae6444 | 2017-11-28 13:59:15 -0800 | [diff] [blame] | 135 | gen_make_syscall(ret, argc, 2) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 136 | else: |
| 137 | sys.stdout.write("\t\tif (_is_user_context()) {") |
| 138 | newline() |
| 139 | |
Andrew Boie | 3ae6444 | 2017-11-28 13:59:15 -0800 | [diff] [blame] | 140 | gen_make_syscall(ret, argc, 3) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 141 | |
| 142 | sys.stdout.write("\t\t} else {") |
| 143 | newline() |
| 144 | |
Andrew Boie | c535455 | 2017-10-14 11:00:12 -0700 | [diff] [blame] | 145 | # Prevent memory access issues if the implementation function gets |
| 146 | # inlined |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 147 | sys.stdout.write("\t\t\tcompiler_barrier();") |
Andrew Boie | c535455 | 2017-10-14 11:00:12 -0700 | [diff] [blame] | 148 | newline() |
| 149 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 150 | sys.stdout.write("\t\t\t") |
| 151 | gen_call_impl(ret, argc) |
| 152 | sys.stdout.write("\t\t}") |
| 153 | newline() |
| 154 | |
| 155 | sys.stdout.write("\t}\n\n") |
| 156 | |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 157 | |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 158 | def gen_defines(argc, kernel_only=False, user_only=False): |
Andrew Boie | 3ff41b9 | 2017-10-08 12:20:24 -0700 | [diff] [blame] | 159 | gen_defines_inner(Retval.VOID, argc, kernel_only, user_only) |
| 160 | gen_defines_inner(Retval.U32, argc, kernel_only, user_only) |
| 161 | gen_defines_inner(Retval.U64, argc, kernel_only, user_only) |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 162 | |
| 163 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 164 | sys.stdout.write( |
| 165 | "/* Auto-generated by gen_syscall_header.py, do not edit! */\n\n") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 166 | sys.stdout.write("#ifndef GEN_SYSCALL_H\n#define GEN_SYSCALL_H\n\n") |
Andrew Boie | d5a2400 | 2018-03-26 13:45:20 -0700 | [diff] [blame] | 167 | sys.stdout.write("#include <syscall.h>\n") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 168 | |
| 169 | for i in range(11): |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 170 | sys.stdout.write( |
| 171 | "#if !defined(CONFIG_USERSPACE) || defined(__ZEPHYR_SUPERVISOR__)\n") |
Andrew Boie | 1d3731f | 2017-09-22 13:52:21 -0700 | [diff] [blame] | 172 | gen_defines(i, kernel_only=True) |
| 173 | sys.stdout.write("#elif defined(__ZEPHYR_USER__)\n") |
| 174 | gen_defines(i, user_only=True) |
| 175 | sys.stdout.write("#else /* mixed kernel/user macros */\n") |
| 176 | gen_defines(i) |
| 177 | sys.stdout.write("#endif /* mixed kernel/user macros */\n\n") |
| 178 | |
| 179 | sys.stdout.write("#endif /* GEN_SYSCALL_H */\n") |