Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch add initial support of COMPAT_NETBSD32 on AArch64.
details: https://anonhg.NetBSD.org/src/rev/f618a7ecb93f
branches: trunk
changeset: 993938:f618a7ecb93f
user: ryo <ryo%NetBSD.org@localhost>
date: Fri Oct 12 01:28:57 2018 +0000
description:
add initial support of COMPAT_NETBSD32 on AArch64.
arm ELF32 EABI binaries could be execute in AArch32 state on AArch64. A32 THUMB mode is not supported yet.
diffstat:
sys/arch/aarch64/aarch64/aarch32_syscall.c | 191 +++++++++++
sys/arch/aarch64/aarch64/cpuswitch.S | 8 +-
sys/arch/aarch64/aarch64/db_disasm.c | 19 +-
sys/arch/aarch64/aarch64/db_machdep.c | 34 +-
sys/arch/aarch64/aarch64/exec_machdep.c | 25 +-
sys/arch/aarch64/aarch64/fault.c | 13 +-
sys/arch/aarch64/aarch64/locore.S | 7 +-
sys/arch/aarch64/aarch64/netbsd32_machdep.c | 479 ++++++++++++++++++++++++++-
sys/arch/aarch64/aarch64/netbsd32_syscall.c | 39 ++
sys/arch/aarch64/aarch64/pmap.c | 45 ++-
sys/arch/aarch64/aarch64/trap.c | 62 ++-
sys/arch/aarch64/aarch64/vectors.S | 20 +-
sys/arch/aarch64/conf/files.aarch64 | 5 +-
sys/arch/aarch64/include/armreg.h | 3 +-
sys/arch/aarch64/include/db_machdep.h | 3 +-
sys/arch/aarch64/include/elf_machdep.h | 9 +-
sys/arch/aarch64/include/netbsd32_machdep.h | 46 ++-
sys/arch/aarch64/include/param.h | 7 +-
sys/arch/aarch64/include/pmap.h | 3 +-
sys/arch/aarch64/include/vmparam.h | 11 +-
sys/arch/arm/include/mcontext.h | 4 +-
sys/arch/evbarm/conf/GENERIC64 | 5 +-
sys/arch/evbarm/conf/RPI64 | 5 +-
23 files changed, 935 insertions(+), 108 deletions(-)
diffs (truncated from 1606 to 300 lines):
diff -r 02a0ca808fee -r f618a7ecb93f sys/arch/aarch64/aarch64/aarch32_syscall.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/aarch64/aarch64/aarch32_syscall.c Fri Oct 12 01:28:57 2018 +0000
@@ -0,0 +1,191 @@
+/* $NetBSD: aarch32_syscall.c,v 1.1 2018/10/12 01:28:57 ryo Exp $ */
+
+/*
+ * Copyright (c) 2018 Ryo Shimizu <ryo%nerv.org@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: aarch32_syscall.c,v 1.1 2018/10/12 01:28:57 ryo Exp $");
+
+#include "opt_multiprocessor.h"
+
+#include <sys/param.h>
+#include <sys/ktrace.h>
+#include <sys/proc.h>
+#include <sys/syscallvar.h>
+#include <uvm/uvm_extern.h>
+
+#include <aarch64/userret.h>
+#include <aarch64/frame.h>
+#include <aarch64/armreg.h>
+
+#ifndef EMULNAME
+#error EMULNAME is not defined
+#endif
+
+#ifndef NARGREG
+#define NARGREG 4 /* 4 args are in registers */
+#endif
+
+static void EMULNAME(syscall)(struct trapframe *);
+
+union args {
+ register_t a64[EMULNAMEU(SYS_MAXSYSARGS)];
+ register32_t a32[EMULNAMEU(SYS_MAXSYSARGS)];
+};
+
+void
+EMULNAME(syscall)(struct trapframe *tf)
+{
+ struct lwp * const l = curlwp;
+ struct proc * const p = l->l_proc;
+ const struct sysent *callp;
+ union args args64buf, args32buf;
+ register_t rval[2];
+ register32_t *args32 = args32buf.a32;
+ int error, i;
+ bool do_trace;
+
+ LWP_CACHE_CREDS(l, p);
+
+ curcpu()->ci_data.cpu_nsyscall++;
+
+ uint32_t code = tf->tf_esr & 0xffff; /* XXX: 16-23bits are omitted */
+
+ /*
+ * XXX: for netbsd32 emulation, SWI_OS_NETBSD should be checked?
+ * 16-23bits of imm of swi is omitted. need to read insn?
+ */
+#ifdef THUMB_CODE
+#error notyet
+ if (tf->tf_spsr & SPSR_A32_T) {
+ code |= tf->tf_reg[0];
+ tf->tf_reg[0] = tf->tf_reg[12]; /* r0 = ip(r12) */
+ }
+#endif
+
+ int nargs_reg = NARGREG; /* number of argument in registers */
+ int regstart = 0; /* args start from r0 */
+
+ code %= EMULNAMEU(SYS_NSYSENT);
+ callp = p->p_emul->e_sysent + code;
+ if (__predict_false(callp->sy_flags & SYCALL_INDIRECT)) {
+ nargs_reg -= 1;
+ regstart = 1; /* args start from r1 */
+ code = tf->tf_reg[0] % EMULNAMEU(SYS_NSYSENT);
+ callp = p->p_emul->e_sysent + code;
+
+ /* don't allow nested syscall */
+ if (__predict_false(callp->sy_flags & SYCALL_INDIRECT)) {
+ error = EINVAL;
+ goto bad;
+ }
+ }
+
+ /* number of argument to fetch from sp */
+ KASSERT(callp->sy_narg <= EMULNAMEU(SYS_MAXSYSARGS));
+ int nargs_sp = callp->sy_narg - nargs_reg;
+
+ /* fetch arguments from tf and sp, and store to args32buf[] */
+ for (i = 0; i < nargs_reg; i++)
+ *args32++ = (uint32_t)tf->tf_reg[regstart++];
+ if (nargs_sp > 0) {
+ error = copyin(
+ (void*)(uintptr_t)(uint32_t)tf->tf_reg[13], /* sp = r13 */
+ args32, nargs_sp * sizeof(register32_t));
+ if (error)
+ goto bad;
+ }
+
+ rval[0] = rval[1] = 0;
+
+#if 0
+ error = sy_invoke(callp, l, args32buf.a32, rval, code);
+#else
+ /*
+ * XXX: trace_enter()/trace_exit() called from sy_invoke() expects
+ * 64bit args, but sy_invoke doesn't take care of it.
+ * therefore call trace_enter(), sy_call(), trace_exit() manually.
+ */
+#ifdef KDTRACE_HOOKS
+#define KDTRACE_ENTRY(a) (a)
+#else
+#define KDTRACE_ENTRY(a) (0)
+#endif
+ do_trace = p->p_trace_enabled &&
+ ((callp->sy_flags & SYCALL_INDIRECT) == 0);
+ if (__predict_false(do_trace ||
+ KDTRACE_ENTRY(callp->sy_entry) || KDTRACE_ENTRY(callp->sy_return))) {
+ /* build 64bit args for trace_enter()/trace_exit() */
+ int nargs = callp->sy_narg;
+ for (i = 0; i < nargs; i++)
+ args64buf.a64[i] = args32buf.a32[i];
+ }
+
+ if (__predict_false(do_trace || KDTRACE_ENTRY(callp->sy_entry)))
+ error = trace_enter(code, callp, args64buf.a64);
+
+ if (error == 0)
+ error = sy_call(callp, l, args32buf.a32, rval);
+
+ if (__predict_false(do_trace || KDTRACE_ENTRY(callp->sy_return)))
+ trace_exit(code, callp, args64buf.a64, rval, error);
+#endif
+
+ if (__predict_true(error == 0)) {
+ tf->tf_reg[0] = rval[0];
+ tf->tf_reg[1] = rval[1];
+ tf->tf_spsr &= ~NZCV_C;
+ } else {
+ switch (error) {
+ case ERESTART:
+ /* redo system call insn */
+ tf->tf_pc -= 4;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ bad:
+#ifndef __HAVE_MINIMAL_EMUL
+ if (p->p_emul->e_errno)
+ error = p->p_emul->e_errno[error];
+#endif
+ tf->tf_reg[0] = error;
+ tf->tf_spsr |= NZCV_C;
+ break;
+ }
+ }
+
+ userret(l);
+}
+
+void EMULNAME(syscall_intern)(struct proc *);
+
+void
+EMULNAME(syscall_intern)(struct proc *p)
+{
+ p->p_md.md_syscall = EMULNAME(syscall);
+}
diff -r 02a0ca808fee -r f618a7ecb93f sys/arch/aarch64/aarch64/cpuswitch.S
--- a/sys/arch/aarch64/aarch64/cpuswitch.S Fri Oct 12 01:16:20 2018 +0000
+++ b/sys/arch/aarch64/aarch64/cpuswitch.S Fri Oct 12 01:28:57 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuswitch.S,v 1.4 2018/07/17 18:08:36 christos Exp $ */
+/* $NetBSD: cpuswitch.S,v 1.5 2018/10/12 01:28:57 ryo Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -33,9 +33,10 @@
#include <aarch64/locore.h>
#include "assym.h"
+#include "opt_compat_netbsd32.h"
#include "opt_ddb.h"
-RCSID("$NetBSD: cpuswitch.S,v 1.4 2018/07/17 18:08:36 christos Exp $")
+RCSID("$NetBSD: cpuswitch.S,v 1.5 2018/10/12 01:28:57 ryo Exp $")
/*
* At IPL_SCHED:
@@ -308,6 +309,9 @@
ldr x0, [x9, #L_PRIVATE] /* tpidr_el0 = curlwp->l_private */
msr tpidr_el0, x0
+#ifdef COMPAT_NETBSD32
+ msr tpidrro_el0, x0
+#endif
unwind_x3_x30
diff -r 02a0ca808fee -r f618a7ecb93f sys/arch/aarch64/aarch64/db_disasm.c
--- a/sys/arch/aarch64/aarch64/db_disasm.c Fri Oct 12 01:16:20 2018 +0000
+++ b/sys/arch/aarch64/aarch64/db_disasm.c Fri Oct 12 01:28:57 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_disasm.c,v 1.4 2018/09/15 19:47:48 jakllsch Exp $ */
+/* $NetBSD: db_disasm.c,v 1.5 2018/10/12 01:28:57 ryo Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 2018/09/15 19:47:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.5 2018/10/12 01:28:57 ryo Exp $");
#include <sys/param.h>
#include <machine/db_machdep.h>
@@ -121,3 +121,18 @@
return strdisasm_buf;
}
+
+/*
+ * disassemble aarch32 insns?
+ */
+const char *
+strdisasm_aarch32(vaddr_t pc)
+{
+ uint32_t insn = *(uint32_t *)pc;
+
+ /* not supported any aarch32 insns yet... */
+ snprintf(strdisasm_buf, sizeof(strdisasm_buf), ".insn 0x%08x", insn);
+
+ return strdisasm_buf;
+}
+
diff -r 02a0ca808fee -r f618a7ecb93f sys/arch/aarch64/aarch64/db_machdep.c
--- a/sys/arch/aarch64/aarch64/db_machdep.c Fri Oct 12 01:16:20 2018 +0000
+++ b/sys/arch/aarch64/aarch64/db_machdep.c Fri Oct 12 01:28:57 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.c,v 1.8 2018/09/15 19:47:48 jakllsch Exp $ */
+/* $NetBSD: db_machdep.c,v 1.9 2018/10/12 01:28:57 ryo Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.8 2018/09/15 19:47:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.9 2018/10/12 01:28:57 ryo Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_compat_netbsd32.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -180,6 +184,31 @@
void
dump_trapframe(struct trapframe *tf, void (*pr)(const char *, ...))
{
+#ifdef COMPAT_NETBSD32
+ if (tf->tf_spsr & SPSR_A32) {
+ (*pr)(" pc=%016"PRIxREGISTER", spsr=%016"PRIxREGISTER
+ " (AArch32)\n", tf->tf_pc, tf->tf_spsr);
+ (*pr)(" esr=%016"PRIxREGISTER", far=%016"PRIxREGISTER"\n",
+ tf->tf_esr, tf->tf_far);
+ (*pr)(" r0=%016"PRIxREGISTER", r1=%016"PRIxREGISTER"\n",
+ tf->tf_reg[0], tf->tf_reg[1]);
+ (*pr)(" r2=%016"PRIxREGISTER", r3=%016"PRIxREGISTER"\n",
+ tf->tf_reg[2], tf->tf_reg[3]);
+ (*pr)(" r4=%016"PRIxREGISTER", r5=%016"PRIxREGISTER"\n",
Home |
Main Index |
Thread Index |
Old Index