blob: 627b8a10d73ec6b356bdf2e276ddbb04c6f7397e [file] [log] [blame]
Andrew Boie1d3731f2017-09-22 13:52:21 -07001#!/usr/bin/env python3
2#
3# Copyright (c) 2017 Intel Corporation
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import sys
Andrew Boie3ff41b92017-10-08 12:20:24 -07008from enum import Enum
9
10class Retval(Enum):
11 VOID = 0
12 U32 = 1
13 U64 = 2
Andrew Boie1d3731f2017-09-22 13:52:21 -070014
Andrew Boie990bf162017-10-03 12:36:49 -070015def gen_macro(ret, argc):
Andrew Boie3ff41b92017-10-08 12:20:24 -070016 if ret == Retval.VOID:
17 suffix = "_VOID"
18 elif ret == Retval.U64:
19 suffix = "_RET64"
20 else:
21 suffix = ""
22
23 sys.stdout.write("K_SYSCALL_DECLARE%d%s(id, name" % (argc, suffix))
24 if (ret != Retval.VOID):
Andrew Boie1d3731f2017-09-22 13:52:21 -070025 sys.stdout.write(", ret")
26 for i in range(argc):
27 sys.stdout.write(", t%d, p%d" % (i, i))
28 sys.stdout.write(")")
29
30def gen_fn(ret, argc, name, extern=False):
31 sys.stdout.write("\t%s %s %s(" %
32 (("extern" if extern else "static inline"),
Andrew Boie3ff41b92017-10-08 12:20:24 -070033 ("ret" if ret != Retval.VOID else "void"), name))
Andrew Boie1d3731f2017-09-22 13:52:21 -070034 if argc == 0:
35 sys.stdout.write("void");
36 else:
37 for i in range(argc):
38 sys.stdout.write("t%d p%d" % (i, i))
39 if i != (argc - 1):
40 sys.stdout.write(", ")
41 sys.stdout.write(")")
42
Andrew Boie3ae64442017-11-28 13:59:15 -080043def tabs(count):
44 sys.stdout.write("\t" * count);
45
46def gen_make_syscall(ret, argc, tabcount):
47 tabs(tabcount)
48
49 # The core kernel is built with the --no-whole-archive linker option.
50 # For all the individual .o files which make up the kernel, if there
51 # are no external references to symbols within these object files,
52 # everything in the object file is dropped.
53 #
54 # This has a subtle interaction with system call handlers. If an object
55 # file has system call handler inside it, and nothing else in the
56 # object file is referenced, then the linker will prefer the weak
57 # version of the handler in the generated syscall_dispatch.c. The
58 # user will get an "unimplemented system call" error if the associated
59 # system call for that handler is made.
60 #
61 # Fix this by making a fake reference to the handler function at the
62 # system call site. The address gets stored inside a special section
63 # "hndlr_ref". This is enough to prevent the handlers from being
64 # dropped, and the hndlr_ref section is itself dropped from the binary
65 # from gc-sections; these references will not consume space.
66
67 sys.stdout.write("static _GENERIC_SECTION(hndlr_ref) __used void *href = (void *)&_handler_##name; \\\n")
68 tabs(tabcount)
Andrew Boie3ff41b92017-10-08 12:20:24 -070069 if (ret != Retval.VOID):
Andrew Boie1d3731f2017-09-22 13:52:21 -070070 sys.stdout.write("return (ret)")
Andrew Boie3ff41b92017-10-08 12:20:24 -070071 if (argc <= 6 and ret != Retval.U64):
Andrew Boie1d3731f2017-09-22 13:52:21 -070072 sys.stdout.write("_arch")
Andrew Boie3ff41b92017-10-08 12:20:24 -070073 sys.stdout.write("_syscall%s_invoke%d(" %
74 (("_ret64" if ret == Retval.U64 else ""), argc))
Andrew Boie1d3731f2017-09-22 13:52:21 -070075 for i in range(argc):
76 sys.stdout.write("(u32_t)p%d, " % (i))
77 sys.stdout.write("id); \\\n")
78
79def gen_call_impl(ret, argc):
Andrew Boie3ff41b92017-10-08 12:20:24 -070080 if (ret != Retval.VOID):
Andrew Boie1d3731f2017-09-22 13:52:21 -070081 sys.stdout.write("return ")
82 sys.stdout.write("_impl_##name(")
83 for i in range(argc):
84 sys.stdout.write("p%d" % (i))
85 if i != (argc - 1):
86 sys.stdout.write(", ")
87 sys.stdout.write("); \\\n")
88
89def newline():
90 sys.stdout.write(" \\\n")
91
92def gen_defines_inner(ret, argc, kernel_only=False, user_only=False):
93 sys.stdout.write("#define ")
Andrew Boie990bf162017-10-03 12:36:49 -070094 gen_macro(ret, argc)
Andrew Boie1d3731f2017-09-22 13:52:21 -070095 newline()
96
Andrew Boie990bf162017-10-03 12:36:49 -070097 if not user_only:
98 gen_fn(ret, argc, "_impl_##name", extern=True)
99 sys.stdout.write(";")
100 newline()
101
Andrew Boie1d3731f2017-09-22 13:52:21 -0700102 gen_fn(ret, argc, "name");
103 newline()
104 sys.stdout.write("\t{")
105 newline()
106
107 if kernel_only:
108 sys.stdout.write("\t\t")
109 gen_call_impl(ret, argc)
110 elif user_only:
Andrew Boie3ae64442017-11-28 13:59:15 -0800111 gen_make_syscall(ret, argc, 2)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700112 else:
113 sys.stdout.write("\t\tif (_is_user_context()) {")
114 newline()
115
Andrew Boie3ae64442017-11-28 13:59:15 -0800116 gen_make_syscall(ret, argc, 3)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700117
118 sys.stdout.write("\t\t} else {")
119 newline()
120
Andrew Boiec5354552017-10-14 11:00:12 -0700121 # Prevent memory access issues if the implementation function gets
122 # inlined
123 sys.stdout.write("\t\t\tcompiler_barrier();");
124 newline()
125
Andrew Boie1d3731f2017-09-22 13:52:21 -0700126 sys.stdout.write("\t\t\t")
127 gen_call_impl(ret, argc)
128 sys.stdout.write("\t\t}")
129 newline()
130
131 sys.stdout.write("\t}\n\n")
132
Andrew Boie3ff41b92017-10-08 12:20:24 -0700133
Andrew Boie1d3731f2017-09-22 13:52:21 -0700134def gen_defines(argc, kernel_only=False, user_only=False):
Andrew Boie3ff41b92017-10-08 12:20:24 -0700135 gen_defines_inner(Retval.VOID, argc, kernel_only, user_only)
136 gen_defines_inner(Retval.U32, argc, kernel_only, user_only)
137 gen_defines_inner(Retval.U64, argc, kernel_only, user_only)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700138
139
140sys.stdout.write("/* Auto-generated by gen_syscall_header.py, do not edit! */\n\n")
141sys.stdout.write("#ifndef GEN_SYSCALL_H\n#define GEN_SYSCALL_H\n\n")
142
143for i in range(11):
Andrew Boiea949b502017-10-10 16:10:39 -0700144 sys.stdout.write("#if !defined(CONFIG_USERSPACE) || defined(__ZEPHYR_SUPERVISOR__)\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700145 gen_defines(i, kernel_only=True)
146 sys.stdout.write("#elif defined(__ZEPHYR_USER__)\n")
147 gen_defines(i, user_only=True)
148 sys.stdout.write("#else /* mixed kernel/user macros */\n")
149 gen_defines(i)
150 sys.stdout.write("#endif /* mixed kernel/user macros */\n\n")
151
152sys.stdout.write("#endif /* GEN_SYSCALL_H */\n")
153
154
155
156
157