base: Fix build errors with gcc 10.x
[gem5.git] / src / sim / syscall_desc.hh
1 /*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * Copyright (c) 2015-2016 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2003-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #ifndef __SIM_SYSCALL_DESC_HH__
43 #define __SIM_SYSCALL_DESC_HH__
44
45 #include <functional>
46 #include <map>
47 #include <string>
48
49 #include "base/logging.hh"
50 #include "base/types.hh"
51 #include "cpu/thread_context.hh"
52 #include "sim/guest_abi.hh"
53 #include "sim/process.hh"
54 #include "sim/syscall_return.hh"
55
56 class SyscallDesc;
57
58 SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);
59
60 /**
61 * This class provides the wrapper interface for the system call
62 * implementations which are defined in the sim/syscall_emul files and
63 * bound to the ISAs in the architecture specific code
64 * (i.e. arch/X86/linux/process.cc).
65 */
66 class SyscallDesc {
67 public:
68 /**
69 * Interface for invoking the system call funcion pointer. Note that
70 * this acts as a gateway for all system calls and serves a good point
71 * to add filters for behaviors or apply checks for all system calls.
72 * @param tc Handle for owning ThreadContext to pass information
73 */
74 void doSyscall(ThreadContext *tc, Fault *fault);
75
76 std::string name() const { return _name; }
77 int num() const { return _num; }
78
79 /**
80 * For use within the system call executor if new threads are created and
81 * need something returned into them.
82 */
83 virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret) = 0;
84
85 protected:
86 using Executor =
87 std::function<SyscallReturn(SyscallDesc *, ThreadContext *)>;
88 using Dumper = std::function<std::string(std::string, ThreadContext *)>;
89
90 SyscallDesc(int num, const char *name, Executor exec, Dumper dump) :
91 _name(name), _num(num), executor(exec), dumper(dump)
92 {}
93
94 private:
95 /** System call name (e.g., open, mmap, clone, socket, etc.) */
96 std::string _name;
97 int _num;
98
99 /** Mechanism for ISAs to connect to the emul function definitions */
100 Executor executor;
101 Dumper dumper;
102 };
103
104 /*
105 * This SyscallDesc subclass template adapts a given syscall implementation so
106 * that some arguments can come from the simulator (desc, num and tc) while the
107 * rest can come from the guest using the GuestABI mechanism.
108 */
109 template <typename ABI>
110 class SyscallDescABI : public SyscallDesc
111 {
112 private:
113 // Aliases to make the code below a little more concise.
114 template <typename ...Args>
115 using ABIExecutor =
116 std::function<SyscallReturn(SyscallDesc *, ThreadContext *, Args...)>;
117
118 template <typename ...Args>
119 using ABIExecutorPtr =
120 SyscallReturn (*)(SyscallDesc *, ThreadContext *, Args...);
121
122
123 // Wrap an executor with guest arguments with a normal executor that gets
124 // those additional arguments from the guest context.
125 template <typename ...Args>
126 static inline Executor
127 buildExecutor(ABIExecutor<Args...> target)
128 {
129 return [target](SyscallDesc *desc,
130 ThreadContext *tc) -> SyscallReturn {
131 // Create a partial function which will stick desc to the front of
132 // the parameter list.
133 auto partial = [target,desc](
134 ThreadContext *tc, Args... args) -> SyscallReturn {
135 return target(desc, tc, args...);
136 };
137
138 // Use invokeSimcall to gather the other arguments based on the
139 // given ABI and pass them to the syscall implementation.
140 return invokeSimcall<ABI, SyscallReturn, Args...>(tc,
141 std::function<SyscallReturn(ThreadContext *, Args...)>(
142 partial));
143 };
144 }
145
146 template <typename ...Args>
147 static inline Dumper
148 buildDumper()
149 {
150 return [](std::string name, ThreadContext *tc) -> std::string {
151 return dumpSimcall<ABI, SyscallReturn, Args...>(name, tc);
152 };
153 }
154
155 public:
156 // Constructors which plumb in buildExecutor.
157 template <typename ...Args>
158 SyscallDescABI(int num, const char *name, ABIExecutor<Args...> target) :
159 SyscallDesc(num, name, buildExecutor<Args...>(target),
160 buildDumper<Args...>())
161 {}
162
163 template <typename ...Args>
164 SyscallDescABI(int num, const char *name, ABIExecutorPtr<Args...> target) :
165 SyscallDescABI(num, name, ABIExecutor<Args...>(target))
166 {}
167
168 SyscallDescABI(int num, const char *name) :
169 SyscallDescABI(num, name, ABIExecutor<>(unimplementedFunc))
170 {}
171
172 void
173 returnInto(ThreadContext *tc, const SyscallReturn &ret) override
174 {
175 GuestABI::Result<ABI, SyscallReturn>::store(tc, ret);
176 }
177 };
178
179 template <typename ABI>
180 class SyscallDescTable
181 {
182 private:
183 std::map<int, SyscallDescABI<ABI>> _descs;
184
185 public:
186 SyscallDescTable(std::initializer_list<SyscallDescABI<ABI>> descs)
187 {
188 for (auto &desc: descs) {
189 auto res = _descs.insert({desc.num(), desc});
190 panic_if(!res.second, "Failed to insert desc %s", desc.name());
191 }
192 }
193
194 SyscallDesc
195 *get(int num, bool fatal_if_missing=true)
196 {
197 auto it = _descs.find(num);
198 if (it == _descs.end()) {
199 if (fatal_if_missing)
200 fatal("Syscall %d out of range", num);
201 else
202 return nullptr;
203 }
204 return &it->second;
205 }
206 };
207
208 #endif // __SIM_SYSCALL_DESC_HH__