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 abi_long ret; 52 53 for (;;) { 54 cpu_exec_start(cs); 55 trapnr = cpu_exec(cs); 56 cpu_exec_end(cs); 57 process_queued_cpu_work(cs); 58 59 switch (trapnr) { 60 case EXCP_SWI: 61 /* See arm64/arm64/trap.c cpu_fetch_syscall_args() */ 62 code = env->xregs[8]; 63 if (code == TARGET_FREEBSD_NR_syscall || 64 code == TARGET_FREEBSD_NR___syscall) { 65 code = env->xregs[0]; 66 arg1 = env->xregs[1]; 67 arg2 = env->xregs[2]; 68 arg3 = env->xregs[3]; 69 arg4 = env->xregs[4]; 70 arg5 = env->xregs[5]; 71 arg6 = env->xregs[6]; 72 arg7 = env->xregs[7]; 73 arg8 = 0; 74 } else { 75 arg1 = env->xregs[0]; 76 arg2 = env->xregs[1]; 77 arg3 = env->xregs[2]; 78 arg4 = env->xregs[3]; 79 arg5 = env->xregs[4]; 80 arg6 = env->xregs[5]; 81 arg7 = env->xregs[6]; 82 arg8 = env->xregs[7]; 83 } 84 ret = do_freebsd_syscall(env, code, arg1, arg2, arg3, 85 arg4, arg5, arg6, arg7, arg8); 86 /* 87 * The carry bit is cleared for no error; set for error. 88 * See arm64/arm64/vm_machdep.c cpu_set_syscall_retval() 89 */ 90 if (ret >= 0) { 91 env->CF = 0; 92 env->xregs[0] = ret; 93 } else if (ret == -TARGET_ERESTART) { 94 env->pc -= 4; 95 break; 96 } else if (ret != -TARGET_EJUSTRETURN) { 97 env->CF = 1; 98 env->xregs[0] = -ret; 99 } 100 break; 101 102 case EXCP_INTERRUPT: 103 /* Just indicate that signals should be handle ASAP. */ 104 break; 105 106 case EXCP_UDEF: 107 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc); 108 break; 109 110 111 case EXCP_PREFETCH_ABORT: 112 case EXCP_DATA_ABORT: 113 /* We should only arrive here with EC in {DATAABORT, INSNABORT}. */ 114 ec = syn_get_ec(env->exception.syndrome); 115 assert(ec == EC_DATAABORT || ec == EC_INSNABORT); 116 117 /* Both EC have the same format for FSC, or close enough. */ 118 fsc = extract32(env->exception.syndrome, 0, 6); 119 switch (fsc) { 120 case 0x04 ... 0x07: /* Translation fault, level {0-3} */ 121 si_signo = TARGET_SIGSEGV; 122 si_code = TARGET_SEGV_MAPERR; 123 break; 124 case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */ 125 case 0x0d ... 0x0f: /* Permission fault, level {1-3} */ 126 si_signo = TARGET_SIGSEGV; 127 si_code = TARGET_SEGV_ACCERR; 128 break; 129 case 0x11: /* Synchronous Tag Check Fault */ 130 si_signo = TARGET_SIGSEGV; 131 si_code = /* TARGET_SEGV_MTESERR; */ TARGET_SEGV_ACCERR; 132 break; 133 case 0x21: /* Alignment fault */ 134 si_signo = TARGET_SIGBUS; 135 si_code = TARGET_BUS_ADRALN; 136 break; 137 default: 138 g_assert_not_reached(); 139 } 140 force_sig_fault(si_signo, si_code, env->exception.vaddress); 141 break; 142 143 case EXCP_DEBUG: 144 case EXCP_BKPT: 145 force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 146 break; 147 148 case EXCP_ATOMIC: 149 cpu_exec_step_atomic(cs); 150 break; 151 152 case EXCP_YIELD: 153 /* nothing to do here for user-mode, just resume guest code */ 154 break; 155 default: 156 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 157 trapnr); 158 cpu_dump_state(cs, stderr, 0); 159 abort(); 160 } /* switch() */ 161 process_pending_signals(env); 162 /* 163 * Exception return on AArch64 always clears the exclusive 164 * monitor, so any return to running guest code implies this. 165 * A strex (successful or otherwise) also clears the monitor, so 166 * we don't need to specialcase EXCP_STREX. 167 */ 168 env->exclusive_addr = -1; 169 } /* for (;;) */ 170 } 171 172 173 /* See arm64/arm64/vm_machdep.c cpu_fork() */ 174 static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp) 175 { 176 if (newsp) { 177 env->xregs[31] = newsp; 178 } 179 env->regs[0] = 0; 180 env->regs[1] = 0; 181 pstate_write(env, 0); 182 } 183 184 static inline void target_cpu_reset(CPUArchState *env) 185 { 186 } 187 188 189 #endif /* TARGET_ARCH_CPU_H */ 190