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
This commit is contained in:
parent
8add6aa962
commit
197cf882e7
|
@ -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, struct exec_package *epp, void *eh0,
|
|||
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
|
||||
|
|
|
@ -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 <ryo@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_machdep.c,v 1.8 2019/11/20 19:37:51 pgoyett
|
|||
#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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue