1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <fcntl.h> // AT_FDCWD, AT_SYMLINK_NOFOLLOW
18 #include <linux/sched.h>
19 #include <linux/unistd.h>
20 #include <sys/stat.h>
21 #include <sys/sysinfo.h>
22 #include <sys/types.h>
23
24 #include <cerrno>
25
26 #include "berberis/base/macros.h"
27 #include "berberis/base/scoped_errno.h"
28 #include "berberis/base/tracing.h"
29 #include "berberis/guest_os_primitives/scoped_pending_signals.h"
30 #include "berberis/guest_state/guest_addr.h"
31 #include "berberis/guest_state/guest_state.h"
32 #include "berberis/instrument/syscall.h"
33 #include "berberis/kernel_api/main_executable_real_path_emulation.h"
34 #include "berberis/kernel_api/runtime_bridge.h"
35 #include "berberis/kernel_api/syscall_emulation_common.h"
36 #include "berberis/kernel_api/tracing.h"
37 #include "berberis/runtime_primitives/runtime_library.h"
38
39 #include "epoll_emulation.h"
40 #include "guest_types.h"
41
42 namespace berberis {
43
44 namespace {
45
FstatatForGuest(int dirfd,const char * path,struct stat * buf,int flags)46 int FstatatForGuest(int dirfd, const char* path, struct stat* buf, int flags) {
47 const char* real_path = nullptr;
48 if ((flags & AT_SYMLINK_NOFOLLOW) == 0) {
49 real_path = TryReadLinkToMainExecutableRealPath(path);
50 }
51 return syscall(__NR_newfstatat, dirfd, real_path ? real_path : path, buf, flags);
52 }
53
Hwprobe(Guest_riscv_hwprobe & pair)54 void Hwprobe(Guest_riscv_hwprobe& pair) {
55 switch (pair.key) {
56 case RISCV_HWPROBE_KEY_MVENDORID:
57 pair.value = 0;
58 break;
59 case RISCV_HWPROBE_KEY_MARCHID:
60 pair.value = 0;
61 break;
62 case RISCV_HWPROBE_KEY_MIMPID:
63 pair.value = 0;
64 break;
65 case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
66 pair.value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA;
67 break;
68 case RISCV_HWPROBE_KEY_IMA_EXT_0:
69 pair.value = RISCV_HWPROBE_IMA_FD | RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V |
70 RISCV_HWPROBE_EXT_ZBA | RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS;
71 break;
72 case RISCV_HWPROBE_KEY_CPUPERF_0:
73 pair.value = RISCV_HWPROBE_MISALIGNED_FAST;
74 break;
75 default:
76 TRACE("unsupported __riscv_hwprobe capability key: %ld", pair.key);
77 pair.key = -1;
78 pair.value = 0;
79 break;
80 }
81 }
82
RunGuestSyscall___NR_execveat(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)83 long RunGuestSyscall___NR_execveat(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
84 UNUSED(arg_1, arg_2, arg_3, arg_4, arg_5);
85 KAPI_TRACE("unimplemented syscall __NR_execveat");
86 errno = ENOSYS;
87 return -1;
88 }
89
RunGuestSyscall___NR_fadvise64(long arg_1,long arg_2,long arg_3,long arg_4)90 long RunGuestSyscall___NR_fadvise64(long arg_1, long arg_2, long arg_3, long arg_4) {
91 // on 64-bit architectures, sys_fadvise64 and sys_fadvise64_64 are equal.
92 return syscall(__NR_fadvise64, arg_1, arg_2, arg_3, arg_4);
93 }
94
RunGuestSyscall___NR_ioctl(long arg_1,long arg_2,long arg_3)95 long RunGuestSyscall___NR_ioctl(long arg_1, long arg_2, long arg_3) {
96 // TODO(b/128614662): translate!
97 KAPI_TRACE("unimplemented ioctl 0x%lx, running host syscall as is", arg_2);
98 return syscall(__NR_ioctl, arg_1, arg_2, arg_3);
99 }
100
RunGuestSyscall___NR_newfstatat(long arg_1,long arg_2,long arg_3,long arg_4)101 long RunGuestSyscall___NR_newfstatat(long arg_1, long arg_2, long arg_3, long arg_4) {
102 struct stat host_stat;
103 int result = FstatatForGuest(static_cast<int>(arg_1), // dirfd
104 bit_cast<const char*>(arg_2), // path
105 &host_stat,
106 static_cast<int>(arg_4)); // flags
107 if (result != -1) {
108 ConvertHostStatToGuestArch(host_stat, bit_cast<GuestAddr>(arg_3));
109 }
110 return result;
111 }
112
RunGuestSyscall___NR_riscv_hwprobe(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)113 long RunGuestSyscall___NR_riscv_hwprobe(long arg_1,
114 long arg_2,
115 long arg_3,
116 long arg_4,
117 long arg_5) {
118 UNUSED(arg_3, arg_4); // cpu_count, cpus_in
119
120 // There are currently no flags defined by the kernel. This may change in the future.
121 static constexpr unsigned int kFlagsAll = 0;
122
123 auto pairs = bit_cast<Guest_riscv_hwprobe*>(arg_1);
124 auto pair_count = bit_cast<size_t>(arg_2);
125 auto flags = static_cast<unsigned int>(bit_cast<unsigned long>(arg_5));
126 if ((flags & ~kFlagsAll) != 0) {
127 return -EINVAL;
128 }
129
130 for (size_t i = 0; i < pair_count; ++i) {
131 Hwprobe(pairs[i]);
132 }
133 return 0;
134 }
135
RunGuestSyscall___NR_riscv_flush_icache(long arg_1,long arg_2,long arg_3)136 long RunGuestSyscall___NR_riscv_flush_icache(long arg_1, long arg_2, long arg_3) {
137 static constexpr uint64_t kFlagsLocal = 1UL;
138 static constexpr uint64_t kFlagsAll = kFlagsLocal;
139
140 // ATTENTION: On RISC-V, arg_2 is the address range end, not the address range size.
141 auto start = bit_cast<GuestAddr>(arg_1);
142 auto end = bit_cast<GuestAddr>(arg_2);
143 auto flags = bit_cast<uint64_t>(arg_3);
144 if (end < start || (flags & ~kFlagsAll) != 0) {
145 errno = EINVAL;
146 return -1;
147 }
148
149 // Ignore kFlagsLocal because we do not have a per-thread cache to clear.
150 TRACE("icache flush: [0x%lx, 0x%lx)", start, end);
151 InvalidateGuestRange(start, end);
152 return 0;
153 }
154
155 // RunGuestSyscallImpl.
156 #include "gen_syscall_emulation_riscv64_to_x86_64-inl.h"
157
158 } // namespace
159
RunGuestSyscall(ThreadState * state)160 void RunGuestSyscall(ThreadState* state) {
161 // ATTENTION: run guest signal handlers instantly!
162 // If signal arrives while in a syscall, syscall should immediately return with EINTR.
163 // In this case pending signals are OK, as guest handlers will run on return from syscall.
164 // BUT, if signal action has SA_RESTART, certain syscalls will restart instead of returning.
165 // In this case, pending signals will never run...
166 ScopedPendingSignalsDisabler scoped_pending_signals_disabler(state->thread);
167 ScopedErrno scoped_errno;
168
169 long guest_nr = state->cpu.x[A7];
170 if (kInstrumentSyscalls) {
171 OnSyscall(state, guest_nr);
172 }
173
174 // RISCV Linux takes arguments in a0-a5 and syscall number in a7.
175 // TODO(b/161722184): if syscall is interrupted by signal, signal handler might overwrite the
176 // return value, so setting A0 here might be incorrect. Investigate!
177 long result = RunGuestSyscallImpl(guest_nr,
178 state->cpu.x[A0],
179 state->cpu.x[A1],
180 state->cpu.x[A2],
181 state->cpu.x[A3],
182 state->cpu.x[A4],
183 state->cpu.x[A5]);
184 if (result == -1) {
185 state->cpu.x[A0] = -errno;
186 } else {
187 state->cpu.x[A0] = result;
188 }
189
190 if (kInstrumentSyscalls) {
191 OnSyscallReturn(state, guest_nr);
192 }
193 }
194
195 } // namespace berberis
196