Skip to content

Commit ebb5e78

Browse files
Alex Smithralfbaechle
authored andcommitted
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: Alex Smith <alex.smith@imgtec.com> Signed-off-by: Markos 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: Ralf Baechle <ralf@linux-mips.org>
1 parent 22773aa commit ebb5e78

File tree

19 files changed

+1114
-124
lines changed

19 files changed

+1114
-124
lines changed

arch/mips/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ obj- := $(platform-)
1717
obj-y += kernel/
1818
obj-y += mm/
1919
obj-y += net/
20+
obj-y += vdso/
2021

2122
ifdef CONFIG_KVM
2223
obj-y += kvm/

arch/mips/include/asm/abi.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@
1111

1212
#include <asm/signal.h>
1313
#include <asm/siginfo.h>
14+
#include <asm/vdso.h>
1415

1516
struct mips_abi {
1617
int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
1718
struct pt_regs *regs, sigset_t *set);
18-
const unsigned long signal_return_offset;
1919
int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
2020
struct pt_regs *regs, sigset_t *set);
21-
const unsigned long rt_signal_return_offset;
2221
const unsigned long restart;
2322

2423
unsigned off_sc_fpregs;
2524
unsigned off_sc_fpc_csr;
2625
unsigned off_sc_used_math;
26+
27+
struct mips_vdso_image *vdso;
2728
};
2829

2930
#endif /* _ASM_ABI_H */

arch/mips/include/asm/elf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef _ASM_ELF_H
99
#define _ASM_ELF_H
1010

11+
#include <linux/auxvec.h>
1112
#include <linux/fs.h>
1213
#include <uapi/linux/elf.h>
1314

@@ -419,6 +420,12 @@ extern const char *__elf_platform;
419420
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
420421
#endif
421422

423+
#define ARCH_DLINFO \
424+
do { \
425+
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
426+
(unsigned long)current->mm->context.vdso); \
427+
} while (0)
428+
422429
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
423430
struct linux_binprm;
424431
extern int arch_setup_additional_pages(struct linux_binprm *bprm,

arch/mips/include/asm/processor.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count;
3636
*/
3737
#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
3838

39-
/*
40-
* A special page (the vdso) is mapped into all processes at the very
41-
* top of the virtual memory space.
42-
*/
43-
#define SPECIAL_PAGES_SIZE PAGE_SIZE
44-
4539
#ifdef CONFIG_32BIT
4640
#ifdef CONFIG_KVM_GUEST
4741
/* User space process size is limited to 1GB in KVM Guest Mode */
@@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count;
8074

8175
#endif
8276

83-
#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
77+
#define STACK_TOP (TASK_SIZE & PAGE_MASK)
8478

8579
/*
8680
* This decides where the kernel will search for a free chunk of vm

arch/mips/include/asm/vdso.h

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,70 @@
11
/*
2-
* This file is subject to the terms and conditions of the GNU General Public
3-
* License. See the file "COPYING" in the main directory of this archive
4-
* for more details.
2+
* Copyright (C) 2015 Imagination Technologies
3+
* Author: Alex Smith <alex.smith@imgtec.com>
54
*
6-
* Copyright (C) 2009 Cavium Networks
5+
* This program is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License as published by the
7+
* Free Software Foundation; either version 2 of the License, or (at your
8+
* option) any later version.
79
*/
810

911
#ifndef __ASM_VDSO_H
1012
#define __ASM_VDSO_H
1113

12-
#include <linux/types.h>
14+
#include <linux/mm_types.h>
1315

16+
/**
17+
* struct mips_vdso_image - Details of a VDSO image.
18+
* @data: Pointer to VDSO image data (page-aligned).
19+
* @size: Size of the VDSO image data (page-aligned).
20+
* @off_sigreturn: Offset of the sigreturn() trampoline.
21+
* @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
22+
* @mapping: Special mapping structure.
23+
*
24+
* This structure contains details of a VDSO image, including the image data
25+
* and offsets of certain symbols required by the kernel. It is generated as
26+
* part of the VDSO build process, aside from the mapping page array, which is
27+
* populated at runtime.
28+
*/
29+
struct mips_vdso_image {
30+
void *data;
31+
unsigned long size;
1432

15-
#ifdef CONFIG_32BIT
16-
struct mips_vdso {
17-
u32 signal_trampoline[2];
18-
u32 rt_signal_trampoline[2];
33+
unsigned long off_sigreturn;
34+
unsigned long off_rt_sigreturn;
35+
36+
struct vm_special_mapping mapping;
1937
};
20-
#else /* !CONFIG_32BIT */
21-
struct mips_vdso {
22-
u32 o32_signal_trampoline[2];
23-
u32 o32_rt_signal_trampoline[2];
24-
u32 rt_signal_trampoline[2];
25-
u32 n32_rt_signal_trampoline[2];
38+
39+
/*
40+
* The following structures are auto-generated as part of the build for each
41+
* ABI by genvdso, see arch/mips/vdso/Makefile.
42+
*/
43+
44+
extern struct mips_vdso_image vdso_image;
45+
46+
#ifdef CONFIG_MIPS32_O32
47+
extern struct mips_vdso_image vdso_image_o32;
48+
#endif
49+
50+
#ifdef CONFIG_MIPS32_N32
51+
extern struct mips_vdso_image vdso_image_n32;
52+
#endif
53+
54+
/**
55+
* union mips_vdso_data - Data provided by the kernel for the VDSO.
56+
*
57+
* This structure contains data needed by functions within the VDSO. It is
58+
* populated by the kernel and mapped read-only into user memory.
59+
*
60+
* Note: Care should be taken when modifying as the layout must remain the same
61+
* for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
62+
*/
63+
union mips_vdso_data {
64+
struct {
65+
};
66+
67+
u8 page[PAGE_SIZE];
2668
};
27-
#endif /* CONFIG_32BIT */
2869

2970
#endif /* __ASM_VDSO_H */

arch/mips/include/uapi/asm/Kbuild

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# UAPI Header export list
22
include include/uapi/asm-generic/Kbuild.asm
33

4-
generic-y += auxvec.h
54
generic-y += ipcbuf.h
65

6+
header-y += auxvec.h
77
header-y += bitfield.h
88
header-y += bitsperlong.h
99
header-y += break.h

arch/mips/include/uapi/asm/auxvec.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (C) 2015 Imagination Technologies
3+
* Author: Alex Smith <alex.smith@imgtec.com>
4+
*
5+
* This program is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License as published by the
7+
* Free Software Foundation; either version 2 of the License, or (at your
8+
* option) any later version.
9+
*/
10+
11+
#ifndef __ASM_AUXVEC_H
12+
#define __ASM_AUXVEC_H
13+
14+
/* Location of VDSO image. */
15+
#define AT_SYSINFO_EHDR 33
16+
17+
#endif /* __ASM_AUXVEC_H */

arch/mips/kernel/signal.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include <asm/ucontext.h>
3737
#include <asm/cpu-features.h>
3838
#include <asm/war.h>
39-
#include <asm/vdso.h>
4039
#include <asm/dsp.h>
4140
#include <asm/inst.h>
4241
#include <asm/msa.h>
@@ -752,16 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
752751
struct mips_abi mips_abi = {
753752
#ifdef CONFIG_TRAD_SIGNALS
754753
.setup_frame = setup_frame,
755-
.signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
756754
#endif
757755
.setup_rt_frame = setup_rt_frame,
758-
.rt_signal_return_offset =
759-
offsetof(struct mips_vdso, rt_signal_trampoline),
760756
.restart = __NR_restart_syscall,
761757

762758
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
763759
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
764760
.off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
761+
762+
.vdso = &vdso_image,
765763
};
766764

767765
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)
801799
}
802800

803801
if (sig_uses_siginfo(&ksig->ka))
804-
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
802+
ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
805803
ksig, regs, oldset);
806804
else
807-
ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
808-
regs, oldset);
805+
ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn,
806+
ksig, regs, oldset);
809807

810808
signal_setup_done(ret, ksig, 0);
811809
}

arch/mips/kernel/signal32.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include <asm/ucontext.h>
3232
#include <asm/fpu.h>
3333
#include <asm/war.h>
34-
#include <asm/vdso.h>
3534
#include <asm/dsp.h>
3635

3736
#include "signal-common.h"
@@ -406,14 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
406405
*/
407406
struct mips_abi mips_abi_32 = {
408407
.setup_frame = setup_frame_32,
409-
.signal_return_offset =
410-
offsetof(struct mips_vdso, o32_signal_trampoline),
411408
.setup_rt_frame = setup_rt_frame_32,
412-
.rt_signal_return_offset =
413-
offsetof(struct mips_vdso, o32_rt_signal_trampoline),
414409
.restart = __NR_O32_restart_syscall,
415410

416411
.off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
417412
.off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
418413
.off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
414+
415+
.vdso = &vdso_image_o32,
419416
};

arch/mips/kernel/signal_n32.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
#include <asm/fpu.h>
3939
#include <asm/cpu-features.h>
4040
#include <asm/war.h>
41-
#include <asm/vdso.h>
4241

4342
#include "signal-common.h"
4443

@@ -151,11 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
151150

152151
struct mips_abi mips_abi_n32 = {
153152
.setup_rt_frame = setup_rt_frame_n32,
154-
.rt_signal_return_offset =
155-
offsetof(struct mips_vdso, n32_rt_signal_trampoline),
156153
.restart = __NR_N32_restart_syscall,
157154

158155
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
159156
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
160157
.off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
158+
159+
.vdso = &vdso_image_n32,
161160
};

0 commit comments

Comments
 (0)