qemu

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

cpu_loop.c (6469B)


      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 
     26 void cpu_loop(CPUAlphaState *env)
     27 {
     28     CPUState *cs = env_cpu(env);
     29     int trapnr, si_code;
     30     abi_long sysret;
     31 
     32     while (1) {
     33         bool arch_interrupt = true;
     34 
     35         cpu_exec_start(cs);
     36         trapnr = cpu_exec(cs);
     37         cpu_exec_end(cs);
     38         process_queued_cpu_work(cs);
     39 
     40         switch (trapnr) {
     41         case EXCP_RESET:
     42             fprintf(stderr, "Reset requested. Exit\n");
     43             exit(EXIT_FAILURE);
     44             break;
     45         case EXCP_MCHK:
     46             fprintf(stderr, "Machine check exception. Exit\n");
     47             exit(EXIT_FAILURE);
     48             break;
     49         case EXCP_SMP_INTERRUPT:
     50         case EXCP_CLK_INTERRUPT:
     51         case EXCP_DEV_INTERRUPT:
     52             fprintf(stderr, "External interrupt. Exit\n");
     53             exit(EXIT_FAILURE);
     54             break;
     55         case EXCP_OPCDEC:
     56         do_sigill:
     57             force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
     58             break;
     59         case EXCP_ARITH:
     60             force_sig_fault(TARGET_SIGFPE, TARGET_FPE_FLTINV, env->pc);
     61             break;
     62         case EXCP_FEN:
     63             /* No-op.  Linux simply re-enables the FPU.  */
     64             break;
     65         case EXCP_CALL_PAL:
     66             switch (env->error_code) {
     67             case 0x80:
     68                 /* BPT */
     69                 goto do_sigtrap_brkpt;
     70             case 0x81:
     71                 /* BUGCHK */
     72                 goto do_sigtrap_unk;
     73             case 0x83:
     74                 /* CALLSYS */
     75                 trapnr = env->ir[IR_V0];
     76                 sysret = do_syscall(env, trapnr,
     77                                     env->ir[IR_A0], env->ir[IR_A1],
     78                                     env->ir[IR_A2], env->ir[IR_A3],
     79                                     env->ir[IR_A4], env->ir[IR_A5],
     80                                     0, 0);
     81                 if (sysret == -QEMU_ERESTARTSYS) {
     82                     env->pc -= 4;
     83                     break;
     84                 }
     85                 if (sysret == -QEMU_ESIGRETURN) {
     86                     break;
     87                 }
     88                 /* Syscall writes 0 to V0 to bypass error check, similar
     89                    to how this is handled internal to Linux kernel.
     90                    (Ab)use trapnr temporarily as boolean indicating error.  */
     91                 trapnr = (env->ir[IR_V0] != 0 && sysret < 0);
     92                 env->ir[IR_V0] = (trapnr ? -sysret : sysret);
     93                 env->ir[IR_A3] = trapnr;
     94                 break;
     95             case 0x86:
     96                 /* IMB */
     97                 /* ??? We can probably elide the code using page_unprotect
     98                    that is checking for self-modifying code.  Instead we
     99                    could simply call tb_flush here.  Until we work out the
    100                    changes required to turn off the extra write protection,
    101                    this can be a no-op.  */
    102                 break;
    103             case 0x9E:
    104                 /* RDUNIQUE */
    105                 /* Handled in the translator for usermode.  */
    106                 abort();
    107             case 0x9F:
    108                 /* WRUNIQUE */
    109                 /* Handled in the translator for usermode.  */
    110                 abort();
    111             case 0xAA:
    112                 /* GENTRAP */
    113                 switch (env->ir[IR_A0]) {
    114                 case TARGET_GEN_INTOVF:
    115                     si_code = TARGET_FPE_INTOVF;
    116                     break;
    117                 case TARGET_GEN_INTDIV:
    118                     si_code = TARGET_FPE_INTDIV;
    119                     break;
    120                 case TARGET_GEN_FLTOVF:
    121                     si_code = TARGET_FPE_FLTOVF;
    122                     break;
    123                 case TARGET_GEN_FLTUND:
    124                     si_code = TARGET_FPE_FLTUND;
    125                     break;
    126                 case TARGET_GEN_FLTINV:
    127                     si_code = TARGET_FPE_FLTINV;
    128                     break;
    129                 case TARGET_GEN_FLTINE:
    130                     si_code = TARGET_FPE_FLTRES;
    131                     break;
    132                 case TARGET_GEN_ROPRAND:
    133                     si_code = TARGET_FPE_FLTUNK;
    134                     break;
    135                 default:
    136                     goto do_sigtrap_unk;
    137                 }
    138                 force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
    139                 break;
    140             default:
    141                 goto do_sigill;
    142             }
    143             break;
    144         case EXCP_DEBUG:
    145         do_sigtrap_brkpt:
    146             force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
    147             break;
    148         do_sigtrap_unk:
    149             force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_UNK, env->pc);
    150             break;
    151         case EXCP_INTERRUPT:
    152             /* Just indicate that signals should be handled asap.  */
    153             break;
    154         case EXCP_ATOMIC:
    155             cpu_exec_step_atomic(cs);
    156             arch_interrupt = false;
    157             break;
    158         default:
    159             fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
    160             cpu_dump_state(cs, stderr, 0);
    161             exit(EXIT_FAILURE);
    162         }
    163         process_pending_signals (env);
    164 
    165         /* Most of the traps imply a transition through PALcode, which
    166            implies an REI instruction has been executed.  Which means
    167            that RX and LOCK_ADDR should be cleared.  But there are a
    168            few exceptions for traps internal to QEMU.  */
    169         if (arch_interrupt) {
    170             env->flags &= ~ENV_FLAG_RX_FLAG;
    171             env->lock_addr = -1;
    172         }
    173     }
    174 }
    175 
    176 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
    177 {
    178     int i;
    179 
    180     for(i = 0; i < 28; i++) {
    181         env->ir[i] = ((abi_ulong *)regs)[i];
    182     }
    183     env->ir[IR_SP] = regs->usp;
    184     env->pc = regs->pc;
    185 }