mips compat: switch to compat_binfmt_elf.c
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 14 Jun 2020 04:18:12 +0000 (00:18 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 6 Jan 2021 13:42:49 +0000 (08:42 -0500)
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: Al Viro <viro@zeniv.linux.org.uk>
arch/mips/Kconfig
arch/mips/include/asm/elf.h
arch/mips/include/asm/elfcore-compat.h [new file with mode: 0644]
arch/mips/kernel/Makefile
arch/mips/kernel/binfmt_elfn32.c [deleted file]
arch/mips/kernel/binfmt_elfo32.c [deleted file]
arch/mips/kernel/scall64-n64.S

index 04aecf51e37612621e49900e80826a0493c67956..a46423f1cabcfbda797d19ff3b41554c1edd5d48 100644 (file)
@@ -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
index d29e43e4f9b14f786075d80ee3243fb8ca2d1dbc..dc8d2863752cfd5e8e2cbd750276f9463e0c32b8 100644 (file)
@@ -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)                         \
-               __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;                                              \
-                                                                       \
+       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;
diff --git a/arch/mips/include/asm/elfcore-compat.h b/arch/mips/include/asm/elfcore-compat.h
new file mode 100644 (file)
index 0000000..2f0f010
--- /dev/null
@@ -0,0 +1,29 @@
+#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
index 2a05b923f579da26bb554c00e67976807c3a3413..943eaeef73e9d27f900590c0f8dd311d43978d49 100644 (file)
@@ -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
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
deleted file mode 100644 (file)
index 573f2a1..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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"
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
deleted file mode 100644 (file)
index f5ee6b4..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Support for o32 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 int 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 elfo32_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_elf32_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"
index 23b2e2b1609cf72f417c5d82172e53a5a2e03701..5e9c497ce099c1768c9888ae3ab10637530574b9 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/unistd.h>
 #include <asm/war.h>
 
-#ifndef CONFIG_BINFMT_ELF32
+#ifndef CONFIG_MIPS32_COMPAT
 /* Neither O32 nor N32, so define handle_sys here */
 #define handle_sys64 handle_sys
 #endif