Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753300AbbH2PV1 (ORCPT ); Sat, 29 Aug 2015 11:21:27 -0400 Received: from mail-yk0-f177.google.com ([209.85.160.177]:33747 "EHLO mail-yk0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752966AbbH2PUl (ORCPT ); Sat, 29 Aug 2015 11:20:41 -0400 From: Brian Gerst To: x86@kernel.org, linux-kernel@vger.kernel.org Cc: Ingo Molnar , "H. Peter Anvin" , Denys Vlasenko , Andy Lutomirski , Linus Torvalds Subject: [PATCH 4/7] x86/vdso32: Build single vdso32 image Date: Sat, 29 Aug 2015 11:20:23 -0400 Message-Id: <1440861626-27008-5-git-send-email-brgerst@gmail.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1440861626-27008-1-git-send-email-brgerst@gmail.com> References: <1440861626-27008-1-git-send-email-brgerst@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12790 Lines: 367 Currently, there are three images that are built for vdso32, differing only in the syscall entry code. The syscall entry is a tiny fraction of the total code, so most of the vdso code is duplicated in memory three times. This patch merges all the syscall entry points into one image, and instead of selecting the image, selects the entry point that is placed in the AT_SYSINFO vector and the ELF entry point. Signed-off-by: Brian Gerst --- arch/x86/entry/vdso/.gitignore | 3 --- arch/x86/entry/vdso/Makefile | 44 ++++++++++++----------------------- arch/x86/entry/vdso/vdso2c.c | 2 ++ arch/x86/entry/vdso/vdso32-setup.c | 15 ++++++------ arch/x86/entry/vdso/vdso32/syscall.S | 8 +++---- arch/x86/entry/vdso/vdso32/sysenter.S | 8 +++---- arch/x86/entry/vdso/vma.c | 6 ++--- arch/x86/ia32/ia32_signal.c | 4 ++-- arch/x86/include/asm/elf.h | 3 +-- arch/x86/include/asm/vdso.h | 11 ++++----- arch/x86/kernel/signal.c | 4 ++-- arch/x86/xen/setup.c | 12 ++-------- 12 files changed, 47 insertions(+), 73 deletions(-) diff --git a/arch/x86/entry/vdso/.gitignore b/arch/x86/entry/vdso/.gitignore index aae8ffd..a6a6ca8 100644 --- a/arch/x86/entry/vdso/.gitignore +++ b/arch/x86/entry/vdso/.gitignore @@ -1,7 +1,4 @@ vdso.lds vdsox32.lds -vdso32-syscall-syms.lds -vdso32-sysenter-syms.lds -vdso32-int80-syms.lds vdso-image-*.c vdso2c diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index b4cd431..282121a 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -19,9 +19,7 @@ obj-y += vma.o # vDSO images to build vdso_img-$(VDSO64-y) += 64 vdso_img-$(VDSOX32-y) += x32 -vdso_img-$(VDSO32-y) += 32-int80 -vdso_img-$(CONFIG_IA32_EMULATION) += 32-syscall -vdso_img-$(VDSO32-y) += 32-sysenter +vdso_img-$(VDSO32-y) += 32 obj-$(VDSO32-y) += vdso32-setup.o @@ -122,15 +120,6 @@ $(obj)/%.so: $(obj)/%.so.dbg $(obj)/vdsox32.so.dbg: $(src)/vdsox32.lds $(vobjx32s) FORCE $(call if_changed,vdso) -# -# Build multiple 32-bit vDSO images to choose from at boot time. -# -vdso32.so-$(VDSO32-y) += int80 -vdso32.so-$(CONFIG_IA32_EMULATION) += syscall -vdso32.so-$(VDSO32-y) += sysenter - -vdso32-images = $(vdso32.so-y:%=vdso32-%.so) - CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1 @@ -138,15 +127,9 @@ VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1 # is not a kbuild sub-make subdirectory. override obj-dirs = $(dir $(obj)) $(obj)/vdso32/ -targets += vdso32/vdso32.lds -targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o) -targets += vdso32/vclock_gettime.o vdso32/sigreturn.o - -$(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%) - KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS)) -$(vdso32-images:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32) -$(vdso32-images:%=$(obj)/%.dbg): asflags-$(CONFIG_X86_64) += -m32 +$(obj)/vdso32.so.dbg: KBUILD_AFLAGS = $(KBUILD_AFLAGS_32) +$(obj)/vdso32.so.dbg: asflags-$(CONFIG_X86_64) += -m32 KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS)) KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32)) @@ -157,14 +140,17 @@ KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) KBUILD_CFLAGS_32 += -fno-omit-frame-pointer KBUILD_CFLAGS_32 += -DDISABLE_BRANCH_PROFILING -$(vdso32-images:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32) - -$(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \ - $(obj)/vdso32/vdso32.lds \ - $(obj)/vdso32/vclock_gettime.o \ - $(obj)/vdso32/note.o \ - $(obj)/vdso32/sigreturn.o \ - $(obj)/vdso32/%.o + +vobjs32-y := vdso32/vclock_gettime.o vdso32/note.o vdso32/sigreturn.o +vobjs32-y += vdso32/int80.o vdso32/sysenter.o +vobjs32-$(CONFIG_COMPAT) += vdso32/syscall.o + +vobjs32 := $(foreach F,$(vobjs32-y),$(obj)/$F) + +targets += vdso32/vdso32.lds $(vobjs32-y) + +$(obj)/vdso32.so.dbg: KBUILD_CFLAGS = $(KBUILD_CFLAGS_32) +$(obj)/vdso32.so.dbg: $(obj)/vdso32/vdso32.lds $(vobjs32) FORCE $(call if_changed,vdso) # @@ -207,4 +193,4 @@ $(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE PHONY += vdso_install $(vdso_img_insttargets) vdso_install: $(vdso_img_insttargets) FORCE -clean-files := vdso32-syscall* vdso32-sysenter* vdso32-int80* vdso64* vdso-image-*.c vdsox32.so* +clean-files := vdso32* vdso64* vdso-image-*.c vdsox32.so* diff --git a/arch/x86/entry/vdso/vdso2c.c b/arch/x86/entry/vdso/vdso2c.c index 8627db2..cda5fa8 100644 --- a/arch/x86/entry/vdso/vdso2c.c +++ b/arch/x86/entry/vdso/vdso2c.c @@ -100,6 +100,8 @@ struct vdso_sym required_syms[] = { {"VDSO32_NOTE_MASK", true}, {"VDSO32_SYSENTER_RETURN", true}, {"__kernel_vsyscall", true}, + {"__kernel_vsyscall_syscall", true}, + {"__kernel_vsyscall_sysenter", true}, {"__kernel_sigreturn", true}, {"__kernel_rt_sigreturn", true}, }; diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c index e904c27..d644762 100644 --- a/arch/x86/entry/vdso/vdso32-setup.c +++ b/arch/x86/entry/vdso/vdso32-setup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -60,23 +61,23 @@ __setup_param("vdso=", vdso_setup, vdso32_setup, 0); #endif /* CONFIG_X86_64 */ -#if defined(CONFIG_X86_32) || defined(CONFIG_COMPAT) -const struct vdso_image *selected_vdso32; -#endif +unsigned long selected_vsyscall; int __init sysenter_setup(void) { #ifdef CONFIG_COMPAT if (vdso32_syscall()) - selected_vdso32 = &vdso_image_32_syscall; + selected_vsyscall = vdso_image_32.sym___kernel_vsyscall_syscall; else #endif if (vdso32_sysenter()) - selected_vdso32 = &vdso_image_32_sysenter; + selected_vsyscall = vdso_image_32.sym___kernel_vsyscall_sysenter; else - selected_vdso32 = &vdso_image_32_int80; + selected_vsyscall = vdso_image_32.sym___kernel_vsyscall; + + ((struct elf32_hdr *)vdso_image_32.data)->e_entry = selected_vsyscall; - init_vdso_image(selected_vdso32); + init_vdso_image(&vdso_image_32); return 0; } diff --git a/arch/x86/entry/vdso/vdso32/syscall.S b/arch/x86/entry/vdso/vdso32/syscall.S index 73f1428..50490c8 100644 --- a/arch/x86/entry/vdso/vdso32/syscall.S +++ b/arch/x86/entry/vdso/vdso32/syscall.S @@ -5,10 +5,10 @@ #include .text - .globl __kernel_vsyscall - .type __kernel_vsyscall,@function + .globl __kernel_vsyscall_syscall + .type __kernel_vsyscall_syscall,@function ALIGN -__kernel_vsyscall: +__kernel_vsyscall_syscall: .LSTART_vsyscall: push %ebp .Lpush_ebp: @@ -19,7 +19,7 @@ __kernel_vsyscall: .Lpop_ebp: ret .LEND_vsyscall: - .size __kernel_vsyscall,.-.LSTART_vsyscall + .size __kernel_vsyscall_syscall,.-.LSTART_vsyscall .section .eh_frame,"a",@progbits .LSTARTFRAME: diff --git a/arch/x86/entry/vdso/vdso32/sysenter.S b/arch/x86/entry/vdso/vdso32/sysenter.S index e8e3080..458954a 100644 --- a/arch/x86/entry/vdso/vdso32/sysenter.S +++ b/arch/x86/entry/vdso/vdso32/sysenter.S @@ -22,10 +22,10 @@ * three words on the parent stack do not get copied to the child. */ .text - .globl __kernel_vsyscall - .type __kernel_vsyscall,@function + .globl __kernel_vsyscall_sysenter + .type __kernel_vsyscall_sysenter,@function ALIGN -__kernel_vsyscall: +__kernel_vsyscall_sysenter: .LSTART_vsyscall: push %ecx .Lpush_ecx: @@ -51,7 +51,7 @@ VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */ .Lpop_ecx: ret .LEND_vsyscall: - .size __kernel_vsyscall,.-.LSTART_vsyscall + .size __kernel_vsyscall_sysenter,.-.LSTART_vsyscall .previous .section .eh_frame,"a",@progbits diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 4345431..c726d49 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -185,14 +185,14 @@ static int load_vdso32(void) if (vdso32_enabled != 1) /* Other values all mean "disabled" */ return 0; - ret = map_vdso(selected_vdso32, false); + ret = map_vdso(&vdso_image_32, false); if (ret) return ret; - if (selected_vdso32->sym_VDSO32_SYSENTER_RETURN) + if (vdso_image_32.sym_VDSO32_SYSENTER_RETURN) current_thread_info()->sysenter_return = current->mm->context.vdso + - selected_vdso32->sym_VDSO32_SYSENTER_RETURN; + vdso_image_32.sym_VDSO32_SYSENTER_RETURN; return 0; } diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index a0a19b7..e6a5c275 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -289,7 +289,7 @@ int ia32_setup_frame(int sig, struct ksignal *ksig, /* Return stub is in 32bit vsyscall page */ if (current->mm->context.vdso) restorer = current->mm->context.vdso + - selected_vdso32->sym___kernel_sigreturn; + vdso_image_32.sym___kernel_sigreturn; else restorer = &frame->retcode; } @@ -368,7 +368,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, restorer = ksig->ka.sa.sa_restorer; else restorer = current->mm->context.vdso + - selected_vdso32->sym___kernel_rt_sigreturn; + vdso_image_32.sym___kernel_rt_sigreturn; put_user_ex(ptr_to_compat(restorer), &frame->pretcode); /* diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 141c561..ccc1d31 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -327,8 +327,7 @@ else \ #define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso) #define VDSO_ENTRY \ - ((unsigned long)current->mm->context.vdso + \ - selected_vdso32->sym___kernel_vsyscall) + ((unsigned long)current->mm->context.vdso + selected_vsyscall) struct linux_binprm; diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index 8021bd2..16d5c18 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -26,6 +26,8 @@ struct vdso_image { long sym___kernel_sigreturn; long sym___kernel_rt_sigreturn; long sym___kernel_vsyscall; + long sym___kernel_vsyscall_syscall; + long sym___kernel_vsyscall_sysenter; long sym_VDSO32_SYSENTER_RETURN; }; @@ -38,13 +40,8 @@ extern const struct vdso_image vdso_image_x32; #endif #if defined CONFIG_X86_32 || defined CONFIG_COMPAT -extern const struct vdso_image vdso_image_32_int80; -#ifdef CONFIG_COMPAT -extern const struct vdso_image vdso_image_32_syscall; -#endif -extern const struct vdso_image vdso_image_32_sysenter; - -extern const struct vdso_image *selected_vdso32; +extern const struct vdso_image vdso_image_32; +extern unsigned long selected_vsyscall; #endif extern void __init init_vdso_image(const struct vdso_image *image); diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index da52e6b..d87ce92 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -299,7 +299,7 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set, if (current->mm->context.vdso) restorer = current->mm->context.vdso + - selected_vdso32->sym___kernel_sigreturn; + vdso_image_32.sym___kernel_sigreturn; else restorer = &frame->retcode; if (ksig->ka.sa.sa_flags & SA_RESTORER) @@ -363,7 +363,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, /* Set up to return from userspace. */ restorer = current->mm->context.vdso + - selected_vdso32->sym___kernel_rt_sigreturn; + vdso_image_32.sym___kernel_rt_sigreturn; if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = ksig->ka.sa.sa_restorer; put_user_ex(restorer, &frame->pretcode); diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 55f388e..b166ffd 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -753,17 +753,9 @@ char * __init xen_auto_xlated_memory_setup(void) static void __init fiddle_vdso(void) { #ifdef CONFIG_X86_32 - /* - * This could be called before selected_vdso32 is initialized, so - * just fiddle with both possible images. vdso_image_32_syscall - * can't be selected, since it only exists on 64-bit systems. - */ u32 *mask; - mask = vdso_image_32_int80.data + - vdso_image_32_int80.sym_VDSO32_NOTE_MASK; - *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT; - mask = vdso_image_32_sysenter.data + - vdso_image_32_sysenter.sym_VDSO32_NOTE_MASK; + mask = vdso_image_32.data + + vdso_image_32.sym_VDSO32_NOTE_MASK; *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT; #endif } -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/