| /* |
| * Copyright (C) 2023 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "berberis/kernel_api/runtime_bridge.h" |
| |
| #include <cerrno> |
| #include <cstdlib> |
| |
| #include "berberis/base/bit_util.h" |
| #include "berberis/base/config.h" |
| #include "berberis/base/tracing.h" |
| #include "berberis/guest_os_primitives/guest_signal.h" |
| #include "berberis/guest_os_primitives/guest_thread.h" |
| #include "berberis/guest_os_primitives/guest_thread_manager.h" |
| #include "berberis/kernel_api/sys_mman_emulation.h" |
| |
| #include "sigevent_emulation.h" |
| |
| namespace berberis { |
| |
| long RunGuestSyscall___NR_rt_sigaction(long sig_num_arg, |
| long act_arg, |
| long old_act_arg, |
| long sigset_size_arg) { |
| TRACE("'rt_sigaction' called for signal %ld", sig_num_arg); |
| int sig_num = static_cast<int>(sig_num_arg); |
| const Guest_sigaction* act = bit_cast<const Guest_sigaction*>(act_arg); |
| Guest_sigaction* old_act = bit_cast<Guest_sigaction*>(old_act_arg); |
| size_t sigset_size = bit_cast<size_t>(sigset_size_arg); |
| |
| if (sigset_size != sizeof(Guest_sigset_t)) { |
| errno = EINVAL; |
| return -1; |
| } |
| |
| int error; |
| if (SetGuestSignalHandler(sig_num, act, old_act, &error)) { |
| return 0; |
| } |
| errno = error; |
| return -1; |
| } |
| |
| long RunGuestSyscall___NR_sigaltstack(long stack, long old_stack) { |
| int error; |
| if (GetCurrentGuestThread()->SigAltStack( |
| bit_cast<const stack_t*>(stack), bit_cast<stack_t*>(old_stack), &error)) { |
| return 0; |
| } |
| errno = error; |
| return -1; |
| } |
| |
| long RunGuestSyscall___NR_timer_create(long arg_1, long arg_2, long arg_3) { |
| struct sigevent host_sigevent; |
| return syscall(__NR_timer_create, |
| arg_1, |
| ConvertGuestSigeventToHost(bit_cast<struct sigevent*>(arg_2), &host_sigevent), |
| arg_3); |
| } |
| |
| long RunGuestSyscall___NR_exit(long code) { |
| ExitCurrentThread(code); |
| return 0; |
| } |
| |
| long RunGuestSyscall___NR_clone(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) { |
| // NOTE: clone syscall argument ordering is architecture dependent. This implementation assumes |
| // CLONE_BACKWARDS is enabled (tls before child_tid), which is true for both x86 and RISC-V. |
| return CloneGuestThread(GetCurrentGuestThread(), arg_1, arg_2, arg_3, arg_4, arg_5); |
| } |
| |
| long RunGuestSyscall___NR_mmap(long arg_1, |
| long arg_2, |
| long arg_3, |
| long arg_4, |
| long arg_5, |
| long arg_6) { |
| return bit_cast<long>(MmapForGuest(bit_cast<void*>(arg_1), // addr |
| bit_cast<size_t>(arg_2), // length |
| static_cast<int>(arg_3), // prot |
| static_cast<int>(arg_4), // flags |
| static_cast<int>(arg_5), // fd |
| static_cast<off64_t>(arg_6))); // offset |
| } |
| |
| long RunGuestSyscall___NR_mmap2(long arg_1, |
| long arg_2, |
| long arg_3, |
| long arg_4, |
| long arg_5, |
| long arg_6) { |
| return bit_cast<long>( |
| MmapForGuest(bit_cast<void*>(arg_1), // addr |
| bit_cast<size_t>(arg_2), // length |
| static_cast<int>(arg_3), // prot |
| static_cast<int>(arg_4), // flags |
| static_cast<int>(arg_5), // fd |
| static_cast<off64_t>(arg_6) * config::kGuestPageSize)); // pgoffset to offset |
| } |
| |
| long RunGuestSyscall___NR_munmap(long arg_1, long arg_2) { |
| return static_cast<long>(MunmapForGuest(bit_cast<void*>(arg_1), // addr |
| bit_cast<size_t>(arg_2))); // length |
| } |
| |
| long RunGuestSyscall___NR_mprotect(long arg_1, long arg_2, long arg_3) { |
| return static_cast<long>(MprotectForGuest(bit_cast<void*>(arg_1), // addr |
| bit_cast<size_t>(arg_2), // length |
| static_cast<int>(arg_3))); // prot |
| } |
| |
| long RunGuestSyscall___NR_mremap(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) { |
| return bit_cast<long>(MremapForGuest(bit_cast<void*>(arg_1), // old_addr |
| bit_cast<size_t>(arg_2), // old_size |
| bit_cast<size_t>(arg_3), // new_size |
| static_cast<int>(arg_4), // flags |
| bit_cast<void*>(arg_5))); // new_addr |
| } |
| |
| } // namespace berberis |