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