blob: fae081205560d260f035144451d1f5fef604858f [file] [log] [blame]
/*
* 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.
*/
#ifndef BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_
#define BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_
#include <csignal>
#include <cstring>
#include "berberis/base/struct_check.h"
#include "berberis/guest_state/guest_addr.h"
namespace berberis {
// Maximum number of signals for the guest kernel.
constexpr int Guest__KERNEL__NSIG = 64;
const GuestAddr Guest_SIG_DFL = 0;
const GuestAddr Guest_SIG_IGN = 1;
const GuestAddr Guest_SIG_ERR = -1;
// Guest siginfo_t, as expected by guest rt_sigqueueinfo syscall.
using Guest_siginfo_t = siginfo_t;
// Guest sigset_t, as expected by guest rt_sigprocmask syscall.
#if defined(BERBERIS_GUEST_LP64)
typedef struct {
unsigned long __bits[1];
} Guest_sigset_t;
CHECK_STRUCT_LAYOUT(Guest_sigset_t, 64, 64);
#else
// TODO(b/283352810): Explicitly support ILP32 guest data model.
// This condition currently assumes ILP32 support.
typedef struct {
unsigned long __bits[2];
} Guest_sigset_t;
CHECK_STRUCT_LAYOUT(Guest_sigset_t, 64, 32);
#endif
// TODO(b/280551353): check other SA_* flags!
static_assert(SA_NODEFER == 0x40000000, "Host and guest SA_NODEFER don't match");
template <typename SmallSigset, typename BigSigset>
inline void ConvertToSmallSigset(const BigSigset& big_sigset, SmallSigset* small_sigset) {
static_assert(sizeof(SmallSigset) <= sizeof(BigSigset), "wrong sigset size");
memcpy(small_sigset, &big_sigset, sizeof(SmallSigset));
}
template <typename SmallSigset, typename BigSigset>
inline void ConvertToBigSigset(const SmallSigset& small_sigset, BigSigset* big_sigset) {
static_assert(sizeof(SmallSigset) <= sizeof(BigSigset), "wrong sigset size");
memset(big_sigset, 0, sizeof(BigSigset));
memcpy(big_sigset, &small_sigset, sizeof(SmallSigset));
}
// TODO(b/283697533): Define Guest_sigaction differently depending on guest platform.
// Guest struct (__kernel_)sigaction, as expected by rt_sigaction syscall.
struct Guest_sigaction {
// Prefix avoids conflict with original 'sa_sigaction' defined as macro.
GuestAddr guest_sa_sigaction;
unsigned long sa_flags;
Guest_sigset_t sa_mask;
};
#if defined(BERBERIS_GUEST_LP64)
CHECK_STRUCT_LAYOUT(Guest_sigaction, 192, 64);
CHECK_FIELD_LAYOUT(Guest_sigaction, guest_sa_sigaction, 0, 64);
CHECK_FIELD_LAYOUT(Guest_sigaction, sa_flags, 64, 64);
CHECK_FIELD_LAYOUT(Guest_sigaction, sa_mask, 128, 64);
#endif
// TODO(b/283352810): Add checks for ILP32 guest data model.
struct Guest_sigaction;
bool SetGuestSignalHandler(int signal,
const Guest_sigaction* act,
Guest_sigaction* old_act,
int* error);
} // namespace berberis
#endif // BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_