xref: /netbsd-src/sys/compat/netbsd32/netbsd32_mod.c (revision c988d5c135d1e8e62f935b530c9164f9884d0f75)
1*c988d5c1Schristos /*	$NetBSD: netbsd32_mod.c,v 1.23 2020/08/08 19:08:48 christos Exp $	*/
292ce8c6aSad 
392ce8c6aSad /*-
492ce8c6aSad  * Copyright (c) 2008 The NetBSD Foundation, Inc.
592ce8c6aSad  * All rights reserved.
692ce8c6aSad  *
792ce8c6aSad  * This code is derived from software developed for The NetBSD Foundation
892ce8c6aSad  * by Andrew Doran.
992ce8c6aSad  *
1092ce8c6aSad  * Redistribution and use in source and binary forms, with or without
1192ce8c6aSad  * modification, are permitted provided that the following conditions
1292ce8c6aSad  * are met:
1392ce8c6aSad  * 1. Redistributions of source code must retain the above copyright
1492ce8c6aSad  *    notice, this list of conditions and the following disclaimer.
1592ce8c6aSad  * 2. Redistributions in binary form must reproduce the above copyright
1692ce8c6aSad  *    notice, this list of conditions and the following disclaimer in the
1792ce8c6aSad  *    documentation and/or other materials provided with the distribution.
1892ce8c6aSad  *
1992ce8c6aSad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2092ce8c6aSad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2192ce8c6aSad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2292ce8c6aSad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2392ce8c6aSad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2492ce8c6aSad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2592ce8c6aSad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2692ce8c6aSad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2792ce8c6aSad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2892ce8c6aSad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2992ce8c6aSad  * POSSIBILITY OF SUCH DAMAGE.
3092ce8c6aSad  */
3192ce8c6aSad 
3200207415Spgoyette /*
3300207415Spgoyette  * Copyright (c) 1998, 2000, 2017 The NetBSD Foundation, Inc.
3400207415Spgoyette  * All rights reserved.
3500207415Spgoyette  *
3600207415Spgoyette  * This code is derived from software contributed to The NetBSD Foundation
3700207415Spgoyette  * by Charles M. Hannum, and by Maxime Villard.
3800207415Spgoyette  *
3900207415Spgoyette  * Redistribution and use in source and binary forms, with or without
4000207415Spgoyette  * modification, are permitted provided that the following conditions
4100207415Spgoyette  * are met:
4200207415Spgoyette  * 1. Redistributions of source code must retain the above copyright
4300207415Spgoyette  *    notice, this list of conditions and the following disclaimer.
4400207415Spgoyette  * 2. Redistributions in binary form must reproduce the above copyright
4500207415Spgoyette  *    notice, this list of conditions and the following disclaimer in the
4600207415Spgoyette  *    documentation and/or other materials provided with the distribution.
4700207415Spgoyette  *
4800207415Spgoyette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
4900207415Spgoyette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
5000207415Spgoyette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5100207415Spgoyette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
5200207415Spgoyette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5300207415Spgoyette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5400207415Spgoyette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5500207415Spgoyette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5600207415Spgoyette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5700207415Spgoyette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5800207415Spgoyette  * POSSIBILITY OF SUCH DAMAGE.
5900207415Spgoyette  */
6000207415Spgoyette 
6192ce8c6aSad #include <sys/cdefs.h>
62*c988d5c1Schristos __KERNEL_RCSID(0, "$NetBSD: netbsd32_mod.c,v 1.23 2020/08/08 19:08:48 christos Exp $");
6392ce8c6aSad 
6492ce8c6aSad #ifdef _KERNEL_OPT
6592ce8c6aSad #include "opt_execfmt.h"
6692ce8c6aSad #endif
6792ce8c6aSad 
6892ce8c6aSad #ifndef ELFSIZE
6992ce8c6aSad #define ELFSIZE ARCH_ELFSIZE
7092ce8c6aSad #endif
7192ce8c6aSad 
7292ce8c6aSad #include <sys/param.h>
7392ce8c6aSad #include <sys/module.h>
7492ce8c6aSad #include <sys/exec.h>
7592ce8c6aSad #include <sys/exec_elf.h>
76d91f98a8Spgoyette #include <sys/module_hook.h>
7700207415Spgoyette #include <sys/compat_stub.h>
7892ce8c6aSad 
792c1f7518Spgoyette #include <compat/netbsd32/netbsd32_sysctl.h>
80d91f98a8Spgoyette #include <compat/netbsd32/netbsd32_kern_proc.h>
8192ce8c6aSad #include <compat/netbsd32/netbsd32_exec.h>
8292ce8c6aSad 
83d91f98a8Spgoyette #define ELF32_AUXSIZE (howmany(ELF_AUX_ENTRIES * sizeof(Aux32Info), \
84d91f98a8Spgoyette     sizeof(Elf32_Addr)) + MAXPATHLEN + ALIGN(1))
85d91f98a8Spgoyette 
86d91f98a8Spgoyette struct compat32_80_modctl_hook_t compat32_80_modctl_hook;
87d91f98a8Spgoyette 
881d577fe3Spgoyette # define	DEPS1	"ksem,compat_util"
890b8f4131Spgoyette 
907fe6b3efSmaxv #if defined(EXEC_ELF32)
917fe6b3efSmaxv # define	DEPS2	",exec_elf32"
927fe6b3efSmaxv #else
937fe6b3efSmaxv # define	DEPS2	""
947fe6b3efSmaxv #endif
957fe6b3efSmaxv 
967fe6b3efSmaxv MODULE(MODULE_CLASS_EXEC, compat_netbsd32, DEPS1 DEPS2);
9792ce8c6aSad 
9892ce8c6aSad static struct execsw netbsd32_execsw[] = {
9992ce8c6aSad #ifdef EXEC_AOUT
10054b7adb1Schristos 	{
10154b7adb1Schristos 		.es_hdrsz = sizeof(struct netbsd32_exec),
10254b7adb1Schristos 		.es_makecmds = exec_netbsd32_makecmds,
10354b7adb1Schristos 		.u = {
10454b7adb1Schristos 			.elf_probe_func = NULL,
10554b7adb1Schristos 		},
10654b7adb1Schristos 		.es_emul = &emul_netbsd32,
10754b7adb1Schristos 		.es_prio = EXECSW_PRIO_FIRST,
10854b7adb1Schristos 		.es_arglen = 0,
10954b7adb1Schristos 		.es_copyargs = netbsd32_copyargs,
11054b7adb1Schristos 		.es_setregs = NULL,
11154b7adb1Schristos 		.es_coredump = coredump_netbsd32,
11254b7adb1Schristos 		.es_setup_stack = exec_setup_stack,
11354b7adb1Schristos 	},
11492ce8c6aSad #endif
11592ce8c6aSad #ifdef EXEC_ELF32
11654b7adb1Schristos 	{
11754b7adb1Schristos 		.es_hdrsz = sizeof (Elf32_Ehdr),
11854b7adb1Schristos 		.es_makecmds = exec_elf32_makecmds,
11954b7adb1Schristos 		.u = {
12054b7adb1Schristos 			.elf_probe_func = netbsd32_elf32_probe,
12154b7adb1Schristos 		},
12254b7adb1Schristos 		.es_emul = &emul_netbsd32,
1235848af8eSmaxv 		.es_prio = EXECSW_PRIO_ANY,
12454b7adb1Schristos 		.es_arglen = ELF32_AUXSIZE,
12554b7adb1Schristos 		.es_copyargs = netbsd32_elf32_copyargs,
12654b7adb1Schristos 		.es_setregs = NULL,
12754b7adb1Schristos 		.es_coredump = coredump_elf32,
1289ac9b69cSmrg 		.es_setup_stack = exec_setup_stack,
12954b7adb1Schristos 	},
13092ce8c6aSad #endif
13192ce8c6aSad };
13292ce8c6aSad 
13300207415Spgoyette #if defined(__amd64__)
134*c988d5c1Schristos #include <x86/cpu.h>
13500207415Spgoyette 
13600207415Spgoyette /* This code was moved here, from $SRC/arch/amd64/amd64/trap.c */
13700207415Spgoyette 
13800207415Spgoyette static int
amd64_oosyscall_handle(struct proc * p,struct trapframe * frame)13900207415Spgoyette amd64_oosyscall_handle(struct proc *p, struct trapframe *frame)
14000207415Spgoyette {
141*c988d5c1Schristos 	int error = EPASSTHROUGH;
142*c988d5c1Schristos #define LCALLSZ	7
14300207415Spgoyette 
14400207415Spgoyette 	/* Check for the oosyscall lcall instruction. */
14500207415Spgoyette 	if (p->p_emul == &emul_netbsd32 &&
146*c988d5c1Schristos 	    frame->tf_rip < VM_MAXUSER_ADDRESS32 - LCALLSZ &&
147*c988d5c1Schristos 	    (error = x86_cpu_is_lcall((void *)frame->tf_rip)) == 0)
148*c988d5c1Schristos 	{
1492ca077cdSpgoyette 		/* Advance past the lcall and save instruction size. */
150*c988d5c1Schristos 		frame->tf_rip += LCALLSZ;
151*c988d5c1Schristos 		frame->tf_err = LCALLSZ;
15200207415Spgoyette 		return 0;
153*c988d5c1Schristos 	}
154*c988d5c1Schristos 
155*c988d5c1Schristos 	return error;
15600207415Spgoyette }
1572ca077cdSpgoyette #endif /* defined(__amd64__) */
15800207415Spgoyette 
15992ce8c6aSad static int
compat_netbsd32_modcmd(modcmd_t cmd,void * arg)16092ce8c6aSad compat_netbsd32_modcmd(modcmd_t cmd, void *arg)
16192ce8c6aSad {
16292ce8c6aSad 	int error;
16392ce8c6aSad 
16492ce8c6aSad 	switch (cmd) {
16592ce8c6aSad 	case MODULE_CMD_INIT:
16692ce8c6aSad 		error = exec_add(netbsd32_execsw,
16792ce8c6aSad 		    __arraycount(netbsd32_execsw));
168d91f98a8Spgoyette 		if (error == 0) {
169d91f98a8Spgoyette 			netbsd32_machdep_md_init();
170d91f98a8Spgoyette 			netbsd32_kern_proc_32_init();
17100207415Spgoyette #if defined(__amd64__)
172416ea473Spgoyette 			MODULE_HOOK_SET(amd64_oosyscall_hook,
173416ea473Spgoyette 			    amd64_oosyscall_handle);
1742ca077cdSpgoyette #endif /* defined(__amd64__) */
175d91f98a8Spgoyette 		}
17692ce8c6aSad 		return error;
17792ce8c6aSad 
17892ce8c6aSad 	case MODULE_CMD_FINI:
17900207415Spgoyette #if defined(__amd64__)
18000207415Spgoyette 		MODULE_HOOK_UNSET(amd64_oosyscall_hook);
1812ca077cdSpgoyette #endif /* defined(__amd64__) */
182d91f98a8Spgoyette 		netbsd32_machdep_md_fini();
1832c1f7518Spgoyette 		netbsd32_sysctl_fini();
184d91f98a8Spgoyette 		netbsd32_kern_proc_32_fini();
185d91f98a8Spgoyette 
18692ce8c6aSad 		error = exec_remove(netbsd32_execsw,
18792ce8c6aSad 		    __arraycount(netbsd32_execsw));
188d91f98a8Spgoyette 		if (error) {
189d91f98a8Spgoyette 			netbsd32_kern_proc_32_init();
190d91f98a8Spgoyette 			netbsd32_machdep_md_init();
19100207415Spgoyette #if defined(__amd64__)
19200207415Spgoyette 			MODULE_HOOK_SET(amd64_oosyscall_hook,
19300207415Spgoyette 			    amd64_oosyscall_handle);
1942ca077cdSpgoyette #endif /* defined(__amd64__) */
195d91f98a8Spgoyette 		}
19692ce8c6aSad 		return error;
19792ce8c6aSad 
19892ce8c6aSad 	default:
19992ce8c6aSad 		return ENOTTY;
20092ce8c6aSad 	}
20192ce8c6aSad }
202