18cbb4fc1SStacey Son /*
28cbb4fc1SStacey Son * ARM AArch64 cpu init and loop
38cbb4fc1SStacey Son *
48cbb4fc1SStacey Son * Copyright (c) 2015 Stacey Son
58cbb4fc1SStacey Son *
68cbb4fc1SStacey Son * This library is free software; you can redistribute it and/or
78cbb4fc1SStacey Son * modify it under the terms of the GNU Lesser General Public
88cbb4fc1SStacey Son * License as published by the Free Software Foundation; either
98cbb4fc1SStacey Son * version 2 of the License, or (at your option) any later version.
108cbb4fc1SStacey Son *
118cbb4fc1SStacey Son * This library is distributed in the hope that it will be useful,
128cbb4fc1SStacey Son * but WITHOUT ANY WARRANTY; without even the implied warranty of
138cbb4fc1SStacey Son * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
148cbb4fc1SStacey Son * Lesser General Public License for more details.
158cbb4fc1SStacey Son *
168cbb4fc1SStacey Son * You should have received a copy of the GNU Lesser General Public
178cbb4fc1SStacey Son * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188cbb4fc1SStacey Son */
198cbb4fc1SStacey Son
208cbb4fc1SStacey Son #ifndef TARGET_ARCH_CPU_H
218cbb4fc1SStacey Son #define TARGET_ARCH_CPU_H
228cbb4fc1SStacey Son
238cbb4fc1SStacey Son #include "target_arch.h"
248cbb4fc1SStacey Son #include "signal-common.h"
258cbb4fc1SStacey Son #include "target/arm/syndrome.h"
268cbb4fc1SStacey Son
278cbb4fc1SStacey Son #define TARGET_DEFAULT_CPU_MODEL "any"
288cbb4fc1SStacey Son
target_cpu_init(CPUARMState * env,struct target_pt_regs * regs)298cbb4fc1SStacey Son static inline void target_cpu_init(CPUARMState *env,
308cbb4fc1SStacey Son struct target_pt_regs *regs)
318cbb4fc1SStacey Son {
328cbb4fc1SStacey Son int i;
338cbb4fc1SStacey Son
348cbb4fc1SStacey Son if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
358cbb4fc1SStacey Son fprintf(stderr, "The selected ARM CPU does not support 64 bit mode\n");
368cbb4fc1SStacey Son exit(1);
378cbb4fc1SStacey Son }
388cbb4fc1SStacey Son for (i = 0; i < 31; i++) {
398cbb4fc1SStacey Son env->xregs[i] = regs->regs[i];
408cbb4fc1SStacey Son }
418cbb4fc1SStacey Son env->pc = regs->pc;
428cbb4fc1SStacey Son env->xregs[31] = regs->sp;
438cbb4fc1SStacey Son }
448cbb4fc1SStacey Son
458cbb4fc1SStacey Son
target_cpu_loop(CPUARMState * env)468cbb4fc1SStacey Son static inline void target_cpu_loop(CPUARMState *env)
478cbb4fc1SStacey Son {
488cbb4fc1SStacey Son CPUState *cs = env_cpu(env);
498cbb4fc1SStacey Son int trapnr, ec, fsc, si_code, si_signo;
508cbb4fc1SStacey Son uint64_t code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
518cbb4fc1SStacey Son abi_long ret;
528cbb4fc1SStacey Son
538cbb4fc1SStacey Son for (;;) {
548cbb4fc1SStacey Son cpu_exec_start(cs);
558cbb4fc1SStacey Son trapnr = cpu_exec(cs);
568cbb4fc1SStacey Son cpu_exec_end(cs);
578cbb4fc1SStacey Son process_queued_cpu_work(cs);
588cbb4fc1SStacey Son
598cbb4fc1SStacey Son switch (trapnr) {
608cbb4fc1SStacey Son case EXCP_SWI:
618cbb4fc1SStacey Son /* See arm64/arm64/trap.c cpu_fetch_syscall_args() */
628cbb4fc1SStacey Son code = env->xregs[8];
638cbb4fc1SStacey Son if (code == TARGET_FREEBSD_NR_syscall ||
648cbb4fc1SStacey Son code == TARGET_FREEBSD_NR___syscall) {
658cbb4fc1SStacey Son code = env->xregs[0];
668cbb4fc1SStacey Son arg1 = env->xregs[1];
678cbb4fc1SStacey Son arg2 = env->xregs[2];
688cbb4fc1SStacey Son arg3 = env->xregs[3];
698cbb4fc1SStacey Son arg4 = env->xregs[4];
708cbb4fc1SStacey Son arg5 = env->xregs[5];
718cbb4fc1SStacey Son arg6 = env->xregs[6];
728cbb4fc1SStacey Son arg7 = env->xregs[7];
738cbb4fc1SStacey Son arg8 = 0;
748cbb4fc1SStacey Son } else {
758cbb4fc1SStacey Son arg1 = env->xregs[0];
768cbb4fc1SStacey Son arg2 = env->xregs[1];
778cbb4fc1SStacey Son arg3 = env->xregs[2];
788cbb4fc1SStacey Son arg4 = env->xregs[3];
798cbb4fc1SStacey Son arg5 = env->xregs[4];
808cbb4fc1SStacey Son arg6 = env->xregs[5];
818cbb4fc1SStacey Son arg7 = env->xregs[6];
828cbb4fc1SStacey Son arg8 = env->xregs[7];
838cbb4fc1SStacey Son }
848cbb4fc1SStacey Son ret = do_freebsd_syscall(env, code, arg1, arg2, arg3,
858cbb4fc1SStacey Son arg4, arg5, arg6, arg7, arg8);
868cbb4fc1SStacey Son /*
878cbb4fc1SStacey Son * The carry bit is cleared for no error; set for error.
888cbb4fc1SStacey Son * See arm64/arm64/vm_machdep.c cpu_set_syscall_retval()
898cbb4fc1SStacey Son */
908cbb4fc1SStacey Son if (ret >= 0) {
91*ce6c541dSStacey Son env->CF = 0;
928cbb4fc1SStacey Son env->xregs[0] = ret;
938cbb4fc1SStacey Son } else if (ret == -TARGET_ERESTART) {
948cbb4fc1SStacey Son env->pc -= 4;
958cbb4fc1SStacey Son break;
968cbb4fc1SStacey Son } else if (ret != -TARGET_EJUSTRETURN) {
97*ce6c541dSStacey Son env->CF = 1;
988cbb4fc1SStacey Son env->xregs[0] = -ret;
998cbb4fc1SStacey Son }
1008cbb4fc1SStacey Son break;
1018cbb4fc1SStacey Son
1028cbb4fc1SStacey Son case EXCP_INTERRUPT:
1038cbb4fc1SStacey Son /* Just indicate that signals should be handle ASAP. */
1048cbb4fc1SStacey Son break;
1058cbb4fc1SStacey Son
1068cbb4fc1SStacey Son case EXCP_UDEF:
1078cbb4fc1SStacey Son force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
1088cbb4fc1SStacey Son break;
1098cbb4fc1SStacey Son
1108cbb4fc1SStacey Son
1118cbb4fc1SStacey Son case EXCP_PREFETCH_ABORT:
1128cbb4fc1SStacey Son case EXCP_DATA_ABORT:
1138cbb4fc1SStacey Son /* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
1148cbb4fc1SStacey Son ec = syn_get_ec(env->exception.syndrome);
1158cbb4fc1SStacey Son assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
1168cbb4fc1SStacey Son
1178cbb4fc1SStacey Son /* Both EC have the same format for FSC, or close enough. */
1188cbb4fc1SStacey Son fsc = extract32(env->exception.syndrome, 0, 6);
1198cbb4fc1SStacey Son switch (fsc) {
1208cbb4fc1SStacey Son case 0x04 ... 0x07: /* Translation fault, level {0-3} */
1218cbb4fc1SStacey Son si_signo = TARGET_SIGSEGV;
1228cbb4fc1SStacey Son si_code = TARGET_SEGV_MAPERR;
1238cbb4fc1SStacey Son break;
1248cbb4fc1SStacey Son case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
1258cbb4fc1SStacey Son case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
1268cbb4fc1SStacey Son si_signo = TARGET_SIGSEGV;
1278cbb4fc1SStacey Son si_code = TARGET_SEGV_ACCERR;
1288cbb4fc1SStacey Son break;
1298cbb4fc1SStacey Son case 0x11: /* Synchronous Tag Check Fault */
1308cbb4fc1SStacey Son si_signo = TARGET_SIGSEGV;
1318cbb4fc1SStacey Son si_code = /* TARGET_SEGV_MTESERR; */ TARGET_SEGV_ACCERR;
1328cbb4fc1SStacey Son break;
1338cbb4fc1SStacey Son case 0x21: /* Alignment fault */
1348cbb4fc1SStacey Son si_signo = TARGET_SIGBUS;
1358cbb4fc1SStacey Son si_code = TARGET_BUS_ADRALN;
1368cbb4fc1SStacey Son break;
1378cbb4fc1SStacey Son default:
1388cbb4fc1SStacey Son g_assert_not_reached();
1398cbb4fc1SStacey Son }
1408cbb4fc1SStacey Son force_sig_fault(si_signo, si_code, env->exception.vaddress);
1418cbb4fc1SStacey Son break;
1428cbb4fc1SStacey Son
1438cbb4fc1SStacey Son case EXCP_DEBUG:
1448cbb4fc1SStacey Son case EXCP_BKPT:
1458cbb4fc1SStacey Son force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
1468cbb4fc1SStacey Son break;
1478cbb4fc1SStacey Son
1488cbb4fc1SStacey Son case EXCP_ATOMIC:
1498cbb4fc1SStacey Son cpu_exec_step_atomic(cs);
1508cbb4fc1SStacey Son break;
1518cbb4fc1SStacey Son
1528cbb4fc1SStacey Son case EXCP_YIELD:
1538cbb4fc1SStacey Son /* nothing to do here for user-mode, just resume guest code */
1548cbb4fc1SStacey Son break;
1558cbb4fc1SStacey Son default:
1568cbb4fc1SStacey Son fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1578cbb4fc1SStacey Son trapnr);
1588cbb4fc1SStacey Son cpu_dump_state(cs, stderr, 0);
1598cbb4fc1SStacey Son abort();
1608cbb4fc1SStacey Son } /* switch() */
1618cbb4fc1SStacey Son process_pending_signals(env);
1628cbb4fc1SStacey Son /*
1638cbb4fc1SStacey Son * Exception return on AArch64 always clears the exclusive
1648cbb4fc1SStacey Son * monitor, so any return to running guest code implies this.
1658cbb4fc1SStacey Son * A strex (successful or otherwise) also clears the monitor, so
1668cbb4fc1SStacey Son * we don't need to specialcase EXCP_STREX.
1678cbb4fc1SStacey Son */
1688cbb4fc1SStacey Son env->exclusive_addr = -1;
1698cbb4fc1SStacey Son } /* for (;;) */
1708cbb4fc1SStacey Son }
1718cbb4fc1SStacey Son
1728cbb4fc1SStacey Son
1738cbb4fc1SStacey Son /* See arm64/arm64/vm_machdep.c cpu_fork() */
target_cpu_clone_regs(CPUARMState * env,target_ulong newsp)1748cbb4fc1SStacey Son static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
1758cbb4fc1SStacey Son {
1768cbb4fc1SStacey Son if (newsp) {
1778cbb4fc1SStacey Son env->xregs[31] = newsp;
1788cbb4fc1SStacey Son }
1798cbb4fc1SStacey Son env->regs[0] = 0;
1808cbb4fc1SStacey Son env->regs[1] = 0;
1818cbb4fc1SStacey Son pstate_write(env, 0);
1828cbb4fc1SStacey Son }
1838cbb4fc1SStacey Son
target_cpu_reset(CPUArchState * env)1848cbb4fc1SStacey Son static inline void target_cpu_reset(CPUArchState *env)
1858cbb4fc1SStacey Son {
1868cbb4fc1SStacey Son }
1878cbb4fc1SStacey Son
1888cbb4fc1SStacey Son
1898cbb4fc1SStacey Son #endif /* TARGET_ARCH_CPU_H */
190