Module Name:    src
Committed By:   ryo
Date:           Fri Oct 12 01:28:58 UTC 2018

Modified Files:
        src/sys/arch/aarch64/aarch64: cpuswitch.S db_disasm.c db_machdep.c
            exec_machdep.c fault.c locore.S netbsd32_machdep.c pmap.c trap.c
            vectors.S
        src/sys/arch/aarch64/conf: files.aarch64
        src/sys/arch/aarch64/include: armreg.h db_machdep.h elf_machdep.h
            netbsd32_machdep.h param.h pmap.h vmparam.h
        src/sys/arch/arm/include: mcontext.h
        src/sys/arch/evbarm/conf: GENERIC64 RPI64
Added Files:
        src/sys/arch/aarch64/aarch64: aarch32_syscall.c netbsd32_syscall.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/aarch64/aarch64/aarch32_syscall.c \
    src/sys/arch/aarch64/aarch64/netbsd32_syscall.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/aarch64/aarch64/cpuswitch.S \
    src/sys/arch/aarch64/aarch64/db_disasm.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/aarch64/aarch64/db_machdep.c \
    src/sys/arch/aarch64/aarch64/vectors.S
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/aarch64/aarch64/exec_machdep.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/aarch64/aarch64/fault.c
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/aarch64/aarch64/locore.S \
    src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/aarch64/aarch64/netbsd32_machdep.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/aarch64/aarch64/trap.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/aarch64/conf/files.aarch64
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/aarch64/include/armreg.h
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/aarch64/include/db_machdep.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/aarch64/include/elf_machdep.h \
    src/sys/arch/aarch64/include/param.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/aarch64/include/netbsd32_machdep.h
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/aarch64/include/pmap.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/aarch64/include/vmparam.h
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/arm/include/mcontext.h
cvs rdiff -u -r1.43 -r1.44 src/sys/arch/evbarm/conf/GENERIC64
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/evbarm/conf/RPI64

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/cpuswitch.S
diff -u src/sys/arch/aarch64/aarch64/cpuswitch.S:1.4 src/sys/arch/aarch64/aarch64/cpuswitch.S:1.5
--- src/sys/arch/aarch64/aarch64/cpuswitch.S:1.4	Tue Jul 17 18:08:36 2018
+++ src/sys/arch/aarch64/aarch64/cpuswitch.S	Fri Oct 12 01:28:57 2018
@@ -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 @@ ENTRY_NP(el0_trap_exit)
 
 	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
 
Index: src/sys/arch/aarch64/aarch64/db_disasm.c
diff -u src/sys/arch/aarch64/aarch64/db_disasm.c:1.4 src/sys/arch/aarch64/aarch64/db_disasm.c:1.5
--- src/sys/arch/aarch64/aarch64/db_disasm.c:1.4	Sat Sep 15 19:47:48 2018
+++ src/sys/arch/aarch64/aarch64/db_disasm.c	Fri Oct 12 01:28:57 2018
@@ -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 <r...@nerv.org>
@@ -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 @@ strdisasm(vaddr_t pc)
 
 	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;
+}
+

Index: src/sys/arch/aarch64/aarch64/db_machdep.c
diff -u src/sys/arch/aarch64/aarch64/db_machdep.c:1.8 src/sys/arch/aarch64/aarch64/db_machdep.c:1.9
--- src/sys/arch/aarch64/aarch64/db_machdep.c:1.8	Sat Sep 15 19:47:48 2018
+++ src/sys/arch/aarch64/aarch64/db_machdep.c	Fri Oct 12 01:28:57 2018
@@ -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 @@ db_regs_t ddb_regs;
 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",
+		    tf->tf_reg[4], tf->tf_reg[5]);
+		(*pr)("    r6=%016"PRIxREGISTER",     r7=%016"PRIxREGISTER"\n",
+		    tf->tf_reg[6], tf->tf_reg[7]);
+		(*pr)("    r8=%016"PRIxREGISTER",     r9=%016"PRIxREGISTER"\n",
+		    tf->tf_reg[8], tf->tf_reg[9]);
+		(*pr)("   r10=%016"PRIxREGISTER",    r11=%016"PRIxREGISTER"\n",
+		    tf->tf_reg[10], tf->tf_reg[11]);
+		(*pr)("   r12=%016"PRIxREGISTER", sp=r13=%016"PRIxREGISTER"\n",
+		    tf->tf_reg[12], tf->tf_reg[13]);
+		(*pr)("lr=r14=%016"PRIxREGISTER", pc=r15=%016"PRIxREGISTER"\n",
+		    tf->tf_reg[14], tf->tf_pc);
+		return;
+	}
+#endif
 	(*pr)("    pc=%016"PRIxREGISTER",   spsr=%016"PRIxREGISTER"\n",
 	    tf->tf_pc, tf->tf_spsr);
 	(*pr)("   esr=%016"PRIxREGISTER",    far=%016"PRIxREGISTER"\n",
@@ -388,6 +417,7 @@ db_md_sysreg_cmd(db_expr_t addr, bool ha
 	SHOW_ARMREG(spsr_el1);
 	SHOW_ARMREG(tcr_el1);
 	SHOW_ARMREG(tpidr_el0);
+	SHOW_ARMREG(tpidrro_el0);
 	SHOW_ARMREG(tpidr_el1);
 	SHOW_ARMREG(ttbr0_el1);
 	SHOW_ARMREG(ttbr1_el1);
Index: src/sys/arch/aarch64/aarch64/vectors.S
diff -u src/sys/arch/aarch64/aarch64/vectors.S:1.8 src/sys/arch/aarch64/aarch64/vectors.S:1.9
--- src/sys/arch/aarch64/aarch64/vectors.S:1.8	Fri Sep 14 05:33:50 2018
+++ src/sys/arch/aarch64/aarch64/vectors.S	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: vectors.S,v 1.8 2018/09/14 05:33:50 ryo Exp $	*/
+/*	$NetBSD: vectors.S,v 1.9 2018/10/12 01:28:57 ryo Exp $	*/
 
 #include <aarch64/asm.h>
 #include "assym.h"
@@ -7,7 +7,7 @@
 	/*
 	 * vector_entry macro must be small enough to fit 0x80 bytes!
 	 */
-	.macro	vector_entry, el, label
+	.macro	vector_entry, el, label, tpidr
 	.align 7	/* aligned 0x80 */
 
 	.if \el == 1
@@ -61,11 +61,11 @@
 	.endif
 
 	.if \el == 0
-	/* curlwp->l_private = tpidr_el0 */
+	/* curlwp->l_private = tpidr{,ro}_el0 */
 	mrs	x1, tpidr_el1		/* curcpu() */
-	ldr	x1, [x1, #CI_CURLWP]	/* x0 = curcpu()->ci_curlwp */
-	mrs	x0, tpidr_el0
-	str	x0, [x1, #L_PRIVATE]	/* curlwp->l_private = tpidr_el0 */
+	ldr	x1, [x1, #CI_CURLWP]	/* x1 = curcpu()->ci_curlwp */
+	mrs	x0, tpidr\tpidr\()_el0
+	str	x0, [x1, #L_PRIVATE]	/* curlwp->l_private = tpidr{,ro}_el0 */
 	.endif
 
 	adr	x30, el\el\()_trap_exit	/* el[01]_trap_exit */
@@ -110,8 +110,8 @@ ENTRY_NP(el1_vectors)
  * Exception taken from lower Exception Level which is using AArch32
  * There are entries for exceptions caused in EL0 (compat user exceptions).
  */
-	vector_entry	0, trap_el0_32sync
-	vector_entry	0, interrupt
-	vector_entry	0, trap_el0_32fiq
-	vector_entry	0, trap_el0_32error
+	vector_entry	0, trap_el0_32sync, ro
+	vector_entry	0, interrupt, ro
+	vector_entry	0, trap_el0_32fiq, ro
+	vector_entry	0, trap_el0_32error, ro
 END(el1_vectors)

Index: src/sys/arch/aarch64/aarch64/exec_machdep.c
diff -u src/sys/arch/aarch64/aarch64/exec_machdep.c:1.2 src/sys/arch/aarch64/aarch64/exec_machdep.c:1.3
--- src/sys/arch/aarch64/aarch64/exec_machdep.c:1.2	Sun Apr  1 04:35:03 2018
+++ src/sys/arch/aarch64/aarch64/exec_machdep.c	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_machdep.c,v 1.2 2018/04/01 04:35:03 ryo Exp $ */
+/* $NetBSD: exec_machdep.c,v 1.3 2018/10/12 01:28:57 ryo 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.2 2018/04/01 04:35:03 ryo Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exec_machdep.c,v 1.3 2018/10/12 01:28:57 ryo Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_compat_netbsd32.h"
@@ -62,19 +62,36 @@ aarch64_netbsd_elf64_probe(struct lwp *l
 }
 #endif
 
+#if EXEC_ELF32
+int
+aarch64_netbsd_elf32_probe(struct lwp *l, struct exec_package *epp, void *eh0,
+	char *itp, vaddr_t *start_p)
+{
+	const Elf32_Ehdr * const eh = eh0;
+	const bool elf_aapcs_p =
+	    (eh->e_flags & EF_ARM_EABIMASK) >= EF_ARM_EABI_VER4;
+
+	/* OABI not support */
+	if (!elf_aapcs_p)
+		return ENOEXEC;
+
+	return 0;
+}
+#endif
+
 void
 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
 {
 	struct proc * const p = l->l_proc;
 	struct trapframe * const tf = l->l_md.md_utf;
 
-	memset(tf, 0, sizeof(*tf));
+	p->p_flag &= ~PK_32;
 
 	/*
 	 * void __start(void (*cleanup)(void), const Obj_Entry *obj,
 	 *    struct ps_strings *ps_strings);
 	 */
-
+	memset(tf, 0, sizeof(*tf));
 	tf->tf_reg[2] = p->p_psstrp;
 	tf->tf_pc = pack->ep_entry;
 	tf->tf_sp = stack & -16L;

Index: src/sys/arch/aarch64/aarch64/fault.c
diff -u src/sys/arch/aarch64/aarch64/fault.c:1.6 src/sys/arch/aarch64/aarch64/fault.c:1.7
--- src/sys/arch/aarch64/aarch64/fault.c:1.6	Sat Jul 21 13:23:48 2018
+++ src/sys/arch/aarch64/aarch64/fault.c	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: fault.c,v 1.6 2018/07/21 13:23:48 ryo Exp $	*/
+/*	$NetBSD: fault.c,v 1.7 2018/10/12 01:28:57 ryo Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,8 +27,9 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.6 2018/07/21 13:23:48 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.7 2018/10/12 01:28:57 ryo Exp $");
 
+#include "opt_compat_netbsd32.h"
 #include "opt_ddb.h"
 #include "opt_uvmhist.h"
 
@@ -118,6 +119,10 @@ is_fatal_abort(uint32_t esr)
 	return true;
 }
 
+/* SPSR_M is SPSR_M_EL0T or SPSR_M_USR32 ? */
+#define IS_SPSR_USER(spsr)	\
+	(((spsr) & (SPSR_M & ~SPSR_A32)) == 0)
+
 void
 data_abort_handler(struct trapframe *tf, uint32_t eclass)
 {
@@ -129,8 +134,8 @@ data_abort_handler(struct trapframe *tf,
 	uint32_t esr, fsc, rw;
 	vm_prot_t ftype;
 	int error = 0, len;
-	const bool user = (__SHIFTOUT(tf->tf_spsr, SPSR_M) == SPSR_M_EL0T) ?
-	    true : false;
+	const bool user = IS_SPSR_USER(tf->tf_spsr) ? true : false;
+
 	bool fatalabort;
 	const char *faultstr;
 	static char panicinfo[256];

Index: src/sys/arch/aarch64/aarch64/locore.S
diff -u src/sys/arch/aarch64/aarch64/locore.S:1.28 src/sys/arch/aarch64/aarch64/locore.S:1.29
--- src/sys/arch/aarch64/aarch64/locore.S:1.28	Thu Oct  4 23:53:13 2018
+++ src/sys/arch/aarch64/aarch64/locore.S	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.28 2018/10/04 23:53:13 ryo Exp $	*/
+/*	$NetBSD: locore.S,v 1.29 2018/10/12 01:28:57 ryo Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,6 +27,7 @@
  */
 
 #include "opt_arm_debug.h"
+#include "opt_compat_netbsd32.h"
 #include "opt_console.h"
 #include "opt_cpuoptions.h"
 #include "opt_ddb.h"
@@ -37,7 +38,7 @@
 #include <aarch64/hypervisor.h>
 #include "assym.h"
 
-RCSID("$NetBSD: locore.S,v 1.28 2018/10/04 23:53:13 ryo Exp $")
+RCSID("$NetBSD: locore.S,v 1.29 2018/10/12 01:28:57 ryo Exp $")
 
 
 /*#define DEBUG_LOCORE			/* debug print */
@@ -172,6 +173,7 @@ vstart:
 
 	/* lwp-private = NULL */
 	msr	tpidr_el0, xzr
+	msr	tpidrro_el0, xzr
 
 	/* set curcpu() */
 	ADDR	x0, cpu_info_store	/* cpu_info_store is cpu_info[0] */
@@ -426,6 +428,7 @@ mp_vstart:
 
 	/* lwp-private = NULL */
 	msr	tpidr_el0, xzr
+	msr	tpidrro_el0, xzr
 
 	/* set curcpu(), and fill curcpu()->ci_{midr,mpidr} */
 	mov	x0, #CPU_INFO_SIZE
Index: src/sys/arch/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.28 src/sys/arch/aarch64/aarch64/pmap.c:1.29
--- src/sys/arch/aarch64/aarch64/pmap.c:1.28	Fri Oct 12 01:13:51 2018
+++ src/sys/arch/aarch64/aarch64/pmap.c	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.28 2018/10/12 01:13:51 ryo Exp $	*/
+/*	$NetBSD: pmap.c,v 1.29 2018/10/12 01:28:57 ryo Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.28 2018/10/12 01:13:51 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.29 2018/10/12 01:28:57 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -735,6 +735,47 @@ _pmap_pte_lookup_l3(struct pmap *pm, vad
 	return NULL;
 }
 
+void
+pmap_icache_sync_range(pmap_t pm, vaddr_t sva, vaddr_t eva)
+{
+	pt_entry_t *ptep, pte;
+	vaddr_t va;
+	vsize_t blocksize = 0;
+
+	pm_lock(pm);
+
+	for (va = sva; va < eva; va += blocksize) {
+		ptep = _pmap_pte_lookup_bs(pm, va, &blocksize);
+		if (blocksize == 0)
+			break;
+		if (ptep != NULL) {
+			vaddr_t eob = (va + blocksize) & ~(blocksize - 1);
+			vsize_t len = ulmin(eva, eob - va);
+
+			pte = *ptep;
+			if (l3pte_writable(pte)) {
+				cpu_icache_sync_range(va, len);
+			} else {
+				/*
+				 * change to writable temporally
+				 * to do cpu_icache_sync_range()
+				 */
+				pt_entry_t opte = pte;
+				pte = pte & ~(LX_BLKPAG_AF|LX_BLKPAG_AP);
+				pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RW);
+				atomic_swap_64(ptep, pte);
+				AARCH64_TLBI_BY_ASID_VA(pm->pm_asid, va, true);
+				cpu_icache_sync_range(va, len);
+				atomic_swap_64(ptep, opte);
+				AARCH64_TLBI_BY_ASID_VA(pm->pm_asid, va, true);
+			}
+			va &= ~(blocksize - 1);
+		}
+	}
+
+	pm_unlock(pm);
+}
+
 static pt_entry_t
 _pmap_pte_adjust_prot(pt_entry_t pte, vm_prot_t prot, vm_prot_t protmask,
     bool user)

Index: src/sys/arch/aarch64/aarch64/netbsd32_machdep.c
diff -u src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.1 src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.2
--- src/sys/arch/aarch64/aarch64/netbsd32_machdep.c:1.1	Sun Apr  1 04:35:03 2018
+++ src/sys/arch/aarch64/aarch64/netbsd32_machdep.c	Fri Oct 12 01:28:57 2018
@@ -1,10 +1,9 @@
-/*-
- * Copyright (c) 2018 The NetBSD Foundation, Inc.
+/*	$NetBSD: netbsd32_machdep.c,v 1.2 2018/10/12 01:28:57 ryo Exp $	*/
+
+/*
+ * Copyright (c) 2018 Ryo Shimizu <r...@nerv.org>
  * All rights reserved.
  *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Nick Hudson
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -14,22 +13,21 @@
  *    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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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
+ * 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(1, "$NetBSD: netbsd32_machdep.c,v 1.1 2018/04/01 04:35:03 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.2 2018/10/12 01:28:57 ryo Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -37,6 +35,7 @@ __KERNEL_RCSID(1, "$NetBSD: netbsd32_mac
 #include <sys/core.h>
 #include <sys/exec.h>
 #include <sys/lwp.h>
+#include <sys/ras.h>
 #include <sys/signalvar.h>
 #include <sys/syscallargs.h>
 
@@ -46,69 +45,486 @@ __KERNEL_RCSID(1, "$NetBSD: netbsd32_mac
 #include <compat/netbsd32/netbsd32_exec.h>
 #include <compat/netbsd32/netbsd32_syscallargs.h>
 
-#include <machine/frame.h>
+#include <aarch64/armreg.h>
+#include <aarch64/cpufunc.h>
+#include <aarch64/frame.h>
+#include <aarch64/machdep.h>
+#include <aarch64/userret.h>
 
 const char machine32[] = MACHINE;
-const char machine_arch32[] = MACHINE_ARCH;
+#ifdef __AARCH64EB__
+const char machine_arch32[] = "earmv7hfeb";
+#else
+const char machine_arch32[] = "earmv7hf";
+#endif
 
 void
 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
 {
+	struct proc * const p = l->l_proc;
+	struct trapframe * const tf = l->l_md.md_utf;
+
+	p->p_flag |= PK_32;
+
+	/*
+	 * void __start(struct ps_strings *ps_strings, const Obj_Entry *obj,
+	 *     void (*cleanup)(void));
+	 */
+	memset(tf, 0, sizeof(*tf));
+	tf->tf_reg[0] = (uint32_t)p->p_psstrp;
+	tf->tf_reg[12] = stack;		/* r12 needed by pre 1.4 crt0.c */
+	tf->tf_reg[13] = stack;		/* sp */
+	tf->tf_reg[14] = pack->ep_entry;/* lr */
+	tf->tf_reg[18] = 0x77777777;	/* svc_lr. adjust to arm_machdep.c */
+	tf->tf_pc = pack->ep_entry;
+
+
+	/* set 32bit mode, and same endian as 64bit's */
+#ifdef __AARCH64EB__
+	tf->tf_spsr = SPSR_M_USR32 | SPSR_A32_E;
+#else
+	tf->tf_spsr = SPSR_M_USR32;
+#endif
+
+#ifdef THUMB_CODE
+	if (pack->ep_entry & 1)
+		tf->tf_spsr |= SPSR_A32_T;
+#endif
+}
+
+/* aarch32 fpscr register is assigned to two registers fpsr/fpcr on aarch64 */
+#define FPSR_BITS							\
+	(FPSR_N32|FPSR_Z32|FPSR_C32|FPSR_V32|FPSR_QC|			\
+	 FPSR_IDC|FPSR_IXC|FPSR_UFC|FPSR_OFC|FPSR_DZC|FPSR_IOC)
+#define FPCR_BITS							\
+	(FPCR_AHP|FPCR_DN|FPCR_FZ|FPCR_RMODE|FPCR_STRIDE|FPCR_LEN|	\
+	 FPCR_IDE|FPCR_IXE|FPCR_UFE|FPCR_OFE|FPCR_DZE|FPCR_IOE)
+
+static int
+netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs)
+{
+	struct proc * const p = l->l_proc;
+	struct trapframe *tf = l->l_md.md_utf;
+	int i;
+
+	if ((p->p_flag & PK_32) == 0)
+		return EINVAL;
+
+	for (i = 0; i < 13; i++)
+		regs->r[i] = tf->tf_reg[i];	/* r0-r12 */
+	regs->r_sp = tf->tf_reg[13];		/* r13 = sp */
+	regs->r_lr = tf->tf_reg[14];		/* r14 = lr */
+	regs->r_pc = tf->tf_pc;			/* r15 = pc */
+	regs->r_cpsr = tf->tf_spsr;
+
+	return 0;
 }
 
+static int
+netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *fpregs,
+    size_t *lenp)
+{
+	struct proc * const p = l->l_proc;
+	struct pcb * const pcb = lwp_getpcb(l);
+	int i;
+
+	if ((p->p_flag & PK_32) == 0)
+		return EINVAL;
+
+	KASSERT(*lenp <= sizeof(*fpregs));
+	fpu_save(l);
+
+	/*
+	 * convert from aarch64's struct fpreg to arm's struct fpreg32
+	 */
+#define VFP_FPEXC_EN		0x40000000	/* VFP Enable bit */
+#define VFP_FPEXC_VECITR	0x00000700	/* VECtor ITeRation count */
+	fpregs->fpr_vfp.vfp_fpexc = VFP_FPEXC_EN | VFP_FPEXC_VECITR;
+
+	fpregs->fpr_vfp.vfp_fpscr =
+	    (pcb->pcb_fpregs.fpsr & FPSR_BITS) |
+	    (pcb->pcb_fpregs.fpcr & FPCR_BITS);
+
+	fpregs->fpr_vfp.vfp_fpinst = 0;
+	fpregs->fpr_vfp.vfp_fpinst2 = 0;
+
+	for (i = 0; i < 32; i++) {
+#ifdef __AARCH64EB__
+		fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[1];
+#else
+		fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[0];
+#endif
+	}
+
+	return 0;
+}
 
 int
 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie,
     struct core32 *chdr)
 {
+	struct netbsd32_cpustate md_core32;
+	struct coreseg32 cseg;
+	int error;
+
+	if (iocookie == NULL) {
+		CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0);
+		chdr->c_hdrsize = ALIGN32(sizeof(*chdr));
+		chdr->c_seghdrsize = ALIGN32(sizeof(cseg));
+		chdr->c_cpusize = sizeof(md_core32);
+		chdr->c_nseg++;
+		return 0;
+	}
+
+	error = netbsd32_process_read_regs(l, &md_core32.regs);
+	if (error)
+		return error;
+
+	error = netbsd32_process_read_fpregs(l, &md_core32.fpregs, NULL);
+	if (error)
+		return error;
+
+	CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU);
+	cseg.c_addr = 0;
+	cseg.c_size = chdr->c_cpusize;
+
+	error = coredump_write(iocookie, UIO_SYSSPACE,
+	    &cseg, chdr->c_seghdrsize);
+	if (error)
+		return error;
 
-	return ENOSYS;
+	return coredump_write(iocookie, UIO_SYSSPACE,
+	    &md_core32, sizeof(md_core32));
 }
 
+static void
+netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
+{
+	struct lwp * const l = curlwp;
+	struct proc * const p = l->l_proc;
+	struct trapframe * const tf = l->l_md.md_utf;
+	struct sigaltstack * const ss = &l->l_sigstk;
+	const int signo = ksi->ksi_signo;
+	const struct sigaction * const sa = &SIGACTION(p, signo);
+	const struct sigact_sigdesc * const sdesc =
+	    &p->p_sigacts->sa_sigdesc[signo];
+	const sig_t handler = sa->sa_handler;
+	struct netbsd32_sigframe_siginfo *fp, frame;
+	int error;
+
+	const bool onstack_p =
+	    (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) &&
+	    (sa->sa_flags & SA_ONSTACK);
+
+	vaddr_t sp = onstack_p ?
+	    ((vaddr_t)ss->ss_sp + ss->ss_size) :
+	    tf->tf_reg[13];	/* r13 = sp on aarch32 */
+
+	fp = (struct netbsd32_sigframe_siginfo *)sp;
+	fp = (struct netbsd32_sigframe_siginfo *)STACK_ALIGN(fp - 1, 8);
+
+	/* XXX: netbsd32_ksi_to_si32 */
+	netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info);
+
+	frame.sf_uc.uc_flags = _UC_SIGMASK;
+	frame.sf_uc.uc_sigmask = *mask;
+	frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink;
+	frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ?
+	    _UC_SETSTACK : _UC_CLRSTACK;
+	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
+	sendsig_reset(l, signo);
+
+	mutex_exit(p->p_lock);
+	cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags);
+	error = copyout(&frame, fp, sizeof(frame));
+	mutex_enter(p->p_lock);
+
+	if (error != 0) {
+		/*
+		 * Process has trashed its stack;
+		 * give it an illegal instruction to halt it in its tracks.
+		 */
+		sigexit(l, SIGILL);
+		/* NOTREACHED */
+	}
+
+	tf->tf_reg[0] = signo;
+	tf->tf_reg[1] = (uint32_t)(uintptr_t)&fp->sf_si;
+	tf->tf_reg[2] = (uint32_t)(uintptr_t)&fp->sf_uc;
+
+	/* the trampoline uses r5 as the uc address */
+	tf->tf_reg[5] = (uint32_t)(uintptr_t)&fp->sf_uc;
+	tf->tf_pc = (uint32_t)(uintptr_t)handler;
+#ifdef THUMB_CODE
+	if (((int)handler) & 1)
+		tf->tf_spsr |= SPSR_A32_T;
+	else
+		tf->tf_spsr &= ~SPSR_A32_T;
+#endif
+	tf->tf_reg[13] = (uint32_t)(uintptr_t)fp;		/* sp */
+	tf->tf_reg[14] = (uint32_t)(uintptr_t)sdesc->sd_tramp;	/* lr */
+
+	/* Remember if we'ere now on the signal stack */
+	if (onstack_p)
+		ss->ss_flags |= SS_ONSTACK;
+}
 
 void
-netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *ss)
+netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
 {
-
+#ifdef COMPAT_16
+#error non EABI generation binaries are not supported
+	if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2)
+		netbsd32_sendsig_sigcontext(ksi, mask);
+	else
+#endif
+		netbsd32_sendsig_siginfo(ksi, mask);
 }
 
 void
 startlwp32(void *arg)
 {
-
+	ucontext32_t *uc = arg;
+	lwp_t *l = curlwp;
+	int error __diagused;
+
+	/*
+	 * entity of *uc is ucontext_t. therefore
+	 * ucontext_t must be greater than ucontext32_t
+	 */
+	CTASSERT(sizeof(ucontext_t) >= sizeof(ucontext32_t));
+
+	error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags);
+	KASSERT(error == 0);
+
+	/* Note: we are freeing ucontext_t, not ucontext32_t. */
+	kmem_free(uc, sizeof(ucontext_t));
+	userret(l);
 }
 
 int
 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp)
 {
+	struct proc * const p = l->l_proc;
+	const uint32_t spsr = mcp->__gregs[_REG_CPSR];
 
-//	const __greg32_t * const gr = mcp->__gregs;
+	KASSERT(p->p_flag & PK_32);
 
-//	/* Make sure the processor mode has not been tampered with. */
-//	if (!VALID_R15_PSR(gr[_REG_PC], gr[_REG_CPSR]))
-//		return EINVAL;
+	if (__SHIFTOUT(spsr, SPSR_M) != SPSR_M_USR32)
+		return EINVAL;
+	if ((spsr & (SPSR_A64_D|SPSR_A|SPSR_I|SPSR_F)) != 0)
+		return EINVAL;
+
+#ifdef __AARCH64EB__
+	if ((spsr & SPSR_A32_E) == 0)
+		return EINVAL;
+#else
+	if ((spsr & SPSR_A32_E) != 0)
+		return EINVAL;
+#endif
+
+	if ((spsr & (SPSR_A|SPSR_I|SPSR_F)) != 0)
+		return EINVAL;
 
 	return 0;
 }
 void
 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flagsp)
 {
+	struct trapframe * const tf = l->l_md.md_utf;
+	__greg32_t *gr = mcp->__gregs;
+	__greg32_t ras_pc;
+
+	gr[_REG_R0]  = tf->tf_reg[0];
+	gr[_REG_R1]  = tf->tf_reg[1];
+	gr[_REG_R2]  = tf->tf_reg[2];
+	gr[_REG_R3]  = tf->tf_reg[3];
+	gr[_REG_R4]  = tf->tf_reg[4];
+	gr[_REG_R5]  = tf->tf_reg[5];
+	gr[_REG_R6]  = tf->tf_reg[6];
+	gr[_REG_R7]  = tf->tf_reg[7];
+	gr[_REG_R8]  = tf->tf_reg[8];
+	gr[_REG_R9]  = tf->tf_reg[9];
+	gr[_REG_R10] = tf->tf_reg[10];
+	gr[_REG_R11] = tf->tf_reg[11];
+	gr[_REG_R12] = tf->tf_reg[12];
+	gr[_REG_R13] = tf->tf_reg[13];
+	gr[_REG_R14] = tf->tf_reg[14];
+	gr[_REG_R15] = tf->tf_pc;
+	gr[_REG_CPSR] = tf->tf_spsr;
+
+	if ((ras_pc = (__greg32_t)(uintptr_t)ras_lookup(l->l_proc,
+	    (void *)(uintptr_t)gr[_REG_R15])) != -1) {
+		gr[_REG_R15] = ras_pc;
+	}
+	*flagsp |= _UC_CPU;
+
+	/* fpu context */
+	if (fpu_used_p(l)) {
+		const struct pcb * const pcb = lwp_getpcb(l);
+		int i;
+
+		fpu_save(l);
+
+		CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) ==
+		    __arraycount(pcb->pcb_fpregs.fp_reg));
+		for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) {
+			mcp->__vfpregs.__vfp_fstmx[i] =
+#ifdef __AARCH64EB__
+			    pcb->pcb_fpregs.fp_reg[i].u64[1];
+#else
+			    pcb->pcb_fpregs.fp_reg[i].u64[0];
+#endif
+		}
+
+		mcp->__vfpregs.__vfp_fpscr =
+		    (pcb->pcb_fpregs.fpsr & FPSR_BITS) |
+		    (pcb->pcb_fpregs.fpcr & FPCR_BITS);
+		mcp->__vfpregs.__vfp_fpsid = 0;	/* XXX: build FPSID from MIDR */
+
+		*flagsp |= _UC_FPU;
+	}
 
+	mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private;
+	*flagsp |= _UC_TLSBASE;
 }
 
 int
 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
 {
+	struct trapframe * const tf = l->l_md.md_utf;
+	const __greg32_t * const gr = mcp->__gregs;
+	struct proc * const p = l->l_proc;
+	int error, i;
+
+	if (flags & _UC_CPU) {
+		error = cpu_mcontext32_validate(l, mcp);
+		if (error != 0)
+			return error;
+
+		tf->tf_reg[0]  = gr[_REG_R0];
+		tf->tf_reg[1]  = gr[_REG_R1];
+		tf->tf_reg[2]  = gr[_REG_R2];
+		tf->tf_reg[3]  = gr[_REG_R3];
+		tf->tf_reg[4]  = gr[_REG_R4];
+		tf->tf_reg[5]  = gr[_REG_R5];
+		tf->tf_reg[6]  = gr[_REG_R6];
+		tf->tf_reg[7]  = gr[_REG_R7];
+		tf->tf_reg[8]  = gr[_REG_R8];
+		tf->tf_reg[9]  = gr[_REG_R9];
+		tf->tf_reg[10] = gr[_REG_R10];
+		tf->tf_reg[11] = gr[_REG_R11];
+		tf->tf_reg[12] = gr[_REG_R12];
+		tf->tf_reg[13] = gr[_REG_R13];
+		tf->tf_reg[14] = gr[_REG_R14];
+		tf->tf_pc      = gr[_REG_R15];
+		tf->tf_spsr    = gr[_REG_CPSR];
+	}
+
+	if (flags & _UC_FPU) {
+		struct pcb * const pcb = lwp_getpcb(l);
+		fpu_discard(l, true);
+
+		CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) ==
+		    __arraycount(pcb->pcb_fpregs.fp_reg));
+		for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) {
+#ifdef __AARCH64EB__
+			pcb->pcb_fpregs.fp_reg[i].u64[0] = 0;
+			pcb->pcb_fpregs.fp_reg[i].u64[1] =
+#else
+			pcb->pcb_fpregs.fp_reg[i].u64[1] = 0;
+			pcb->pcb_fpregs.fp_reg[i].u64[0] =
+#endif
+			    mcp->__vfpregs.__vfp_fstmx[i];
+		}
+		pcb->pcb_fpregs.fpsr =
+		    mcp->__vfpregs.__vfp_fpscr & FPSR_BITS;
+		pcb->pcb_fpregs.fpcr =
+		    mcp->__vfpregs.__vfp_fpscr & FPCR_BITS;
+	}
+
+	if (flags &_UC_TLSBASE)
+		l->l_private = (void *)(uintptr_t)mcp->_mc_tlsbase;
+
+	mutex_enter(p->p_lock);
+	if (flags & _UC_SETSTACK)
+		l->l_sigstk.ss_flags |= SS_ONSTACK;
+	if (flags & _UC_CLRSTACK)
+		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
+	mutex_exit(p->p_lock);
 
-	return EINVAL;
+	return 0;
+}
+
+static int
+arm32_sync_icache(struct lwp *l, const void *args, register_t *retval)
+{
+	struct netbsd32_arm_sync_icache_args ua;
+	struct faultbuf fb;
+	int error;
+
+	error = copyin(args, &ua, sizeof(ua));
+	if (error != 0)
+		return error;
+
+	if ((vaddr_t)ua.addr + ua.len > VM_MAXUSER_ADDRESS32)
+		return EINVAL;
+
+	/* use cpu_set_onfault() by way of precaution */
+	if ((error = cpu_set_onfault(&fb)) == 0) {
+		pmap_icache_sync_range(
+		    vm_map_pmap(&l->l_proc->p_vmspace->vm_map),
+		    (vaddr_t)ua.addr, (vaddr_t)ua.addr + ua.len);
+		cpu_unset_onfault();
+	}
+
+	*retval = 0;
+	return error;
+}
+
+static int
+arm32_drain_writebuf(struct lwp *l, const void *args, register_t *retval)
+{
+	aarch64_drain_writebuf();
+
+	*retval = 0;
+	return 0;
 }
 
 int
 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap,
-	register_t *retval)
+    register_t *retval)
 {
-
-	return EINVAL;
+	/* {
+		syscallarg(int) op;
+		syscallarg(netbsd32_voidp) parms;
+	} */
+	int error;
+
+	switch (SCARG(uap, op)) {
+	case ARM_SYNC_ICACHE:
+		error = arm32_sync_icache(l,
+		    NETBSD32PTR64(SCARG(uap, parms)), retval);
+		break;
+	case ARM_DRAIN_WRITEBUF:
+		error = arm32_drain_writebuf(l,
+		    NETBSD32PTR64(SCARG(uap, parms)), retval);
+		break;
+	case ARM_VFP_FPSCR:
+		printf("%s: ARM_VFP_FPSCR not implemented\n", __func__);
+		error = EINVAL;
+		break;
+	case ARM_FPU_USED:
+		printf("%s: ARM_FPU_USED not implemented\n", __func__);
+		error = EINVAL;
+		break;
+	default:
+		printf("%s: op=%d: not implemented\n", __func__,
+		    SCARG(uap, op));
+		error = EINVAL;
+		break;
+	}
+	return error;
 }
 
 vaddr_t
@@ -116,8 +532,7 @@ netbsd32_vm_default_addr(struct proc *p,
     int topdown)
 {
 	if (topdown)
-		return VM_DEFAULT_ADDRESS_TOPDOWN(base, sz);
+		return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz);
 	else
-		return VM_DEFAULT_ADDRESS_BOTTOMUP(base, sz);
+		return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz);
 }
-

Index: src/sys/arch/aarch64/aarch64/trap.c
diff -u src/sys/arch/aarch64/aarch64/trap.c:1.10 src/sys/arch/aarch64/aarch64/trap.c:1.11
--- src/sys/arch/aarch64/aarch64/trap.c:1.10	Fri Sep 14 13:47:14 2018
+++ src/sys/arch/aarch64/aarch64/trap.c	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.10 2018/09/14 13:47:14 ryo Exp $ */
+/* $NetBSD: trap.c,v 1.11 2018/10/12 01:28:57 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.10 2018/09/14 13:47:14 ryo Exp $");
+__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.11 2018/10/12 01:28:57 ryo Exp $");
 
 #include "opt_arm_intr_impl.h"
 #include "opt_compat_netbsd32.h"
@@ -267,21 +267,21 @@ trap_el0_sync(struct trapframe *tf)
 	case ESR_EC_BRKPNT_EL0:
 	case ESR_EC_SW_STEP_EL0:
 	case ESR_EC_WTCHPNT_EL0:
-		/* XXX notyet */
 		do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
 		userret(l);
 		break;
 
 	default:
-		/* XXX notyet */
 	case ESR_EC_UNKNOWN:
 #ifdef DDB
 		if (sigill_debug) {
 			/* show illegal instruction */
-			printf("TRAP: pid %d (%s), uid %d: %s: pc=0x%016lx: %s\n",
+			printf("TRAP: pid %d (%s), uid %d: %s:"
+			    " esr=0x%lx: pc=0x%lx: %s\n",
 			    curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
 			    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
-			    eclass_trapname(eclass), tf->tf_pc, strdisasm(tf->tf_pc));
+			    eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
+			    strdisasm(tf->tf_pc));
 		}
 #endif
 		/* illegal or not implemented instruction */
@@ -317,48 +317,58 @@ trap_el0_32sync(struct trapframe *tf)
 	daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
 
 	switch (eclass) {
-	case ESR_EC_FP_ACCESS:
-		fpu_load(l);
-		userret(l);
-		break;
-
+#ifdef COMPAT_NETBSD32
 	case ESR_EC_INSN_ABT_EL0:
 	case ESR_EC_DATA_ABT_EL0:
 		data_abort_handler(tf, eclass);
 		userret(l);
 		break;
 
+	case ESR_EC_SVC_A32:
+		(*l->l_proc->p_md.md_syscall)(tf);
+		break;
+	case ESR_EC_FP_ACCESS:
+		fpu_load(l);
+		userret(l);
+		break;
+	case ESR_EC_FP_TRAP_A32:
+		do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
+		userret(l);
+
 	case ESR_EC_PC_ALIGNMENT:
 		do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
 		userret(l);
 		break;
 	case ESR_EC_SP_ALIGNMENT:
-		do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr);
+		do_trapsignal(l, SIGBUS, BUS_ADRALN,
+		    (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */
 		userret(l);
 		break;
 
-#ifdef COMPAT_NETBSD32
-	case ESR_EC_SVC_A32:
-		(*l->l_proc->p_md.md_syscall)(tf);
+	case ESR_EC_BKPT_INSN_A32:
+		do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
+		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:
-	case ESR_EC_FP_TRAP_A32:
-	case ESR_EC_BKPT_INSN_A32:
-		/* XXX notyet */
-		printf("%s:%d: %s\n", __func__, __LINE__,
-		    eclass_trapname(eclass));
-		do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
-		userret(l);
-		break;
 #endif /* COMPAT_NETBSD32 */
 	default:
-		/* XXX notyet */
-		printf("%s:%d: %s\n", __func__, __LINE__,
-		    eclass_trapname(eclass));
+#ifdef DDB
+		if (sigill_debug) {
+			/* show illegal instruction */
+			printf("TRAP: pid %d (%s), uid %d: %s:"
+			    " esr=0x%lx: pc=0x%lx: %s\n",
+			    curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
+			    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
+			    eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
+			    strdisasm_aarch32(tf->tf_pc));
+		}
+#endif
+		/* illegal or not implemented instruction */
 		do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
 		userret(l);
 		break;

Index: src/sys/arch/aarch64/conf/files.aarch64
diff -u src/sys/arch/aarch64/conf/files.aarch64:1.6 src/sys/arch/aarch64/conf/files.aarch64:1.7
--- src/sys/arch/aarch64/conf/files.aarch64:1.6	Sat Oct  6 17:46:46 2018
+++ src/sys/arch/aarch64/conf/files.aarch64	Fri Oct 12 01:28:57 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: files.aarch64,v 1.6 2018/10/06 17:46:46 skrll Exp $
+#	$NetBSD: files.aarch64,v 1.7 2018/10/12 01:28:57 ryo Exp $
 
 defflag opt_cpuoptions.h	AARCH64_ALIGNMENT_CHECK
 defflag opt_cpuoptions.h	AARCH64_EL0_STACK_ALIGNMENT_CHECK
@@ -117,8 +117,7 @@ file	arch/aarch64/aarch64/pmap_page.S
 # NetBSD 32-bit binary compatibility
 include "compat/netbsd32/files.netbsd32"
 file	arch/aarch64/aarch64/netbsd32_machdep.c		compat_netbsd32
-#file	arch/aarch64/aarch32/aarch32_oabi_machdep.c	compat_aarch32_oabi
-#file	arch/aarch64/aarch32/aarch32_eabi_machdep.c	compat_aarch32_eabi
+file	arch/aarch64/aarch64/netbsd32_syscall.c		compat_netbsd32
 #file	arch/aarch64/aarch32/compat_13_machdep.c	compat_13 & compat_netbsd32
 #file	arch/aarch64/aarch32/compat_16_machdep.c	compat_16 & compat_netbsd32
 

Index: src/sys/arch/aarch64/include/armreg.h
diff -u src/sys/arch/aarch64/include/armreg.h:1.18 src/sys/arch/aarch64/include/armreg.h:1.19
--- src/sys/arch/aarch64/include/armreg.h:1.18	Sun Aug 12 17:21:35 2018
+++ src/sys/arch/aarch64/include/armreg.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: armreg.h,v 1.18 2018/08/12 17:21:35 skrll Exp $ */
+/* $NetBSD: armreg.h,v 1.19 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -599,6 +599,7 @@ AARCH64REG_WRITE_INLINE(spsr_el1)
 #define	SPSR_I	 		__BIT(7)	// IRQ Mask
 #define	SPSR_F	 		__BIT(6)	// FIQ Mask
 #define	SPSR_A32_T 		__BIT(5)	// A32 Thumb Mode
+#define	SPSR_A32		__BIT(4)	// A32 Mode (a part of SPSR_M)
 #define	SPSR_M	 		__BITS(4,0)	// Execution State
 #define	 SPSR_M_EL3H 		 0x0d
 #define	 SPSR_M_EL3T 		 0x0c

Index: src/sys/arch/aarch64/include/db_machdep.h
diff -u src/sys/arch/aarch64/include/db_machdep.h:1.7 src/sys/arch/aarch64/include/db_machdep.h:1.8
--- src/sys/arch/aarch64/include/db_machdep.h:1.7	Sat Sep 15 19:47:48 2018
+++ src/sys/arch/aarch64/include/db_machdep.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.h,v 1.7 2018/09/15 19:47:48 jakllsch Exp $ */
+/* $NetBSD: db_machdep.h,v 1.8 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -203,6 +203,7 @@ db_addr_t db_branch_taken(db_expr_t, db_
 #define DB_MACHINE_COMMANDS
 void dump_trapframe(struct trapframe *, void (*)(const char *, ...));
 const char *strdisasm(vaddr_t);
+const char *strdisasm_aarch32(vaddr_t);
 void db_machdep_init(void);
 
 /* hardware breakpoint/watchpoint functions */

Index: src/sys/arch/aarch64/include/elf_machdep.h
diff -u src/sys/arch/aarch64/include/elf_machdep.h:1.3 src/sys/arch/aarch64/include/elf_machdep.h:1.4
--- src/sys/arch/aarch64/include/elf_machdep.h:1.3	Wed Aug 15 11:08:18 2018
+++ src/sys/arch/aarch64/include/elf_machdep.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: elf_machdep.h,v 1.3 2018/08/15 11:08:18 ryo Exp $ */
+/* $NetBSD: elf_machdep.h,v 1.4 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -64,8 +64,8 @@
 #define	EF_ARM_EABI_VER4	0x04000000
 #define	EF_ARM_EABI_VER5	0x05000000
 
-#define ELF32_MACHDEP_ID_CASES                                          \
-		case EM_AARCH64:					\
+#define ELF32_MACHDEP_ID_CASES						\
+		case EM_ARM:						\
 			break;
 
 #define	ELF64_MACHDEP_ID_CASES						\
@@ -73,6 +73,7 @@
 			break;
 
 #define	ELF64_MACHDEP_ID	EM_AARCH64
+#define ELF32_MACHDEP_ID	EM_ARM
 
 #define	KERN_ELFSIZE		64
 #define ARCH_ELFSIZE		64	/* MD native binary size */
@@ -242,6 +243,8 @@ struct exec_package;
 
 int aarch64_netbsd_elf64_probe(struct lwp *, struct exec_package *, void *,
 	char *, vaddr_t *);
+int aarch64_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *,
+	char *, vaddr_t *);
 #endif
 
 #elif defined(__arm__)
Index: src/sys/arch/aarch64/include/param.h
diff -u src/sys/arch/aarch64/include/param.h:1.3 src/sys/arch/aarch64/include/param.h:1.4
--- src/sys/arch/aarch64/include/param.h:1.3	Sat Apr 28 10:53:02 2018
+++ src/sys/arch/aarch64/include/param.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: param.h,v 1.3 2018/04/28 10:53:02 jmcneill Exp $ */
+/* $NetBSD: param.h,v 1.4 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -80,7 +80,10 @@
 
 /* AARCH64-specific macro to align a stack pointer (downwards). */
 #define STACK_ALIGNBYTES	(16 - 1)
-#define ALIGNBYTES32		7
+
+#define ALIGNBYTES32		(4 - 1)
+#define ALIGN32(p)		\
+	(((uintptr_t)(p) + ALIGNBYTES32) & ~ALIGNBYTES32)
 
 #define DEV_BSHIFT		9	/* log2(DEV_BSIZE) */
 #define DEV_BSIZE		(1 << DEV_BSHIFT)

Index: src/sys/arch/aarch64/include/netbsd32_machdep.h
diff -u src/sys/arch/aarch64/include/netbsd32_machdep.h:1.1 src/sys/arch/aarch64/include/netbsd32_machdep.h:1.2
--- src/sys/arch/aarch64/include/netbsd32_machdep.h:1.1	Sun Apr  1 04:35:03 2018
+++ src/sys/arch/aarch64/include/netbsd32_machdep.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_machdep.h,v 1.1 2018/04/01 04:35:03 ryo Exp $	*/
+/*	$NetBSD: netbsd32_machdep.h,v 1.2 2018/10/12 01:28:58 ryo Exp $	*/
 
 #ifndef _MACHINE_NETBSD32_H_
 #define _MACHINE_NETBSD32_H_
@@ -15,8 +15,6 @@ typedef	struct { NETBSD32_POINTER_TYPE i
 
 typedef netbsd32_pointer_t netbsd32_sigcontextp_t;
 
-#define netbsd32_syscall_intern syscall_intern
-
 struct netbsd32_sigcontext13 {
 	int32_t		sc_onstack;		/* sigstack state to restore */
 	int32_t		__sc_mask13;		/* signal mask to restore (old style) */
@@ -67,6 +65,46 @@ struct netbsd32_sigcontext {
 	sigset_t	sc_mask;		/* signal mask to restore (new style) */
 };
 
-#define NETBSD32_MID_MACHINE MID_ARM
+struct netbsd32_sigframe_siginfo {
+	siginfo32_t sf_si;
+	ucontext32_t sf_uc;
+};
+
+struct reg32 {
+	uint32_t r[13];
+	uint32_t r_sp;
+	uint32_t r_lr;
+	uint32_t r_pc;
+	uint32_t r_cpsr;
+};
+
+struct vfpreg32 {
+	uint32_t vfp_fpexc;
+	uint32_t vfp_fpscr;
+	uint32_t vfp_fpinst;
+	uint32_t vfp_fpinst2;
+	uint64_t vfp_regs[33];	/* In case we need fstmx format. */
+};
+
+struct fpreg32 {
+	struct vfpreg32 fpr_vfp;
+};
+
+/* same as cpustate in arm/arm/core_machdep.c  */
+struct netbsd32_cpustate {
+	struct reg32 regs;
+	struct fpreg32 fpregs;
+};
+
+/* compat netbsd/arm sysarch(2) */
+#define ARM_SYNC_ICACHE		0
+#define ARM_DRAIN_WRITEBUF	1
+#define ARM_VFP_FPSCR		2
+#define ARM_FPU_USED		3
+
+struct netbsd32_arm_sync_icache_args {
+	netbsd32_uintptr_t addr;	/* Virtual start address */
+	netbsd32_size_t len;		/* Region size */
+};
 
 #endif /* _MACHINE_NETBSD32_H_ */

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.13 src/sys/arch/aarch64/include/pmap.h:1.14
--- src/sys/arch/aarch64/include/pmap.h:1.13	Fri Oct 12 00:57:17 2018
+++ src/sys/arch/aarch64/include/pmap.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.13 2018/10/12 00:57:17 ryo Exp $ */
+/* $NetBSD: pmap.h,v 1.14 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -248,6 +248,7 @@ aarch64_mmap_flags(paddr_t mdpgno)
 #define pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count)
 
 bool	pmap_extract_coherency(pmap_t, vaddr_t, paddr_t *, bool *);
+void	pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t);
 
 #define	PMAP_MAPSIZE1	L2_SIZE
 

Index: src/sys/arch/aarch64/include/vmparam.h
diff -u src/sys/arch/aarch64/include/vmparam.h:1.6 src/sys/arch/aarch64/include/vmparam.h:1.7
--- src/sys/arch/aarch64/include/vmparam.h:1.6	Fri Sep 14 05:37:42 2018
+++ src/sys/arch/aarch64/include/vmparam.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: vmparam.h,v 1.6 2018/09/14 05:37:42 ryo Exp $ */
+/* $NetBSD: vmparam.h,v 1.7 2018/10/12 01:28:58 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
 #endif
 
 #ifndef	MAXDSIZ32
-#define	MAXDSIZ32	(1536*1024*1024)	/* max data size */
+#define	MAXDSIZ32	(3U*1024*1024*1024)	/* max data size */
 #endif
 
 #ifndef	MAXSSIZ32
@@ -116,7 +116,7 @@
 #define	VM_MAXUSER_ADDRESS	((vaddr_t) (1L << 48) - PAGE_SIZE)
 #define	VM_MAX_ADDRESS		VM_MAXUSER_ADDRESS
 
-#define VM_MAXUSER_ADDRESS32	((vaddr_t) 0x7ffff000)
+#define VM_MAXUSER_ADDRESS32	((vaddr_t) 0xfffff000)
 
 /*
  * Give ourselves 64GB of mappable kernel space.  That leaves the rest
@@ -137,6 +137,11 @@
 #define USRIOSIZE		(PAGE_SIZE / 8)
 #define VM_PHYS_SIZE		(USRIOSIZE * PAGE_SIZE)
 
+#define VM_DEFAULT_ADDRESS32_TOPDOWN(da, sz) \
+	trunc_page(USRSTACK32 - MAXSSIZ32 - (sz) - user_stack_guard_size)
+#define VM_DEFAULT_ADDRESS32_BOTTOMUP(da, sz) \
+	round_page((vaddr_t)(da) + (vsize_t)MAXDSIZ32)
+
 /*
  * Since we have the address space, we map all of physical memory (RAM)
  * using block page table entries.

Index: src/sys/arch/arm/include/mcontext.h
diff -u src/sys/arch/arm/include/mcontext.h:1.20 src/sys/arch/arm/include/mcontext.h:1.21
--- src/sys/arch/arm/include/mcontext.h:1.20	Sun Apr  1 04:35:04 2018
+++ src/sys/arch/arm/include/mcontext.h	Fri Oct 12 01:28:58 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.20 2018/04/01 04:35:04 ryo Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.21 2018/10/12 01:28:58 ryo Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -142,7 +142,7 @@ typedef struct {
 
 /* Compat structures */
 typedef struct {
-#ifdef __ARM_EABI__
+#if 1 /* __ARM_EABI__ is default on aarch64 */
 	unsigned int	__vfp_fpscr;
 	uint64_t	__vfp_fstmx[32];
 	unsigned int	__vfp_fpsid;

Index: src/sys/arch/evbarm/conf/GENERIC64
diff -u src/sys/arch/evbarm/conf/GENERIC64:1.43 src/sys/arch/evbarm/conf/GENERIC64:1.44
--- src/sys/arch/evbarm/conf/GENERIC64:1.43	Wed Oct  3 06:02:33 2018
+++ src/sys/arch/evbarm/conf/GENERIC64	Fri Oct 12 01:28:58 2018
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC64,v 1.43 2018/10/03 06:02:33 skrll Exp $
+#	$NetBSD: GENERIC64,v 1.44 2018/10/12 01:28:58 ryo Exp $
 #
 #	GENERIC ARM (aarch64) kernel
 #
@@ -89,6 +89,9 @@ makeoptions	COPY_SYMTAB=1
 
 config		netbsd		root on ? type ?
 
+options 	COMPAT_NETBSD32
+options 	EXEC_ELF32
+
 # Device tree support
 armfdt0		at root
 simplebus*	at fdt? pass 0

Index: src/sys/arch/evbarm/conf/RPI64
diff -u src/sys/arch/evbarm/conf/RPI64:1.7 src/sys/arch/evbarm/conf/RPI64:1.8
--- src/sys/arch/evbarm/conf/RPI64:1.7	Wed Aug  1 20:04:11 2018
+++ src/sys/arch/evbarm/conf/RPI64	Fri Oct 12 01:28:58 2018
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: RPI64,v 1.7 2018/08/01 20:04:11 maxv Exp $
+#	$NetBSD: RPI64,v 1.8 2018/10/12 01:28:58 ryo Exp $
 #
 #	RPI64 - Raspberry Pi 3 and Pi 2 v1.2 in AARCH64 mode
 #
@@ -61,6 +61,9 @@ options 	LOCKDEBUG
 
 config		netbsd		root on ? type ?
 
+options 	COMPAT_NETBSD32
+options 	EXEC_ELF32
+
 # Device tree support
 armfdt0 	at root
 simplebus*	at fdt? pass 0

Added files:

Index: src/sys/arch/aarch64/aarch64/aarch32_syscall.c
diff -u /dev/null src/sys/arch/aarch64/aarch64/aarch32_syscall.c:1.1
--- /dev/null	Fri Oct 12 01:28:58 2018
+++ src/sys/arch/aarch64/aarch64/aarch32_syscall.c	Fri Oct 12 01:28:57 2018
@@ -0,0 +1,191 @@
+/*	$NetBSD: aarch32_syscall.c,v 1.1 2018/10/12 01:28:57 ryo Exp $	*/
+
+/*
+ * Copyright (c) 2018 Ryo Shimizu <r...@nerv.org>
+ * 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);
+}
Index: src/sys/arch/aarch64/aarch64/netbsd32_syscall.c
diff -u /dev/null src/sys/arch/aarch64/aarch64/netbsd32_syscall.c:1.1
--- /dev/null	Fri Oct 12 01:28:58 2018
+++ src/sys/arch/aarch64/aarch64/netbsd32_syscall.c	Fri Oct 12 01:28:57 2018
@@ -0,0 +1,39 @@
+/*	$NetBSD: netbsd32_syscall.c,v 1.1 2018/10/12 01:28:57 ryo Exp $	*/
+
+/*
+ * Copyright (c) 2018 Ryo Shimizu <r...@nerv.org>
+ * 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: netbsd32_syscall.c,v 1.1 2018/10/12 01:28:57 ryo Exp $");
+
+#include "opt_compat_netbsd32.h"
+
+#include <compat/netbsd32/netbsd32_syscall.h>
+
+#define EMULNAME(x)		__CONCAT(netbsd32_,x)
+#define EMULNAMEU(x)		__CONCAT(NETBSD32_,x)
+
+#include "aarch32_syscall.c"

Reply via email to