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


      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    uint64_t fault_address;
     27    /* AArch64 registers */
     28    uint64_t regs[31];
     29    uint64_t sp;
     30    uint64_t pc;
     31    uint64_t pstate;
     32    /* 4K reserved for FP/SIMD state and future expansion */
     33    char __reserved[4096] __attribute__((__aligned__(16)));
     34};
     35
     36struct target_ucontext {
     37    abi_ulong tuc_flags;
     38    abi_ulong tuc_link;
     39    target_stack_t tuc_stack;
     40    target_sigset_t tuc_sigmask;
     41    /* glibc uses a 1024-bit sigset_t */
     42    char __unused[1024 / 8 - sizeof(target_sigset_t)];
     43    /* last for future expansion */
     44    struct target_sigcontext tuc_mcontext;
     45};
     46
     47/*
     48 * Header to be used at the beginning of structures extending the user
     49 * context. Such structures must be placed after the rt_sigframe on the stack
     50 * and be 16-byte aligned. The last structure must be a dummy one with the
     51 * magic and size set to 0.
     52 */
     53struct target_aarch64_ctx {
     54    uint32_t magic;
     55    uint32_t size;
     56};
     57
     58#define TARGET_FPSIMD_MAGIC 0x46508001
     59
     60struct target_fpsimd_context {
     61    struct target_aarch64_ctx head;
     62    uint32_t fpsr;
     63    uint32_t fpcr;
     64    uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
     65};
     66
     67#define TARGET_EXTRA_MAGIC  0x45585401
     68
     69struct target_extra_context {
     70    struct target_aarch64_ctx head;
     71    uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
     72    uint32_t size; /* size in bytes of the extra space */
     73    uint32_t reserved[3];
     74};
     75
     76#define TARGET_SVE_MAGIC    0x53564501
     77
     78struct target_sve_context {
     79    struct target_aarch64_ctx head;
     80    uint16_t vl;
     81    uint16_t reserved[3];
     82    /* The actual SVE data immediately follows.  It is laid out
     83     * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
     84     * the original struct pointer.
     85     */
     86};
     87
     88#define TARGET_SVE_VQ_BYTES  16
     89
     90#define TARGET_SVE_SIG_ZREG_SIZE(VQ)  ((VQ) * TARGET_SVE_VQ_BYTES)
     91#define TARGET_SVE_SIG_PREG_SIZE(VQ)  ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
     92
     93#define TARGET_SVE_SIG_REGS_OFFSET \
     94    QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
     95#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
     96    (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
     97#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
     98    (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
     99#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
    100    (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
    101#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
    102    (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
    103
    104struct target_rt_sigframe {
    105    struct target_siginfo info;
    106    struct target_ucontext uc;
    107};
    108
    109struct target_rt_frame_record {
    110    uint64_t fp;
    111    uint64_t lr;
    112};
    113
    114static void target_setup_general_frame(struct target_rt_sigframe *sf,
    115                                       CPUARMState *env, target_sigset_t *set)
    116{
    117    int i;
    118
    119    __put_user(0, &sf->uc.tuc_flags);
    120    __put_user(0, &sf->uc.tuc_link);
    121
    122    target_save_altstack(&sf->uc.tuc_stack, env);
    123
    124    for (i = 0; i < 31; i++) {
    125        __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
    126    }
    127    __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
    128    __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
    129    __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
    130
    131    __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
    132
    133    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
    134        __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
    135    }
    136}
    137
    138static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
    139                                       CPUARMState *env)
    140{
    141    int i;
    142
    143    __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
    144    __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
    145    __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
    146    __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
    147
    148    for (i = 0; i < 32; i++) {
    149        uint64_t *q = aa64_vfp_qreg(env, i);
    150#ifdef TARGET_WORDS_BIGENDIAN
    151        __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
    152        __put_user(q[1], &fpsimd->vregs[i * 2]);
    153#else
    154        __put_user(q[0], &fpsimd->vregs[i * 2]);
    155        __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
    156#endif
    157    }
    158}
    159
    160static void target_setup_extra_record(struct target_extra_context *extra,
    161                                      uint64_t datap, uint32_t extra_size)
    162{
    163    __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
    164    __put_user(sizeof(struct target_extra_context), &extra->head.size);
    165    __put_user(datap, &extra->datap);
    166    __put_user(extra_size, &extra->size);
    167}
    168
    169static void target_setup_end_record(struct target_aarch64_ctx *end)
    170{
    171    __put_user(0, &end->magic);
    172    __put_user(0, &end->size);
    173}
    174
    175static void target_setup_sve_record(struct target_sve_context *sve,
    176                                    CPUARMState *env, int vq, int size)
    177{
    178    int i, j;
    179
    180    __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
    181    __put_user(size, &sve->head.size);
    182    __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
    183
    184    /* Note that SVE regs are stored as a byte stream, with each byte element
    185     * at a subsequent address.  This corresponds to a little-endian store
    186     * of our 64-bit hunks.
    187     */
    188    for (i = 0; i < 32; ++i) {
    189        uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
    190        for (j = 0; j < vq * 2; ++j) {
    191            __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
    192        }
    193    }
    194    for (i = 0; i <= 16; ++i) {
    195        uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
    196        for (j = 0; j < vq; ++j) {
    197            uint64_t r = env->vfp.pregs[i].p[j >> 2];
    198            __put_user_e(r >> ((j & 3) * 16), p + j, le);
    199        }
    200    }
    201}
    202
    203static void target_restore_general_frame(CPUARMState *env,
    204                                         struct target_rt_sigframe *sf)
    205{
    206    sigset_t set;
    207    uint64_t pstate;
    208    int i;
    209
    210    target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
    211    set_sigmask(&set);
    212
    213    for (i = 0; i < 31; i++) {
    214        __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
    215    }
    216
    217    __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
    218    __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
    219    __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
    220    pstate_write(env, pstate);
    221}
    222
    223static void target_restore_fpsimd_record(CPUARMState *env,
    224                                         struct target_fpsimd_context *fpsimd)
    225{
    226    uint32_t fpsr, fpcr;
    227    int i;
    228
    229    __get_user(fpsr, &fpsimd->fpsr);
    230    vfp_set_fpsr(env, fpsr);
    231    __get_user(fpcr, &fpsimd->fpcr);
    232    vfp_set_fpcr(env, fpcr);
    233
    234    for (i = 0; i < 32; i++) {
    235        uint64_t *q = aa64_vfp_qreg(env, i);
    236#ifdef TARGET_WORDS_BIGENDIAN
    237        __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
    238        __get_user(q[1], &fpsimd->vregs[i * 2]);
    239#else
    240        __get_user(q[0], &fpsimd->vregs[i * 2]);
    241        __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
    242#endif
    243    }
    244}
    245
    246static void target_restore_sve_record(CPUARMState *env,
    247                                      struct target_sve_context *sve, int vq)
    248{
    249    int i, j;
    250
    251    /* Note that SVE regs are stored as a byte stream, with each byte element
    252     * at a subsequent address.  This corresponds to a little-endian load
    253     * of our 64-bit hunks.
    254     */
    255    for (i = 0; i < 32; ++i) {
    256        uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
    257        for (j = 0; j < vq * 2; ++j) {
    258            __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
    259        }
    260    }
    261    for (i = 0; i <= 16; ++i) {
    262        uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
    263        for (j = 0; j < vq; ++j) {
    264            uint16_t r;
    265            __get_user_e(r, p + j, le);
    266            if (j & 3) {
    267                env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
    268            } else {
    269                env->vfp.pregs[i].p[j >> 2] = r;
    270            }
    271        }
    272    }
    273}
    274
    275static int target_restore_sigframe(CPUARMState *env,
    276                                   struct target_rt_sigframe *sf)
    277{
    278    struct target_aarch64_ctx *ctx, *extra = NULL;
    279    struct target_fpsimd_context *fpsimd = NULL;
    280    struct target_sve_context *sve = NULL;
    281    uint64_t extra_datap = 0;
    282    bool used_extra = false;
    283    bool err = false;
    284    int vq = 0, sve_size = 0;
    285
    286    target_restore_general_frame(env, sf);
    287
    288    ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
    289    while (ctx) {
    290        uint32_t magic, size, extra_size;
    291
    292        __get_user(magic, &ctx->magic);
    293        __get_user(size, &ctx->size);
    294        switch (magic) {
    295        case 0:
    296            if (size != 0) {
    297                err = true;
    298                goto exit;
    299            }
    300            if (used_extra) {
    301                ctx = NULL;
    302            } else {
    303                ctx = extra;
    304                used_extra = true;
    305            }
    306            continue;
    307
    308        case TARGET_FPSIMD_MAGIC:
    309            if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
    310                err = true;
    311                goto exit;
    312            }
    313            fpsimd = (struct target_fpsimd_context *)ctx;
    314            break;
    315
    316        case TARGET_SVE_MAGIC:
    317            if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
    318                vq = (env->vfp.zcr_el[1] & 0xf) + 1;
    319                sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
    320                if (!sve && size == sve_size) {
    321                    sve = (struct target_sve_context *)ctx;
    322                    break;
    323                }
    324            }
    325            err = true;
    326            goto exit;
    327
    328        case TARGET_EXTRA_MAGIC:
    329            if (extra || size != sizeof(struct target_extra_context)) {
    330                err = true;
    331                goto exit;
    332            }
    333            __get_user(extra_datap,
    334                       &((struct target_extra_context *)ctx)->datap);
    335            __get_user(extra_size,
    336                       &((struct target_extra_context *)ctx)->size);
    337            extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
    338            break;
    339
    340        default:
    341            /* Unknown record -- we certainly didn't generate it.
    342             * Did we in fact get out of sync?
    343             */
    344            err = true;
    345            goto exit;
    346        }
    347        ctx = (void *)ctx + size;
    348    }
    349
    350    /* Require FPSIMD always.  */
    351    if (fpsimd) {
    352        target_restore_fpsimd_record(env, fpsimd);
    353    } else {
    354        err = true;
    355    }
    356
    357    /* SVE data, if present, overwrites FPSIMD data.  */
    358    if (sve) {
    359        target_restore_sve_record(env, sve, vq);
    360    }
    361
    362 exit:
    363    unlock_user(extra, extra_datap, 0);
    364    return err;
    365}
    366
    367static abi_ulong get_sigframe(struct target_sigaction *ka,
    368                              CPUARMState *env, int size)
    369{
    370    abi_ulong sp;
    371
    372    sp = target_sigsp(get_sp_from_cpustate(env), ka);
    373
    374    sp = (sp - size) & ~15;
    375
    376    return sp;
    377}
    378
    379typedef struct {
    380    int total_size;
    381    int extra_base;
    382    int extra_size;
    383    int std_end_ofs;
    384    int extra_ofs;
    385    int extra_end_ofs;
    386} target_sigframe_layout;
    387
    388static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
    389{
    390    /* Make sure there will always be space for the end marker.  */
    391    const int std_size = sizeof(struct target_rt_sigframe)
    392                         - sizeof(struct target_aarch64_ctx);
    393    int this_loc = l->total_size;
    394
    395    if (l->extra_base) {
    396        /* Once we have begun an extra space, all allocations go there.  */
    397        l->extra_size += this_size;
    398    } else if (this_size + this_loc > std_size) {
    399        /* This allocation does not fit in the standard space.  */
    400        /* Allocate the extra record.  */
    401        l->extra_ofs = this_loc;
    402        l->total_size += sizeof(struct target_extra_context);
    403
    404        /* Allocate the standard end record.  */
    405        l->std_end_ofs = l->total_size;
    406        l->total_size += sizeof(struct target_aarch64_ctx);
    407
    408        /* Allocate the requested record.  */
    409        l->extra_base = this_loc = l->total_size;
    410        l->extra_size = this_size;
    411    }
    412    l->total_size += this_size;
    413
    414    return this_loc;
    415}
    416
    417static void target_setup_frame(int usig, struct target_sigaction *ka,
    418                               target_siginfo_t *info, target_sigset_t *set,
    419                               CPUARMState *env)
    420{
    421    target_sigframe_layout layout = {
    422        /* Begin with the size pointing to the reserved space.  */
    423        .total_size = offsetof(struct target_rt_sigframe,
    424                               uc.tuc_mcontext.__reserved),
    425    };
    426    int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
    427    struct target_rt_sigframe *frame;
    428    struct target_rt_frame_record *fr;
    429    abi_ulong frame_addr, return_addr;
    430
    431    /* FPSIMD record is always in the standard space.  */
    432    fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
    433                                      &layout);
    434
    435    /* SVE state needs saving only if it exists.  */
    436    if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
    437        vq = (env->vfp.zcr_el[1] & 0xf) + 1;
    438        sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
    439        sve_ofs = alloc_sigframe_space(sve_size, &layout);
    440    }
    441
    442    if (layout.extra_ofs) {
    443        /* Reserve space for the extra end marker.  The standard end marker
    444         * will have been allocated when we allocated the extra record.
    445         */
    446        layout.extra_end_ofs
    447            = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
    448    } else {
    449        /* Reserve space for the standard end marker.
    450         * Do not use alloc_sigframe_space because we cheat
    451         * std_size therein to reserve space for this.
    452         */
    453        layout.std_end_ofs = layout.total_size;
    454        layout.total_size += sizeof(struct target_aarch64_ctx);
    455    }
    456
    457    /* We must always provide at least the standard 4K reserved space,
    458     * even if we don't use all of it (this is part of the ABI)
    459     */
    460    layout.total_size = MAX(layout.total_size,
    461                            sizeof(struct target_rt_sigframe));
    462
    463    /*
    464     * Reserve space for the standard frame unwind pair: fp, lr.
    465     * Despite the name this is not a "real" record within the frame.
    466     */
    467    fr_ofs = layout.total_size;
    468    layout.total_size += sizeof(struct target_rt_frame_record);
    469
    470    frame_addr = get_sigframe(ka, env, layout.total_size);
    471    trace_user_setup_frame(env, frame_addr);
    472    frame = lock_user(VERIFY_WRITE, frame_addr, layout.total_size, 0);
    473    if (!frame) {
    474        goto give_sigsegv;
    475    }
    476
    477    target_setup_general_frame(frame, env, set);
    478    target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
    479    target_setup_end_record((void *)frame + layout.std_end_ofs);
    480    if (layout.extra_ofs) {
    481        target_setup_extra_record((void *)frame + layout.extra_ofs,
    482                                  frame_addr + layout.extra_base,
    483                                  layout.extra_size);
    484        target_setup_end_record((void *)frame + layout.extra_end_ofs);
    485    }
    486    if (sve_ofs) {
    487        target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
    488    }
    489
    490    /* Set up the stack frame for unwinding.  */
    491    fr = (void *)frame + fr_ofs;
    492    __put_user(env->xregs[29], &fr->fp);
    493    __put_user(env->xregs[30], &fr->lr);
    494
    495    if (ka->sa_flags & TARGET_SA_RESTORER) {
    496        return_addr = ka->sa_restorer;
    497    } else {
    498        return_addr = default_rt_sigreturn;
    499    }
    500    env->xregs[0] = usig;
    501    env->xregs[29] = frame_addr + fr_ofs;
    502    env->xregs[30] = return_addr;
    503    env->xregs[31] = frame_addr;
    504    env->pc = ka->_sa_handler;
    505
    506    /* Invoke the signal handler as if by indirect call.  */
    507    if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
    508        env->btype = 2;
    509    }
    510
    511    if (info) {
    512        tswap_siginfo(&frame->info, info);
    513        env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
    514        env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
    515    }
    516
    517    unlock_user(frame, frame_addr, layout.total_size);
    518    return;
    519
    520 give_sigsegv:
    521    unlock_user(frame, frame_addr, layout.total_size);
    522    force_sigsegv(usig);
    523}
    524
    525void setup_rt_frame(int sig, struct target_sigaction *ka,
    526                    target_siginfo_t *info, target_sigset_t *set,
    527                    CPUARMState *env)
    528{
    529    target_setup_frame(sig, ka, info, set, env);
    530}
    531
    532void setup_frame(int sig, struct target_sigaction *ka,
    533                 target_sigset_t *set, CPUARMState *env)
    534{
    535    target_setup_frame(sig, ka, 0, set, env);
    536}
    537
    538long do_rt_sigreturn(CPUARMState *env)
    539{
    540    struct target_rt_sigframe *frame = NULL;
    541    abi_ulong frame_addr = env->xregs[31];
    542
    543    trace_user_do_rt_sigreturn(env, frame_addr);
    544    if (frame_addr & 15) {
    545        goto badframe;
    546    }
    547
    548    if  (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
    549        goto badframe;
    550    }
    551
    552    if (target_restore_sigframe(env, frame)) {
    553        goto badframe;
    554    }
    555
    556    target_restore_altstack(&frame->uc.tuc_stack, env);
    557
    558    unlock_user_struct(frame, frame_addr, 0);
    559    return -TARGET_QEMU_ESIGRETURN;
    560
    561 badframe:
    562    unlock_user_struct(frame, frame_addr, 0);
    563    force_sig(TARGET_SIGSEGV);
    564    return -TARGET_QEMU_ESIGRETURN;
    565}
    566
    567long do_sigreturn(CPUARMState *env)
    568{
    569    return do_rt_sigreturn(env);
    570}
    571
    572void setup_sigtramp(abi_ulong sigtramp_page)
    573{
    574    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
    575    assert(tramp != NULL);
    576
    577    /*
    578     * mov x8,#__NR_rt_sigreturn; svc #0
    579     * Since these are instructions they need to be put as little-endian
    580     * regardless of target default or current CPU endianness.
    581     */
    582    __put_user_e(0xd2801168, &tramp[0], le);
    583    __put_user_e(0xd4000001, &tramp[1], le);
    584
    585    default_rt_sigreturn = sigtramp_page;
    586    unlock_user(tramp, sigtramp_page, 8);
    587}