1*da8c70eaSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*da8c70eaSSong Gao /* 3*da8c70eaSSong Gao * QEMU LoongArch user cpu_loop. 4*da8c70eaSSong Gao * 5*da8c70eaSSong Gao * Copyright (c) 2021 Loongson Technology Corporation Limited 6*da8c70eaSSong Gao */ 7*da8c70eaSSong Gao 8*da8c70eaSSong Gao #include "qemu/osdep.h" 9*da8c70eaSSong Gao #include "qemu.h" 10*da8c70eaSSong Gao #include "user-internals.h" 11*da8c70eaSSong Gao #include "cpu_loop-common.h" 12*da8c70eaSSong Gao #include "signal-common.h" 13*da8c70eaSSong Gao 14*da8c70eaSSong Gao void cpu_loop(CPULoongArchState *env) 15*da8c70eaSSong Gao { 16*da8c70eaSSong Gao CPUState *cs = env_cpu(env); 17*da8c70eaSSong Gao int trapnr, si_code; 18*da8c70eaSSong Gao abi_long ret; 19*da8c70eaSSong Gao 20*da8c70eaSSong Gao for (;;) { 21*da8c70eaSSong Gao cpu_exec_start(cs); 22*da8c70eaSSong Gao trapnr = cpu_exec(cs); 23*da8c70eaSSong Gao cpu_exec_end(cs); 24*da8c70eaSSong Gao process_queued_cpu_work(cs); 25*da8c70eaSSong Gao 26*da8c70eaSSong Gao switch (trapnr) { 27*da8c70eaSSong Gao case EXCP_INTERRUPT: 28*da8c70eaSSong Gao /* just indicate that signals should be handled asap */ 29*da8c70eaSSong Gao break; 30*da8c70eaSSong Gao case EXCCODE_SYS: 31*da8c70eaSSong Gao env->pc += 4; 32*da8c70eaSSong Gao ret = do_syscall(env, env->gpr[11], 33*da8c70eaSSong Gao env->gpr[4], env->gpr[5], 34*da8c70eaSSong Gao env->gpr[6], env->gpr[7], 35*da8c70eaSSong Gao env->gpr[8], env->gpr[9], 36*da8c70eaSSong Gao -1, -1); 37*da8c70eaSSong Gao if (ret == -QEMU_ERESTARTSYS) { 38*da8c70eaSSong Gao env->pc -= 4; 39*da8c70eaSSong Gao break; 40*da8c70eaSSong Gao } 41*da8c70eaSSong Gao if (ret == -QEMU_ESIGRETURN) { 42*da8c70eaSSong Gao /* 43*da8c70eaSSong Gao * Returning from a successful sigreturn syscall. 44*da8c70eaSSong Gao * Avoid clobbering register state. 45*da8c70eaSSong Gao */ 46*da8c70eaSSong Gao break; 47*da8c70eaSSong Gao } 48*da8c70eaSSong Gao env->gpr[4] = ret; 49*da8c70eaSSong Gao break; 50*da8c70eaSSong Gao case EXCCODE_INE: 51*da8c70eaSSong Gao force_sig_fault(TARGET_SIGILL, 0, env->pc); 52*da8c70eaSSong Gao break; 53*da8c70eaSSong Gao case EXCCODE_FPE: 54*da8c70eaSSong Gao si_code = TARGET_FPE_FLTUNK; 55*da8c70eaSSong Gao if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { 56*da8c70eaSSong Gao si_code = TARGET_FPE_FLTINV; 57*da8c70eaSSong Gao } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { 58*da8c70eaSSong Gao si_code = TARGET_FPE_FLTDIV; 59*da8c70eaSSong Gao } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { 60*da8c70eaSSong Gao si_code = TARGET_FPE_FLTOVF; 61*da8c70eaSSong Gao } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { 62*da8c70eaSSong Gao si_code = TARGET_FPE_FLTUND; 63*da8c70eaSSong Gao } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { 64*da8c70eaSSong Gao si_code = TARGET_FPE_FLTRES; 65*da8c70eaSSong Gao } 66*da8c70eaSSong Gao force_sig_fault(TARGET_SIGFPE, si_code, env->pc); 67*da8c70eaSSong Gao break; 68*da8c70eaSSong Gao case EXCP_DEBUG: 69*da8c70eaSSong Gao case EXCCODE_BRK: 70*da8c70eaSSong Gao force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 71*da8c70eaSSong Gao break; 72*da8c70eaSSong Gao case EXCCODE_BCE: 73*da8c70eaSSong Gao force_sig_fault(TARGET_SIGSYS, TARGET_SI_KERNEL, env->pc); 74*da8c70eaSSong Gao break; 75*da8c70eaSSong Gao case EXCP_ATOMIC: 76*da8c70eaSSong Gao cpu_exec_step_atomic(cs); 77*da8c70eaSSong Gao break; 78*da8c70eaSSong Gao default: 79*da8c70eaSSong Gao EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", 80*da8c70eaSSong Gao trapnr); 81*da8c70eaSSong Gao exit(EXIT_FAILURE); 82*da8c70eaSSong Gao } 83*da8c70eaSSong Gao process_pending_signals(env); 84*da8c70eaSSong Gao } 85*da8c70eaSSong Gao } 86*da8c70eaSSong Gao 87*da8c70eaSSong Gao void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 88*da8c70eaSSong Gao { 89*da8c70eaSSong Gao int i; 90*da8c70eaSSong Gao 91*da8c70eaSSong Gao for (i = 0; i < 32; i++) { 92*da8c70eaSSong Gao env->gpr[i] = regs->regs[i]; 93*da8c70eaSSong Gao } 94*da8c70eaSSong Gao env->pc = regs->csr.era; 95*da8c70eaSSong Gao 96*da8c70eaSSong Gao } 97