cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

signal.c (7603B)


      1/*
      2 *  Emulation of Linux signals
      3 *
      4 *  Copyright (c) 2003 Fabrice Bellard
      5 *
      6 *  This program is free software; you can redistribute it and/or modify
      7 *  it under the terms of the GNU General Public License as published by
      8 *  the Free Software Foundation; either version 2 of the License, or
      9 *  (at your option) any later version.
     10 *
     11 *  This program is distributed in the hope that it will be useful,
     12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 *  GNU General Public License for more details.
     15 *
     16 *  You should have received a copy of the GNU General Public License
     17 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19#include "qemu/osdep.h"
     20#include "qemu.h"
     21#include "user-internals.h"
     22#include "signal-common.h"
     23#include "linux-user/trace.h"
     24
     25struct target_sigcontext {
     26    abi_long sc_onstack;
     27    abi_long sc_mask;
     28    abi_long sc_pc;
     29    abi_long sc_ps;
     30    abi_long sc_regs[32];
     31    abi_long sc_ownedfp;
     32    abi_long sc_fpregs[32];
     33    abi_ulong sc_fpcr;
     34    abi_ulong sc_fp_control;
     35    abi_ulong sc_reserved1;
     36    abi_ulong sc_reserved2;
     37    abi_ulong sc_ssize;
     38    abi_ulong sc_sbase;
     39    abi_ulong sc_traparg_a0;
     40    abi_ulong sc_traparg_a1;
     41    abi_ulong sc_traparg_a2;
     42    abi_ulong sc_fp_trap_pc;
     43    abi_ulong sc_fp_trigger_sum;
     44    abi_ulong sc_fp_trigger_inst;
     45};
     46
     47struct target_ucontext {
     48    abi_ulong tuc_flags;
     49    abi_ulong tuc_link;
     50    abi_ulong tuc_osf_sigmask;
     51    target_stack_t tuc_stack;
     52    struct target_sigcontext tuc_mcontext;
     53    target_sigset_t tuc_sigmask;
     54};
     55
     56struct target_sigframe {
     57    struct target_sigcontext sc;
     58};
     59
     60struct target_rt_sigframe {
     61    target_siginfo_t info;
     62    struct target_ucontext uc;
     63};
     64
     65#define INSN_MOV_R30_R16        0x47fe0410
     66#define INSN_LDI_R0             0x201f0000
     67#define INSN_CALLSYS            0x00000083
     68
     69static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
     70                             abi_ulong frame_addr, target_sigset_t *set)
     71{
     72    int i;
     73
     74    __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
     75    __put_user(set->sig[0], &sc->sc_mask);
     76    __put_user(env->pc, &sc->sc_pc);
     77    __put_user(8, &sc->sc_ps);
     78
     79    for (i = 0; i < 31; ++i) {
     80        __put_user(env->ir[i], &sc->sc_regs[i]);
     81    }
     82    __put_user(0, &sc->sc_regs[31]);
     83
     84    for (i = 0; i < 31; ++i) {
     85        __put_user(env->fir[i], &sc->sc_fpregs[i]);
     86    }
     87    __put_user(0, &sc->sc_fpregs[31]);
     88    __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
     89
     90    __put_user(0, &sc->sc_traparg_a0); /* FIXME */
     91    __put_user(0, &sc->sc_traparg_a1); /* FIXME */
     92    __put_user(0, &sc->sc_traparg_a2); /* FIXME */
     93}
     94
     95static void restore_sigcontext(CPUAlphaState *env,
     96                               struct target_sigcontext *sc)
     97{
     98    uint64_t fpcr;
     99    int i;
    100
    101    __get_user(env->pc, &sc->sc_pc);
    102
    103    for (i = 0; i < 31; ++i) {
    104        __get_user(env->ir[i], &sc->sc_regs[i]);
    105    }
    106    for (i = 0; i < 31; ++i) {
    107        __get_user(env->fir[i], &sc->sc_fpregs[i]);
    108    }
    109
    110    __get_user(fpcr, &sc->sc_fpcr);
    111    cpu_alpha_store_fpcr(env, fpcr);
    112}
    113
    114static inline abi_ulong get_sigframe(struct target_sigaction *sa,
    115                                     CPUAlphaState *env,
    116                                     unsigned long framesize)
    117{
    118    abi_ulong sp;
    119
    120    sp = target_sigsp(get_sp_from_cpustate(env), sa);
    121
    122    return (sp - framesize) & -32;
    123}
    124
    125void setup_frame(int sig, struct target_sigaction *ka,
    126                 target_sigset_t *set, CPUAlphaState *env)
    127{
    128    abi_ulong frame_addr, r26;
    129    struct target_sigframe *frame;
    130    int err = 0;
    131
    132    frame_addr = get_sigframe(ka, env, sizeof(*frame));
    133    trace_user_setup_frame(env, frame_addr);
    134    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
    135        goto give_sigsegv;
    136    }
    137
    138    setup_sigcontext(&frame->sc, env, frame_addr, set);
    139
    140    if (ka->ka_restorer) {
    141        r26 = ka->ka_restorer;
    142    } else {
    143        r26 = default_sigreturn;
    144    }
    145
    146    unlock_user_struct(frame, frame_addr, 1);
    147
    148    if (err) {
    149give_sigsegv:
    150        force_sigsegv(sig);
    151        return;
    152    }
    153
    154    env->ir[IR_RA] = r26;
    155    env->ir[IR_PV] = env->pc = ka->_sa_handler;
    156    env->ir[IR_A0] = sig;
    157    env->ir[IR_A1] = 0;
    158    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
    159    env->ir[IR_SP] = frame_addr;
    160}
    161
    162void setup_rt_frame(int sig, struct target_sigaction *ka,
    163                    target_siginfo_t *info,
    164                    target_sigset_t *set, CPUAlphaState *env)
    165{
    166    abi_ulong frame_addr, r26;
    167    struct target_rt_sigframe *frame;
    168    int i, err = 0;
    169
    170    frame_addr = get_sigframe(ka, env, sizeof(*frame));
    171    trace_user_setup_rt_frame(env, frame_addr);
    172    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
    173        goto give_sigsegv;
    174    }
    175
    176    tswap_siginfo(&frame->info, info);
    177
    178    __put_user(0, &frame->uc.tuc_flags);
    179    __put_user(0, &frame->uc.tuc_link);
    180    __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
    181
    182    target_save_altstack(&frame->uc.tuc_stack, env);
    183
    184    setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
    185    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
    186        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
    187    }
    188
    189    if (ka->ka_restorer) {
    190        r26 = ka->ka_restorer;
    191    } else {
    192        r26 = default_rt_sigreturn;
    193    }
    194
    195    if (err) {
    196give_sigsegv:
    197        force_sigsegv(sig);
    198        return;
    199    }
    200
    201    env->ir[IR_RA] = r26;
    202    env->ir[IR_PV] = env->pc = ka->_sa_handler;
    203    env->ir[IR_A0] = sig;
    204    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
    205    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
    206    env->ir[IR_SP] = frame_addr;
    207}
    208
    209long do_sigreturn(CPUAlphaState *env)
    210{
    211    struct target_sigcontext *sc;
    212    abi_ulong sc_addr = env->ir[IR_A0];
    213    target_sigset_t target_set;
    214    sigset_t set;
    215
    216    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
    217        goto badframe;
    218    }
    219
    220    target_sigemptyset(&target_set);
    221    __get_user(target_set.sig[0], &sc->sc_mask);
    222
    223    target_to_host_sigset_internal(&set, &target_set);
    224    set_sigmask(&set);
    225
    226    restore_sigcontext(env, sc);
    227    unlock_user_struct(sc, sc_addr, 0);
    228    return -TARGET_QEMU_ESIGRETURN;
    229
    230badframe:
    231    force_sig(TARGET_SIGSEGV);
    232    return -TARGET_QEMU_ESIGRETURN;
    233}
    234
    235long do_rt_sigreturn(CPUAlphaState *env)
    236{
    237    abi_ulong frame_addr = env->ir[IR_A0];
    238    struct target_rt_sigframe *frame;
    239    sigset_t set;
    240
    241    trace_user_do_rt_sigreturn(env, frame_addr);
    242    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
    243        goto badframe;
    244    }
    245    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
    246    set_sigmask(&set);
    247
    248    restore_sigcontext(env, &frame->uc.tuc_mcontext);
    249    target_restore_altstack(&frame->uc.tuc_stack, env);
    250
    251    unlock_user_struct(frame, frame_addr, 0);
    252    return -TARGET_QEMU_ESIGRETURN;
    253
    254
    255badframe:
    256    unlock_user_struct(frame, frame_addr, 0);
    257    force_sig(TARGET_SIGSEGV);
    258    return -TARGET_QEMU_ESIGRETURN;
    259}
    260
    261void setup_sigtramp(abi_ulong sigtramp_page)
    262{
    263    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6 * 4, 0);
    264    assert(tramp != NULL);
    265
    266    default_sigreturn = sigtramp_page;
    267    __put_user(INSN_MOV_R30_R16, &tramp[0]);
    268    __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, &tramp[1]);
    269    __put_user(INSN_CALLSYS, &tramp[2]);
    270
    271    default_rt_sigreturn = sigtramp_page + 3 * 4;
    272    __put_user(INSN_MOV_R30_R16, &tramp[3]);
    273    __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, &tramp[4]);
    274    __put_user(INSN_CALLSYS, &tramp[5]);
    275
    276    unlock_user(tramp, sigtramp_page, 6 * 4);
    277}