On Fri, 16 Jan 2015, Markos Chandras wrote: > diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c > index c92b15df6893..2ac33d2375ca 100644 > --- a/arch/mips/kernel/elf.c > +++ b/arch/mips/kernel/elf.c > @@ -11,29 +11,102 @@ > #include <linux/elf.h> > #include <linux/sched.h> > > +/* FPU modes */ > enum { > - FP_ERROR = -1, > - FP_DOUBLE_64A = -2, > + FP_FRE, > + FP_FR0, > + FP_FR1, > }; > > +/** > + * struct mode_req - ABI FPU mode requirements > + * @single: The program being loaded needs an FPU but it will only issue > + * single precision instructions meaning that it can execute in > + * either FR0 or FR1. > + * @soft: The soft(-float) requirement means that the program being > + * loaded needs has no FPU dependency at all (i.e. it has no > + * FPU instructions). > + * @fr1: The program being loaded depends on FPU being in FR=1 mode. > + * @frdefault: The program being loaded depends on the default FPU mode. > + * That is FR0 for O32 and FR1 for N32/N64. > + * @fre: The program being loaded depends on FPU with FRE=1. This mode is > + * a bridge which uses FR=1 whilst still being able to maintain > + * full compatibility with pre-existing code using the O32 FP32 > + * ABI. > + * > + * More information about the FP ABIs can be found here: > + * > + * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up > + * > + */ > + > +struct mode_req { > + bool single; > + bool soft; > + bool fr1; > + bool frdefault; > + bool fre; > +}; > + > +static const struct mode_req fpu_reqs[] = { > + [MIPS_ABI_FP_ANY] = { true, true, true, true, true }, > + [MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true }, > + [MIPS_ABI_FP_SINGLE] = { true, false, false, false, false }, > + [MIPS_ABI_FP_SOFT] = { false, true, false, false, false }, > + [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false }, > + [MIPS_ABI_FP_XX] = { false, false, true, true, true }, > + [MIPS_ABI_FP_64] = { false, false, true, false, false }, > + [MIPS_ABI_FP_64A] = { false, false, true, false, true } > +}; > + > +/* > + * Mode requirements when .MIPS.abiflags is not present in the ELF. > + * Not present means that everything is acceptable except FR1. > + */ > +static struct mode_req none_req = { true, true, false, true, true }; > + > int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, > bool is_interp, struct arch_elf_state *state) > { > - struct elfhdr *ehdr = _ehdr; > - struct elf_phdr *phdr = _phdr; > + struct elf32_hdr *ehdr32 = _ehdr; > + struct elf32_phdr *phdr32 = _phdr; > + struct elf64_phdr *phdr64 = _phdr; Minor nit, I won't be picking on it if you have a strong feeling against, but I think it would be slightly cleaner if you had used unions here -- no risk of people picking bad habits that would hurt if any of these structures were written, causing aliasing issues. So e.g.: union { struct elf32_hdr e32; struct elf64_hdr e64; } *ehdr = _ehdr; union { struct elf32_phdr p32; struct elf64_phdr p64; } *phdr = _phdr; and then: > + /* Lets see if this is an O32 ELF */ > + if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) { > + /* FR = 1 for N32 */ > + if (ehdr32->e_flags & EF_MIPS_ABI2) > + state->overall_fp_mode = FP_FR1; > + else > + /* Set a good default FPU mode for O32*/ > + state->overall_fp_mode = cpu_has_mips_r6 ? > + FP_FRE : FP_FR0; > + > + if (phdr32->p_type != PT_MIPS_ABIFLAGS) > + return 0; > + > + if (phdr32->p_filesz < sizeof(abiflags)) > + return -EINVAL; > + > + ret = kernel_read(elf, phdr32->p_offset, > + (char *)&abiflags, > + sizeof(abiflags)); /* Lets see if this is an O32 ELF */ if (ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32) { /* FR = 1 for N32 */ if (ehdr->e32.e_flags & EF_MIPS_ABI2) state->overall_fp_mode = FP_FR1; else /* Set a good default FPU mode for O32*/ state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0; if (phdr->p32.p_type != PT_MIPS_ABIFLAGS) return 0; if (phdr->p32.p_filesz < sizeof(abiflags)) return -EINVAL; ret = kernel_read(elf, phdr->p32.p_offset, (char *)&abiflags, sizeof(abiflags)); -- and so on... As you can see the result isn't even much different in terms of readability or source code size, while avoiding any possible aliasing issues. Maciej