Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/aarch64 PR port-arm/54702



details:   https://anonhg.NetBSD.org/src/rev/18ee1e5b5500
branches:  trunk
changeset: 465478:18ee1e5b5500
user:      rin <rin%NetBSD.org@localhost>
date:      Sun Nov 24 04:08:36 2019 +0000

description:
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

diffstat:

 sys/arch/aarch64/aarch64/exec_machdep.c     |   11 ++-
 sys/arch/aarch64/aarch64/netbsd32_machdep.c |   10 +-
 sys/arch/aarch64/aarch64/trap.c             |  108 +++++++++++++++++++++++++++-
 sys/arch/aarch64/include/netbsd32_machdep.h |    5 +-
 sys/arch/aarch64/include/param.h            |   12 ++-
 sys/arch/aarch64/include/proc.h             |   13 +++-
 6 files changed, 145 insertions(+), 14 deletions(-)

diffs (truncated from 301 to 300 lines):

diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/aarch64/exec_machdep.c
--- a/sys/arch/aarch64/aarch64/exec_machdep.c   Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/aarch64/exec_machdep.c   Sun Nov 24 04:08:36 2019 +0000
@@ -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 @@
            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
diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/aarch64/netbsd32_machdep.c
--- a/sys/arch/aarch64/aarch64/netbsd32_machdep.c       Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/aarch64/netbsd32_machdep.c       Sun Nov 24 04:08:36 2019 +0000
@@ -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@localhost>
@@ -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 @@
 #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)
diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/aarch64/trap.c
--- a/sys/arch/aarch64/aarch64/trap.c   Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/aarch64/trap.c   Sun Nov 24 04:08:36 2019 +0000
@@ -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 @@
        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 @@
                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
diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/include/netbsd32_machdep.h
--- a/sys/arch/aarch64/include/netbsd32_machdep.h       Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/include/netbsd32_machdep.h       Sun Nov 24 04:08:36 2019 +0000
@@ -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 @@
        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_ */
diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/include/param.h
--- a/sys/arch/aarch64/include/param.h  Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/include/param.h  Sun Nov 24 04:08:36 2019 +0000
@@ -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 */
 
diff -r 5435147e92c4 -r 18ee1e5b5500 sys/arch/aarch64/include/proc.h
--- a/sys/arch/aarch64/include/proc.h   Sun Nov 24 02:06:16 2019 +0000
+++ b/sys/arch/aarch64/include/proc.h   Sun Nov 24 04:08:36 2019 +0000
@@ -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 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__)
 



Home | Main Index | Thread Index | Old Index