/*
 *  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"

typedef struct target_sigcontext {
    struct target_pt_regs regs;
    abi_ulong oldmask;
} target_sigcontext;

typedef struct target_ucontext {
    abi_ulong tuc_flags;
    abi_ulong tuc_link;
    target_stack_t tuc_stack;
    target_sigcontext tuc_mcontext;
    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
} target_ucontext;

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

static void restore_sigcontext(CPUOpenRISCState *env, target_sigcontext *sc)
{
    int i;
    abi_ulong v;

    for (i = 0; i < 32; ++i) {
        __get_user(v, &sc->regs.gpr[i]);
        cpu_set_gpr(env, i, v);
    }
    __get_user(env->pc, &sc->regs.pc);

    /* Make sure the supervisor flag is clear.  */
    __get_user(v, &sc->regs.sr);
    cpu_set_sr(env, v & ~SR_SM);
}

/* Set up a signal frame.  */

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

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

    __put_user(env->pc, &sc->regs.pc);
    __put_user(cpu_get_sr(env), &sc->regs.sr);
}

static inline abi_ulong get_sigframe(struct target_sigaction *ka,
                                     CPUOpenRISCState *env,
                                     size_t frame_size)
{
    target_ulong sp = get_sp_from_cpustate(env);

    /* Honor redzone now.  If we swap to signal stack, no need to waste
     * the 128 bytes by subtracting afterward.
     */
    sp -= 128;

    sp = target_sigsp(sp, ka);
    sp -= frame_size;
    sp = QEMU_ALIGN_DOWN(sp, 4);

    return sp;
}

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

    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 give_sigsegv;
    }

    if (ka->sa_flags & SA_SIGINFO) {
        tswap_siginfo(&frame->info, info);
    }

    __put_user(0, &frame->uc.tuc_flags);
    __put_user(0, &frame->uc.tuc_link);

    target_save_altstack(&frame->uc.tuc_stack, env);
    setup_sigcontext(&frame->uc.tuc_mcontext, env);
    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
    }

    /* Set up registers for signal handler */
    cpu_set_gpr(env, 9, default_rt_sigreturn);
    cpu_set_gpr(env, 3, sig);
    cpu_set_gpr(env, 4, frame_addr + offsetof(target_rt_sigframe, info));
    cpu_set_gpr(env, 5, frame_addr + offsetof(target_rt_sigframe, uc));
    cpu_set_gpr(env, 1, frame_addr);

    /* For debugging convenience, set ppc to the insn that faulted.  */
    env->ppc = env->pc;
    /* When setting the PC for the signal handler, exit delay slot.  */
    env->pc = ka->_sa_handler;
    env->dflag = 0;
    return;

give_sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sigsegv(sig);
}

long do_rt_sigreturn(CPUOpenRISCState *env)
{
    abi_ulong frame_addr = get_sp_from_cpustate(env);
    target_rt_sigframe *frame;
    sigset_t set;

    trace_user_do_rt_sigreturn(env, 0);
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
        goto badframe;
    }
    if (frame_addr & 3) {
        goto badframe;
    }

    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
    set_sigmask(&set);

    restore_sigcontext(env, &frame->uc.tuc_mcontext);
    target_restore_altstack(&frame->uc.tuc_stack, env);

    unlock_user_struct(frame, frame_addr, 0);
    return cpu_get_gpr(env, 11);

 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);

    /* This is l.ori r11,r0,__NR_sigreturn; l.sys 1 */
    __put_user(0xa9600000 | TARGET_NR_rt_sigreturn, tramp + 0);
    __put_user(0x20000001, tramp + 1);

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