qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cpu_loop.c (16152B)


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