1 /* 2 * ARM AArch64 cpu init and loop 3 * 4 * Copyright (c) 2015 Stacey Son 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library 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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef TARGET_ARCH_CPU_H 21 #define TARGET_ARCH_CPU_H 22 23 #include "target_arch.h" 24 #include "signal-common.h" 25 #include "target/arm/syndrome.h" 26 27 #define TARGET_DEFAULT_CPU_MODEL "any" 28 29 static inline void target_cpu_init(CPUARMState *env, 30 struct target_pt_regs *regs) 31 { 32 int i; 33 34 if (!(arm_feature(env, ARM_FEATURE_AARCH64))) { 35 fprintf(stderr, "The selected ARM CPU does not support 64 bit mode\n"); 36 exit(1); 37 } 38 for (i = 0; i < 31; i++) { 39 env->xregs[i] = regs->regs[i]; 40 } 41 env->pc = regs->pc; 42 env->xregs[31] = regs->sp; 43 } 44 45 46 static inline void target_cpu_loop(CPUARMState *env) 47 { 48 CPUState *cs = env_cpu(env); 49 int trapnr, ec, fsc, si_code, si_signo; 50 uint64_t code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; 51 uint32_t pstate; 52 abi_long ret; 53 54 for (;;) { 55 cpu_exec_start(cs); 56 trapnr = cpu_exec(cs); 57 cpu_exec_end(cs); 58 process_queued_cpu_work(cs); 59 60 switch (trapnr) { 61 case EXCP_SWI: 62 /* See arm64/arm64/trap.c cpu_fetch_syscall_args() */ 63 code = env->xregs[8]; 64 if (code == TARGET_FREEBSD_NR_syscall || 65 code == TARGET_FREEBSD_NR___syscall) { 66 code = env->xregs[0]; 67 arg1 = env->xregs[1]; 68 arg2 = env->xregs[2]; 69 arg3 = env->xregs[3]; 70 arg4 = env->xregs[4]; 71 arg5 = env->xregs[5]; 72 arg6 = env->xregs[6]; 73 arg7 = env->xregs[7]; 74 arg8 = 0; 75 } else { 76 arg1 = env->xregs[0]; 77 arg2 = env->xregs[1]; 78 arg3 = env->xregs[2]; 79 arg4 = env->xregs[3]; 80 arg5 = env->xregs[4]; 81 arg6 = env->xregs[5]; 82 arg7 = env->xregs[6]; 83 arg8 = env->xregs[7]; 84 } 85 ret = do_freebsd_syscall(env, code, arg1, arg2, arg3, 86 arg4, arg5, arg6, arg7, arg8); 87 /* 88 * The carry bit is cleared for no error; set for error. 89 * See arm64/arm64/vm_machdep.c cpu_set_syscall_retval() 90 */ 91 pstate = pstate_read(env); 92 if (ret >= 0) { 93 pstate &= ~PSTATE_C; 94 env->xregs[0] = ret; 95 } else if (ret == -TARGET_ERESTART) { 96 env->pc -= 4; 97 break; 98 } else if (ret != -TARGET_EJUSTRETURN) { 99 pstate |= PSTATE_C; 100 env->xregs[0] = -ret; 101 } 102 pstate_write(env, pstate); 103 break; 104 105 case EXCP_INTERRUPT: 106 /* Just indicate that signals should be handle ASAP. */ 107 break; 108 109 case EXCP_UDEF: 110 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc); 111 break; 112 113 114 case EXCP_PREFETCH_ABORT: 115 case EXCP_DATA_ABORT: 116 /* We should only arrive here with EC in {DATAABORT, INSNABORT}. */ 117 ec = syn_get_ec(env->exception.syndrome); 118 assert(ec == EC_DATAABORT || ec == EC_INSNABORT); 119 120 /* Both EC have the same format for FSC, or close enough. */ 121 fsc = extract32(env->exception.syndrome, 0, 6); 122 switch (fsc) { 123 case 0x04 ... 0x07: /* Translation fault, level {0-3} */ 124 si_signo = TARGET_SIGSEGV; 125 si_code = TARGET_SEGV_MAPERR; 126 break; 127 case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */ 128 case 0x0d ... 0x0f: /* Permission fault, level {1-3} */ 129 si_signo = TARGET_SIGSEGV; 130 si_code = TARGET_SEGV_ACCERR; 131 break; 132 case 0x11: /* Synchronous Tag Check Fault */ 133 si_signo = TARGET_SIGSEGV; 134 si_code = /* TARGET_SEGV_MTESERR; */ TARGET_SEGV_ACCERR; 135 break; 136 case 0x21: /* Alignment fault */ 137 si_signo = TARGET_SIGBUS; 138 si_code = TARGET_BUS_ADRALN; 139 break; 140 default: 141 g_assert_not_reached(); 142 } 143 force_sig_fault(si_signo, si_code, env->exception.vaddress); 144 break; 145 146 case EXCP_DEBUG: 147 case EXCP_BKPT: 148 force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 149 break; 150 151 case EXCP_ATOMIC: 152 cpu_exec_step_atomic(cs); 153 break; 154 155 case EXCP_YIELD: 156 /* nothing to do here for user-mode, just resume guest code */ 157 break; 158 default: 159 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 160 trapnr); 161 cpu_dump_state(cs, stderr, 0); 162 abort(); 163 } /* switch() */ 164 process_pending_signals(env); 165 /* 166 * Exception return on AArch64 always clears the exclusive 167 * monitor, so any return to running guest code implies this. 168 * A strex (successful or otherwise) also clears the monitor, so 169 * we don't need to specialcase EXCP_STREX. 170 */ 171 env->exclusive_addr = -1; 172 } /* for (;;) */ 173 } 174 175 176 /* See arm64/arm64/vm_machdep.c cpu_fork() */ 177 static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp) 178 { 179 if (newsp) { 180 env->xregs[31] = newsp; 181 } 182 env->regs[0] = 0; 183 env->regs[1] = 0; 184 pstate_write(env, 0); 185 } 186 187 static inline void target_cpu_reset(CPUArchState *env) 188 { 189 } 190 191 192 #endif /* TARGET_ARCH_CPU_H */ 193