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"