mirror of https://github.com/xemu-project/xemu.git
bsd-user: Misc changes for 9.1 (I hope)
V2: Add missing bsd-user/aarch64/target.h This patch series includes two main sets of patches. To make it simple to review, I've included the changes from my student which the later changes depend on. I've included a change from Jessica and Doug as well. I've reviewed them, but more eyes never hurt. I've also included a number of 'touch up' patches needed either to get the aarch64 building, or to implmement suggestions from prior review cycles. The main one is what's charitably described as a kludge: force aarch64 to use 4k pages. The qemu-project (and blitz branch) hasn't had the necessary changes to bsd-user needed to support variable page size. Sorry this is so late... Live has conspired to delay me. -----BEGIN PGP SIGNATURE----- Comment: GPGTools - https://gpgtools.org iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmahejwACgkQbBzRKH2w EQCXuQ/+Pj1Izmox/y9X1trn1T8KC7JdMtimdLiGMaS4C6+gcThXJkIB4l9ZStbV 7rI540mpqVf0KSRLYwc2/ATyhYU7Ffsz02WPn7Xn/NvmmITp4kjw9Z0gd7C7mPVq fS8DJbTyFQDy5dO8FUKLaTfnlYQe+NCnL421t9wFkIrlEepFygRaBaJN5yWVoC+0 1Ob6dG+JEV5BmNguMufvvI3S7nEFEnSBGpNqW3ljrRHAZjdNhv8d9GBYbj1laR1r HQ6r5+u4ZmKCuUbchS0jxGkug0DjuQC7iq+rQ/7fhLYLChkPZ4P2RxNv8ibzKjEV wlTy5LaM+WZNzKWdcHfDFMomeSnnUkOOfAMipMney2jedEjTIwCFDnP4zCAuG83V RbdXWfleP1rDto3AQ765pFneqm3+su2Dh4TKaTSnq6gd1eORJ2IL8dubCfcVwZCy TofemXPWh0HX3kwlD9IB9rqplQZFL78TkQ47btftxinHCLCQOOHRDPVG0IahQPjo pgK4yVH7WA7pWV2Xbo4ngG3sX5U1TyBCbfkkAwhq+P3gjnU8zxonx8Tk/qLeEDdH KEypi/pkGFQKZY0wc/y4XM+XQh6E1l8gMaQ4gJWK1qlyVtUKM1BiNQ2lweohYzC8 p6WAfBQLPpzY4mDWfJMF6DsgObLwWmYbgKzuOtHgST1D/Ebk3Zo= =RPuN -----END PGP SIGNATURE----- Merge tag 'bsd-user-for-9.1-pull-request' of gitlab.com:bsdimp/qemu into staging bsd-user: Misc changes for 9.1 (I hope) V2: Add missing bsd-user/aarch64/target.h This patch series includes two main sets of patches. To make it simple to review, I've included the changes from my student which the later changes depend on. I've included a change from Jessica and Doug as well. I've reviewed them, but more eyes never hurt. I've also included a number of 'touch up' patches needed either to get the aarch64 building, or to implmement suggestions from prior review cycles. The main one is what's charitably described as a kludge: force aarch64 to use 4k pages. The qemu-project (and blitz branch) hasn't had the necessary changes to bsd-user needed to support variable page size. Sorry this is so late... Live has conspired to delay me. # -----BEGIN PGP SIGNATURE----- # Comment: GPGTools - https://gpgtools.org # # iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmahejwACgkQbBzRKH2w # EQCXuQ/+Pj1Izmox/y9X1trn1T8KC7JdMtimdLiGMaS4C6+gcThXJkIB4l9ZStbV # 7rI540mpqVf0KSRLYwc2/ATyhYU7Ffsz02WPn7Xn/NvmmITp4kjw9Z0gd7C7mPVq # fS8DJbTyFQDy5dO8FUKLaTfnlYQe+NCnL421t9wFkIrlEepFygRaBaJN5yWVoC+0 # 1Ob6dG+JEV5BmNguMufvvI3S7nEFEnSBGpNqW3ljrRHAZjdNhv8d9GBYbj1laR1r # HQ6r5+u4ZmKCuUbchS0jxGkug0DjuQC7iq+rQ/7fhLYLChkPZ4P2RxNv8ibzKjEV # wlTy5LaM+WZNzKWdcHfDFMomeSnnUkOOfAMipMney2jedEjTIwCFDnP4zCAuG83V # RbdXWfleP1rDto3AQ765pFneqm3+su2Dh4TKaTSnq6gd1eORJ2IL8dubCfcVwZCy # TofemXPWh0HX3kwlD9IB9rqplQZFL78TkQ47btftxinHCLCQOOHRDPVG0IahQPjo # pgK4yVH7WA7pWV2Xbo4ngG3sX5U1TyBCbfkkAwhq+P3gjnU8zxonx8Tk/qLeEDdH # KEypi/pkGFQKZY0wc/y4XM+XQh6E1l8gMaQ4gJWK1qlyVtUKM1BiNQ2lweohYzC8 # p6WAfBQLPpzY4mDWfJMF6DsgObLwWmYbgKzuOtHgST1D/Ebk3Zo= # =RPuN # -----END PGP SIGNATURE----- # gpg: Signature made Thu 25 Jul 2024 08:03:40 AM AEST # gpg: using RSA key 2035F894B00AA3CF7CCDE1B76C1CD1287DB01100 # gpg: Good signature from "Warner Losh <wlosh@netflix.com>" [unknown] # gpg: aka "Warner Losh <imp@bsdimp.com>" [unknown] # gpg: aka "Warner Losh <imp@freebsd.org>" [unknown] # gpg: aka "Warner Losh <imp@village.org>" [unknown] # gpg: aka "Warner Losh <wlosh@bsdimp.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 2035 F894 B00A A3CF 7CCD E1B7 6C1C D128 7DB0 1100 * tag 'bsd-user-for-9.1-pull-request' of gitlab.com:bsdimp/qemu: bsd-user: Add target.h for aarch64. bsd-user: Add aarch64 build to tree bsd-user: Make compile for non-linux user-mode stuff bsd-user: Define TARGET_SIGSTACK_ALIGN and use it to round stack bsd-user: Sync fork_start/fork_end with linux-user bsd-user: Hard wire aarch64 to be 4k pages only bsd-user: Simplify the implementation of execve bsd-user:Add AArch64 improvements and signal handling functions bsd-user:Add set_mcontext function for ARM AArch64 bsd-user:Add setup_sigframe_arch function for ARM AArch64 bsd-user:Add get_mcontext function for ARM AArch64 bsd-user:Add ARM AArch64 signal handling support bsd-user:Add ARM AArch64 support and capabilities bsd-user:Add AArch64 register handling and related functions bsd-user:Add CPU initialization and management functions Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
029e13a8a5
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* ARM AArch64 specific signal definitions for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "qemu.h"
|
||||
|
||||
/*
|
||||
* Compare to sendsig() in sys/arm64/arm64/exec_machdep.c
|
||||
* Assumes that target stack frame memory is locked.
|
||||
*/
|
||||
abi_long set_sigtramp_args(CPUARMState *regs, int sig,
|
||||
struct target_sigframe *frame,
|
||||
abi_ulong frame_addr,
|
||||
struct target_sigaction *ka)
|
||||
{
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
* x0 = signal number
|
||||
* x1 = siginfo pointer
|
||||
* x2 = ucontext pointer
|
||||
* pc/elr = signal handler pointer
|
||||
* sp = sigframe struct pointer
|
||||
* lr = sigtramp at base of user stack
|
||||
*/
|
||||
|
||||
regs->xregs[0] = sig;
|
||||
regs->xregs[1] = frame_addr +
|
||||
offsetof(struct target_sigframe, sf_si);
|
||||
regs->xregs[2] = frame_addr +
|
||||
offsetof(struct target_sigframe, sf_uc);
|
||||
|
||||
regs->pc = ka->_sa_handler;
|
||||
regs->xregs[TARGET_REG_SP] = frame_addr;
|
||||
regs->xregs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare to get_mcontext() in arm64/arm64/machdep.c
|
||||
* Assumes that the memory is locked if mcp points to user memory.
|
||||
*/
|
||||
abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
|
||||
{
|
||||
int err = 0, i;
|
||||
uint64_t *gr = mcp->mc_gpregs.gp_x;
|
||||
|
||||
mcp->mc_gpregs.gp_spsr = pstate_read(regs);
|
||||
if (flags & TARGET_MC_GET_CLEAR_RET) {
|
||||
gr[0] = 0UL;
|
||||
mcp->mc_gpregs.gp_spsr &= ~CPSR_C;
|
||||
} else {
|
||||
gr[0] = tswap64(regs->xregs[0]);
|
||||
}
|
||||
|
||||
for (i = 1; i < 30; i++) {
|
||||
gr[i] = tswap64(regs->xregs[i]);
|
||||
}
|
||||
|
||||
mcp->mc_gpregs.gp_sp = tswap64(regs->xregs[TARGET_REG_SP]);
|
||||
mcp->mc_gpregs.gp_lr = tswap64(regs->xregs[TARGET_REG_LR]);
|
||||
mcp->mc_gpregs.gp_elr = tswap64(regs->pc);
|
||||
|
||||
/* XXX FP? */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare to arm64/arm64/exec_machdep.c sendsig()
|
||||
* Assumes that the memory is locked if frame points to user memory.
|
||||
*/
|
||||
abi_long setup_sigframe_arch(CPUARMState *env, abi_ulong frame_addr,
|
||||
struct target_sigframe *frame, int flags)
|
||||
{
|
||||
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
|
||||
|
||||
get_mcontext(env, mcp, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare to set_mcontext() in arm64/arm64/machdep.c
|
||||
* Assumes that the memory is locked if frame points to user memory.
|
||||
*/
|
||||
abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int srflag)
|
||||
{
|
||||
int err = 0, i;
|
||||
const uint64_t *gr = mcp->mc_gpregs.gp_x;
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
regs->xregs[i] = tswap64(gr[i]);
|
||||
}
|
||||
|
||||
regs->xregs[TARGET_REG_SP] = tswap64(mcp->mc_gpregs.gp_sp);
|
||||
regs->xregs[TARGET_REG_LR] = tswap64(mcp->mc_gpregs.gp_lr);
|
||||
regs->pc = mcp->mc_gpregs.gp_elr;
|
||||
pstate_write(regs, mcp->mc_gpregs.gp_spsr);
|
||||
|
||||
/* XXX FP? */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compare to sys_sigreturn() in arm64/arm64/machdep.c */
|
||||
abi_long get_ucontext_sigreturn(CPUARMState *regs, abi_ulong target_sf,
|
||||
abi_ulong *target_uc)
|
||||
{
|
||||
uint32_t pstate = pstate_read(regs);
|
||||
|
||||
*target_uc = 0;
|
||||
|
||||
if ((pstate & PSTATE_M) != PSTATE_MODE_EL0t ||
|
||||
(pstate & (PSTATE_F | PSTATE_I | PSTATE_A | PSTATE_D)) != 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
*target_uc = target_sf;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Aarch64 general target stuff that's common to all aarch details
|
||||
*
|
||||
* Copyright (c) 2022 M. Warner Losh <imp@bsdimp.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef TARGET_H
|
||||
#define TARGET_H
|
||||
|
||||
/*
|
||||
* aaarch64 ABI does not 'lump' the registers for 64-bit args.
|
||||
*/
|
||||
static inline bool regpairs_aligned(void *cpu_env)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* TARGET_H */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* ARM AArch64 specific prototypes for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_H
|
||||
#define TARGET_ARCH_H
|
||||
|
||||
#include "qemu.h"
|
||||
#include "target/arm/cpu-features.h"
|
||||
|
||||
void target_cpu_set_tls(CPUARMState *env, target_ulong newtls);
|
||||
target_ulong target_cpu_get_tls(CPUARMState *env);
|
||||
|
||||
#endif /* TARGET_ARCH_H */
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* ARM AArch64 specific CPU for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey Son
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "target_arch.h"
|
||||
|
||||
/* See cpu_set_user_tls() in arm64/arm64/vm_machdep.c */
|
||||
void target_cpu_set_tls(CPUARMState *env, target_ulong newtls)
|
||||
{
|
||||
env->cp15.tpidr_el[0] = newtls;
|
||||
}
|
||||
|
||||
target_ulong target_cpu_get_tls(CPUARMState *env)
|
||||
{
|
||||
return env->cp15.tpidr_el[0];
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* ARM AArch64 cpu init and loop
|
||||
*
|
||||
* Copyright (c) 2015 Stacey Son
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_CPU_H
|
||||
#define TARGET_ARCH_CPU_H
|
||||
|
||||
#include "target_arch.h"
|
||||
#include "signal-common.h"
|
||||
#include "target/arm/syndrome.h"
|
||||
|
||||
#define TARGET_DEFAULT_CPU_MODEL "any"
|
||||
|
||||
static inline void target_cpu_init(CPUARMState *env,
|
||||
struct target_pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
|
||||
fprintf(stderr, "The selected ARM CPU does not support 64 bit mode\n");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < 31; i++) {
|
||||
env->xregs[i] = regs->regs[i];
|
||||
}
|
||||
env->pc = regs->pc;
|
||||
env->xregs[31] = regs->sp;
|
||||
}
|
||||
|
||||
|
||||
static inline void target_cpu_loop(CPUARMState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, ec, fsc, si_code, si_signo;
|
||||
uint64_t code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
|
||||
abi_long ret;
|
||||
|
||||
for (;;) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_SWI:
|
||||
/* See arm64/arm64/trap.c cpu_fetch_syscall_args() */
|
||||
code = env->xregs[8];
|
||||
if (code == TARGET_FREEBSD_NR_syscall ||
|
||||
code == TARGET_FREEBSD_NR___syscall) {
|
||||
code = env->xregs[0];
|
||||
arg1 = env->xregs[1];
|
||||
arg2 = env->xregs[2];
|
||||
arg3 = env->xregs[3];
|
||||
arg4 = env->xregs[4];
|
||||
arg5 = env->xregs[5];
|
||||
arg6 = env->xregs[6];
|
||||
arg7 = env->xregs[7];
|
||||
arg8 = 0;
|
||||
} else {
|
||||
arg1 = env->xregs[0];
|
||||
arg2 = env->xregs[1];
|
||||
arg3 = env->xregs[2];
|
||||
arg4 = env->xregs[3];
|
||||
arg5 = env->xregs[4];
|
||||
arg6 = env->xregs[5];
|
||||
arg7 = env->xregs[6];
|
||||
arg8 = env->xregs[7];
|
||||
}
|
||||
ret = do_freebsd_syscall(env, code, arg1, arg2, arg3,
|
||||
arg4, arg5, arg6, arg7, arg8);
|
||||
/*
|
||||
* The carry bit is cleared for no error; set for error.
|
||||
* See arm64/arm64/vm_machdep.c cpu_set_syscall_retval()
|
||||
*/
|
||||
if (ret >= 0) {
|
||||
env->CF = 0;
|
||||
env->xregs[0] = ret;
|
||||
} else if (ret == -TARGET_ERESTART) {
|
||||
env->pc -= 4;
|
||||
break;
|
||||
} else if (ret != -TARGET_EJUSTRETURN) {
|
||||
env->CF = 1;
|
||||
env->xregs[0] = -ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_INTERRUPT:
|
||||
/* Just indicate that signals should be handle ASAP. */
|
||||
break;
|
||||
|
||||
case EXCP_UDEF:
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
|
||||
break;
|
||||
|
||||
|
||||
case EXCP_PREFETCH_ABORT:
|
||||
case EXCP_DATA_ABORT:
|
||||
/* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
|
||||
ec = syn_get_ec(env->exception.syndrome);
|
||||
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
||||
|
||||
/* Both EC have the same format for FSC, or close enough. */
|
||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||
switch (fsc) {
|
||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
case 0x11: /* Synchronous Tag Check Fault */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = /* TARGET_SEGV_MTESERR; */ TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
case 0x21: /* Alignment fault */
|
||||
si_signo = TARGET_SIGBUS;
|
||||
si_code = TARGET_BUS_ADRALN;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
force_sig_fault(si_signo, si_code, env->exception.vaddress);
|
||||
break;
|
||||
|
||||
case EXCP_DEBUG:
|
||||
case EXCP_BKPT:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
|
||||
case EXCP_YIELD:
|
||||
/* nothing to do here for user-mode, just resume guest code */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||
trapnr);
|
||||
cpu_dump_state(cs, stderr, 0);
|
||||
abort();
|
||||
} /* switch() */
|
||||
process_pending_signals(env);
|
||||
/*
|
||||
* Exception return on AArch64 always clears the exclusive
|
||||
* monitor, so any return to running guest code implies this.
|
||||
* A strex (successful or otherwise) also clears the monitor, so
|
||||
* we don't need to specialcase EXCP_STREX.
|
||||
*/
|
||||
env->exclusive_addr = -1;
|
||||
} /* for (;;) */
|
||||
}
|
||||
|
||||
|
||||
/* See arm64/arm64/vm_machdep.c cpu_fork() */
|
||||
static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
|
||||
{
|
||||
if (newsp) {
|
||||
env->xregs[31] = newsp;
|
||||
}
|
||||
env->regs[0] = 0;
|
||||
env->regs[1] = 0;
|
||||
pstate_write(env, 0);
|
||||
}
|
||||
|
||||
static inline void target_cpu_reset(CPUArchState *env)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_ARCH_CPU_H */
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* ARM AArch64 ELF definitions for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_ELF_H
|
||||
#define TARGET_ARCH_ELF_H
|
||||
|
||||
#define ELF_START_MMAP 0x80000000
|
||||
#define ELF_ET_DYN_LOAD_ADDR 0x100000
|
||||
|
||||
#define elf_check_arch(x) ((x) == EM_AARCH64)
|
||||
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#define ELF_DATA ELFDATA2LSB
|
||||
#define ELF_ARCH EM_AARCH64
|
||||
|
||||
#define USE_ELF_CORE_DUMP
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
enum {
|
||||
ARM_HWCAP_A64_FP = 1 << 0,
|
||||
ARM_HWCAP_A64_ASIMD = 1 << 1,
|
||||
ARM_HWCAP_A64_EVTSTRM = 1 << 2,
|
||||
ARM_HWCAP_A64_AES = 1 << 3,
|
||||
ARM_HWCAP_A64_PMULL = 1 << 4,
|
||||
ARM_HWCAP_A64_SHA1 = 1 << 5,
|
||||
ARM_HWCAP_A64_SHA2 = 1 << 6,
|
||||
ARM_HWCAP_A64_CRC32 = 1 << 7,
|
||||
ARM_HWCAP_A64_ATOMICS = 1 << 8,
|
||||
ARM_HWCAP_A64_FPHP = 1 << 9,
|
||||
ARM_HWCAP_A64_ASIMDHP = 1 << 10,
|
||||
ARM_HWCAP_A64_CPUID = 1 << 11,
|
||||
ARM_HWCAP_A64_ASIMDRDM = 1 << 12,
|
||||
ARM_HWCAP_A64_JSCVT = 1 << 13,
|
||||
ARM_HWCAP_A64_FCMA = 1 << 14,
|
||||
ARM_HWCAP_A64_LRCPC = 1 << 15,
|
||||
ARM_HWCAP_A64_DCPOP = 1 << 16,
|
||||
ARM_HWCAP_A64_SHA3 = 1 << 17,
|
||||
ARM_HWCAP_A64_SM3 = 1 << 18,
|
||||
ARM_HWCAP_A64_SM4 = 1 << 19,
|
||||
ARM_HWCAP_A64_ASIMDDP = 1 << 20,
|
||||
ARM_HWCAP_A64_SHA512 = 1 << 21,
|
||||
ARM_HWCAP_A64_SVE = 1 << 22,
|
||||
ARM_HWCAP_A64_ASIMDFHM = 1 << 23,
|
||||
ARM_HWCAP_A64_DIT = 1 << 24,
|
||||
ARM_HWCAP_A64_USCAT = 1 << 25,
|
||||
ARM_HWCAP_A64_ILRCPC = 1 << 26,
|
||||
ARM_HWCAP_A64_FLAGM = 1 << 27,
|
||||
ARM_HWCAP_A64_SSBS = 1 << 28,
|
||||
ARM_HWCAP_A64_SB = 1 << 29,
|
||||
ARM_HWCAP_A64_PACA = 1 << 30,
|
||||
ARM_HWCAP_A64_PACG = 1UL << 31,
|
||||
|
||||
ARM_HWCAP2_A64_DCPODP = 1 << 0,
|
||||
ARM_HWCAP2_A64_SVE2 = 1 << 1,
|
||||
ARM_HWCAP2_A64_SVEAES = 1 << 2,
|
||||
ARM_HWCAP2_A64_SVEPMULL = 1 << 3,
|
||||
ARM_HWCAP2_A64_SVEBITPERM = 1 << 4,
|
||||
ARM_HWCAP2_A64_SVESHA3 = 1 << 5,
|
||||
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
|
||||
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
|
||||
ARM_HWCAP2_A64_FRINT = 1 << 8,
|
||||
ARM_HWCAP2_A64_SVEI8MM = 1 << 9,
|
||||
ARM_HWCAP2_A64_SVEF32MM = 1 << 10,
|
||||
ARM_HWCAP2_A64_SVEF64MM = 1 << 11,
|
||||
ARM_HWCAP2_A64_SVEBF16 = 1 << 12,
|
||||
ARM_HWCAP2_A64_I8MM = 1 << 13,
|
||||
ARM_HWCAP2_A64_BF16 = 1 << 14,
|
||||
ARM_HWCAP2_A64_DGH = 1 << 15,
|
||||
ARM_HWCAP2_A64_RNG = 1 << 16,
|
||||
ARM_HWCAP2_A64_BTI = 1 << 17,
|
||||
ARM_HWCAP2_A64_MTE = 1 << 18,
|
||||
};
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
#define ELF_HWCAP2 get_elf_hwcap2()
|
||||
|
||||
#define GET_FEATURE_ID(feat, hwcap) \
|
||||
do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
|
||||
|
||||
static uint32_t get_elf_hwcap(void)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(thread_cpu);
|
||||
uint32_t hwcaps = 0;
|
||||
|
||||
hwcaps |= ARM_HWCAP_A64_FP;
|
||||
hwcaps |= ARM_HWCAP_A64_ASIMD;
|
||||
hwcaps |= ARM_HWCAP_A64_CPUID;
|
||||
|
||||
/* probe for the extra features */
|
||||
|
||||
GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
|
||||
GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
|
||||
GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1);
|
||||
GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2);
|
||||
GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512);
|
||||
GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32);
|
||||
GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3);
|
||||
GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
|
||||
GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
|
||||
GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
|
||||
GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
|
||||
GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
|
||||
GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
|
||||
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
|
||||
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
|
||||
GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
|
||||
GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
|
||||
GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
|
||||
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
|
||||
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
|
||||
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
|
||||
GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
|
||||
GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
static uint32_t get_elf_hwcap2(void)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(thread_cpu);
|
||||
uint32_t hwcaps = 0;
|
||||
|
||||
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
|
||||
GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2);
|
||||
GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES);
|
||||
GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL);
|
||||
GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM);
|
||||
GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3);
|
||||
GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4);
|
||||
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
||||
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
||||
GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM);
|
||||
GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM);
|
||||
GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM);
|
||||
GET_FEATURE_ID(aa64_sve_bf16, ARM_HWCAP2_A64_SVEBF16);
|
||||
GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM);
|
||||
GET_FEATURE_ID(aa64_bf16, ARM_HWCAP2_A64_BF16);
|
||||
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
|
||||
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
|
||||
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
#undef GET_FEATURE_ID
|
||||
|
||||
#endif /* TARGET_ARCH_ELF_H */
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* FreeBSD arm64 register structures
|
||||
*
|
||||
* Copyright (c) 2015 Stacey Son
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_REG_H
|
||||
#define TARGET_ARCH_REG_H
|
||||
|
||||
/* See sys/arm64/include/reg.h */
|
||||
typedef struct target_reg {
|
||||
uint64_t x[30];
|
||||
uint64_t lr;
|
||||
uint64_t sp;
|
||||
uint64_t elr;
|
||||
uint64_t spsr;
|
||||
} target_reg_t;
|
||||
|
||||
typedef struct target_fpreg {
|
||||
Int128 fp_q[32];
|
||||
uint32_t fp_sr;
|
||||
uint32_t fp_cr;
|
||||
} target_fpreg_t;
|
||||
|
||||
#define tswapreg(ptr) tswapal(ptr)
|
||||
|
||||
static inline void target_copy_regs(target_reg_t *regs, CPUARMState *env)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
regs->x[i] = tswapreg(env->xregs[i]);
|
||||
}
|
||||
regs->lr = tswapreg(env->xregs[30]);
|
||||
regs->sp = tswapreg(env->xregs[31]);
|
||||
regs->elr = tswapreg(env->pc);
|
||||
regs->spsr = tswapreg(pstate_read(env));
|
||||
}
|
||||
|
||||
#undef tswapreg
|
||||
|
||||
#endif /* TARGET_ARCH_REG_H */
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* ARM AArch64 specific signal definitions for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_SIGNAL_H
|
||||
#define TARGET_ARCH_SIGNAL_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#define TARGET_REG_X0 0
|
||||
#define TARGET_REG_X30 30
|
||||
#define TARGET_REG_X31 31
|
||||
#define TARGET_REG_LR TARGET_REG_X30
|
||||
#define TARGET_REG_SP TARGET_REG_X31
|
||||
|
||||
#define TARGET_INSN_SIZE 4 /* arm64 instruction size */
|
||||
|
||||
/* Size of the signal trampolin code. See _sigtramp(). */
|
||||
#define TARGET_SZSIGCODE ((abi_ulong)(9 * TARGET_INSN_SIZE))
|
||||
|
||||
/* compare to sys/arm64/include/_limits.h */
|
||||
#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
|
||||
#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size */
|
||||
|
||||
/* struct __mcontext in sys/arm64/include/ucontext.h */
|
||||
|
||||
struct target_gpregs {
|
||||
uint64_t gp_x[30];
|
||||
uint64_t gp_lr;
|
||||
uint64_t gp_sp;
|
||||
uint64_t gp_elr;
|
||||
uint32_t gp_spsr;
|
||||
uint32_t gp_pad;
|
||||
};
|
||||
|
||||
struct target_fpregs {
|
||||
Int128 fp_q[32];
|
||||
uint32_t fp_sr;
|
||||
uint32_t fp_cr;
|
||||
uint32_t fp_flags;
|
||||
uint32_t fp_pad;
|
||||
};
|
||||
|
||||
struct target__mcontext {
|
||||
struct target_gpregs mc_gpregs;
|
||||
struct target_fpregs mc_fpregs;
|
||||
uint32_t mc_flags;
|
||||
#define TARGET_MC_FP_VALID 0x1
|
||||
uint32_t mc_pad;
|
||||
uint64_t mc_spare[8];
|
||||
};
|
||||
|
||||
typedef struct target__mcontext target_mcontext_t;
|
||||
|
||||
#define TARGET_MCONTEXT_SIZE 880
|
||||
#define TARGET_UCONTEXT_SIZE 960
|
||||
|
||||
#include "target_os_ucontext.h"
|
||||
|
||||
struct target_sigframe {
|
||||
target_siginfo_t sf_si; /* saved siginfo */
|
||||
target_ucontext_t sf_uc; /* saved ucontext */
|
||||
};
|
||||
|
||||
#define TARGET_SIGSTACK_ALIGN 16
|
||||
|
||||
#endif /* TARGET_ARCH_SIGNAL_H */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* ARM AArch64 sigcode for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_SIGTRAMP_H
|
||||
#define TARGET_ARCH_SIGTRAMP_H
|
||||
|
||||
/* Compare to ENTRY(sigcode) in arm64/arm64/locore.S */
|
||||
static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
|
||||
unsigned sys_sigreturn)
|
||||
{
|
||||
int i;
|
||||
uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
|
||||
|
||||
uint32_t sigtramp_code[] = {
|
||||
/* 1 */ 0x910003e0, /* mov x0, sp */
|
||||
/* 2 */ 0x91000000 + (sigf_uc << 10), /* add x0, x0, #SIGF_UC */
|
||||
/* 3 */ 0xd2800000 + (sys_sigreturn << 5) + 0x8, /* mov x8, #SYS_sigreturn */
|
||||
/* 4 */ 0xd4000001, /* svc #0 */
|
||||
/* 5 */ 0xd2800028 + (sys_exit << 5) + 0x8, /* mov x8, #SYS_exit */
|
||||
/* 6 */ 0xd4000001, /* svc #0 */
|
||||
/* 7 */ 0x17fffffc, /* b -4 */
|
||||
/* 8 */ sys_sigreturn,
|
||||
/* 9 */ sys_exit
|
||||
};
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
tswap32s(&sigtramp_code[i]);
|
||||
}
|
||||
|
||||
return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
|
||||
}
|
||||
#endif /* TARGET_ARCH_SIGTRAMP_H */
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* ARM AArch64 sysarch() system call emulation for bsd-user.
|
||||
*
|
||||
* Copyright (c) 2015 <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_SYSARCH_H
|
||||
#define TARGET_ARCH_SYSARCH_H
|
||||
|
||||
#include "target_syscall.h"
|
||||
#include "target_arch.h"
|
||||
|
||||
/* See sysarch() in sys/arm64/arm64/sys_machdep.c */
|
||||
static inline abi_long do_freebsd_arch_sysarch(CPUARMState *env, int op,
|
||||
abi_ulong parms)
|
||||
{
|
||||
int ret = -TARGET_EOPNOTSUPP;
|
||||
|
||||
fprintf(stderr, "sysarch");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void do_freebsd_arch_print_sysarch(
|
||||
const struct syscallname *name, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* TARGET_ARCH_SYSARCH_H */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* ARM AArch64 thread support for bsd-user.
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_THREAD_H
|
||||
#define TARGET_ARCH_THREAD_H
|
||||
|
||||
/* Compare to arm64/arm64/vm_machdep.c cpu_set_upcall_kse() */
|
||||
static inline void target_thread_set_upcall(CPUARMState *regs, abi_ulong entry,
|
||||
abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
|
||||
{
|
||||
abi_ulong sp;
|
||||
|
||||
/*
|
||||
* Make sure the stack is properly aligned.
|
||||
* arm64/include/param.h (STACKLIGN() macro)
|
||||
*/
|
||||
sp = ROUND_DOWN(stack_base + stack_size, 16);
|
||||
|
||||
/* sp = stack base */
|
||||
regs->xregs[31] = sp;
|
||||
/* pc = start function entry */
|
||||
regs->pc = entry;
|
||||
/* r0 = arg */
|
||||
regs->xregs[0] = arg;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline void target_thread_init(struct target_pt_regs *regs,
|
||||
struct image_info *infop)
|
||||
{
|
||||
abi_long stack = infop->start_stack;
|
||||
|
||||
/*
|
||||
* Make sure the stack is properly aligned.
|
||||
* arm64/include/param.h (STACKLIGN() macro)
|
||||
*/
|
||||
|
||||
memset(regs, 0, sizeof(*regs));
|
||||
regs->regs[0] = infop->start_stack;
|
||||
regs->pc = infop->entry;
|
||||
regs->sp = ROUND_DOWN(stack, 16);
|
||||
}
|
||||
|
||||
#endif /* TARGET_ARCH_THREAD_H */
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* ARM AArch64 VM parameters definitions for bsd-user.
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARCH_VMPARAM_H
|
||||
#define TARGET_ARCH_VMPARAM_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
/**
|
||||
* FreeBSD/arm64 Address space layout.
|
||||
*
|
||||
* ARMv8 implements up to a 48 bit virtual address space. The address space is
|
||||
* split into 2 regions at each end of the 64 bit address space, with an
|
||||
* out of range "hole" in the middle.
|
||||
*
|
||||
* We limit the size of the two spaces to 39 bits each.
|
||||
*
|
||||
* Upper region: 0xffffffffffffffff
|
||||
* 0xffffff8000000000
|
||||
*
|
||||
* Hole: 0xffffff7fffffffff
|
||||
* 0x0000008000000000
|
||||
*
|
||||
* Lower region: 0x0000007fffffffff
|
||||
* 0x0000000000000000
|
||||
*
|
||||
* The upper region for the kernel, and the lower region for userland.
|
||||
*/
|
||||
|
||||
|
||||
/* compare to sys/arm64/include/vmparam.h */
|
||||
#define TARGET_MAXTSIZ (1 * GiB) /* max text size */
|
||||
#define TARGET_DFLDSIZ (128 * MiB) /* initial data size limit */
|
||||
#define TARGET_MAXDSIZ (1 * GiB) /* max data size */
|
||||
#define TARGET_DFLSSIZ (128 * MiB) /* initial stack size limit */
|
||||
#define TARGET_MAXSSIZ (1 * GiB) /* max stack size */
|
||||
#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */
|
||||
|
||||
/* KERNBASE - 512 MB */
|
||||
#define TARGET_VM_MAXUSER_ADDRESS (0x00007fffff000000ULL - (512 * MiB))
|
||||
#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
|
||||
{
|
||||
return state->xregs[31]; /* sp */
|
||||
}
|
||||
|
||||
static inline void set_second_rval(CPUARMState *state, abi_ulong retval2)
|
||||
{
|
||||
state->xregs[1] = retval2; /* XXX not really used on 64-bit arch */
|
||||
}
|
||||
|
||||
static inline abi_ulong get_second_rval(CPUARMState *state)
|
||||
{
|
||||
return state->xregs[1];
|
||||
}
|
||||
|
||||
#endif /* TARGET_ARCH_VMPARAM_H */
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* ARM AArch64 specific CPU for bsd-user
|
||||
*
|
||||
* Copyright (c) 2015 Stacey D. Son <sson at Freebsd>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BSD_USER_AARCH64_TARGET_SYSCALL_H
|
||||
#define BSD_USER_AARCH64_TARGET_SYSCALL_H
|
||||
|
||||
/*
|
||||
* The aarch64 registers are named:
|
||||
*
|
||||
* x0 through x30 - for 64-bit-wide access (same registers)
|
||||
* Register '31' is one of two registers depending on the instruction context:
|
||||
* For instructions dealing with the stack, it is the stack pointer, named rsp
|
||||
* For all other instructions, it is a "zero" register, which returns 0 when
|
||||
* read and discards data when written - named rzr (xzr, wzr)
|
||||
*
|
||||
* Usage during syscall/function call:
|
||||
* r0-r7 are used for arguments and return values
|
||||
* For syscalls, the syscall number is in r8
|
||||
* r9-r15 are for temporary values (may get trampled)
|
||||
* r16-r18 are used for intra-procedure-call and platform values (avoid)
|
||||
* The called routine is expected to preserve r19-r28
|
||||
* r29 and r30 are used as the frame register and link register (avoid)
|
||||
* See the ARM Procedure Call Reference for details.
|
||||
*/
|
||||
struct target_pt_regs {
|
||||
uint64_t regs[31];
|
||||
uint64_t sp;
|
||||
uint64_t pc;
|
||||
uint64_t pstate;
|
||||
};
|
||||
|
||||
#define TARGET_HW_MACHINE "arm64"
|
||||
#define TARGET_HW_MACHINE_ARCH "aarch64"
|
||||
|
||||
#endif /* BSD_USER_AARCH64_TARGET_SYSCALL_H */
|
|
@ -86,4 +86,6 @@ struct target_sigframe {
|
|||
target_mcontext_vfp_t sf_vfp; /* actual saved VFP context */
|
||||
};
|
||||
|
||||
#define TARGET_SIGSTACK_ALIGN 8
|
||||
|
||||
#endif /* TARGET_ARCH_SIGNAL_H */
|
||||
|
|
|
@ -26,65 +26,13 @@ struct kinfo_proc;
|
|||
|
||||
#include "qemu.h"
|
||||
|
||||
/*
|
||||
* Get the filename for the given file descriptor.
|
||||
* Note that this may return NULL (fail) if no longer cached in the kernel.
|
||||
*/
|
||||
static char *
|
||||
get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
|
||||
{
|
||||
char *ret = NULL;
|
||||
unsigned int cnt;
|
||||
struct procstat *procstat = NULL;
|
||||
struct kinfo_proc *kp = NULL;
|
||||
struct filestat_list *head = NULL;
|
||||
struct filestat *fst;
|
||||
|
||||
procstat = procstat_open_sysctl();
|
||||
if (procstat == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
|
||||
if (kp == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
head = procstat_getfiles(procstat, kp, 0);
|
||||
if (head == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
STAILQ_FOREACH(fst, head, next) {
|
||||
if (fd == fst->fs_fd) {
|
||||
if (fst->fs_path != NULL) {
|
||||
(void)strlcpy(filename, fst->fs_path, len);
|
||||
ret = filename;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (head != NULL) {
|
||||
procstat_freefiles(procstat, head);
|
||||
}
|
||||
if (kp != NULL) {
|
||||
procstat_freeprocs(procstat, kp);
|
||||
}
|
||||
if (procstat != NULL) {
|
||||
procstat_close(procstat);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* execve/fexecve
|
||||
*/
|
||||
abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
||||
abi_ulong guest_envp, int do_fexec)
|
||||
{
|
||||
char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
|
||||
char **argp, **envp, **qarg0;
|
||||
int argc, envc;
|
||||
abi_ulong gp;
|
||||
abi_ulong addr;
|
||||
|
@ -117,9 +65,7 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
|||
qarg0 = argp = g_new0(char *, argc + 9);
|
||||
/* save the first argument for the emulator */
|
||||
*argp++ = (char *)getprogname();
|
||||
qargp = argp;
|
||||
*argp++ = (char *)getprogname();
|
||||
qarg1 = argp;
|
||||
envp = g_new0(char *, envc + 1);
|
||||
for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
|
||||
if (get_user_ual(addr, gp)) {
|
||||
|
@ -137,7 +83,6 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
|||
total_size += strlen(*q) + 1;
|
||||
}
|
||||
*q++ = NULL;
|
||||
qargend = q;
|
||||
|
||||
for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
|
||||
if (get_user_ual(addr, gp)) {
|
||||
|
@ -166,71 +111,14 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
|||
}
|
||||
|
||||
if (do_fexec) {
|
||||
if (((int)path_or_fd > 0 &&
|
||||
is_target_elf_binary((int)path_or_fd)) == 1) {
|
||||
char execpath[PATH_MAX];
|
||||
|
||||
/*
|
||||
* The executable is an elf binary for the target
|
||||
* arch. execve() it using the emulator if we can
|
||||
* determine the filename path from the fd.
|
||||
*/
|
||||
if (get_filename_from_fd(getpid(), (int)path_or_fd, execpath,
|
||||
sizeof(execpath)) != NULL) {
|
||||
memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
|
||||
qarg1[1] = qarg1[0];
|
||||
qarg1[0] = (char *)"-0";
|
||||
qarg1 += 2;
|
||||
qargend += 2;
|
||||
*qarg1 = execpath;
|
||||
#ifndef DONT_INHERIT_INTERP_PREFIX
|
||||
memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
|
||||
*qarg1++ = (char *)"-L";
|
||||
*qarg1++ = (char *)interp_prefix;
|
||||
#endif
|
||||
ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
|
||||
} else {
|
||||
/* Getting the filename path failed. */
|
||||
ret = -TARGET_EBADF;
|
||||
goto execve_end;
|
||||
}
|
||||
} else {
|
||||
ret = get_errno(fexecve((int)path_or_fd, argp, envp));
|
||||
}
|
||||
ret = get_errno(fexecve((int)path_or_fd, argp, envp));
|
||||
} else {
|
||||
int fd;
|
||||
|
||||
p = lock_user_string(path_or_fd);
|
||||
if (p == NULL) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto execve_end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the header and see if it a target elf binary. If so
|
||||
* then execute using qemu user mode emulator.
|
||||
*/
|
||||
fd = open(p, O_RDONLY | O_CLOEXEC);
|
||||
if (fd > 0 && is_target_elf_binary(fd) == 1) {
|
||||
close(fd);
|
||||
/* execve() as a target binary using emulator. */
|
||||
memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
|
||||
qarg1[1] = qarg1[0];
|
||||
qarg1[0] = (char *)"-0";
|
||||
qarg1 += 2;
|
||||
qargend += 2;
|
||||
*qarg1 = (char *)p;
|
||||
#ifndef DONT_INHERIT_INTERP_PREFIX
|
||||
memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
|
||||
*qarg1++ = (char *)"-L";
|
||||
*qarg1++ = (char *)interp_prefix;
|
||||
#endif
|
||||
ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
|
||||
} else {
|
||||
close(fd);
|
||||
/* Execve() as a host native binary. */
|
||||
ret = get_errno(execve(p, argp, envp));
|
||||
}
|
||||
ret = get_errno(execve(p, argp, envp));
|
||||
unlock_user(p, path_or_fd, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,4 +88,6 @@ struct target_sigframe {
|
|||
uint32_t __spare__[2];
|
||||
};
|
||||
|
||||
#define TARGET_SIGSTACK_ALIGN 8
|
||||
|
||||
#endif /* TARGET_ARCH_SIGNAL_H */
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "qemu/path.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/plugin.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "user/guest-base.h"
|
||||
#include "tcg/startup.h"
|
||||
|
@ -90,7 +91,6 @@ unsigned long reserved_va;
|
|||
|
||||
const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
|
||||
const char *qemu_uname_release;
|
||||
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
|
||||
|
||||
unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
|
||||
unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
|
||||
|
@ -104,8 +104,9 @@ unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
|
|||
void fork_start(void)
|
||||
{
|
||||
start_exclusive();
|
||||
cpu_list_lock();
|
||||
mmap_fork_start();
|
||||
cpu_list_lock();
|
||||
qemu_plugin_user_prefork_lock();
|
||||
gdbserver_fork_start();
|
||||
}
|
||||
|
||||
|
@ -113,31 +114,31 @@ void fork_end(pid_t pid)
|
|||
{
|
||||
bool child = pid == 0;
|
||||
|
||||
qemu_plugin_user_postfork(child);
|
||||
mmap_fork_end(child);
|
||||
if (child) {
|
||||
CPUState *cpu, *next_cpu;
|
||||
/*
|
||||
* Child processes created by fork() only have a single thread. Discard
|
||||
* information about the parent threads.
|
||||
* Child processes created by fork() only have a single thread.
|
||||
* Discard information about the parent threads.
|
||||
*/
|
||||
CPU_FOREACH_SAFE(cpu, next_cpu) {
|
||||
if (cpu != thread_cpu) {
|
||||
QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
|
||||
}
|
||||
}
|
||||
mmap_fork_end(child);
|
||||
/*
|
||||
* qemu_init_cpu_list() takes care of reinitializing the exclusive
|
||||
* state, so we don't need to end_exclusive() here.
|
||||
*/
|
||||
qemu_init_cpu_list();
|
||||
get_task_state(thread_cpu)->ts_tid = qemu_get_thread_id();
|
||||
gdbserver_fork_end(thread_cpu, pid);
|
||||
} else {
|
||||
mmap_fork_end(child);
|
||||
cpu_list_unlock();
|
||||
gdbserver_fork_end(thread_cpu, pid);
|
||||
end_exclusive();
|
||||
}
|
||||
gdbserver_fork_end(thread_cpu, pid);
|
||||
/*
|
||||
* qemu_init_cpu_list() reinitialized the child exclusive state, but we
|
||||
* also need to keep current_cpu consistent, so call end_exclusive() for
|
||||
* both child and parent.
|
||||
*/
|
||||
end_exclusive();
|
||||
}
|
||||
|
||||
void cpu_loop(CPUArchState *env)
|
||||
|
@ -247,22 +248,6 @@ adjust_ssize(void)
|
|||
setrlimit(RLIMIT_STACK, &rl);
|
||||
}
|
||||
|
||||
static void save_proc_pathname(char *argv0)
|
||||
{
|
||||
int mib[4];
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PATHNAME;
|
||||
mib[3] = -1;
|
||||
|
||||
len = sizeof(qemu_proc_pathname);
|
||||
if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
|
||||
perror("sysctl");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *filename;
|
||||
|
@ -292,7 +277,6 @@ int main(int argc, char **argv)
|
|||
usage();
|
||||
}
|
||||
|
||||
save_proc_pathname(argv[0]);
|
||||
|
||||
error_init(argv[0]);
|
||||
module_call_init(MODULE_INIT_TRACE);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#ifndef QEMU_H
|
||||
#define QEMU_H
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "qemu/int128.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/units.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
|
|
@ -728,14 +728,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *ka,
|
|||
sp = ts->sigaltstack_used.ss_sp + ts->sigaltstack_used.ss_size;
|
||||
}
|
||||
|
||||
/* TODO: make this a target_arch function / define */
|
||||
#if defined(TARGET_ARM)
|
||||
return (sp - frame_size) & ~7;
|
||||
#elif defined(TARGET_AARCH64)
|
||||
return (sp - frame_size) & ~15;
|
||||
#else
|
||||
return sp - frame_size;
|
||||
#endif
|
||||
return ROUND_DOWN(sp - frame_size, TARGET_SIGSTACK_ALIGN);
|
||||
}
|
||||
|
||||
/* compare to $M/$M/exec_machdep.c sendsig and sys/kern/kern_sig.c sigexit */
|
||||
|
|
|
@ -97,4 +97,6 @@ struct target_sigframe {
|
|||
uint32_t __spare__[2];
|
||||
};
|
||||
|
||||
#define TARGET_SIGSTACK_ALIGN 16
|
||||
|
||||
#endif /* TARGET_ARCH_SIGNAL_H */
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml
|
|
@ -21,9 +21,13 @@
|
|||
#ifdef CONFIG_USER_ONLY
|
||||
# ifdef TARGET_AARCH64
|
||||
# define TARGET_TAGGED_ADDRESSES
|
||||
# ifdef __FreeBSD__
|
||||
# define TARGET_PAGE_BITS 12
|
||||
# else
|
||||
/* Allow user-only to vary page size from 4k */
|
||||
# define TARGET_PAGE_BITS_VARY
|
||||
# define TARGET_PAGE_BITS_MIN 12
|
||||
# endif
|
||||
# else
|
||||
# define TARGET_PAGE_BITS 12
|
||||
# endif
|
||||
|
|
|
@ -404,6 +404,7 @@ int aarch64_gdb_get_tag_ctl_reg(CPUState *cs, GByteArray *buf, int reg)
|
|||
|
||||
int aarch64_gdb_set_tag_ctl_reg(CPUState *cs, uint8_t *buf, int reg)
|
||||
{
|
||||
#if defined(CONFIG_LINUX)
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
|
||||
|
@ -425,6 +426,9 @@ int aarch64_gdb_set_tag_ctl_reg(CPUState *cs, uint8_t *buf, int reg)
|
|||
arm_set_mte_tcf0(env, tcf);
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_q_memtag(GArray *params, void *user_ctx)
|
||||
|
|
Loading…
Reference in New Issue