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/b229ca61092e
branches:  trunk
changeset: 836320:b229ca61092e
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 b1cffc2d8daf -r b229ca61092e 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 b1cffc2d8daf -r b229ca61092e 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 b1cffc2d8daf -r b229ca61092e 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 b1cffc2d8daf -r b229ca61092e 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