qemu/linux-user/s390x/cpu_loop.c
<<
>>
Prefs
   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 "cpu_loop-common.h"
  23
  24/* s390x masks the fault address it reports in si_addr for SIGSEGV and SIGBUS */
  25#define S390X_FAIL_ADDR_MASK -4096LL
  26
  27void cpu_loop(CPUS390XState *env)
  28{
  29    CPUState *cs = CPU(s390_env_get_cpu(env));
  30    int trapnr, n, sig;
  31    target_siginfo_t info;
  32    target_ulong addr;
  33    abi_long ret;
  34
  35    while (1) {
  36        cpu_exec_start(cs);
  37        trapnr = cpu_exec(cs);
  38        cpu_exec_end(cs);
  39        process_queued_cpu_work(cs);
  40
  41        switch (trapnr) {
  42        case EXCP_INTERRUPT:
  43            /* Just indicate that signals should be handled asap.  */
  44            break;
  45
  46        case EXCP_SVC:
  47            n = env->int_svc_code;
  48            if (!n) {
  49                /* syscalls > 255 */
  50                n = env->regs[1];
  51            }
  52            env->psw.addr += env->int_svc_ilen;
  53            ret = do_syscall(env, n, env->regs[2], env->regs[3],
  54                             env->regs[4], env->regs[5],
  55                             env->regs[6], env->regs[7], 0, 0);
  56            if (ret == -TARGET_ERESTARTSYS) {
  57                env->psw.addr -= env->int_svc_ilen;
  58            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
  59                env->regs[2] = ret;
  60            }
  61            break;
  62
  63        case EXCP_DEBUG:
  64            sig = TARGET_SIGTRAP;
  65            n = TARGET_TRAP_BRKPT;
  66            goto do_signal_pc;
  67        case EXCP_PGM:
  68            n = env->int_pgm_code;
  69            switch (n) {
  70            case PGM_OPERATION:
  71            case PGM_PRIVILEGED:
  72                sig = TARGET_SIGILL;
  73                n = TARGET_ILL_ILLOPC;
  74                goto do_signal_pc;
  75            case PGM_PROTECTION:
  76            case PGM_ADDRESSING:
  77                sig = TARGET_SIGSEGV;
  78                /* XXX: check env->error_code */
  79                n = TARGET_SEGV_MAPERR;
  80                addr = env->__excp_addr & S390X_FAIL_ADDR_MASK;
  81                goto do_signal;
  82            case PGM_EXECUTE:
  83            case PGM_SPECIFICATION:
  84            case PGM_SPECIAL_OP:
  85            case PGM_OPERAND:
  86            do_sigill_opn:
  87                sig = TARGET_SIGILL;
  88                n = TARGET_ILL_ILLOPN;
  89                goto do_signal_pc;
  90
  91            case PGM_FIXPT_OVERFLOW:
  92                sig = TARGET_SIGFPE;
  93                n = TARGET_FPE_INTOVF;
  94                goto do_signal_pc;
  95            case PGM_FIXPT_DIVIDE:
  96                sig = TARGET_SIGFPE;
  97                n = TARGET_FPE_INTDIV;
  98                goto do_signal_pc;
  99
 100            case PGM_DATA:
 101                n = (env->fpc >> 8) & 0xff;
 102                if (n == 0xff) {
 103                    /* compare-and-trap */
 104                    goto do_sigill_opn;
 105                } else {
 106                    /* An IEEE exception, simulated or otherwise.  */
 107                    if (n & 0x80) {
 108                        n = TARGET_FPE_FLTINV;
 109                    } else if (n & 0x40) {
 110                        n = TARGET_FPE_FLTDIV;
 111                    } else if (n & 0x20) {
 112                        n = TARGET_FPE_FLTOVF;
 113                    } else if (n & 0x10) {
 114                        n = TARGET_FPE_FLTUND;
 115                    } else if (n & 0x08) {
 116                        n = TARGET_FPE_FLTRES;
 117                    } else {
 118                        /* ??? Quantum exception; BFP, DFP error.  */
 119                        goto do_sigill_opn;
 120                    }
 121                    sig = TARGET_SIGFPE;
 122                    goto do_signal_pc;
 123                }
 124
 125            default:
 126                fprintf(stderr, "Unhandled program exception: %#x\n", n);
 127                cpu_dump_state(cs, stderr, fprintf, 0);
 128                exit(EXIT_FAILURE);
 129            }
 130            break;
 131
 132        do_signal_pc:
 133            addr = env->psw.addr;
 134        do_signal:
 135            info.si_signo = sig;
 136            info.si_errno = 0;
 137            info.si_code = n;
 138            info._sifields._sigfault._addr = addr;
 139            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 140            break;
 141
 142        case EXCP_ATOMIC:
 143            cpu_exec_step_atomic(cs);
 144            break;
 145        default:
 146            fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
 147            cpu_dump_state(cs, stderr, fprintf, 0);
 148            exit(EXIT_FAILURE);
 149        }
 150        process_pending_signals (env);
 151    }
 152}
 153
 154void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
 155{
 156    int i;
 157    for (i = 0; i < 16; i++) {
 158        env->regs[i] = regs->gprs[i];
 159    }
 160    env->psw.mask = regs->psw.mask;
 161    env->psw.addr = regs->psw.addr;
 162}
 163