blob: d0f8114719c21e1d4e1286eed82763efaee92fae [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
Andrew Boiec78c5e62019-03-11 14:45:43 -07007"""
8Generation script for syscall_macros.h
9
10The generation of macros for invoking system calls of various number
11of arguments, in different execution types (supervisor only, user only,
12mixed supervisor/user code) is tedious and repetitive. Rather than writing
13by hand, this script generates it.
14
15This script has no inputs, and emits the generated header to stdout.
16"""
17
Andrew Boie1d3731f2017-09-22 13:52:21 -070018import sys
Andrew Boie3ff41b92017-10-08 12:20:24 -070019from enum import Enum
20
Anas Nashif72565532017-12-12 08:19:25 -050021
Andrew Boie3ff41b92017-10-08 12:20:24 -070022class Retval(Enum):
23 VOID = 0
24 U32 = 1
25 U64 = 2
Andrew Boie1d3731f2017-09-22 13:52:21 -070026
Anas Nashif72565532017-12-12 08:19:25 -050027
Andrew Boie990bf162017-10-03 12:36:49 -070028def gen_macro(ret, argc):
Andrew Boie3ff41b92017-10-08 12:20:24 -070029 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 Magnussonba312fe2019-03-20 19:30:29 +010037 if ret != Retval.VOID:
Andrew Boie1d3731f2017-09-22 13:52:21 -070038 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 Nashif72565532017-12-12 08:19:25 -050043
Andrew Boie1d3731f2017-09-22 13:52:21 -070044def gen_fn(ret, argc, name, extern=False):
45 sys.stdout.write("\t%s %s %s(" %
Anas Nashif72565532017-12-12 08:19:25 -050046 (("extern" if extern else "static inline"),
47 ("ret" if ret != Retval.VOID else "void"), name))
Andrew Boie1d3731f2017-09-22 13:52:21 -070048 if argc == 0:
Anas Nashif72565532017-12-12 08:19:25 -050049 sys.stdout.write("void")
Andrew Boie1d3731f2017-09-22 13:52:21 -070050 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 Nashif72565532017-12-12 08:19:25 -050057
Andrew Boie3ae64442017-11-28 13:59:15 -080058def tabs(count):
Anas Nashif72565532017-12-12 08:19:25 -050059 sys.stdout.write("\t" * count)
60
Andrew Boie3ae64442017-11-28 13:59:15 -080061
62def 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 Nashif72565532017-12-12 08:19:25 -050083 sys.stdout.write(
Andrew Boie7ea21122019-03-15 10:47:05 -070084 "static Z_GENERIC_SECTION(hndlr_ref) __used void *href = (void *)&z_hdlr_##name; \\\n")
Andrew Boie3ae64442017-11-28 13:59:15 -080085 tabs(tabcount)
Ulf Magnussonba312fe2019-03-20 19:30:29 +010086 if ret != Retval.VOID:
Andrew Boie1d3731f2017-09-22 13:52:21 -070087 sys.stdout.write("return (ret)")
Flavio Ceolin91b61232018-09-11 18:05:14 -070088 else:
89 sys.stdout.write("return (void)")
Andrew Boie3ff41b92017-10-08 12:20:24 -070090 if (argc <= 6 and ret != Retval.U64):
Patrik Flykt4344e272019-03-08 14:19:05 -070091 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 Nashif72565532017-12-12 08:19:25 -050095 (("_ret64" if ret == Retval.U64 else ""), argc))
Andrew Boie1d3731f2017-09-22 13:52:21 -070096 for i in range(argc):
97 sys.stdout.write("(u32_t)p%d, " % (i))
98 sys.stdout.write("id); \\\n")
99
Anas Nashif72565532017-12-12 08:19:25 -0500100
Andrew Boie1d3731f2017-09-22 13:52:21 -0700101def gen_call_impl(ret, argc):
Ulf Magnussonba312fe2019-03-20 19:30:29 +0100102 if ret != Retval.VOID:
Andrew Boie1d3731f2017-09-22 13:52:21 -0700103 sys.stdout.write("return ")
Patrik Flykt4344e272019-03-08 14:19:05 -0700104 sys.stdout.write("z_impl_##name(")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700105 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 Nashif72565532017-12-12 08:19:25 -0500111
Andrew Boie1d3731f2017-09-22 13:52:21 -0700112def newline():
113 sys.stdout.write(" \\\n")
114
Anas Nashif72565532017-12-12 08:19:25 -0500115
Andrew Boie1d3731f2017-09-22 13:52:21 -0700116def gen_defines_inner(ret, argc, kernel_only=False, user_only=False):
117 sys.stdout.write("#define ")
Andrew Boie990bf162017-10-03 12:36:49 -0700118 gen_macro(ret, argc)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700119 newline()
120
Andrew Boie990bf162017-10-03 12:36:49 -0700121 if not user_only:
Patrik Flykt4344e272019-03-08 14:19:05 -0700122 gen_fn(ret, argc, "z_impl_##name", extern=True)
Andrew Boie990bf162017-10-03 12:36:49 -0700123 sys.stdout.write(";")
124 newline()
125
Anas Nashif72565532017-12-12 08:19:25 -0500126 gen_fn(ret, argc, "name")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700127 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 Boie3ae64442017-11-28 13:59:15 -0800135 gen_make_syscall(ret, argc, 2)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700136 else:
137 sys.stdout.write("\t\tif (_is_user_context()) {")
138 newline()
139
Andrew Boie3ae64442017-11-28 13:59:15 -0800140 gen_make_syscall(ret, argc, 3)
Andrew Boie1d3731f2017-09-22 13:52:21 -0700141
142 sys.stdout.write("\t\t} else {")
143 newline()
144
Andrew Boiec5354552017-10-14 11:00:12 -0700145 # Prevent memory access issues if the implementation function gets
146 # inlined
Anas Nashif72565532017-12-12 08:19:25 -0500147 sys.stdout.write("\t\t\tcompiler_barrier();")
Andrew Boiec5354552017-10-14 11:00:12 -0700148 newline()
149
Andrew Boie1d3731f2017-09-22 13:52:21 -0700150 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 Boie3ff41b92017-10-08 12:20:24 -0700157
Andrew Boie1d3731f2017-09-22 13:52:21 -0700158def gen_defines(argc, kernel_only=False, user_only=False):
Andrew Boie3ff41b92017-10-08 12:20:24 -0700159 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 Boie1d3731f2017-09-22 13:52:21 -0700162
163
Anas Nashif72565532017-12-12 08:19:25 -0500164sys.stdout.write(
165 "/* Auto-generated by gen_syscall_header.py, do not edit! */\n\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700166sys.stdout.write("#ifndef GEN_SYSCALL_H\n#define GEN_SYSCALL_H\n\n")
Andrew Boied5a24002018-03-26 13:45:20 -0700167sys.stdout.write("#include <syscall.h>\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700168
169for i in range(11):
Anas Nashif72565532017-12-12 08:19:25 -0500170 sys.stdout.write(
171 "#if !defined(CONFIG_USERSPACE) || defined(__ZEPHYR_SUPERVISOR__)\n")
Andrew Boie1d3731f2017-09-22 13:52:21 -0700172 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
179sys.stdout.write("#endif /* GEN_SYSCALL_H */\n")