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

cpu_loop.c (8962B)


      1/*
      2 *  qemu user cpu loop
      3 *
      4 *  Copyright (c) 2003-2008 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
     20#include "qemu/osdep.h"
     21#include "qemu.h"
     22#include "user-internals.h"
     23#include "cpu_loop-common.h"
     24#include "signal-common.h"
     25
     26static void xtensa_rfw(CPUXtensaState *env)
     27{
     28    xtensa_restore_owb(env);
     29    env->pc = env->sregs[EPC1];
     30}
     31
     32static void xtensa_rfwu(CPUXtensaState *env)
     33{
     34    env->sregs[WINDOW_START] |= (1 << env->sregs[WINDOW_BASE]);
     35    xtensa_rfw(env);
     36}
     37
     38static void xtensa_rfwo(CPUXtensaState *env)
     39{
     40    env->sregs[WINDOW_START] &= ~(1 << env->sregs[WINDOW_BASE]);
     41    xtensa_rfw(env);
     42}
     43
     44static void xtensa_overflow4(CPUXtensaState *env)
     45{
     46    put_user_ual(env->regs[0], env->regs[5] - 16);
     47    put_user_ual(env->regs[1], env->regs[5] - 12);
     48    put_user_ual(env->regs[2], env->regs[5] -  8);
     49    put_user_ual(env->regs[3], env->regs[5] -  4);
     50    xtensa_rfwo(env);
     51}
     52
     53static void xtensa_underflow4(CPUXtensaState *env)
     54{
     55    get_user_ual(env->regs[0], env->regs[5] - 16);
     56    get_user_ual(env->regs[1], env->regs[5] - 12);
     57    get_user_ual(env->regs[2], env->regs[5] -  8);
     58    get_user_ual(env->regs[3], env->regs[5] -  4);
     59    xtensa_rfwu(env);
     60}
     61
     62static void xtensa_overflow8(CPUXtensaState *env)
     63{
     64    put_user_ual(env->regs[0], env->regs[9] - 16);
     65    get_user_ual(env->regs[0], env->regs[1] - 12);
     66    put_user_ual(env->regs[1], env->regs[9] - 12);
     67    put_user_ual(env->regs[2], env->regs[9] -  8);
     68    put_user_ual(env->regs[3], env->regs[9] -  4);
     69    put_user_ual(env->regs[4], env->regs[0] - 32);
     70    put_user_ual(env->regs[5], env->regs[0] - 28);
     71    put_user_ual(env->regs[6], env->regs[0] - 24);
     72    put_user_ual(env->regs[7], env->regs[0] - 20);
     73    xtensa_rfwo(env);
     74}
     75
     76static void xtensa_underflow8(CPUXtensaState *env)
     77{
     78    get_user_ual(env->regs[0], env->regs[9] - 16);
     79    get_user_ual(env->regs[1], env->regs[9] - 12);
     80    get_user_ual(env->regs[2], env->regs[9] -  8);
     81    get_user_ual(env->regs[7], env->regs[1] - 12);
     82    get_user_ual(env->regs[3], env->regs[9] -  4);
     83    get_user_ual(env->regs[4], env->regs[7] - 32);
     84    get_user_ual(env->regs[5], env->regs[7] - 28);
     85    get_user_ual(env->regs[6], env->regs[7] - 24);
     86    get_user_ual(env->regs[7], env->regs[7] - 20);
     87    xtensa_rfwu(env);
     88}
     89
     90static void xtensa_overflow12(CPUXtensaState *env)
     91{
     92    put_user_ual(env->regs[0],  env->regs[13] - 16);
     93    get_user_ual(env->regs[0],  env->regs[1]  - 12);
     94    put_user_ual(env->regs[1],  env->regs[13] - 12);
     95    put_user_ual(env->regs[2],  env->regs[13] -  8);
     96    put_user_ual(env->regs[3],  env->regs[13] -  4);
     97    put_user_ual(env->regs[4],  env->regs[0]  - 48);
     98    put_user_ual(env->regs[5],  env->regs[0]  - 44);
     99    put_user_ual(env->regs[6],  env->regs[0]  - 40);
    100    put_user_ual(env->regs[7],  env->regs[0]  - 36);
    101    put_user_ual(env->regs[8],  env->regs[0]  - 32);
    102    put_user_ual(env->regs[9],  env->regs[0]  - 28);
    103    put_user_ual(env->regs[10], env->regs[0]  - 24);
    104    put_user_ual(env->regs[11], env->regs[0]  - 20);
    105    xtensa_rfwo(env);
    106}
    107
    108static void xtensa_underflow12(CPUXtensaState *env)
    109{
    110    get_user_ual(env->regs[0],  env->regs[13] - 16);
    111    get_user_ual(env->regs[1],  env->regs[13] - 12);
    112    get_user_ual(env->regs[2],  env->regs[13] -  8);
    113    get_user_ual(env->regs[11], env->regs[1]  - 12);
    114    get_user_ual(env->regs[3],  env->regs[13] -  4);
    115    get_user_ual(env->regs[4],  env->regs[11] - 48);
    116    get_user_ual(env->regs[5],  env->regs[11] - 44);
    117    get_user_ual(env->regs[6],  env->regs[11] - 40);
    118    get_user_ual(env->regs[7],  env->regs[11] - 36);
    119    get_user_ual(env->regs[8],  env->regs[11] - 32);
    120    get_user_ual(env->regs[9],  env->regs[11] - 28);
    121    get_user_ual(env->regs[10], env->regs[11] - 24);
    122    get_user_ual(env->regs[11], env->regs[11] - 20);
    123    xtensa_rfwu(env);
    124}
    125
    126void cpu_loop(CPUXtensaState *env)
    127{
    128    CPUState *cs = env_cpu(env);
    129    target_siginfo_t info;
    130    abi_ulong ret;
    131    int trapnr;
    132
    133    while (1) {
    134        cpu_exec_start(cs);
    135        trapnr = cpu_exec(cs);
    136        cpu_exec_end(cs);
    137        process_queued_cpu_work(cs);
    138
    139        env->sregs[PS] &= ~PS_EXCM;
    140        switch (trapnr) {
    141        case EXCP_INTERRUPT:
    142            break;
    143
    144        case EXC_WINDOW_OVERFLOW4:
    145            xtensa_overflow4(env);
    146            break;
    147        case EXC_WINDOW_UNDERFLOW4:
    148            xtensa_underflow4(env);
    149            break;
    150        case EXC_WINDOW_OVERFLOW8:
    151            xtensa_overflow8(env);
    152            break;
    153        case EXC_WINDOW_UNDERFLOW8:
    154            xtensa_underflow8(env);
    155            break;
    156        case EXC_WINDOW_OVERFLOW12:
    157            xtensa_overflow12(env);
    158            break;
    159        case EXC_WINDOW_UNDERFLOW12:
    160            xtensa_underflow12(env);
    161            break;
    162
    163        case EXC_USER:
    164            switch (env->sregs[EXCCAUSE]) {
    165            case ILLEGAL_INSTRUCTION_CAUSE:
    166            case PRIVILEGED_CAUSE:
    167                info.si_signo = TARGET_SIGILL;
    168                info.si_errno = 0;
    169                info.si_code =
    170                    env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ?
    171                    TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC;
    172                info._sifields._sigfault._addr = env->sregs[EPC1];
    173                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    174                break;
    175
    176            case SYSCALL_CAUSE:
    177                env->pc += 3;
    178                ret = do_syscall(env, env->regs[2],
    179                                 env->regs[6], env->regs[3],
    180                                 env->regs[4], env->regs[5],
    181                                 env->regs[8], env->regs[9], 0, 0);
    182                switch (ret) {
    183                default:
    184                    env->regs[2] = ret;
    185                    break;
    186
    187                case -TARGET_ERESTARTSYS:
    188                    env->pc -= 3;
    189                    break;
    190
    191                case -TARGET_QEMU_ESIGRETURN:
    192                    break;
    193                }
    194                break;
    195
    196            case ALLOCA_CAUSE:
    197                env->sregs[PS] = deposit32(env->sregs[PS],
    198                                           PS_OWB_SHIFT,
    199                                           PS_OWB_LEN,
    200                                           env->sregs[WINDOW_BASE]);
    201
    202                switch (env->regs[0] & 0xc0000000) {
    203                case 0x00000000:
    204                case 0x40000000:
    205                    xtensa_rotate_window(env, -1);
    206                    xtensa_underflow4(env);
    207                    break;
    208
    209                case 0x80000000:
    210                    xtensa_rotate_window(env, -2);
    211                    xtensa_underflow8(env);
    212                    break;
    213
    214                case 0xc0000000:
    215                    xtensa_rotate_window(env, -3);
    216                    xtensa_underflow12(env);
    217                    break;
    218                }
    219                break;
    220
    221            case INTEGER_DIVIDE_BY_ZERO_CAUSE:
    222                info.si_signo = TARGET_SIGFPE;
    223                info.si_errno = 0;
    224                info.si_code = TARGET_FPE_INTDIV;
    225                info._sifields._sigfault._addr = env->sregs[EPC1];
    226                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    227                break;
    228
    229            case LOAD_PROHIBITED_CAUSE:
    230            case STORE_PROHIBITED_CAUSE:
    231                info.si_signo = TARGET_SIGSEGV;
    232                info.si_errno = 0;
    233                info.si_code = TARGET_SEGV_ACCERR;
    234                info._sifields._sigfault._addr = env->sregs[EXCVADDR];
    235                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    236                break;
    237
    238            default:
    239                fprintf(stderr, "exccause = %d\n", env->sregs[EXCCAUSE]);
    240                g_assert_not_reached();
    241            }
    242            break;
    243        case EXCP_DEBUG:
    244            info.si_signo = TARGET_SIGTRAP;
    245            info.si_errno = 0;
    246            info.si_code = TARGET_TRAP_BRKPT;
    247            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    248            break;
    249        case EXC_DEBUG:
    250        default:
    251            fprintf(stderr, "trapnr = %d\n", trapnr);
    252            g_assert_not_reached();
    253        }
    254        process_pending_signals(env);
    255    }
    256}
    257
    258void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
    259{
    260    int i;
    261    for (i = 0; i < 16; ++i) {
    262        env->regs[i] = regs->areg[i];
    263    }
    264    env->sregs[WINDOW_START] = regs->windowstart;
    265    env->pc = regs->pc;
    266}