Skip to content
This repository has been archived by the owner on Jun 3, 2023. It is now read-only.

Commit

Permalink
MIPS: Initial implementation of a VDSO
Browse files Browse the repository at this point in the history
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.

[[email protected]:
- 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: Alex Smith <[email protected]>
Signed-off-by: Markos Chandras <[email protected]>
Cc: Matthew Fortune <[email protected]>
Cc: [email protected]
Patchwork: https://patchwork.linux-mips.org/patch/11337/
Signed-off-by: Ralf Baechle <[email protected]>
  • Loading branch information
Alex Smith authored and ralfbaechle committed Nov 11, 2015
1 parent 22773aa commit ebb5e78
Show file tree
Hide file tree
Showing 19 changed files with 1,114 additions and 124 deletions.
1 change: 1 addition & 0 deletions arch/mips/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ obj- := $(platform-)
obj-y += kernel/
obj-y += mm/
obj-y += net/
obj-y += vdso/

ifdef CONFIG_KVM
obj-y += kvm/
Expand Down
5 changes: 3 additions & 2 deletions arch/mips/include/asm/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
7 changes: 7 additions & 0 deletions arch/mips/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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,
Expand Down
8 changes: 1 addition & 7 deletions arch/mips/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
73 changes: 57 additions & 16 deletions arch/mips/include/asm/vdso.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,70 @@
/*
* 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 <[email protected]>
*
* 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 */
2 changes: 1 addition & 1 deletion arch/mips/include/uapi/asm/Kbuild
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# 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
Expand Down
17 changes: 17 additions & 0 deletions arch/mips/include/uapi/asm/auxvec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <[email protected]>
*
* 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 */
12 changes: 5 additions & 7 deletions arch/mips/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down
7 changes: 2 additions & 5 deletions arch/mips/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
};
5 changes: 2 additions & 3 deletions arch/mips/kernel/signal_n32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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,
};
Loading

0 comments on commit ebb5e78

Please sign in to comment.