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