Commit ebb5e78c authored by Alex Smith's avatar Alex Smith Committed by Ralf Baechle

MIPS: Initial implementation of a VDSO

Add an initial implementation of a proper (i.e. an ELF shared library)
VDSO. With this commit it does not export any symbols, it only replaces
the current signal return trampoline page. A later commit will add user
implementations of gettimeofday()/clock_gettime().

To support both new toolchains and old ones which don't generate ABI
flags section, we define its content manually and then use a tool
(genvdso) to patch up the section to have the correct name and type.
genvdso also extracts symbol offsets ({,rt_}sigreturn) needed by the
kernel, and generates a C file containing a "struct mips_vdso_image"
containing both the VDSO data and these offsets. This C file is
compiled into the kernel.

On 64-bit kernels we require a different VDSO for each supported ABI,
so we may build up to 3 different VDSOs. The VDSO to use is selected by
the mips_abi structure.

A kernel/user shared data page is created and mapped below the VDSO
image. This is currently empty, but will be used by the user time
function implementations which are added later.

[markos.chandras@imgtec.com:
- Add more comments
- Move abi detection in genvdso.h since it's the get_symbol function
that needs it.
- Add an R6 specific way to calculate the base address of VDSO in order
to avoid the branch instruction which affects performance.
- Do not patch .gnu.attributes since it's not needed for dynamic linking.
- Simplify Makefile a little bit.
- checkpatch fixes
- Restrict VDSO support for binutils < 2.25 for pre-R6
- Include atomic64.h for O32 variant on MIPS64]
Signed-off-by: default avatarAlex Smith <alex.smith@imgtec.com>
Signed-off-by: default avatarMarkos Chandras <markos.chandras@imgtec.com>
Cc: Matthew Fortune <matthew.fortune@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/11337/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 22773aa9
......@@ -17,6 +17,7 @@ obj- := $(platform-)
obj-y += kernel/
obj-y += mm/
obj-y += net/
obj-y += vdso/
ifdef CONFIG_KVM
obj-y += kvm/
......
......@@ -11,19 +11,20 @@
#include <asm/signal.h>
#include <asm/siginfo.h>
#include <asm/vdso.h>
struct mips_abi {
int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set);
const unsigned long signal_return_offset;
int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set);
const unsigned long rt_signal_return_offset;
const unsigned long restart;
unsigned off_sc_fpregs;
unsigned off_sc_fpc_csr;
unsigned off_sc_used_math;
struct mips_vdso_image *vdso;
};
#endif /* _ASM_ABI_H */
......@@ -8,6 +8,7 @@
#ifndef _ASM_ELF_H
#define _ASM_ELF_H
#include <linux/auxvec.h>
#include <linux/fs.h>
#include <uapi/linux/elf.h>
......@@ -419,6 +420,12 @@ extern const char *__elf_platform;
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif
#define ARCH_DLINFO \
do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
(unsigned long)current->mm->context.vdso); \
} while (0)
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
......
......@@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count;
*/
#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
/*
* A special page (the vdso) is mapped into all processes at the very
* top of the virtual memory space.
*/
#define SPECIAL_PAGES_SIZE PAGE_SIZE
#ifdef CONFIG_32BIT
#ifdef CONFIG_KVM_GUEST
/* User space process size is limited to 1GB in KVM Guest Mode */
......@@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count;
#endif
#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
#define STACK_TOP (TASK_SIZE & PAGE_MASK)
/*
* This decides where the kernel will search for a free chunk of vm
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* Copyright (C) 2009 Cavium Networks
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
#include <linux/types.h>
#include <linux/mm_types.h>
/**
* struct mips_vdso_image - Details of a VDSO image.
* @data: Pointer to VDSO image data (page-aligned).
* @size: Size of the VDSO image data (page-aligned).
* @off_sigreturn: Offset of the sigreturn() trampoline.
* @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
* @mapping: Special mapping structure.
*
* This structure contains details of a VDSO image, including the image data
* and offsets of certain symbols required by the kernel. It is generated as
* part of the VDSO build process, aside from the mapping page array, which is
* populated at runtime.
*/
struct mips_vdso_image {
void *data;
unsigned long size;
#ifdef CONFIG_32BIT
struct mips_vdso {
u32 signal_trampoline[2];
u32 rt_signal_trampoline[2];
unsigned long off_sigreturn;
unsigned long off_rt_sigreturn;
struct vm_special_mapping mapping;
};
#else /* !CONFIG_32BIT */
struct mips_vdso {
u32 o32_signal_trampoline[2];
u32 o32_rt_signal_trampoline[2];
u32 rt_signal_trampoline[2];
u32 n32_rt_signal_trampoline[2];
/*
* The following structures are auto-generated as part of the build for each
* ABI by genvdso, see arch/mips/vdso/Makefile.
*/
extern struct mips_vdso_image vdso_image;
#ifdef CONFIG_MIPS32_O32
extern struct mips_vdso_image vdso_image_o32;
#endif
#ifdef CONFIG_MIPS32_N32
extern struct mips_vdso_image vdso_image_n32;
#endif
/**
* union mips_vdso_data - Data provided by the kernel for the VDSO.
*
* This structure contains data needed by functions within the VDSO. It is
* populated by the kernel and mapped read-only into user memory.
*
* Note: Care should be taken when modifying as the layout must remain the same
* for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
*/
union mips_vdso_data {
struct {
};
u8 page[PAGE_SIZE];
};
#endif /* CONFIG_32BIT */
#endif /* __ASM_VDSO_H */
# UAPI Header export list
include include/uapi/asm-generic/Kbuild.asm
generic-y += auxvec.h
generic-y += ipcbuf.h
header-y += auxvec.h
header-y += bitfield.h
header-y += bitsperlong.h
header-y += break.h
......
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_AUXVEC_H
#define __ASM_AUXVEC_H
/* Location of VDSO image. */
#define AT_SYSINFO_EHDR 33
#endif /* __ASM_AUXVEC_H */
......@@ -36,7 +36,6 @@
#include <asm/ucontext.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include <asm/vdso.h>
#include <asm/dsp.h>
#include <asm/inst.h>
#include <asm/msa.h>
......@@ -752,16 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
struct mips_abi mips_abi = {
#ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame,
.signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
#endif
.setup_rt_frame = setup_rt_frame,
.rt_signal_return_offset =
offsetof(struct mips_vdso, rt_signal_trampoline),
.restart = __NR_restart_syscall,
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
.off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
.vdso = &vdso_image,
};
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
......@@ -801,11 +799,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
}
if (sig_uses_siginfo(&ksig->ka))
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
ksig, regs, oldset);
else
ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
regs, oldset);
ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn,
ksig, regs, oldset);
signal_setup_done(ret, ksig, 0);
}
......
......@@ -31,7 +31,6 @@
#include <asm/ucontext.h>
#include <asm/fpu.h>
#include <asm/war.h>
#include <asm/vdso.h>
#include <asm/dsp.h>
#include "signal-common.h"
......@@ -406,14 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
*/
struct mips_abi mips_abi_32 = {
.setup_frame = setup_frame_32,
.signal_return_offset =
offsetof(struct mips_vdso, o32_signal_trampoline),
.setup_rt_frame = setup_rt_frame_32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, o32_rt_signal_trampoline),
.restart = __NR_O32_restart_syscall,
.off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
.off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
.vdso = &vdso_image_o32,
};
......@@ -38,7 +38,6 @@
#include <asm/fpu.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include <asm/vdso.h>
#include "signal-common.h"
......@@ -151,11 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
struct mips_abi mips_abi_n32 = {
.setup_rt_frame = setup_rt_frame_n32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, n32_rt_signal_trampoline),
.restart = __NR_N32_restart_syscall,
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
.off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
.vdso = &vdso_image_n32,
};
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* Copyright (C) 2009, 2010 Cavium Networks, Inc.
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/unistd.h>
#include <linux/random.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/abi.h>
#include <asm/vdso.h>
#include <asm/uasm.h>
#include <asm/processor.h>
/* Kernel-provided data used by the VDSO. */
static union mips_vdso_data vdso_data __page_aligned_data;
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
* Mapping for the VDSO data pages. The real pages are mapped manually, as
* what we map and where within the area they are mapped is determined at
* runtime.
*/
#define __NR_O32_sigreturn 4119
#define __NR_O32_rt_sigreturn 4193
#define __NR_N32_rt_sigreturn 6211
static struct page *no_pages[] = { NULL };
static struct vm_special_mapping vdso_vvar_mapping = {
.name = "[vvar]",
.pages = no_pages,
};
static struct page *vdso_page;
static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
static void __init init_vdso_image(struct mips_vdso_image *image)
{
uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */
uasm_i_syscall(&tramp, 0);
unsigned long num_pages, i;
BUG_ON(!PAGE_ALIGNED(image->data));
BUG_ON(!PAGE_ALIGNED(image->size));
num_pages = image->size / PAGE_SIZE;
for (i = 0; i < num_pages; i++) {
image->mapping.pages[i] =
virt_to_page(image->data + (i * PAGE_SIZE));
}
}
static int __init init_vdso(void)
{
struct mips_vdso *vdso;
vdso_page = alloc_page(GFP_KERNEL);
if (!vdso_page)
panic("Cannot allocate vdso");
vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
if (!vdso)
panic("Cannot map vdso");
clear_page(vdso);
install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
#ifdef CONFIG_32BIT
install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
#else
install_trampoline(vdso->n32_rt_signal_trampoline,
__NR_N32_rt_sigreturn);
install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
install_trampoline(vdso->o32_rt_signal_trampoline,
__NR_O32_rt_sigreturn);
init_vdso_image(&vdso_image);
#ifdef CONFIG_MIPS32_O32
init_vdso_image(&vdso_image_o32);
#endif
vunmap(vdso);
#ifdef CONFIG_MIPS32_N32
init_vdso_image(&vdso_image_n32);
#endif
return 0;
}
subsys_initcall(init_vdso);
static unsigned long vdso_addr(unsigned long start)
{
unsigned long offset = 0UL;
if (current->flags & PF_RANDOMIZE) {
offset = get_random_int();
offset <<= PAGE_SHIFT;
if (TASK_IS_32BIT_ADDR)
offset &= 0xfffffful;
else
offset &= 0xffffffful;
}
return STACK_TOP + offset;
}
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
int ret;
unsigned long addr;
struct mips_vdso_image *image = current->thread.abi->vdso;
struct mm_struct *mm = current->mm;
unsigned long base, vdso_addr;
struct vm_area_struct *vma;
int ret;
down_write(&mm->mmap_sem);
addr = vdso_addr(mm->start_stack);
addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
base = get_unmapped_area(NULL, 0, PAGE_SIZE + image->size, 0, 0);
if (IS_ERR_VALUE(base)) {
ret = base;
goto out;
}
ret = install_special_mapping(mm, addr, PAGE_SIZE,
VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
&vdso_page);
vdso_addr = base + PAGE_SIZE;
vma = _install_special_mapping(mm, base, PAGE_SIZE,
VM_READ | VM_MAYREAD,
&vdso_vvar_mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out;
}
/* Map data page. */
ret = remap_pfn_range(vma, base,
virt_to_phys(&vdso_data) >> PAGE_SHIFT,
PAGE_SIZE, PAGE_READONLY);
if (ret)
goto up_fail;
goto out;
/* Map VDSO image. */
vma = _install_special_mapping(mm, vdso_addr, image->size,
VM_READ | VM_EXEC |
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
&image->mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out;
}
mm->context.vdso = (void *)addr;
mm->context.vdso = (void *)vdso_addr;
ret = 0;
up_fail:
out:
up_write(&mm->mmap_sem);
return ret;
}
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
return "[vdso]";
return NULL;
}
*.so*
vdso-*image.c
genvdso
vdso*.lds
# Objects to go into the VDSO.
obj-vdso-y := elf.o gettimeofday.o sigreturn.o
# Common compiler flags between ABIs.
ccflags-vdso := \
$(filter -I%,$(KBUILD_CFLAGS)) \
$(filter -E%,$(KBUILD_CFLAGS)) \
$(filter -march=%,$(KBUILD_CFLAGS))
cflags-vdso := $(ccflags-vdso) \
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
-O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
$(call cc-option, -fno-stack-protector)
aflags-vdso := $(ccflags-vdso) \
$(filter -I%,$(KBUILD_CFLAGS)) \
$(filter -E%,$(KBUILD_CFLAGS)) \
-D__ASSEMBLY__ -Wa,-gdwarf-2
#
# For the pre-R6 code in arch/mips/vdso/vdso.h for locating
# the base address of VDSO, the linker will emit a R_MIPS_PC32
# relocation in binutils > 2.25 but it will fail with older versions
# because that relocation is not supported for that symbol. As a result
# of which we are forced to disable the VDSO symbols when building
# with < 2.25 binutils on pre-R6 kernels. For more references on why we
# can't use other methods to get the base address of VDSO please refer to
# the comments on that file.
#
ifndef CONFIG_CPU_MIPSR6
ifeq ($(call ld-ifversion, -gt, 22400000, y),)
$(warning MIPS VDSO requires binutils > 2.24)
obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
ccflags-vdso += -DDISABLE_MIPS_VDSO
endif
endif
# VDSO linker flags.
VDSO_LDFLAGS := \
-Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
-nostdlib -shared \
$(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
$(call cc-ldoption, -Wl$(comma)--build-id)
GCOV_PROFILE := n
#
# Shared build commands.
#
quiet_cmd_vdsold = VDSO $@
cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
-Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
hostprogs-y := genvdso
quiet_cmd_genvdso = GENVDSO $@
define cmd_genvdso
cp $< $(<:%.dbg=%) && \
$(OBJCOPY) -S $< $(<:%.dbg=%) && \
$(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
endef
#
# Build native VDSO.
#
native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
targets += $(obj-vdso-y)
targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
$(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi)
$(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
$(call if_changed,vdsold)
$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
$(call if_changed,genvdso)
obj-y += vdso-image.o
#
# Build O32 VDSO.
#
# Define these outside the ifdef to ensure they are picked up by clean.
targets += $(obj-vdso-y:%.o=%-o32.o)
targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
ifdef CONFIG_MIPS32_O32
obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o)
$(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32
$(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32
$(obj)/%-o32.o: $(src)/%.S FORCE
$(call if_changed_dep,as_o_S)
$(obj)/%-o32.o: $(src)/%.c FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
$(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
$(call if_changed_dep,cpp_lds_S)
$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
$(call if_changed,vdsold)
$(obj)/vdso-o32-image.c: VDSO_NAME := o32
$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
$(call if_changed,genvdso)
obj-y += vdso-o32-image.o
endif
#
# Build N32 VDSO.
#
targets += $(obj-vdso-y:%.o=%-n32.o)
targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
ifdef CONFIG_MIPS32_N32
obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o)
$(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32
$(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32
$(obj)/%-n32.o: $(src)/%.S FORCE
$(call if_changed_dep,as_o_S)
$(obj)/%-n32.o: $(src)/%.c FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
$(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
$(call if_changed_dep,cpp_lds_S)
$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
$(call if_changed,vdsold)
$(obj)/vdso-n32-image.c: VDSO_NAME := n32
$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
$(call if_changed,genvdso)
obj-y += vdso-n32-image.o
endif
# FIXME: Need install rule for debug.
# Needs to deal with dependency for generation of dbg by cmd_genvdso...
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "vdso.h"
#include <linux/elfnote.h>
#include <linux/version.h>
ELFNOTE_START(Linux, 0, "a")
.long LINUX_VERSION_CODE
ELFNOTE_END
/*
* The .MIPS.abiflags section must be defined with the FP ABI flags set
* to 'any' to be able to link with both old and new libraries.
* Newer toolchains are capable of automatically generating this, but we want
* to work with older toolchains as well. Therefore, we define the contents of
* this section here (under different names), and then genvdso will patch
* it to have the correct name and type.
*
* We base the .MIPS.abiflags section on preprocessor definitions rather than
* CONFIG_* because we need to match the particular ABI we are building the
* VDSO for.
*
* See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
* for the .MIPS.abiflags section description.
*/
.section .mips_abiflags, "a"
.align 3
__mips_abiflags:
.hword 0 /* version */
.byte __mips /* isa_level */
/* isa_rev */
#ifdef __mips_isa_rev
.byte __mips_isa_rev
#else
.byte 0
#endif
/* gpr_size */
#ifdef __mips64
.byte 2 /* AFL_REG_64 */
#else
.byte 1 /* AFL_REG_32 */
#endif
/* cpr1_size */
#if (defined(__mips_isa_rev) && __mips_isa_rev >= 6) || defined(__mips64)
.byte 2 /* AFL_REG_64 */
#else
.byte 1 /* AFL_REG_32 */
#endif
.byte 0 /* cpr2_size (AFL_REG_NONE) */
.byte 0 /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */
.word 0 /* isa_ext */
.word 0 /* ases */
.word 0 /* flags1 */
.word 0 /* flags2 */
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/*
* This tool is used to generate the real VDSO images from the raw image. It
* first patches up the MIPS ABI flags and GNU attributes sections defined in
* elf.S to have the correct name and type. It then generates a C source file
* to be compiled into the kernel containing the VDSO image data and a
* mips_vdso_image struct for it, including symbol offsets extracted from the
* image.
*
* We need to be passed both a stripped and unstripped VDSO image. The stripped
* image is compiled into the kernel, but we must also patch up the unstripped
* image's ABI flags sections so that it can be installed and used for
* debugging.
*/
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>