diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-07-25 09:53:57 +1000 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-07-25 09:53:57 +1000 |
commit | 029e13a8a56a2931e7c24c0db52ae7256b932cb0 (patch) | |
tree | cc99f8010af47daa4b77e889c7b7c7314d358a0f | |
parent | 9726687f2fdfe7ae4a3014d78c2b2f639f75e303 (diff) | |
parent | ec018b76798e1196882ebcbf3df15e6d86ac9d7c (diff) |
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>
-rw-r--r-- | bsd-user/aarch64/signal.c | 137 | ||||
-rw-r--r-- | bsd-user/aarch64/target.h | 20 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch.h | 29 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_cpu.c | 31 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_cpu.h | 189 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_elf.h | 163 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_reg.h | 56 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_signal.h | 82 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_sigtramp.h | 48 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_sysarch.h | 42 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_thread.h | 61 | ||||
-rw-r--r-- | bsd-user/aarch64/target_arch_vmparam.h | 74 | ||||
-rw-r--r-- | bsd-user/aarch64/target_syscall.h | 51 | ||||
-rw-r--r-- | bsd-user/arm/target_arch_signal.h | 2 | ||||
-rw-r--r-- | bsd-user/freebsd/os-proc.c | 118 | ||||
-rw-r--r-- | bsd-user/i386/target_arch_signal.h | 2 | ||||
-rw-r--r-- | bsd-user/main.c | 44 | ||||
-rw-r--r-- | bsd-user/qemu.h | 3 | ||||
-rw-r--r-- | bsd-user/signal.c | 9 | ||||
-rw-r--r-- | bsd-user/x86_64/target_arch_signal.h | 2 | ||||
-rw-r--r-- | configs/targets/aarch64-bsd-user.mak | 3 | ||||
-rw-r--r-- | target/arm/cpu-param.h | 4 | ||||
-rw-r--r-- | target/arm/gdbstub64.c | 4 |
23 files changed, 1021 insertions, 153 deletions
diff --git a/bsd-user/aarch64/signal.c b/bsd-user/aarch64/signal.c new file mode 100644 index 0000000000..6bc73a798f --- /dev/null +++ b/bsd-user/aarch64/signal.c @@ -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; +} diff --git a/bsd-user/aarch64/target.h b/bsd-user/aarch64/target.h new file mode 100644 index 0000000000..702aeb7fc5 --- /dev/null +++ b/bsd-user/aarch64/target.h @@ -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 */ diff --git a/bsd-user/aarch64/target_arch.h b/bsd-user/aarch64/target_arch.h new file mode 100644 index 0000000000..4815a56ae3 --- /dev/null +++ b/bsd-user/aarch64/target_arch.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 */ diff --git a/bsd-user/aarch64/target_arch_cpu.c b/bsd-user/aarch64/target_arch_cpu.c new file mode 100644 index 0000000000..b2fa59efaf --- /dev/null +++ b/bsd-user/aarch64/target_arch_cpu.c @@ -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]; +} diff --git a/bsd-user/aarch64/target_arch_cpu.h b/bsd-user/aarch64/target_arch_cpu.h new file mode 100644 index 0000000000..b288e0d069 --- /dev/null +++ b/bsd-user/aarch64/target_arch_cpu.h @@ -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 */ diff --git a/bsd-user/aarch64/target_arch_elf.h b/bsd-user/aarch64/target_arch_elf.h new file mode 100644 index 0000000000..cc87f475b3 --- /dev/null +++ b/bsd-user/aarch64/target_arch_elf.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 */ diff --git a/bsd-user/aarch64/target_arch_reg.h b/bsd-user/aarch64/target_arch_reg.h new file mode 100644 index 0000000000..b53302e7f7 --- /dev/null +++ b/bsd-user/aarch64/target_arch_reg.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 */ diff --git a/bsd-user/aarch64/target_arch_signal.h b/bsd-user/aarch64/target_arch_signal.h new file mode 100644 index 0000000000..b72ba7aa50 --- /dev/null +++ b/bsd-user/aarch64/target_arch_signal.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 */ diff --git a/bsd-user/aarch64/target_arch_sigtramp.h b/bsd-user/aarch64/target_arch_sigtramp.h new file mode 100644 index 0000000000..8cdd33b621 --- /dev/null +++ b/bsd-user/aarch64/target_arch_sigtramp.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 */ diff --git a/bsd-user/aarch64/target_arch_sysarch.h b/bsd-user/aarch64/target_arch_sysarch.h new file mode 100644 index 0000000000..b003015daf --- /dev/null +++ b/bsd-user/aarch64/target_arch_sysarch.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 */ diff --git a/bsd-user/aarch64/target_arch_thread.h b/bsd-user/aarch64/target_arch_thread.h new file mode 100644 index 0000000000..4c911e605a --- /dev/null +++ b/bsd-user/aarch64/target_arch_thread.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 */ diff --git a/bsd-user/aarch64/target_arch_vmparam.h b/bsd-user/aarch64/target_arch_vmparam.h new file mode 100644 index 0000000000..0c35491970 --- /dev/null +++ b/bsd-user/aarch64/target_arch_vmparam.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 */ diff --git a/bsd-user/aarch64/target_syscall.h b/bsd-user/aarch64/target_syscall.h new file mode 100644 index 0000000000..08ae913c42 --- /dev/null +++ b/bsd-user/aarch64/target_syscall.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 */ diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h index 02b2b33e07..10f96b8bfc 100644 --- a/bsd-user/arm/target_arch_signal.h +++ b/bsd-user/arm/target_arch_signal.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 */ diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c index e0203e259b..bf993f1b66 100644 --- a/bsd-user/freebsd/os-proc.c +++ b/bsd-user/freebsd/os-proc.c @@ -27,64 +27,12 @@ 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); } diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index 279dadc22c..2c14153ab6 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -88,4 +88,6 @@ struct target_sigframe { uint32_t __spare__[2]; }; +#define TARGET_SIGSTACK_ALIGN 8 + #endif /* TARGET_ARCH_SIGNAL_H */ diff --git a/bsd-user/main.c b/bsd-user/main.c index dcad266c2c..cc980e6f40 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -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); diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 9d2fc7148e..3736c41786 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -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" diff --git a/bsd-user/signal.c b/bsd-user/signal.c index 8b6654b91d..da49b9bffc 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -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 */ diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index ca24bf1e7f..f833ee66ce 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -97,4 +97,6 @@ struct target_sigframe { uint32_t __spare__[2]; }; +#define TARGET_SIGSTACK_ALIGN 16 + #endif /* TARGET_ARCH_SIGNAL_H */ diff --git a/configs/targets/aarch64-bsd-user.mak b/configs/targets/aarch64-bsd-user.mak new file mode 100644 index 0000000000..8aaa5d8c80 --- /dev/null +++ b/configs/targets/aarch64-bsd-user.mak @@ -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 diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h index 2d5f3aa312..fa6cae0e3a 100644 --- a/target/arm/cpu-param.h +++ b/target/arm/cpu-param.h @@ -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 diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index c8cef8cbc0..5221381cc8 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -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) |