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 (11389B)


      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_ulong  sc_mask;
     27    abi_ulong  sc_usp;
     28    abi_ulong  sc_d0;
     29    abi_ulong  sc_d1;
     30    abi_ulong  sc_a0;
     31    abi_ulong  sc_a1;
     32    unsigned short sc_sr;
     33    abi_ulong  sc_pc;
     34};
     35
     36struct target_sigframe
     37{
     38    abi_ulong pretcode;
     39    int sig;
     40    int code;
     41    abi_ulong psc;
     42    abi_ulong extramask[TARGET_NSIG_WORDS-1];
     43    struct target_sigcontext sc;
     44};
     45
     46typedef int target_greg_t;
     47#define TARGET_NGREG 18
     48typedef target_greg_t target_gregset_t[TARGET_NGREG];
     49
     50typedef struct target_fpregset {
     51    int f_fpcntl[3];
     52    int f_fpregs[8*3];
     53} target_fpregset_t;
     54
     55struct target_mcontext {
     56    int version;
     57    target_gregset_t gregs;
     58    target_fpregset_t fpregs;
     59};
     60
     61#define TARGET_MCONTEXT_VERSION 2
     62
     63struct target_ucontext {
     64    abi_ulong tuc_flags;
     65    abi_ulong tuc_link;
     66    target_stack_t tuc_stack;
     67    struct target_mcontext tuc_mcontext;
     68    abi_long tuc_filler[80];
     69    target_sigset_t tuc_sigmask;
     70};
     71
     72struct target_rt_sigframe
     73{
     74    abi_ulong pretcode;
     75    int sig;
     76    abi_ulong pinfo;
     77    abi_ulong puc;
     78    struct target_siginfo info;
     79    struct target_ucontext uc;
     80};
     81
     82static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
     83                             abi_ulong mask)
     84{
     85    uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
     86    __put_user(mask, &sc->sc_mask);
     87    __put_user(env->aregs[7], &sc->sc_usp);
     88    __put_user(env->dregs[0], &sc->sc_d0);
     89    __put_user(env->dregs[1], &sc->sc_d1);
     90    __put_user(env->aregs[0], &sc->sc_a0);
     91    __put_user(env->aregs[1], &sc->sc_a1);
     92    __put_user(sr, &sc->sc_sr);
     93    __put_user(env->pc, &sc->sc_pc);
     94}
     95
     96static void
     97restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
     98{
     99    int temp;
    100
    101    __get_user(env->aregs[7], &sc->sc_usp);
    102    __get_user(env->dregs[0], &sc->sc_d0);
    103    __get_user(env->dregs[1], &sc->sc_d1);
    104    __get_user(env->aregs[0], &sc->sc_a0);
    105    __get_user(env->aregs[1], &sc->sc_a1);
    106    __get_user(env->pc, &sc->sc_pc);
    107    __get_user(temp, &sc->sc_sr);
    108    cpu_m68k_set_ccr(env, temp);
    109}
    110
    111/*
    112 * Determine which stack to use..
    113 */
    114static inline abi_ulong
    115get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
    116             size_t frame_size)
    117{
    118    abi_ulong sp;
    119
    120    sp = target_sigsp(get_sp_from_cpustate(regs), ka);
    121
    122
    123    return ((sp - frame_size) & -8UL);
    124}
    125
    126void setup_frame(int sig, struct target_sigaction *ka,
    127                 target_sigset_t *set, CPUM68KState *env)
    128{
    129    struct target_sigframe *frame;
    130    abi_ulong frame_addr;
    131    abi_ulong sc_addr;
    132    int i;
    133
    134    frame_addr = get_sigframe(ka, env, sizeof *frame);
    135    trace_user_setup_frame(env, frame_addr);
    136    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
    137        goto give_sigsegv;
    138    }
    139
    140    __put_user(sig, &frame->sig);
    141
    142    sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
    143    __put_user(sc_addr, &frame->psc);
    144
    145    setup_sigcontext(&frame->sc, env, set->sig[0]);
    146
    147    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
    148        __put_user(set->sig[i], &frame->extramask[i - 1]);
    149    }
    150
    151    /* Set up to return from userspace.  */
    152    __put_user(default_sigreturn, &frame->pretcode);
    153
    154    env->aregs[7] = frame_addr;
    155    env->pc = ka->_sa_handler;
    156
    157    unlock_user_struct(frame, frame_addr, 1);
    158    return;
    159
    160give_sigsegv:
    161    force_sigsegv(sig);
    162}
    163
    164static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
    165                                           CPUM68KState *env)
    166{
    167    int i;
    168    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
    169
    170    __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
    171    __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
    172    /* fpiar is not emulated */
    173
    174    for (i = 0; i < 8; i++) {
    175        uint32_t high = env->fregs[i].d.high << 16;
    176        __put_user(high, &fpregs->f_fpregs[i * 3]);
    177        __put_user(env->fregs[i].d.low,
    178                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
    179    }
    180}
    181
    182static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
    183                                           CPUM68KState *env)
    184{
    185    target_greg_t *gregs = uc->tuc_mcontext.gregs;
    186    uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
    187
    188    __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
    189    __put_user(env->dregs[0], &gregs[0]);
    190    __put_user(env->dregs[1], &gregs[1]);
    191    __put_user(env->dregs[2], &gregs[2]);
    192    __put_user(env->dregs[3], &gregs[3]);
    193    __put_user(env->dregs[4], &gregs[4]);
    194    __put_user(env->dregs[5], &gregs[5]);
    195    __put_user(env->dregs[6], &gregs[6]);
    196    __put_user(env->dregs[7], &gregs[7]);
    197    __put_user(env->aregs[0], &gregs[8]);
    198    __put_user(env->aregs[1], &gregs[9]);
    199    __put_user(env->aregs[2], &gregs[10]);
    200    __put_user(env->aregs[3], &gregs[11]);
    201    __put_user(env->aregs[4], &gregs[12]);
    202    __put_user(env->aregs[5], &gregs[13]);
    203    __put_user(env->aregs[6], &gregs[14]);
    204    __put_user(env->aregs[7], &gregs[15]);
    205    __put_user(env->pc, &gregs[16]);
    206    __put_user(sr, &gregs[17]);
    207
    208    target_rt_save_fpu_state(uc, env);
    209
    210    return 0;
    211}
    212
    213static inline void target_rt_restore_fpu_state(CPUM68KState *env,
    214                                               struct target_ucontext *uc)
    215{
    216    int i;
    217    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
    218    uint32_t fpcr;
    219
    220    __get_user(fpcr, &fpregs->f_fpcntl[0]);
    221    cpu_m68k_set_fpcr(env, fpcr);
    222    __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
    223    /* fpiar is not emulated */
    224
    225    for (i = 0; i < 8; i++) {
    226        uint32_t high;
    227        __get_user(high, &fpregs->f_fpregs[i * 3]);
    228        env->fregs[i].d.high = high >> 16;
    229        __get_user(env->fregs[i].d.low,
    230                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
    231    }
    232}
    233
    234static inline int target_rt_restore_ucontext(CPUM68KState *env,
    235                                             struct target_ucontext *uc)
    236{
    237    int temp;
    238    target_greg_t *gregs = uc->tuc_mcontext.gregs;
    239
    240    __get_user(temp, &uc->tuc_mcontext.version);
    241    if (temp != TARGET_MCONTEXT_VERSION)
    242        goto badframe;
    243
    244    /* restore passed registers */
    245    __get_user(env->dregs[0], &gregs[0]);
    246    __get_user(env->dregs[1], &gregs[1]);
    247    __get_user(env->dregs[2], &gregs[2]);
    248    __get_user(env->dregs[3], &gregs[3]);
    249    __get_user(env->dregs[4], &gregs[4]);
    250    __get_user(env->dregs[5], &gregs[5]);
    251    __get_user(env->dregs[6], &gregs[6]);
    252    __get_user(env->dregs[7], &gregs[7]);
    253    __get_user(env->aregs[0], &gregs[8]);
    254    __get_user(env->aregs[1], &gregs[9]);
    255    __get_user(env->aregs[2], &gregs[10]);
    256    __get_user(env->aregs[3], &gregs[11]);
    257    __get_user(env->aregs[4], &gregs[12]);
    258    __get_user(env->aregs[5], &gregs[13]);
    259    __get_user(env->aregs[6], &gregs[14]);
    260    __get_user(env->aregs[7], &gregs[15]);
    261    __get_user(env->pc, &gregs[16]);
    262    __get_user(temp, &gregs[17]);
    263    cpu_m68k_set_ccr(env, temp);
    264
    265    target_rt_restore_fpu_state(env, uc);
    266
    267    return 0;
    268
    269badframe:
    270    return 1;
    271}
    272
    273void setup_rt_frame(int sig, struct target_sigaction *ka,
    274                    target_siginfo_t *info,
    275                    target_sigset_t *set, CPUM68KState *env)
    276{
    277    struct target_rt_sigframe *frame;
    278    abi_ulong frame_addr;
    279    abi_ulong info_addr;
    280    abi_ulong uc_addr;
    281    int err = 0;
    282    int i;
    283
    284    frame_addr = get_sigframe(ka, env, sizeof *frame);
    285    trace_user_setup_rt_frame(env, frame_addr);
    286    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
    287        goto give_sigsegv;
    288    }
    289
    290    __put_user(sig, &frame->sig);
    291
    292    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
    293    __put_user(info_addr, &frame->pinfo);
    294
    295    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
    296    __put_user(uc_addr, &frame->puc);
    297
    298    tswap_siginfo(&frame->info, info);
    299
    300    /* Create the ucontext */
    301
    302    __put_user(0, &frame->uc.tuc_flags);
    303    __put_user(0, &frame->uc.tuc_link);
    304    target_save_altstack(&frame->uc.tuc_stack, env);
    305    err |= target_rt_setup_ucontext(&frame->uc, env);
    306
    307    if (err)
    308        goto give_sigsegv;
    309
    310    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
    311        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
    312    }
    313
    314    /* Set up to return from userspace.  */
    315    __put_user(default_rt_sigreturn, &frame->pretcode);
    316
    317    env->aregs[7] = frame_addr;
    318    env->pc = ka->_sa_handler;
    319
    320    unlock_user_struct(frame, frame_addr, 1);
    321    return;
    322
    323give_sigsegv:
    324    unlock_user_struct(frame, frame_addr, 1);
    325    force_sigsegv(sig);
    326}
    327
    328long do_sigreturn(CPUM68KState *env)
    329{
    330    struct target_sigframe *frame;
    331    abi_ulong frame_addr = env->aregs[7] - 4;
    332    target_sigset_t target_set;
    333    sigset_t set;
    334    int i;
    335
    336    trace_user_do_sigreturn(env, frame_addr);
    337    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
    338        goto badframe;
    339
    340    /* set blocked signals */
    341
    342    __get_user(target_set.sig[0], &frame->sc.sc_mask);
    343
    344    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
    345        __get_user(target_set.sig[i], &frame->extramask[i - 1]);
    346    }
    347
    348    target_to_host_sigset_internal(&set, &target_set);
    349    set_sigmask(&set);
    350
    351    /* restore registers */
    352
    353    restore_sigcontext(env, &frame->sc);
    354
    355    unlock_user_struct(frame, frame_addr, 0);
    356    return -TARGET_QEMU_ESIGRETURN;
    357
    358badframe:
    359    force_sig(TARGET_SIGSEGV);
    360    return -TARGET_QEMU_ESIGRETURN;
    361}
    362
    363long do_rt_sigreturn(CPUM68KState *env)
    364{
    365    struct target_rt_sigframe *frame;
    366    abi_ulong frame_addr = env->aregs[7] - 4;
    367    sigset_t set;
    368
    369    trace_user_do_rt_sigreturn(env, frame_addr);
    370    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
    371        goto badframe;
    372
    373    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
    374    set_sigmask(&set);
    375
    376    /* restore registers */
    377
    378    if (target_rt_restore_ucontext(env, &frame->uc))
    379        goto badframe;
    380
    381    target_restore_altstack(&frame->uc.tuc_stack, env);
    382
    383    unlock_user_struct(frame, frame_addr, 0);
    384    return -TARGET_QEMU_ESIGRETURN;
    385
    386badframe:
    387    unlock_user_struct(frame, frame_addr, 0);
    388    force_sig(TARGET_SIGSEGV);
    389    return -TARGET_QEMU_ESIGRETURN;
    390}
    391
    392void setup_sigtramp(abi_ulong sigtramp_page)
    393{
    394    void *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 4 + 6, 0);
    395    assert(tramp != NULL);
    396
    397    default_sigreturn = sigtramp_page;
    398
    399    /* moveq #,d0; trap #0 */
    400    __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), (uint32_t *)tramp);
    401
    402    default_rt_sigreturn = sigtramp_page + 4;
    403
    404    /* moveq #,d0; notb d0; trap #0 */
    405    __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
    406               (uint32_t *)(tramp + 4));
    407    __put_user(0x4e40, (uint16_t *)(tramp + 8));
    408
    409    unlock_user(tramp, sigtramp_page, 4 + 6);
    410}