Commit 0bb87f05 authored by Al Viro's avatar Al Viro
Browse files

mips compat: switch to compat_binfmt_elf.c



Like amd64, mips has two 32bit ABIs - o32 and n32.  Unlike amd64,
it does not use compat_binfmt_elf.c for either of those; each
of those ABIs has a binfmt handler of its own, both very similar
to fs/compat_binfmt_elf.c.  And the same technics as we use on
amd64 can be used to make fs/compat_binfmt_elf.c handle both.
	* merge elfo32_check_arch() with elfn32_check_arch(),
make that serve as compat_elf_check_arch().  Note that
SET_PERSONALITY2() is already the same for all ABI variants -
it looks at the elf header to choose the flags to set.
	* add asm/elfcore-compat.h, using the bigger (n32) variant
of elf32_prstatus as compat_elf_prstatus there.
	* make PRSTATUS_SIZE() and SET_PR_FPVALID() choose the
right layout, same as done for amd64.  test_thread_flag(TIF_32BIT_REGS)
is used as the predicate.

Voila - we are rid of binfmt_elf{n,o}32.c; fs/compat_binfmt_elf.c is
used, same as for all other ELF-supporting 64bit architectures that
need 32bit compat.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2fb33bec
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ config MIPS
	select SET_FS
	select SYSCTL_EXCEPTION_TRACE
	select VIRT_TO_BUS
	select ARCH_HAS_ELFCORE_COMPAT

config MIPS_FIXUP_BIGPHYS_ADDR
	bool
@@ -3277,6 +3278,7 @@ config MIPS32_O32
	select ARCH_WANT_OLD_COMPAT_IPC
	select COMPAT
	select MIPS32_COMPAT
	select COMPAT_BINFMT_ELF
	select SYSVIPC_COMPAT if SYSVIPC
	help
	  Select this option if you want to run o32 binaries.  These are pure
@@ -3290,6 +3292,7 @@ config MIPS32_N32
	depends on 64BIT
	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
	select COMPAT
	select COMPAT_BINFMT_ELF
	select MIPS32_COMPAT
	select SYSVIPC_COMPAT if SYSVIPC
	help
@@ -3300,11 +3303,6 @@ config MIPS32_N32

	  If unsure, say N.

config BINFMT_ELF32
	bool
	default y if MIPS32_O32 || MIPS32_N32
	select ELFCORE

menu "Power management options"

config ARCH_HIBERNATION_POSSIBLE
+19 −35
Original line number Diff line number Diff line
@@ -201,7 +201,6 @@ struct mips_elf_abiflags_v0 {
	uint32_t flags2;
};

#ifndef ELF_ARCH
/* ELF register definitions */
#define ELF_NGREG	45
#define ELF_NFPREG	33
@@ -219,7 +218,7 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
/*
 * This is used to ensure we don't load something for the wrong architecture.
 */
#define elf_check_arch elfo32_check_arch
#define elf_check_arch elf32_check_arch

/*
 * These are used to set parameters in the core dumps.
@@ -235,7 +234,8 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
/*
 * This is used to ensure we don't load something for the wrong architecture.
 */
#define elf_check_arch elfn64_check_arch
#define elf_check_arch elf64_check_arch
#define compat_elf_check_arch elf32_check_arch

/*
 * These are used to set parameters in the core dumps.
@@ -257,8 +257,6 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
#endif
#define ELF_ARCH	EM_MIPS

#endif /* !defined(ELF_ARCH) */

/*
 * In order to be sure that we don't attempt to execute an O32 binary which
 * requires 64 bit FP (FR=1) on a system which does not support it we refuse
@@ -277,9 +275,9 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
#define vmcore_elf64_check_arch mips_elf_check_machine

/*
 * Return non-zero if HDR identifies an o32 ELF binary.
 * Return non-zero if HDR identifies an o32 or n32 ELF binary.
 */
#define elfo32_check_arch(hdr)						\
#define elf32_check_arch(hdr)						\
({									\
	int __res = 1;							\
	struct elfhdr *__h = (hdr);					\
@@ -288,21 +286,26 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
		__res = 0;						\
	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
		__res = 0;						\
	if ((__h->e_flags & EF_MIPS_ABI2) != 0)				\
	if ((__h->e_flags & EF_MIPS_ABI2) != 0) {			\
		if (!IS_ENABLED(CONFIG_MIPS32_N32) ||			\
		     (__h->e_flags & EF_MIPS_ABI))			\
			__res = 0;					\
	} else {							\
		if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32)) \
			__res = 0;					\
		if (((__h->e_flags & EF_MIPS_ABI) != 0) &&		\
		    ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32))	\
			__res = 0;					\
		if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO)	\
			__res = 0;					\
									\
	}								\
	__res;								\
})

/*
 * Return non-zero if HDR identifies an n64 ELF binary.
 */
#define elfn64_check_arch(hdr)						\
#define elf64_check_arch(hdr)						\
({									\
	int __res = 1;							\
	struct elfhdr *__h = (hdr);					\
@@ -315,25 +318,6 @@ void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
	__res;								\
})

/*
 * Return non-zero if HDR identifies an n32 ELF binary.
 */
#define elfn32_check_arch(hdr)						\
({									\
	int __res = 1;							\
	struct elfhdr *__h = (hdr);					\
									\
	if (!mips_elf_check_machine(__h))				\
		__res = 0;						\
	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
		__res = 0;						\
	if (((__h->e_flags & EF_MIPS_ABI2) == 0) ||			\
	    ((__h->e_flags & EF_MIPS_ABI) != 0))			\
		__res = 0;						\
									\
	__res;								\
})

struct mips_abi;

extern struct mips_abi mips_abi;
+29 −0
Original line number Diff line number Diff line
#ifndef _ASM_MIPS_ELFCORE_COMPAT_H
#define _ASM_MIPS_ELFCORE_COMPAT_H

/*
 * On mips we have two 32bit ABIs - o32 and n32.  The latter
 * has bigger registers, so we use it for compat_elf_regset_t.
 * The former uses o32_elf_prstatus and PRSTATUS_SIZE/SET_PR_FPVALID
 * are used to choose the size and location of ->pr_fpvalid of
 * the layout actually used.
 */
typedef elf_gregset_t compat_elf_gregset_t;

struct o32_elf_prstatus
{
	struct compat_elf_prstatus_common	common;
	unsigned int 			pr_reg[ELF_NGREG];
	compat_int_t			pr_fpvalid;
};

#define PRSTATUS_SIZE \
	(!test_thread_flag(TIF_32BIT_REGS) \
		? sizeof(struct compat_elf_prstatus) \
		: sizeof(struct o32_elf_prstatus))
#define SET_PR_FPVALID(S) \
	(*(!test_thread_flag(TIF_32BIT_REGS) \
		? &(S)->pr_fpvalid 	\
		: &((struct o32_elf_prstatus *)(S))->pr_fpvalid) = 1)

#endif
+2 −2
Original line number Diff line number Diff line
@@ -80,8 +80,8 @@ obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_32BIT)		+= scall32-o32.o
obj-$(CONFIG_64BIT)		+= scall64-n64.o
obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o ptrace32.o signal32.o
obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o signal_o32.o
obj-$(CONFIG_MIPS32_N32)	+= scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32)	+= scall64-o32.o signal_o32.o

obj-$(CONFIG_KGDB)		+= kgdb.o
obj-$(CONFIG_PROC_FS)		+= proc.o

arch/mips/kernel/binfmt_elfn32.c

deleted100644 → 0
+0 −65
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Support for n32 Linux/MIPS ELF binaries.
 * Author: Ralf Baechle (ralf@linux-mips.org)
 *
 * Copyright (C) 1999, 2001 Ralf Baechle
 * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
 *
 * Heavily inspired by the 32-bit Sparc compat code which is
 * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
 * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek	(jj@ultra.linux.cz)
 */

#define ELF_ARCH		EM_MIPS
#define ELF_CLASS		ELFCLASS32
#ifdef __MIPSEB__
#define ELF_DATA		ELFDATA2MSB;
#else /* __MIPSEL__ */
#define ELF_DATA		ELFDATA2LSB;
#endif

/* ELF register definitions */
#define ELF_NGREG	45
#define ELF_NFPREG	33

typedef unsigned long elf_greg_t;
typedef elf_greg_t elf_gregset_t[ELF_NGREG];

typedef double elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];

/*
 * This is used to ensure we don't load something for the wrong architecture.
 */
#define elf_check_arch elfn32_check_arch

#include <asm/processor.h>
#include <linux/elfcore.h>
#include <linux/compat.h>
#include <linux/math64.h>
#include <linux/elfcore-compat.h>

#define elf_prstatus elf_prstatus32
#define elf_prstatus_common compat_elf_prstatus_common
struct elf_prstatus32
{
	struct compat_elf_prstatus_common common;
	elf_gregset_t pr_reg;	/* GP registers */
	int pr_fpvalid;		/* True if math co-processor being used.  */
};
#define elf_prpsinfo compat_elf_prpsinfo

#define init_elf_binfmt init_elfn32_binfmt

#undef ns_to_kernel_old_timeval
#define ns_to_kernel_old_timeval ns_to_old_timeval32

/*
 * Some data types as stored in coredump.
 */
#define user_long_t             compat_long_t
#define user_siginfo_t          compat_siginfo_t
#define copy_siginfo_to_external        copy_siginfo_to_external32

#include "../../../fs/binfmt_elf.c"
Loading