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