Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 0bb87f05 2fb33bec

+54 -174
+3 -5
arch/mips/Kconfig
··· 92 92 select SET_FS 93 93 select SYSCTL_EXCEPTION_TRACE 94 94 select VIRT_TO_BUS 95 + select ARCH_HAS_ELFCORE_COMPAT 95 96 96 97 config MIPS_FIXUP_BIGPHYS_ADDR 97 98 bool ··· 3278 3277 select ARCH_WANT_OLD_COMPAT_IPC 3279 3278 select COMPAT 3280 3279 select MIPS32_COMPAT 3280 + select COMPAT_BINFMT_ELF 3281 3281 select SYSVIPC_COMPAT if SYSVIPC 3282 3282 help 3283 3283 Select this option if you want to run o32 binaries. These are pure ··· 3292 3290 depends on 64BIT 3293 3291 select ARCH_WANT_COMPAT_IPC_PARSE_VERSION 3294 3292 select COMPAT 3293 + select COMPAT_BINFMT_ELF 3295 3294 select MIPS32_COMPAT 3296 3295 select SYSVIPC_COMPAT if SYSVIPC 3297 3296 help ··· 3302 3299 cases. 3303 3300 3304 3301 If unsure, say N. 3305 - 3306 - config BINFMT_ELF32 3307 - bool 3308 - default y if MIPS32_O32 || MIPS32_N32 3309 - select ELFCORE 3310 3302 3311 3303 menu "Power management options" 3312 3304
+19 -35
arch/mips/include/asm/elf.h
··· 201 201 uint32_t flags2; 202 202 }; 203 203 204 - #ifndef ELF_ARCH 205 204 /* ELF register definitions */ 206 205 #define ELF_NGREG 45 207 206 #define ELF_NFPREG 33 ··· 218 219 /* 219 220 * This is used to ensure we don't load something for the wrong architecture. 220 221 */ 221 - #define elf_check_arch elfo32_check_arch 222 + #define elf_check_arch elf32_check_arch 222 223 223 224 /* 224 225 * These are used to set parameters in the core dumps. ··· 234 235 /* 235 236 * This is used to ensure we don't load something for the wrong architecture. 236 237 */ 237 - #define elf_check_arch elfn64_check_arch 238 + #define elf_check_arch elf64_check_arch 239 + #define compat_elf_check_arch elf32_check_arch 238 240 239 241 /* 240 242 * These are used to set parameters in the core dumps. ··· 257 257 #endif 258 258 #define ELF_ARCH EM_MIPS 259 259 260 - #endif /* !defined(ELF_ARCH) */ 261 - 262 260 /* 263 261 * In order to be sure that we don't attempt to execute an O32 binary which 264 262 * requires 64 bit FP (FR=1) on a system which does not support it we refuse ··· 275 277 #define vmcore_elf64_check_arch mips_elf_check_machine 276 278 277 279 /* 278 - * Return non-zero if HDR identifies an o32 ELF binary. 280 + * Return non-zero if HDR identifies an o32 or n32 ELF binary. 279 281 */ 280 - #define elfo32_check_arch(hdr) \ 282 + #define elf32_check_arch(hdr) \ 281 283 ({ \ 282 284 int __res = 1; \ 283 285 struct elfhdr *__h = (hdr); \ ··· 286 288 __res = 0; \ 287 289 if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ 288 290 __res = 0; \ 289 - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ 290 - __res = 0; \ 291 - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ 292 - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ 293 - __res = 0; \ 294 - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ 295 - __res = 0; \ 296 - \ 291 + if ((__h->e_flags & EF_MIPS_ABI2) != 0) { \ 292 + if (!IS_ENABLED(CONFIG_MIPS32_N32) || \ 293 + (__h->e_flags & EF_MIPS_ABI)) \ 294 + __res = 0; \ 295 + } else { \ 296 + if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32)) \ 297 + __res = 0; \ 298 + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ 299 + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ 300 + __res = 0; \ 301 + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ 302 + __res = 0; \ 303 + } \ 297 304 __res; \ 298 305 }) 299 306 300 307 /* 301 308 * Return non-zero if HDR identifies an n64 ELF binary. 302 309 */ 303 - #define elfn64_check_arch(hdr) \ 310 + #define elf64_check_arch(hdr) \ 304 311 ({ \ 305 312 int __res = 1; \ 306 313 struct elfhdr *__h = (hdr); \ ··· 313 310 if (!mips_elf_check_machine(__h)) \ 314 311 __res = 0; \ 315 312 if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ 316 - __res = 0; \ 317 - \ 318 - __res; \ 319 - }) 320 - 321 - /* 322 - * Return non-zero if HDR identifies an n32 ELF binary. 323 - */ 324 - #define elfn32_check_arch(hdr) \ 325 - ({ \ 326 - int __res = 1; \ 327 - struct elfhdr *__h = (hdr); \ 328 - \ 329 - if (!mips_elf_check_machine(__h)) \ 330 - __res = 0; \ 331 - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ 332 - __res = 0; \ 333 - if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ 334 - ((__h->e_flags & EF_MIPS_ABI) != 0)) \ 335 313 __res = 0; \ 336 314 \ 337 315 __res; \
+29
arch/mips/include/asm/elfcore-compat.h
··· 1 + #ifndef _ASM_MIPS_ELFCORE_COMPAT_H 2 + #define _ASM_MIPS_ELFCORE_COMPAT_H 3 + 4 + /* 5 + * On mips we have two 32bit ABIs - o32 and n32. The latter 6 + * has bigger registers, so we use it for compat_elf_regset_t. 7 + * The former uses o32_elf_prstatus and PRSTATUS_SIZE/SET_PR_FPVALID 8 + * are used to choose the size and location of ->pr_fpvalid of 9 + * the layout actually used. 10 + */ 11 + typedef elf_gregset_t compat_elf_gregset_t; 12 + 13 + struct o32_elf_prstatus 14 + { 15 + struct compat_elf_prstatus_common common; 16 + unsigned int pr_reg[ELF_NGREG]; 17 + compat_int_t pr_fpvalid; 18 + }; 19 + 20 + #define PRSTATUS_SIZE \ 21 + (!test_thread_flag(TIF_32BIT_REGS) \ 22 + ? sizeof(struct compat_elf_prstatus) \ 23 + : sizeof(struct o32_elf_prstatus)) 24 + #define SET_PR_FPVALID(S) \ 25 + (*(!test_thread_flag(TIF_32BIT_REGS) \ 26 + ? &(S)->pr_fpvalid \ 27 + : &((struct o32_elf_prstatus *)(S))->pr_fpvalid) = 1) 28 + 29 + #endif
+2 -2
arch/mips/kernel/Makefile
··· 80 80 obj-$(CONFIG_32BIT) += scall32-o32.o 81 81 obj-$(CONFIG_64BIT) += scall64-n64.o 82 82 obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o 83 - obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o 84 - obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o signal_o32.o 83 + obj-$(CONFIG_MIPS32_N32) += scall64-n32.o signal_n32.o 84 + obj-$(CONFIG_MIPS32_O32) += scall64-o32.o signal_o32.o 85 85 86 86 obj-$(CONFIG_KGDB) += kgdb.o 87 87 obj-$(CONFIG_PROC_FS) += proc.o
-65
arch/mips/kernel/binfmt_elfn32.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Support for n32 Linux/MIPS ELF binaries. 4 - * Author: Ralf Baechle (ralf@linux-mips.org) 5 - * 6 - * Copyright (C) 1999, 2001 Ralf Baechle 7 - * Copyright (C) 1999, 2001 Silicon Graphics, Inc. 8 - * 9 - * Heavily inspired by the 32-bit Sparc compat code which is 10 - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) 11 - * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) 12 - */ 13 - 14 - #define ELF_ARCH EM_MIPS 15 - #define ELF_CLASS ELFCLASS32 16 - #ifdef __MIPSEB__ 17 - #define ELF_DATA ELFDATA2MSB; 18 - #else /* __MIPSEL__ */ 19 - #define ELF_DATA ELFDATA2LSB; 20 - #endif 21 - 22 - /* ELF register definitions */ 23 - #define ELF_NGREG 45 24 - #define ELF_NFPREG 33 25 - 26 - typedef unsigned long elf_greg_t; 27 - typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 28 - 29 - typedef double elf_fpreg_t; 30 - typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; 31 - 32 - /* 33 - * This is used to ensure we don't load something for the wrong architecture. 34 - */ 35 - #define elf_check_arch elfn32_check_arch 36 - 37 - #include <asm/processor.h> 38 - #include <linux/elfcore.h> 39 - #include <linux/compat.h> 40 - #include <linux/math64.h> 41 - #include <linux/elfcore-compat.h> 42 - 43 - #define elf_prstatus elf_prstatus32 44 - #define elf_prstatus_common compat_elf_prstatus_common 45 - struct elf_prstatus32 46 - { 47 - struct compat_elf_prstatus_common common; 48 - elf_gregset_t pr_reg; /* GP registers */ 49 - int pr_fpvalid; /* True if math co-processor being used. */ 50 - }; 51 - #define elf_prpsinfo compat_elf_prpsinfo 52 - 53 - #define init_elf_binfmt init_elfn32_binfmt 54 - 55 - #undef ns_to_kernel_old_timeval 56 - #define ns_to_kernel_old_timeval ns_to_old_timeval32 57 - 58 - /* 59 - * Some data types as stored in coredump. 60 - */ 61 - #define user_long_t compat_long_t 62 - #define user_siginfo_t compat_siginfo_t 63 - #define copy_siginfo_to_external copy_siginfo_to_external32 64 - 65 - #include "../../../fs/binfmt_elf.c"
-66
arch/mips/kernel/binfmt_elfo32.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Support for o32 Linux/MIPS ELF binaries. 4 - * Author: Ralf Baechle (ralf@linux-mips.org) 5 - * 6 - * Copyright (C) 1999, 2001 Ralf Baechle 7 - * Copyright (C) 1999, 2001 Silicon Graphics, Inc. 8 - * 9 - * Heavily inspired by the 32-bit Sparc compat code which is 10 - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) 11 - * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) 12 - */ 13 - 14 - #define ELF_ARCH EM_MIPS 15 - #define ELF_CLASS ELFCLASS32 16 - #ifdef __MIPSEB__ 17 - #define ELF_DATA ELFDATA2MSB; 18 - #else /* __MIPSEL__ */ 19 - #define ELF_DATA ELFDATA2LSB; 20 - #endif 21 - 22 - /* ELF register definitions */ 23 - #define ELF_NGREG 45 24 - #define ELF_NFPREG 33 25 - 26 - typedef unsigned int elf_greg_t; 27 - typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 28 - 29 - typedef double elf_fpreg_t; 30 - typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; 31 - 32 - /* 33 - * This is used to ensure we don't load something for the wrong architecture. 34 - */ 35 - #define elf_check_arch elfo32_check_arch 36 - 37 - #include <asm/processor.h> 38 - 39 - #include <linux/elfcore.h> 40 - #include <linux/compat.h> 41 - #include <linux/math64.h> 42 - #include <linux/elfcore-compat.h> 43 - 44 - #define elf_prstatus elf_prstatus32 45 - #define elf_prstatus_common compat_elf_prstatus_common 46 - struct elf_prstatus32 47 - { 48 - struct compat_elf_prstatus_common common; 49 - elf_gregset_t pr_reg; /* GP registers */ 50 - int pr_fpvalid; /* True if math co-processor being used. */ 51 - }; 52 - #define elf_prpsinfo compat_elf_prpsinfo 53 - 54 - #define init_elf_binfmt init_elf32_binfmt 55 - 56 - #undef ns_to_kernel_old_timeval 57 - #define ns_to_kernel_old_timeval ns_to_old_timeval32 58 - 59 - /* 60 - * Some data types as stored in coredump. 61 - */ 62 - #define user_long_t compat_long_t 63 - #define user_siginfo_t compat_siginfo_t 64 - #define copy_siginfo_to_external copy_siginfo_to_external32 65 - 66 - #include "../../../fs/binfmt_elf.c"
+1 -1
arch/mips/kernel/scall64-n64.S
··· 20 20 #include <asm/unistd.h> 21 21 #include <asm/war.h> 22 22 23 - #ifndef CONFIG_BINFMT_ELF32 23 + #ifndef CONFIG_MIPS32_COMPAT 24 24 /* Neither O32 nor N32, so define handle_sys here */ 25 25 #define handle_sys64 handle_sys 26 26 #endif