blob: cab36cdb41ae7625cc2b7d59a734d53d26835cf7 [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
Anas Nashif72565532017-12-12 08:19:25 -050010
Andrew Boie3ff41b92017-10-08 12:20:24 -070011class Retval(Enum):
12 VOID = 0
13 U32 = 1
14 U64 = 2
Andrew Boie1d3731f2017-09-22 13:52:21 -070015
Anas Nashif72565532017-12-12 08:19:25 -050016
Andrew Boie990bf162017-10-03 12:36:49 -070017def gen_macro(ret, argc):
Andrew Boie3ff41b92017-10-08 12:20:24 -070018 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 Boie1d3731f2017-09-22 13:52:21 -070027 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 Nashif72565532017-12-12 08:19:25 -050032
Andrew Boie1d3731f2017-09-22 13:52:21 -070033def gen_fn(ret, argc, name, extern=False):
34 sys.stdout.write("\t%s %s %s(" %
Anas Nashif72565532017-12-12 08:19:25 -050035 (("extern" if extern else "static inline"),
36 ("ret" if ret != Retval.VOID else "void"), name))
Andrew Boie1d3731f2017-09-22 13:52:21 -070037 if argc == 0:
Anas Nashif72565532017-12-12 08:19:25 -050038 sys.stdout.write("void")
Andrew Boie1d3731f2017-09-22 13:52:21 -070039 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 Nashif72565532017-12-12 08:19:25 -050046
Andrew Boie3ae64442017-11-28 13:59:15 -080047def tabs(count):
Anas Nashif72565532017-12-12 08:19:25 -050048 sys.stdout.write("\t" * count)
49
Andrew Boie3ae64442017-11-28 13:59:15 -080050
51def 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 Nashif72565532017-12-12 08:19:25 -050072 sys.stdout.write(
Flavio Ceolin6fc84fe2018-09-24 16:29:10 -070073 "static _GENERIC_SECTION(hndlr_ref) __used void *href = (void *)&hdlr_##name; \\\n")
Andrew Boie3ae64442017-11-28 13:59:15 -080074 tabs(tabcount)
Andrew Boie3ff41b92017-10-08 12:20:24 -070075 if (ret != Retval.VOID):
Andrew Boie1d3731f2017-09-22 13:52:21 -070076 sys.stdout.write("return (ret)")
Flavio Ceolin91b61232018-09-11 18:05:14 -070077 else:
78 sys.stdout.write("return (void)")
Andrew Boie3ff41b92017-10-08 12:20:24 -070079 if (argc <= 6 and ret != Retval.U64):
Andrew Boie1d3731f2017-09-22 13:52:21 -070080 sys.stdout.write("_arch")
Andrew Boie3ff41b92017-10-08 12:20:24 -070081 sys.stdout.write("_syscall%s_invoke%d(" %
Anas Nashif72565532017-12-12 08:19:25 -050082 (("_ret64" if ret == Retval.U64 else ""), argc))
Andrew Boie1d3731f2017-09-22 13:52:21 -070083 for i in range(argc):
84 sys.stdout.write("(u32_t)p%d, " % (i))
85 sys.stdout.write("id); \\\n")
86
Anas Nashif72565532017-12-12 08:19:25 -050087
Andrew Boie1d3731f2017-09-22 13:52:21 -070088def gen_call_impl(ret, argc):
Andrew Boie3ff41b92017-10-08 12:20:24 -070089 if (ret != Retval.VOID):
Andrew Boie1d3731f2017-09-22 13:52:21 -070090 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 Nashif72565532017-12-12 08:19:25 -050098
Andrew Boie1d3731f2017-09-22 13:52:21 -070099def newline():
100 sys.stdout.write(" \\\n")
101
Anas Nashif72565532017-12-12 08:19:25 -0500102
Andrew Boie1d3731f2017-09-22 13:52:21 -0700103def gen_defines_inner(ret, argc, kernel_only=False, user_only=False):
104 sys.stdout.write("#define ")
Andrew Boie990bf162017-10-03 12:36:49 -0700105 gen_macro(ret, argc)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700106 newline()
107
Andrew Boie990bf162017-10-03 12:36:49 -0700108 if not user_only:
109 gen_fn(ret, argc, "_impl_##name", extern=True)
110 sys.stdout.write(";")
111 newline()
112
Anas Nashif72565532017-12-12 08:19:25 -0500113 gen_fn(ret, argc, "name")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700114 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 Boie3ae64442017-11-28 13:59:15 -0800122 gen_make_syscall(ret, argc, 2)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700123 else:
124 sys.stdout.write("\t\tif (_is_user_context()) {")
125 newline()
126
Andrew Boie3ae64442017-11-28 13:59:15 -0800127 gen_make_syscall(ret, argc, 3)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700128
129 sys.stdout.write("\t\t} else {")
130 newline()
131
Andrew Boiec5354552017-10-14 11:00:12 -0700132 # Prevent memory access issues if the implementation function gets
133 # inlined
Anas Nashif72565532017-12-12 08:19:25 -0500134 sys.stdout.write("\t\t\tcompiler_barrier();")
Andrew Boiec5354552017-10-14 11:00:12 -0700135 newline()
136
Andrew Boie1d3731f2017-09-22 13:52:21 -0700137 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 Boie3ff41b92017-10-08 12:20:24 -0700144
Andrew Boie1d3731f2017-09-22 13:52:21 -0700145def gen_defines(argc, kernel_only=False, user_only=False):
Andrew Boie3ff41b92017-10-08 12:20:24 -0700146 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 Boie1d3731f2017-09-22 13:52:21 -0700149
150
Anas Nashif72565532017-12-12 08:19:25 -0500151sys.stdout.write(
152 "/* Auto-generated by gen_syscall_header.py, do not edit! */\n\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700153sys.stdout.write("#ifndef GEN_SYSCALL_H\n#define GEN_SYSCALL_H\n\n")
Andrew Boied5a24002018-03-26 13:45:20 -0700154sys.stdout.write("#include <syscall.h>\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700155
156for i in range(11):
Anas Nashif72565532017-12-12 08:19:25 -0500157 sys.stdout.write(
158 "#if !defined(CONFIG_USERSPACE) || defined(__ZEPHYR_SUPERVISOR__)\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700159 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
166sys.stdout.write("#endif /* GEN_SYSCALL_H */\n")