Module Name: src Committed By: rin Date: Sun Nov 24 04:08:36 UTC 2019
Modified Files: src/sys/arch/aarch64/aarch64: exec_machdep.c netbsd32_machdep.c trap.c src/sys/arch/aarch64/include: netbsd32_machdep.h param.h proc.h Log Message: PR port-arm/54702 Add support for earmv6hf binaries on COMPAT_NETBSD32 for aarch64: - Emulate ARMv6 instructions with cache operations register (c7), that are deprecated since ARMv7, and disabled on ARMv8 with LP64 kernel. - ep_machine_arch (default: earmv7hf) is copied from executables, as we do for mips64. "uname -p" reports earmv6hf if compiled for earmv6hf; configure scripts etc can determine the appropriate architecture. Many thanks to ryo@ for helping me to add support of Thumb-mode, as well as providing exhaustive test cases: https://github.com/ryo/mcr_test/ We've confirmed: - Emulation works in Thumb-mode. - T32 16-bit length illegal instruction results in SIGILL, even if it is located nearby a boundary b/w mapped and unmapped pages. - T32 32-bit instruction results in SIGSEGV if it is located across a boundary b/w mapped and unmapped pages. XXX pullup to netbsd-9 To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/arch/aarch64/aarch64/exec_machdep.c cvs rdiff -u -r1.8 -r1.9 src/sys/arch/aarch64/aarch64/netbsd32_machdep.c cvs rdiff -u -r1.20 -r1.21 src/sys/arch/aarch64/aarch64/trap.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/aarch64/include/netbsd32_machdep.h cvs rdiff -u -r1.12 -r1.13 src/sys/arch/aarch64/include/param.h cvs rdiff -u -r1.3 -r1.4 src/sys/arch/aarch64/include/proc.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/aarch64/aarch64/exec_machdep.c diff -u src/sys/arch/aarch64/aarch64/exec_machdep.c:1.4 src/sys/arch/aarch64/aarch64/exec_machdep.c:1.5 --- src/sys/arch/aarch64/aarch64/exec_machdep.c:1.4 Wed Nov 28 08:12:15 2018 +++ src/sys/arch/aarch64/aarch64/exec_machdep.c Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: exec_machdep.c,v 1.4 2018/11/28 08:12:15 ryo Exp $ */ +/* $NetBSD: exec_machdep.c,v 1.5 2019/11/24 04:08:36 rin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: exec_machdep.c,v 1.4 2018/11/28 08:12:15 ryo Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exec_machdep.c,v 1.5 2019/11/24 04:08:36 rin Exp $"); #include "opt_compat_netbsd.h" #include "opt_compat_netbsd32.h" @@ -83,6 +83,13 @@ aarch64_netbsd_elf32_probe(struct lwp *l ID_AA64PFR0_EL1_EL0_64_32) return ENOEXEC; + /* + * Copy (if any) the machine_arch of the executable to the proc. + */ + if (epp->ep_machine_arch[0] != 0) + strlcpy(l->l_proc->p_md.md_march32, epp->ep_machine_arch, + sizeof(l->l_proc->p_md.md_march32)); + return 0; } #endif Index: src/sys/arch/aarch64/aarch64/netbsd32_machdep.c diff -u src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.8 src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.9 --- src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.8 Wed Nov 20 19:37:51 2019 +++ src/sys/arch/aarch64/aarch64/netbsd32_machdep.c Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_machdep.c,v 1.8 2019/11/20 19:37:51 pgoyette Exp $ */ +/* $NetBSD: netbsd32_machdep.c,v 1.9 2019/11/24 04:08:36 rin Exp $ */ /* * Copyright (c) 2018 Ryo Shimizu <r...@nerv.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.8 2019/11/20 19:37:51 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.9 2019/11/24 04:08:36 rin Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -55,11 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_mac #include <aarch64/userret.h> const char machine32[] = MACHINE; -#ifdef __AARCH64EB__ -const char machine_arch32[] = "earmv7hfeb"; -#else -const char machine_arch32[] = "earmv7hf"; -#endif +const char machine_arch32[] = MACHINE32_ARCH; void netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) Index: src/sys/arch/aarch64/aarch64/trap.c diff -u src/sys/arch/aarch64/aarch64/trap.c:1.20 src/sys/arch/aarch64/aarch64/trap.c:1.21 --- src/sys/arch/aarch64/aarch64/trap.c:1.20 Thu Nov 21 19:23:58 2019 +++ src/sys/arch/aarch64/aarch64/trap.c Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.20 2019/11/21 19:23:58 ad Exp $ */ +/* $NetBSD: trap.c,v 1.21 2019/11/24 04:08:36 rin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.20 2019/11/21 19:23:58 ad Exp $"); +__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.21 2019/11/24 04:08:36 rin Exp $"); #include "opt_arm_intr_impl.h" #include "opt_compat_netbsd32.h" @@ -321,6 +321,103 @@ interrupt(struct trapframe *tf) cpu_dosoftints(); } +#ifdef COMPAT_NETBSD32 + +/* + * 32-bit length Thumb instruction. See ARMv7 DDI0406A A6.3. + */ +#define THUMB_32BIT(hi) (((hi) & 0xe000) == 0xe000 && ((hi) & 0x1800)) + +static int +fetch_arm_insn(struct trapframe *tf, uint32_t *insn) +{ + + /* THUMB? */ + if (tf->tf_spsr & SPSR_A32_T) { + uint16_t *pc = (uint16_t *)(tf->tf_pc & ~1UL); /* XXX */ + uint16_t hi, lo; + + hi = *pc; + if (!THUMB_32BIT(hi)) { + /* 16-bit Thumb instruction */ + *insn = hi; + return 2; + } + + /* + * 32-bit Thumb instruction: + * We can safely retrieve the lower-half word without + * consideration of a page fault; If present, it must + * have occurred already in the decode stage. + */ + lo = *(pc + 1); + + *insn = ((uint32_t)hi << 16) | lo; + return 4; + } + + *insn = *(uint32_t *)tf->tf_pc; + return 4; +} + +static int +emul_arm_insn(struct trapframe *tf) +{ + uint32_t insn; + int insn_size; + + insn_size = fetch_arm_insn(tf, &insn); + + switch (insn_size) { + case 2: + /* T32-16bit instruction */ + + /* XXX: some T32 IT instruction deprecated should be emulated */ + break; + case 4: + /* T32-32bit instruction, or A32 instruction */ + + /* + * Emulate ARMv6 instructions with cache operations + * register (c7), that can be used in user mode. + */ + switch (insn & 0x0fff0fff) { + case 0x0e070f95: + /* + * mcr p15, 0, <Rd>, c7, c5, 4 + * (flush prefetch buffer) + */ + __asm __volatile("isb sy" ::: "memory"); + goto emulated; + case 0x0e070f9a: + /* + * mcr p15, 0, <Rd>, c7, c10, 4 + * (data synchronization barrier) + */ + __asm __volatile("dsb sy" ::: "memory"); + goto emulated; + case 0x0e070fba: + /* + * mcr p15, 0, <Rd>, c7, c10, 5 + * (data memory barrier) + */ + __asm __volatile("dmb sy" ::: "memory"); + goto emulated; + default: + break; + } + break; + } + + /* unknown, or unsupported instruction */ + return 1; + + emulated: + tf->tf_pc += insn_size; + return 0; +} +#endif /* COMPAT_NETBSD32 */ + void trap_el0_32sync(struct trapframe *tf) { @@ -371,11 +468,18 @@ trap_el0_32sync(struct trapframe *tf) userret(l); break; + case ESR_EC_UNKNOWN: + if (emul_arm_insn(tf)) + goto unknown; + userret(l); + break; + case ESR_EC_CP15_RT: case ESR_EC_CP15_RRT: case ESR_EC_CP14_RT: case ESR_EC_CP14_DT: case ESR_EC_CP14_RRT: +unknown: #endif /* COMPAT_NETBSD32 */ default: #ifdef DDB Index: src/sys/arch/aarch64/include/netbsd32_machdep.h diff -u src/sys/arch/aarch64/include/netbsd32_machdep.h:1.2 src/sys/arch/aarch64/include/netbsd32_machdep.h:1.3 --- src/sys/arch/aarch64/include/netbsd32_machdep.h:1.2 Fri Oct 12 01:28:58 2018 +++ src/sys/arch/aarch64/include/netbsd32_machdep.h Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_machdep.h,v 1.2 2018/10/12 01:28:58 ryo Exp $ */ +/* $NetBSD: netbsd32_machdep.h,v 1.3 2019/11/24 04:08:36 rin Exp $ */ #ifndef _MACHINE_NETBSD32_H_ #define _MACHINE_NETBSD32_H_ @@ -107,4 +107,7 @@ struct netbsd32_arm_sync_icache_args { netbsd32_size_t len; /* Region size */ }; +/* Support varying ABI names for netbsd32 */ +#define PROC_MACHINE_ARCH32(P) ((P)->p_md.md_march32) + #endif /* _MACHINE_NETBSD32_H_ */ Index: src/sys/arch/aarch64/include/param.h diff -u src/sys/arch/aarch64/include/param.h:1.12 src/sys/arch/aarch64/include/param.h:1.13 --- src/sys/arch/aarch64/include/param.h:1.12 Sat Oct 19 18:04:26 2019 +++ src/sys/arch/aarch64/include/param.h Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.12 2019/10/19 18:04:26 jmcneill Exp $ */ +/* $NetBSD: param.h,v 1.13 2019/11/24 04:08:36 rin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -59,9 +59,13 @@ # ifdef __AARCH64EB__ # define _MACHINE_ARCH aarch64eb # define MACHINE_ARCH "aarch64eb" +# define _MACHINE32_ARCH earmv7hfeb +# define MACHINE32_ARCH "earmv7hfeb" # else # define _MACHINE_ARCH aarch64 # define MACHINE_ARCH "aarch64" +# define _MACHINE32_ARCH earmv7hf +# define MACHINE32_ARCH "earmv7hf" # endif /* __AARCH64EB__ */ # endif /* MACHINE_ARCH */ #else @@ -69,14 +73,20 @@ # undef MACHINE # undef _MACHINE_ARCH # undef MACHINE_ARCH +# undef _MACHINE32_ARCH +# undef MACHINE32_ARCH # define _MACHINE aarch64 # define MACHINE "aarch64" # ifdef __AARCH64EB__ # define _MACHINE_ARCH aarch64eb # define MACHINE_ARCH "aarch64eb" +# define _MACHINE32_ARCH earmv7hfeb +# define MACHINE32_ARCH "earmv7hfeb" # else # define _MACHINE_ARCH aarch64 # define MACHINE_ARCH "aarch64" +# define _MACHINE32_ARCH earmv7hf +# define MACHINE32_ARCH "earmv7hf" # endif /* __AARCH64EB__ */ #endif /* !_KERNEL */ Index: src/sys/arch/aarch64/include/proc.h diff -u src/sys/arch/aarch64/include/proc.h:1.3 src/sys/arch/aarch64/include/proc.h:1.4 --- src/sys/arch/aarch64/include/proc.h:1.3 Thu Dec 27 09:55:27 2018 +++ src/sys/arch/aarch64/include/proc.h Sun Nov 24 04:08:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.3 2018/12/27 09:55:27 mrg Exp $ */ +/* $NetBSD: proc.h,v 1.4 2019/11/24 04:08:36 rin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -34,6 +34,10 @@ #ifdef __aarch64__ +#ifdef _KERNEL_OPT +#include "opt_compat_netbsd32.h" +#endif + struct mdlwp { void *md_onfault; struct trapframe *md_utf; @@ -43,8 +47,15 @@ struct mdlwp { struct mdproc { void (*md_syscall)(struct trapframe *); +#ifdef COMPAT_NETBSD32 + char md_march32[12]; /* machine arch of executable */ +#endif }; +#ifdef COMPAT_NETBSD32 +#define PROC0_MD_INITIALIZERS .p_md = { .md_march32 = MACHINE32_ARCH }, +#endif + #elif defined(__arm__) #include <arm/proc.h>