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


      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-common.h"
     22#include "qemu.h"
     23#include "user-internals.h"
     24#include "cpu_loop-common.h"
     25#include "signal-common.h"
     26
     27static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
     28{
     29    return cpu_get_host_ticks();
     30}
     31
     32uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
     33{
     34    return cpu_ppc_get_tb(env);
     35}
     36
     37uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
     38{
     39    return cpu_ppc_get_tb(env) >> 32;
     40}
     41
     42uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
     43{
     44    return cpu_ppc_get_tb(env);
     45}
     46
     47uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
     48{
     49    return cpu_ppc_get_tb(env) >> 32;
     50}
     51
     52uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
     53{
     54    return cpu_ppc_get_tb(env);
     55}
     56
     57uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
     58__attribute__ (( alias ("cpu_ppc_load_tbu") ));
     59
     60uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
     61{
     62    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
     63}
     64
     65/* XXX: to be fixed */
     66int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
     67{
     68    return -1;
     69}
     70
     71int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
     72{
     73    return -1;
     74}
     75
     76void cpu_loop(CPUPPCState *env)
     77{
     78    CPUState *cs = env_cpu(env);
     79    target_siginfo_t info;
     80    int trapnr;
     81    target_ulong ret;
     82
     83    for(;;) {
     84        bool arch_interrupt;
     85
     86        cpu_exec_start(cs);
     87        trapnr = cpu_exec(cs);
     88        cpu_exec_end(cs);
     89        process_queued_cpu_work(cs);
     90
     91        arch_interrupt = true;
     92        switch (trapnr) {
     93        case POWERPC_EXCP_NONE:
     94            /* Just go on */
     95            break;
     96        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
     97            cpu_abort(cs, "Critical interrupt while in user mode. "
     98                      "Aborting\n");
     99            break;
    100        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
    101            cpu_abort(cs, "Machine check exception while in user mode. "
    102                      "Aborting\n");
    103            break;
    104        case POWERPC_EXCP_DSI:      /* Data storage exception                */
    105            /* XXX: check this. Seems bugged */
    106            switch (env->error_code & 0xFF000000) {
    107            case 0x40000000:
    108            case 0x42000000:
    109                info.si_signo = TARGET_SIGSEGV;
    110                info.si_errno = 0;
    111                info.si_code = TARGET_SEGV_MAPERR;
    112                break;
    113            case 0x04000000:
    114                info.si_signo = TARGET_SIGILL;
    115                info.si_errno = 0;
    116                info.si_code = TARGET_ILL_ILLADR;
    117                break;
    118            case 0x08000000:
    119                info.si_signo = TARGET_SIGSEGV;
    120                info.si_errno = 0;
    121                info.si_code = TARGET_SEGV_ACCERR;
    122                break;
    123            default:
    124                /* Let's send a regular segfault... */
    125                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
    126                          env->error_code);
    127                info.si_signo = TARGET_SIGSEGV;
    128                info.si_errno = 0;
    129                info.si_code = TARGET_SEGV_MAPERR;
    130                break;
    131            }
    132            info._sifields._sigfault._addr = env->spr[SPR_DAR];
    133            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    134            break;
    135        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
    136            /* XXX: check this */
    137            switch (env->error_code & 0xFF000000) {
    138            case 0x40000000:
    139                info.si_signo = TARGET_SIGSEGV;
    140            info.si_errno = 0;
    141                info.si_code = TARGET_SEGV_MAPERR;
    142                break;
    143            case 0x10000000:
    144            case 0x08000000:
    145                info.si_signo = TARGET_SIGSEGV;
    146                info.si_errno = 0;
    147                info.si_code = TARGET_SEGV_ACCERR;
    148                break;
    149            default:
    150                /* Let's send a regular segfault... */
    151                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
    152                          env->error_code);
    153                info.si_signo = TARGET_SIGSEGV;
    154                info.si_errno = 0;
    155                info.si_code = TARGET_SEGV_MAPERR;
    156                break;
    157            }
    158            info._sifields._sigfault._addr = env->nip - 4;
    159            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    160            break;
    161        case POWERPC_EXCP_EXTERNAL: /* External input                        */
    162            cpu_abort(cs, "External interrupt while in user mode. "
    163                      "Aborting\n");
    164            break;
    165        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
    166            /* XXX: check this */
    167            info.si_signo = TARGET_SIGBUS;
    168            info.si_errno = 0;
    169            info.si_code = TARGET_BUS_ADRALN;
    170            info._sifields._sigfault._addr = env->nip;
    171            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    172            break;
    173        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
    174        case POWERPC_EXCP_HV_EMU:   /* HV emulation                          */
    175            /* XXX: check this */
    176            switch (env->error_code & ~0xF) {
    177            case POWERPC_EXCP_FP:
    178                info.si_signo = TARGET_SIGFPE;
    179                info.si_errno = 0;
    180                switch (env->error_code & 0xF) {
    181                case POWERPC_EXCP_FP_OX:
    182                    info.si_code = TARGET_FPE_FLTOVF;
    183                    break;
    184                case POWERPC_EXCP_FP_UX:
    185                    info.si_code = TARGET_FPE_FLTUND;
    186                    break;
    187                case POWERPC_EXCP_FP_ZX:
    188                case POWERPC_EXCP_FP_VXZDZ:
    189                    info.si_code = TARGET_FPE_FLTDIV;
    190                    break;
    191                case POWERPC_EXCP_FP_XX:
    192                    info.si_code = TARGET_FPE_FLTRES;
    193                    break;
    194                case POWERPC_EXCP_FP_VXSOFT:
    195                    info.si_code = TARGET_FPE_FLTINV;
    196                    break;
    197                case POWERPC_EXCP_FP_VXSNAN:
    198                case POWERPC_EXCP_FP_VXISI:
    199                case POWERPC_EXCP_FP_VXIDI:
    200                case POWERPC_EXCP_FP_VXIMZ:
    201                case POWERPC_EXCP_FP_VXVC:
    202                case POWERPC_EXCP_FP_VXSQRT:
    203                case POWERPC_EXCP_FP_VXCVI:
    204                    info.si_code = TARGET_FPE_FLTSUB;
    205                    break;
    206                default:
    207                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
    208                              env->error_code);
    209                    break;
    210                }
    211                break;
    212            case POWERPC_EXCP_INVAL:
    213                info.si_signo = TARGET_SIGILL;
    214                info.si_errno = 0;
    215                switch (env->error_code & 0xF) {
    216                case POWERPC_EXCP_INVAL_INVAL:
    217                    info.si_code = TARGET_ILL_ILLOPC;
    218                    break;
    219                case POWERPC_EXCP_INVAL_LSWX:
    220                    info.si_code = TARGET_ILL_ILLOPN;
    221                    break;
    222                case POWERPC_EXCP_INVAL_SPR:
    223                    info.si_code = TARGET_ILL_PRVREG;
    224                    break;
    225                case POWERPC_EXCP_INVAL_FP:
    226                    info.si_code = TARGET_ILL_COPROC;
    227                    break;
    228                default:
    229                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
    230                              env->error_code & 0xF);
    231                    info.si_code = TARGET_ILL_ILLADR;
    232                    break;
    233                }
    234                break;
    235            case POWERPC_EXCP_PRIV:
    236                info.si_signo = TARGET_SIGILL;
    237                info.si_errno = 0;
    238                switch (env->error_code & 0xF) {
    239                case POWERPC_EXCP_PRIV_OPC:
    240                    info.si_code = TARGET_ILL_PRVOPC;
    241                    break;
    242                case POWERPC_EXCP_PRIV_REG:
    243                    info.si_code = TARGET_ILL_PRVREG;
    244                    break;
    245                default:
    246                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
    247                              env->error_code & 0xF);
    248                    info.si_code = TARGET_ILL_PRVOPC;
    249                    break;
    250                }
    251                break;
    252            case POWERPC_EXCP_TRAP:
    253                cpu_abort(cs, "Tried to call a TRAP\n");
    254                break;
    255            default:
    256                /* Should not happen ! */
    257                cpu_abort(cs, "Unknown program exception (%02x)\n",
    258                          env->error_code);
    259                break;
    260            }
    261            info._sifields._sigfault._addr = env->nip;
    262            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    263            break;
    264        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
    265            info.si_signo = TARGET_SIGILL;
    266            info.si_errno = 0;
    267            info.si_code = TARGET_ILL_COPROC;
    268            info._sifields._sigfault._addr = env->nip;
    269            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    270            break;
    271        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
    272        case POWERPC_EXCP_SYSCALL_VECTORED:
    273            cpu_abort(cs, "Syscall exception while in user mode. "
    274                      "Aborting\n");
    275            break;
    276        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
    277            info.si_signo = TARGET_SIGILL;
    278            info.si_errno = 0;
    279            info.si_code = TARGET_ILL_COPROC;
    280            info._sifields._sigfault._addr = env->nip;
    281            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    282            break;
    283        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
    284            cpu_abort(cs, "Decrementer interrupt while in user mode. "
    285                      "Aborting\n");
    286            break;
    287        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
    288            cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
    289                      "Aborting\n");
    290            break;
    291        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
    292            cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
    293                      "Aborting\n");
    294            break;
    295        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
    296            cpu_abort(cs, "Data TLB exception while in user mode. "
    297                      "Aborting\n");
    298            break;
    299        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
    300            cpu_abort(cs, "Instruction TLB exception while in user mode. "
    301                      "Aborting\n");
    302            break;
    303        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
    304            info.si_signo = TARGET_SIGILL;
    305            info.si_errno = 0;
    306            info.si_code = TARGET_ILL_COPROC;
    307            info._sifields._sigfault._addr = env->nip;
    308            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    309            break;
    310        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
    311            cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
    312            break;
    313        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
    314            cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
    315            break;
    316        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
    317            cpu_abort(cs, "Performance monitor exception not handled\n");
    318            break;
    319        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
    320            cpu_abort(cs, "Doorbell interrupt while in user mode. "
    321                       "Aborting\n");
    322            break;
    323        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
    324            cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
    325                      "Aborting\n");
    326            break;
    327        case POWERPC_EXCP_RESET:    /* System reset exception                */
    328            cpu_abort(cs, "Reset interrupt while in user mode. "
    329                      "Aborting\n");
    330            break;
    331        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
    332            cpu_abort(cs, "Data segment exception while in user mode. "
    333                      "Aborting\n");
    334            break;
    335        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
    336            cpu_abort(cs, "Instruction segment exception "
    337                      "while in user mode. Aborting\n");
    338            break;
    339        /* PowerPC 64 with hypervisor mode support */
    340        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
    341            cpu_abort(cs, "Hypervisor decrementer interrupt "
    342                      "while in user mode. Aborting\n");
    343            break;
    344        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
    345            /* Nothing to do:
    346             * we use this exception to emulate step-by-step execution mode.
    347             */
    348            break;
    349        /* PowerPC 64 with hypervisor mode support */
    350        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
    351            cpu_abort(cs, "Hypervisor data storage exception "
    352                      "while in user mode. Aborting\n");
    353            break;
    354        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
    355            cpu_abort(cs, "Hypervisor instruction storage exception "
    356                      "while in user mode. Aborting\n");
    357            break;
    358        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
    359            cpu_abort(cs, "Hypervisor data segment exception "
    360                      "while in user mode. Aborting\n");
    361            break;
    362        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
    363            cpu_abort(cs, "Hypervisor instruction segment exception "
    364                      "while in user mode. Aborting\n");
    365            break;
    366        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
    367            info.si_signo = TARGET_SIGILL;
    368            info.si_errno = 0;
    369            info.si_code = TARGET_ILL_COPROC;
    370            info._sifields._sigfault._addr = env->nip;
    371            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    372            break;
    373        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
    374            cpu_abort(cs, "Programmable interval timer interrupt "
    375                      "while in user mode. Aborting\n");
    376            break;
    377        case POWERPC_EXCP_IO:       /* IO error exception                    */
    378            cpu_abort(cs, "IO error exception while in user mode. "
    379                      "Aborting\n");
    380            break;
    381        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
    382            cpu_abort(cs, "Run mode exception while in user mode. "
    383                      "Aborting\n");
    384            break;
    385        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
    386            cpu_abort(cs, "Emulation trap exception not handled\n");
    387            break;
    388        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
    389            cpu_abort(cs, "Instruction fetch TLB exception "
    390                      "while in user-mode. Aborting");
    391            break;
    392        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
    393            cpu_abort(cs, "Data load TLB exception while in user-mode. "
    394                      "Aborting");
    395            break;
    396        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
    397            cpu_abort(cs, "Data store TLB exception while in user-mode. "
    398                      "Aborting");
    399            break;
    400        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
    401            cpu_abort(cs, "Floating-point assist exception not handled\n");
    402            break;
    403        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
    404            cpu_abort(cs, "Instruction address breakpoint exception "
    405                      "not handled\n");
    406            break;
    407        case POWERPC_EXCP_SMI:      /* System management interrupt           */
    408            cpu_abort(cs, "System management interrupt while in user mode. "
    409                      "Aborting\n");
    410            break;
    411        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
    412            cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
    413                      "Aborting\n");
    414            break;
    415        case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */
    416            cpu_abort(cs, "Performance monitor exception not handled\n");
    417            break;
    418        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
    419            cpu_abort(cs, "Vector assist exception not handled\n");
    420            break;
    421        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
    422            cpu_abort(cs, "Soft patch exception not handled\n");
    423            break;
    424        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
    425            cpu_abort(cs, "Maintenance exception while in user mode. "
    426                      "Aborting\n");
    427            break;
    428        case POWERPC_EXCP_SYSCALL_USER:
    429            /* system call in user-mode emulation */
    430            /* WARNING:
    431             * PPC ABI uses overflow flag in cr0 to signal an error
    432             * in syscalls.
    433             */
    434            env->crf[0] &= ~0x1;
    435            env->nip += 4;
    436            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
    437                             env->gpr[5], env->gpr[6], env->gpr[7],
    438                             env->gpr[8], 0, 0);
    439            if (ret == -TARGET_ERESTARTSYS) {
    440                env->nip -= 4;
    441                break;
    442            }
    443            if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
    444                /* Returning from a successful sigreturn syscall.
    445                   Avoid corrupting register state.  */
    446                break;
    447            }
    448            if (ret > (target_ulong)(-515)) {
    449                env->crf[0] |= 0x1;
    450                ret = -ret;
    451            }
    452            env->gpr[3] = ret;
    453            break;
    454        case EXCP_DEBUG:
    455            info.si_signo = TARGET_SIGTRAP;
    456            info.si_errno = 0;
    457            info.si_code = TARGET_TRAP_BRKPT;
    458            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
    459            break;
    460        case EXCP_INTERRUPT:
    461            /* just indicate that signals should be handled asap */
    462            break;
    463        case EXCP_ATOMIC:
    464            cpu_exec_step_atomic(cs);
    465            arch_interrupt = false;
    466            break;
    467        default:
    468            cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
    469            break;
    470        }
    471        process_pending_signals(env);
    472
    473        /* Most of the traps imply a transition through kernel mode,
    474         * which implies an REI instruction has been executed.  Which
    475         * means that RX and LOCK_ADDR should be cleared.  But there
    476         * are a few exceptions for traps internal to QEMU.
    477         */
    478        if (arch_interrupt) {
    479            env->reserve_addr = -1;
    480        }
    481    }
    482}
    483
    484void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
    485{
    486    int i;
    487
    488#if defined(TARGET_PPC64)
    489    int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
    490#if defined(TARGET_ABI32)
    491    ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag));
    492#else
    493    ppc_store_msr(env, env->msr | (target_ulong)1 << flag);
    494#endif
    495#endif
    496
    497    env->nip = regs->nip;
    498    for(i = 0; i < 32; i++) {
    499        env->gpr[i] = regs->gpr[i];
    500    }
    501}