sim: Add a transitional syscall ABI which defers to Process.
[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 * Authors: Steve Reinhardt
42 * Kevin Lim
43 * Brandon Potter
44 */
45
46 #ifndef __SIM_SYSCALL_DESC_HH__
47 #define __SIM_SYSCALL_DESC_HH__
48
49 #include <functional>
50 #include <string>
51
52 #include "base/types.hh"
53 #include "cpu/thread_context.hh"
54 #include "sim/guest_abi.hh"
55 #include "sim/process.hh"
56 #include "sim/syscall_return.hh"
57
58 class SyscallDesc;
59
60 SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
61 ThreadContext *tc);
62
63 /**
64 * This class provides the wrapper interface for the system call
65 * implementations which are defined in the sim/syscall_emul files and
66 * bound to the ISAs in the architecture specific code
67 * (i.e. arch/X86/linux/process.cc).
68 */
69 class SyscallDesc {
70 public:
71 using SyscallExecutor =
72 std::function<SyscallReturn(SyscallDesc *, int num, ThreadContext *)>;
73
74 SyscallDesc(const char *name, SyscallExecutor sys_exec=unimplementedFunc)
75 : _name(name), executor(sys_exec)
76 {}
77
78 /**
79 * Interface for invoking the system call funcion pointer. Note that
80 * this acts as a gateway for all system calls and serves a good point
81 * to add filters for behaviors or apply checks for all system calls.
82 * @param callnum Number associated with call (by operating system)
83 * @param proc Handle for the owning Process to pass information
84 * @param tc Handle for owning ThreadContext to pass information
85 */
86 void doSyscall(int callnum, ThreadContext *tc, Fault *fault);
87
88 std::string name() { return _name; }
89
90 private:
91 /** System call name (e.g., open, mmap, clone, socket, etc.) */
92 std::string _name;
93
94 /** Mechanism for ISAs to connect to the emul function definitions */
95 SyscallExecutor executor;
96 };
97
98 /*
99 * This SyscallDesc subclass template adapts a given syscall implementation so
100 * that some arguments can come from the simulator (desc, num and tc) while the
101 * rest can come from the guest using the GuestABI mechanism.
102 */
103 template <typename ABI>
104 class SyscallDescABI : public SyscallDesc
105 {
106 private:
107 // Aliases to make the code below a little more concise.
108 template <typename ...Args>
109 using SyscallABIExecutor =
110 std::function<SyscallReturn(SyscallDesc *, int,
111 ThreadContext *, Args...)>;
112
113 template <typename ...Args>
114 using SyscallABIExecutorPtr =
115 SyscallReturn (*)(SyscallDesc *, int, ThreadContext *, Args...);
116
117
118 // Wrap an executor with guest arguments with a normal executor that gets
119 // those additional arguments from the guest context.
120 template <typename ...Args>
121 static inline SyscallExecutor
122 buildExecutor(SyscallABIExecutor<Args...> target)
123 {
124 return [target](SyscallDesc *desc, int num,
125 ThreadContext *tc) -> SyscallReturn {
126 // Create a partial function which will stick desc and num to the
127 // front of the parameter list.
128 auto partial = [target,desc,num](
129 ThreadContext *tc, Args... args) -> SyscallReturn {
130 return target(desc, num, tc, args...);
131 };
132
133 // Use invokeSimcall to gather the other arguments based on the
134 // given ABI and pass them to the syscall implementation.
135 return invokeSimcall<ABI, SyscallReturn, Args...>(tc,
136 std::function<SyscallReturn(ThreadContext *, Args...)>(
137 partial));
138 };
139 }
140
141
142 public:
143 // Constructors which plumb in buildExecutor.
144 template <typename ...Args>
145 SyscallDescABI(const char *name, SyscallABIExecutor<Args...> target) :
146 SyscallDesc(name, buildExecutor<Args...>(target))
147 {}
148
149 template <typename ...Args>
150 SyscallDescABI(const char *name, SyscallABIExecutorPtr<Args...> target) :
151 SyscallDescABI(name, SyscallABIExecutor<Args...>(target))
152 {}
153
154 using SyscallDesc::SyscallDesc;
155 };
156
157 struct DefaultSyscallABI
158 {
159 using Position = int;
160 };
161
162 namespace GuestABI
163 {
164
165 template <>
166 struct Result<DefaultSyscallABI, SyscallReturn>
167 {
168 static void
169 store(ThreadContext *tc, const SyscallReturn &ret)
170 {
171 auto *process = tc->getProcessPtr();
172 process->setSyscallReturn(tc, ret);
173 }
174 };
175
176 template <typename Arg>
177 struct Argument<DefaultSyscallABI, Arg,
178 typename std::enable_if<std::is_integral<Arg>::value>::type>
179 {
180 static Arg
181 get(ThreadContext *tc, DefaultSyscallABI::Position &position)
182 {
183 auto *process = tc->getProcessPtr();
184 return process->getSyscallArg(tc, position);
185 }
186 };
187
188 template <typename Arg>
189 struct Argument<DefaultSyscallABI, Arg,
190 typename std::enable_if<std::is_pointer<Arg>::value>::type>
191 {
192 static Arg
193 get(ThreadContext *tc, DefaultSyscallABI::Position &position)
194 {
195 auto *process = tc->getProcessPtr();
196 RegVal reg = process->getSyscallArg(tc, position);
197 return (Arg)(uintptr_t)(reg);
198 }
199 };
200
201 } // namespace GuestABI
202
203 #endif // __SIM_SYSCALL_DESC_HH__