/*
 *  Emulation of Linux signals
 *
 *  Copyright (c) 2003 Fabrice Bellard
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
#include "qemu/osdep.h"
#include "qemu.h"
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
#include "vdso-asmoffset.h"

/* Signal handler invocation must be transparent for the code being
   interrupted. Complete CPU (hart) state is saved on entry and restored
   before returning from the handler. Process sigmask is also saved to block
   signals while the handler is running. The handler gets its own stack,
   which also doubles as storage for the CPU state and sigmask.

   The code below is qemu re-implementation of arch/riscv/kernel/signal.c */

struct target_sigcontext {
    abi_long pc;
    abi_long gpr[31]; /* x0 is not present, so all offsets must be -1 */
    uint64_t fpr[32];
    uint32_t fcsr;
}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */

QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, fpr) != offsetof_freg0);

struct target_ucontext {
    abi_ulong uc_flags;
    abi_ptr uc_link;
    target_stack_t uc_stack;
    target_sigset_t uc_sigmask;
    uint8_t   __unused[1024 / 8 - sizeof(target_sigset_t)];
    struct target_sigcontext uc_mcontext QEMU_ALIGNED(16);
};

struct target_rt_sigframe {
    struct target_siginfo info;
    struct target_ucontext uc;
};

QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe)
                  != sizeof_rt_sigframe);
QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.uc_mcontext)
                  != offsetof_uc_mcontext);

static abi_ulong get_sigframe(struct target_sigaction *ka,
                              CPURISCVState *regs, size_t framesize)
{
    abi_ulong sp = get_sp_from_cpustate(regs);

    /* If we are on the alternate signal stack and would overflow it, don't.
       Return an always-bogus address instead so we will die with SIGSEGV. */
    if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) {
        return -1L;
    }

    /* This is the X/Open sanctioned signal stack switching.  */
    sp = target_sigsp(sp, ka) - framesize;
    sp &= ~0xf;

    return sp;
}

static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
{
    int i;

    __put_user(env->pc, &sc->pc);

    for (i = 1; i < 32; i++) {
        __put_user(env->gpr[i], &sc->gpr[i - 1]);
    }
    for (i = 0; i < 32; i++) {
        __put_user(env->fpr[i], &sc->fpr[i]);
    }

    uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
    __put_user(fcsr, &sc->fcsr);
}

static void setup_ucontext(struct target_ucontext *uc,
                           CPURISCVState *env, target_sigset_t *set)
{
    __put_user(0,    &(uc->uc_flags));
    __put_user(0,    &(uc->uc_link));

    target_save_altstack(&uc->uc_stack, env);

    int i;
    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
        __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
    }

    setup_sigcontext(&uc->uc_mcontext, env);
}

void setup_rt_frame(int sig, struct target_sigaction *ka,
                    target_siginfo_t *info,
                    target_sigset_t *set, CPURISCVState *env)
{
    abi_ulong frame_addr;
    struct target_rt_sigframe *frame;

    frame_addr = get_sigframe(ka, env, sizeof(*frame));
    trace_user_setup_rt_frame(env, frame_addr);

    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
        goto badframe;
    }

    setup_ucontext(&frame->uc, env, set);
    frame->info = *info;

    env->pc = ka->_sa_handler;
    env->gpr[xSP] = frame_addr;
    env->gpr[xA0] = sig;
    env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
    env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
    env->gpr[xRA] = default_rt_sigreturn;

    return;

badframe:
    unlock_user_struct(frame, frame_addr, 1);
    if (sig == TARGET_SIGSEGV) {
        ka->_sa_handler = TARGET_SIG_DFL;
    }
    force_sig(TARGET_SIGSEGV);
}

static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
{
    int i;

    __get_user(env->pc, &sc->pc);

    for (i = 1; i < 32; ++i) {
        __get_user(env->gpr[i], &sc->gpr[i - 1]);
    }
    for (i = 0; i < 32; ++i) {
        __get_user(env->fpr[i], &sc->fpr[i]);
    }

    uint32_t fcsr;
    __get_user(fcsr, &sc->fcsr);
    riscv_csr_write(env, CSR_FCSR, fcsr);
}

static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
{
    sigset_t blocked;
    target_sigset_t target_set;
    int i;

    target_sigemptyset(&target_set);
    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
        __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
    }

    target_to_host_sigset_internal(&blocked, &target_set);
    set_sigmask(&blocked);

    restore_sigcontext(env, &uc->uc_mcontext);
}

long do_rt_sigreturn(CPURISCVState *env)
{
    struct target_rt_sigframe *frame;
    abi_ulong frame_addr;

    frame_addr = env->gpr[xSP];
    trace_user_do_sigreturn(env, frame_addr);
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
        goto badframe;
    }

    restore_ucontext(env, &frame->uc);
    target_restore_altstack(&frame->uc.uc_stack, env);

    unlock_user_struct(frame, frame_addr, 0);
    return -QEMU_ESIGRETURN;

badframe:
    unlock_user_struct(frame, frame_addr, 0);
    force_sig(TARGET_SIGSEGV);
    return 0;
}

void setup_sigtramp(abi_ulong sigtramp_page)
{
    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
    assert(tramp != NULL);

    __put_user(0x08b00893, tramp + 0);  /* li a7, 139 = __NR_rt_sigreturn */
    __put_user(0x00000073, tramp + 1);  /* ecall */

    default_rt_sigreturn = sigtramp_page;
    unlock_user(tramp, sigtramp_page, 8);
}
