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:
Richard Henderson 2024-07-25 09:53:57 +10:00
commit 029e13a8a5
23 changed files with 1021 additions and 153 deletions

137
bsd-user/aarch64/signal.c Normal file
View File

@ -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;
}

20
bsd-user/aarch64/target.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -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];
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -88,4 +88,6 @@ struct target_sigframe {
uint32_t __spare__[2];
};
#define TARGET_SIGSTACK_ALIGN 8
#endif /* TARGET_ARCH_SIGNAL_H */

View File

@ -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);

View File

@ -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"

View File

@ -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 */

View File

@ -97,4 +97,6 @@ struct target_sigframe {
uint32_t __spare__[2];
};
#define TARGET_SIGSTACK_ALIGN 16
#endif /* TARGET_ARCH_SIGNAL_H */

View File

@ -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

View File

@ -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

View File

@ -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)