Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: cpu_exec.c,v 1.70 2022/09/29 07:00:46 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1992, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by Ralph
      8  * Campbell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. Neither the name of the University nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  *
     34  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
     35  */
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: cpu_exec.c,v 1.70 2022/09/29 07:00:46 skrll Exp $");
     39 
     40 #include "opt_compat_netbsd.h"
     41 #include "opt_compat_ultrix.h"
     42 #include "opt_execfmt.h"
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/proc.h>
     47 #include <sys/vnode.h>
     48 #include <sys/exec.h>
     49 #include <sys/namei.h>
     50 #include <sys/resourcevar.h>
     51 
     52 #include <uvm/uvm_extern.h>
     53 
     54 #include <compat/common/compat_util.h>
     55 
     56 #ifdef EXEC_ECOFF
     57 #include <sys/exec_ecoff.h>
     58 #endif
     59 #include <sys/exec_elf.h>			/* mandatory */
     60 #include <mips/locore.h>
     61 #include <mips/reg.h>
     62 #include <mips/regnum.h>			/* symbolic register indices */
     63 
     64 #include <compat/common/compat_util.h>
     65 
     66 #ifdef EXEC_ECOFF
     67 void
     68 cpu_exec_ecoff_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack)
     69 {
     70 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
     71 	struct trapframe *tf = l->l_md.md_utf;
     72 
     73 	tf->tf_regs[_R_GP] = (register_t)execp->a.gp_value;
     74 }
     75 
     76 /*
     77  * cpu_exec_ecoff_probe()
     78  *	cpu-dependent ECOFF format hook for execve().
     79  *
     80  * Do any machine-dependent diddling of the exec package when doing ECOFF.
     81  */
     82 int
     83 cpu_exec_ecoff_probe(struct lwp *l, struct exec_package *epp)
     84 {
     85 
     86 	/* NetBSD/mips does not have native ECOFF binaries. */
     87 	return ENOEXEC;
     88 }
     89 #endif /* EXEC_ECOFF */
     90 
     91 #if EXEC_ELF32
     92 int
     93 mips_netbsd_elf32_probe(struct lwp *l, struct exec_package *epp, void *eh0,
     94 	char *itp, vaddr_t *start_p)
     95 {
     96 	struct proc * const p = l->l_proc;
     97 	const Elf32_Ehdr * const eh = eh0;
     98 #ifdef DEBUG_EXEC
     99 	int old_abi = p->p_md.md_abi;
    100 #endif /* DEBUG_EXEC */
    101 	const char *itp_suffix = NULL;
    102 
    103 	/*
    104 	 * Verify we can support the architecture.
    105 	 */
    106 	switch (eh->e_flags & EF_MIPS_ARCH) {
    107 	case EF_MIPS_ARCH_1:
    108 		break;
    109 	case EF_MIPS_ARCH_2:
    110 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS2)
    111 			return ENOEXEC;
    112 		break;
    113 	case EF_MIPS_ARCH_3:
    114 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS3)
    115 			return ENOEXEC;
    116 		break;
    117 	case EF_MIPS_ARCH_4:
    118 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS4)
    119 			return ENOEXEC;
    120 		break;
    121 	case EF_MIPS_ARCH_5:
    122 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS5)
    123 			return ENOEXEC;
    124 		break;
    125 	case EF_MIPS_ARCH_32:
    126 	case EF_MIPS_ARCH_64:
    127 		if (!CPUISMIPSNN && !CPUISMIPS32R2 && !CPUISMIPS64R2)
    128 			return ENOEXEC;
    129 		break;
    130 	case EF_MIPS_ARCH_32R2:
    131 	case EF_MIPS_ARCH_64R2:
    132 		if (!CPUISMIPS32R2 && !CPUISMIPS64R2)
    133 			return ENOEXEC;
    134 		break;
    135 	}
    136 
    137 	switch (eh->e_flags & (EF_MIPS_ABI|EF_MIPS_ABI2)) {
    138 #if !defined(__mips_o32)
    139 	case EF_MIPS_ABI2:
    140 		itp_suffix = "n32";
    141 		p->p_md.md_abi = _MIPS_BSD_API_N32;
    142 #ifdef DEBUG_EXEC
    143 		if (old_abi != p->p_md.md_abi)
    144 			printf("pid %d(%s): ABI set to N32 (e_flags=%#x)\n", p->p_pid, p->p_comm, eh->e_flags);
    145 #endif /* DEBUG_EXEC */
    146 		break;
    147 #endif
    148 #ifdef COMPAT_16
    149 	case 0:
    150 		*start_p = ELF32_LINK_ADDR;
    151 		/* FALLTHROUGH */
    152 #endif
    153 	case EF_MIPS_ABI_O32:
    154 		itp_suffix = "o32";
    155 		p->p_md.md_abi = _MIPS_BSD_API_O32;
    156 #ifdef DEBUG_EXEC
    157 		if (old_abi != p->p_md.md_abi)
    158 			printf("pid %d(%s): ABI set to O32 (e_flags=%#x)\n", p->p_pid, p->p_comm, eh->e_flags);
    159 #endif /* DEBUG_EXEC */
    160 		break;
    161 	default:
    162 		return ENOEXEC;
    163 	}
    164 
    165 	(void)compat_elf_check_interp(epp, itp, itp_suffix);
    166 	return 0;
    167 }
    168 
    169 void
    170 coredump_elf32_setup(struct lwp *l, void *eh0)
    171 {
    172 	struct proc * const p = l->l_proc;
    173 	Elf32_Ehdr * const eh = eh0;
    174 
    175 	/*
    176 	 * Mark the type of CPU that the dump happened on.
    177 	 */
    178 	if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS64R2) {
    179 		eh->e_flags |= EF_MIPS_ARCH_64R2;
    180 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS64) {
    181 		eh->e_flags |= EF_MIPS_ARCH_64;
    182 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS32R2) {
    183 		eh->e_flags |= EF_MIPS_ARCH_32R2;
    184 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS32) {
    185 		eh->e_flags |= EF_MIPS_ARCH_32;
    186 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS5) {
    187 		eh->e_flags |= EF_MIPS_ARCH_5;
    188 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS4) {
    189 		eh->e_flags |= EF_MIPS_ARCH_4;
    190 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS3) {
    191 		eh->e_flags |= EF_MIPS_ARCH_3;
    192 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS2) {
    193 		eh->e_flags |= EF_MIPS_ARCH_2;
    194 	} else {
    195 		eh->e_flags |= EF_MIPS_ARCH_1;
    196 	}
    197 
    198 	switch (p->p_md.md_abi) {
    199 	case _MIPS_BSD_API_N32:
    200 		eh->e_flags |= EF_MIPS_ABI2;
    201 		break;
    202 	case _MIPS_BSD_API_O32:
    203 		eh->e_flags |= EF_MIPS_ABI_O32;
    204 		break;
    205 	}
    206 }
    207 #endif
    208 
    209 #if EXEC_ELF64
    210 int
    211 mips_netbsd_elf64_probe(struct lwp *l, struct exec_package *epp, void *eh0,
    212 	char *itp, vaddr_t *start_p)
    213 {
    214 	struct proc * const p = l->l_proc;
    215 	const Elf64_Ehdr * const eh = eh0;
    216 #ifdef DEBUG_EXEC
    217 	int old_abi = p->p_md.md_abi;
    218 #endif /* DEBUG_EXEC */
    219 	const char *itp_suffix = NULL;
    220 
    221 	switch (eh->e_flags & EF_MIPS_ARCH) {
    222 	case EF_MIPS_ARCH_1:
    223 		return ENOEXEC;
    224 	case EF_MIPS_ARCH_2:
    225 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS2)
    226 			return ENOEXEC;
    227 		break;
    228 	case EF_MIPS_ARCH_3:
    229 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS3)
    230 			return ENOEXEC;
    231 		break;
    232 	case EF_MIPS_ARCH_4:
    233 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS4)
    234 			return ENOEXEC;
    235 		break;
    236 	case EF_MIPS_ARCH_5:
    237 		if (mips_options.mips_cpu_arch < CPU_ARCH_MIPS5)
    238 			return ENOEXEC;
    239 		break;
    240 	case EF_MIPS_ARCH_32:
    241 	case EF_MIPS_ARCH_32R2:
    242 		return ENOEXEC;
    243 	case EF_MIPS_ARCH_64:
    244 		if (!CPUISMIPS64 && !CPUISMIPS64R2)
    245 			return ENOEXEC;
    246 		break;
    247 	case EF_MIPS_ARCH_64R2:
    248 		if (!CPUISMIPS64R2)
    249 			return ENOEXEC;
    250 		break;
    251 	}
    252 
    253 	switch (eh->e_flags & (EF_MIPS_ABI|EF_MIPS_ABI2)) {
    254 	case 0:
    255 		itp_suffix = "64";
    256 		p->p_md.md_abi = _MIPS_BSD_API_N64;
    257 #ifdef DEBUG_EXEC
    258 		if (old_abi != p->p_md.md_abi)
    259 			printf("pid %d(%s): ABI set to N64 (e_flags=%#x)\n", p->p_pid, p->p_comm, eh->e_flags);
    260 #endif /* DEBUG_EXEC */
    261 		break;
    262 	case EF_MIPS_ABI_O64:
    263 		itp_suffix = "o64";
    264 		p->p_md.md_abi = _MIPS_BSD_API_O64;
    265 #ifdef DEBUG_EXEC
    266 		if (old_abi != p->p_md.md_abi)
    267 			printf("pid %d(%s): ABI set to O64 (e_flags=%#x)\n", p->p_pid, p->p_comm, eh->e_flags);
    268 #endif /* DEBUG_EXEC */
    269 		break;
    270 	default:
    271 		return ENOEXEC;
    272 	}
    273 
    274 	(void)compat_elf_check_interp(epp, itp, itp_suffix);
    275 	return 0;
    276 }
    277 
    278 void
    279 coredump_elf64_setup(struct lwp *l, void *eh0)
    280 {
    281 	struct proc * const p = l->l_proc;
    282 	Elf64_Ehdr * const eh = eh0;
    283 
    284 	/*
    285 	 * Mark the type of CPU that the dump happened on.
    286 	 */
    287 	if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS64) {
    288 		eh->e_flags |= EF_MIPS_ARCH_64;
    289 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS32) {
    290 		eh->e_flags |= EF_MIPS_ARCH_32;
    291 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS5) {
    292 		eh->e_flags |= EF_MIPS_ARCH_5;
    293 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS4) {
    294 		eh->e_flags |= EF_MIPS_ARCH_4;
    295 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS3) {
    296 		eh->e_flags |= EF_MIPS_ARCH_3;
    297 	} else if (mips_options.mips_cpu_arch & CPU_ARCH_MIPS2) {
    298 		eh->e_flags |= EF_MIPS_ARCH_2;
    299 	} else {
    300 		eh->e_flags |= EF_MIPS_ARCH_1;
    301 	}
    302 	switch (p->p_md.md_abi) {
    303 	case _MIPS_BSD_API_N64:
    304 		eh->e_flags |= EF_MIPS_ABI2;
    305 		break;
    306 	case _MIPS_BSD_API_O64:
    307 		eh->e_flags |= EF_MIPS_ABI_O64;
    308 		break;
    309 	}
    310 }
    311 #endif
    312