vdso function descriptors (VDS64_HAS_DESCRIPTORS)?
Subsystems (3)
I was wondering if there was history behind VDS64_HAS_DESCRIPTORS and in what cases would one want to turn them on? (Note, I'm assuming they are an implementation of Function Descriptors. [1])
arch/powerpc/include/asm/vdso.h unsets the macro:
/* Define if 64 bits VDSO has procedure descriptors */ #undef VDS64_HAS_DESCRIPTORS
so I don't believe they are ever used by default -- in this case V_FUNCTION_BEGIN doesn't add to the .opd section with .name, .TOC base, etc.
Manually setting VDS64_HAS_DESCRIPTORS results in a vdso64.so in which binutils tools like readelf properly report functions with symbol type FUNC instead of NOTYPE.
Are there pieces of the build/etc toolchain unprepared for function descriptors? I'm just trying to figure out why the code defaults to unsetting them.
Thanks,
-- Joe
[1] http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
Quoted 3 lines · Joe Lawrence
I was wondering if there was history behind
VDS64_HAS_DESCRIPTORSand in what cases would one want to turn them on? (Note, I'm assuming they are an implementation of Function Descriptors. [1])
It's from the very first patch implementing VDSOs for powerpc, which says:
commit 86b67fe764e9e54443226a3a0b298f650588d6c5
Author: Benjamin Herrenschmidt <[email protected]> Date: Fri Mar 4 17:33:32 2005 -0800
[PATCH] ppc64: Implement a vDSO and use it for signal trampoline
[...]
Note that
the symbols exposed by the vDSO aren't "normal" function symbols, apps can't be expected to link against them directly, the vDSO's are both seen as if they were linked at 0 and the symbols just contain offsets to the various functions. This is done on purpose to avoid a relocation step (ppc64 functions normally have descriptors with abs addresses in them). When glibc uses those functions, it's expected to use it's own trampolines that know how to reach them.
so already then this was unused code, presumably it was just used during development.
Quoted 9 lines
arch/powerpc/include/asm/vdso.hunsets the macro:/* Define if 64 bits VDSO has procedure descriptors */ #undef
VDS64_HAS_DESCRIPTORSso I don't believe they are ever used by default -- in this case
V_FUNCTION_BEGINdoesn't add to the .opd section with .name, .TOC base, etc.
Quoted 7 lines
Manually setting
VDS64_HAS_DESCRIPTORSresults in a vdso64.so in which binutils tools like readelf properly report functions with symbol type FUNC instead of NOTYPE.Are there pieces of the build/etc toolchain unprepared for function descriptors? I'm just trying to figure out why the code defaults to unsetting them.
Because direct calls are faster than indirect calls? Ben might have a fuller explanation, cc:ing him.
Segher
Quoted 9 lines · Segher Boessenkool
Quoted 9 lines
so I don't believe they are ever used by default -- in this case
V_FUNCTION_BEGINdoesn't add to the .opd section with .name, .TOC base, etc.Manually setting
VDS64_HAS_DESCRIPTORSresults in a vdso64.so in which binutils tools like readelf properly report functions with symbol type FUNC instead of NOTYPE.
Quoted 6 lines
Quoted 3 lines
Are there pieces of the build/etc toolchain unprepared for function descriptors? I'm just trying to figure out why the code defaults to unsetting them.
Because direct calls are faster than indirect calls? Ben might have a fuller explanation, cc:ing him.
I don't remember why :-) I think I didn't want to mess with the OPD fixup in glibc back then.
Ben.
Quoted 14 lines · Benjamin Herrenschmidt
Quoted 13 lines · Segher Boessenkool
Quoted 12 lines
so I don't believe they are ever used by default -- in this case
V_FUNCTION_BEGINdoesn't add to the .opd section with .name, .TOC base, etc.Manually setting
VDS64_HAS_DESCRIPTORSresults in a vdso64.so in which binutils tools like readelf properly report functions with symbol type FUNC instead of NOTYPE.Are there pieces of the build/etc toolchain unprepared for function descriptors? I'm just trying to figure out why the code defaults to unsetting them.
Quoted 6 lines
Quoted 2 lines
Because direct calls are faster than indirect calls? Ben might have a fuller explanation, cc:ing him.
I don't remember why :-) I think I didn't want to mess with the OPD fixup in glibc back then.
Does it make sense to just drop the unused VDS64_HAS_DESCRIPTORS code then?
-- Joe
Quoted 7 lines · Joe Lawrence
On
Quoted 3 lines
I don't remember why :-) I think I didn't want to mess with the OPD fixup in glibc back then.
Does it make sense to just drop the unused
VDS64_HAS_DESCRIPTORScode then?
I'd think so yes.
Cheers,
Ben.
PATCH 1/1 powerpc/vdso: remove deprecated VDS64_HAS_DESCRIPTORS references
The original 2005 patch that introduced the powerpc vdso, pre-git ("ppc64: Implement a vDSO and use it for signal trampoline") notes that:
... symbols exposed by the vDSO aren't "normal" function symbols, apps can't be expected to link against them directly, the vDSO's are both seen as if they were linked at 0 and the symbols just contain offsets to the various functions. This is done on purpose to avoid a relocation step (ppc64 functions normally have descriptors with abs addresses in them). When glibc uses those functions, it's expected to use it's own trampolines that know how to reach them.
Despite that explanation, there remains dead #ifdef VDS64_HAS_DESCRIPTORS code-blocks that provide alternate function definitions that setup function descriptors.
Since VDS64_HAS_DESCRIPTORS has been unused for all these years, we might as well finally remove it from the codebase.
--- arch/powerpc/include/asm/vdso.h | 24 ------------------------ arch/powerpc/kernel/vdso.c | 5 ----- 2 files changed, 29 deletions(-)
arch/powerpc/include/asm/vdso.h +0 -24
@@ -13,9 +13,6 @@#define VDSO_VERSION_STRING LINUX_2.6.15 -/* Define if 64 bits VDSO has procedure descriptors */ -#undef VDS64_HAS_DESCRIPTORS -#ifndef __ASSEMBLY__/* Offsets relative to thread->vdso_base */
@@ -28,25 +25,6 @@ int vdso_getcpu_init(void);#else /* __ASSEMBLY__ */ #ifdef __VDSO64__ -#ifdef VDS64_HAS_DESCRIPTORS -#define V_FUNCTION_BEGIN (name) \ - .globl name; \ - .section ".opd","a"; \ - .align 3; \ - name: \ - .quad .name,.TOC.@tocbase,0; \ - .previous; \ - .globl .name; \ - .type .name,@function; \ - .name: \ - -#define V_FUNCTION_END (name) \ - .size .name,.-.name; - -#define V_LOCAL_FUNC (name) (.name) - -#else /* VDS64_HAS_DESCRIPTORS */ -#define V_FUNCTION_BEGIN (name) \ .globl name; \ name: \
@@ -55,8 +33,6 @@ int vdso_getcpu_init(void); .size name,.-name;#define V_LOCAL_FUNC (name) (name) - -#endif /* VDS64_HAS_DESCRIPTORS */ #endif /* __VDSO64__ */ #ifdef __VDSO32__
arch/powerpc/kernel/vdso.c +0 -5
@@ -391,12 +391,7 @@ static unsigned long __init find_function64(struct lib64_elfinfo *lib, symname);return 0 ; } -#ifdef VDS64_HAS_DESCRIPTORS -return *((u64 *)(vdso64_kbase + sym->st_value -VDSO64_LBASE )) - -VDSO64_LBASE ; -#else return sym->st_value -VDSO64_LBASE ; -#endif } static int __init vdso_do_func_patch64(struct lib32_elfinfo *v32,
Signature · 1 line
2.21.1
Michael Ellerman
reviewerRe: [PATCH] powerpc/vdso: remove deprecated VDS64_HAS_DESCRIPTORS references
Quoted 10 lines · Joe Lawrence
The original 2005 patch that introduced the powerpc vdso, pre-git ("ppc64: Implement a vDSO and use it for signal trampoline") notes that:
... symbols exposed by the vDSO aren't "normal" function symbols, apps can't be expected to link against them directly, the vDSO's are both seen as if they were linked at 0 and the symbols just contain offsets to the various functions. This is done on purpose to avoid a relocation step (ppc64 functions normally have descriptors with abs addresses in them). When glibc uses those functions, it's expected to use it's own trampolines that know how to reach them.
For the archives, that's here:
https://github.com/mpe/linux-fullhistory/commit/5f2dd691b62da9d9cc54b938f8b29c22c93cb805
And reproduced below.
cheers
commit 5f2dd691b62da9d9cc54b938f8b29c22c93cb805
Author: Benjamin Herrenschmidt <[email protected]> AuthorDate: Fri Mar 4 17:33:32 2005 -0800 Commit: Linus Torvalds <[email protected]> CommitDate: Fri Mar 4 17:33:32 2005 -0800
[PATCH] ppc64: Implement a vDSO and use it for signal trampoline
This patch adds to the ppc64 kernel a virtual .so (vDSO) that is mapped into every process space, similar to the x86 vsyscall page. However, the implementation is very different (and doesn't use the gate area mecanism). Actually, it contains two implementations, a 32 bits and a 64 bits one.
These vDSO's are currently mapped at 0x100000 (+1Mb) when possible (when a process load section isn't already there). In the future, we can randomize that address, or even imagine having a special phdr entry letting apps that wnat finer control over their address space to put it elsewhere (or not at all).
The implementation adds a hook to binfmt_elf to let the architecture add a real VMA to the process space instead of using the gate area mecanism. This mecanism wasn't very suitable for ppc, we couldn't just "shove" PTE entries mapping kernel addresses into userland without expensive changes to our hash table management. Instead, I made the vDSO be a normal VMA which, additionally, means it supports copy-on-write semantics if made writable via ptrace/mprotect, thus allowing breakpoints in the vDSO code.
The current implementation of the vDSOs contain the signal trampolines with appropriate DWARF informations, which enable us to use non-executable stacks (patches to come later) along with a few more functions that we hope glibc will soon make good use of (this is the "hard" part now :) Note that the symbols exposed by the vDSO aren't "normal" function symbols, apps can't be expected to link against them directly, the vDSO's are both seen as if they were linked at 0 and the symbols just contain offsets to the various functions. This is done on purpose to avoid a relocation step (ppc64 functions normally have descriptors with abs addresses in them). When glibc uses those functions, it's expected to use it's own trampolines that know how to reach them.
In some cases, the vDSO contains several versions of a given function (for various CPUs), the kernel will "patch" the symbol table at boot to make it point to the appropriate one transparently. What is currently implemented is:
- int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
This is a fully userland implementation of gettimeofday, with no barriers and no locks, and providing 100% equivalent results to the syscall version
- void __kernel_sync_dicache(unsigned long start, unsigned long end)
This function sync's the data and instruction caches (for making data executable), it is expected that userland loaders use this instead of doing it themselves, as the kernel will provide optimized versions for the current CPU. Currently, the vDSO procides a full one for all CPUs prior to POWER5 and a nop one for POWER5 which implements hardware snooping at the L1 level. In the future, an intermediate implementation may be done for the POWER4 and 970 which don't need the "dcbst" loop (the L1D cache is write-through on those).
- void *__kernel_get_syscall_map(unsigned int *syscall_count);
Returns a pointer to a map of implemented syscalls on the currently running kernel. The map is agnostic to the size of "long", unlike kernel bitops, it stores bits from top to bottom so that memory actually contains a linear bitmap check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of * 32 bits int at N >> 5.
Note about backward compatibility issues: A bug in the ppc64 libgcc unwinder makes it unable to unwind stacks properly accross signals if the signal trampoline isn't on the stack. This has been fixed in CVS for gcc 4.0 and will be soon on the stable branch, but the problem exist will all currently used versions.
That means that until glibc gets the patch to enable it's use of the vDSO symbols for the DWARF unwinder (rather trivial patch that will be pushed to glibc CVS soon hopefully), unwinding from a signal handler will not work for 64 bits applications.
I consider this as a non-issue though as a patch is about to be produced, which can easily get pushed to "live" distros like debian, gentoo, fedora, etc... soon enough (it breaks compatilbity with kernels below 2.4.20 unfortunately as our signal stack layout changed, crap crap crap), as there are few 64 bits applications out there (expect gentoo), as it's only really an issue with C++ code relying on throwing exceptions out of signal handlers (extremely rare it seems), and as "release" distros like SLES or RHEL will probably have the vDSO enabled glibc _and_ the unwinder fix by the time they release a version with a 2.6.11 or 2.6.12 kernel anyway :)
So far, I yet have to see an app failing because of that...
Finally, many many many thanks to Alan Modra for writing the DWARF information of the signal handlers and debugging the libgcc issues !
arch/ppc64/Makefile +21 -0
@@ -15,17 +15,38 @@ KERNELLOAD := 0xc000000000000000 +# Set default 32 bits cross compilers for vdso and boot wrapper +CROSS32_COMPILE ?= + +CROSS32CC := $(CROSS32_COMPILE)gcc +CROSS32AS := $(CROSS32_COMPILE)as +CROSS32LD := $(CROSS32_COMPILE)ld +CROSS32OBJCOPY := $(CROSS32_COMPILE)objcopy + +# If we have a biarch compiler, use it for 32 bits cross compile if +# CROSS32_COMPILE wasn't explicitely defined, and add proper explicit +# target type to target compilers + HAS_BIARCH := $(call cc-option-yn, -m64) ifeq ($(HAS_BIARCH),y) +ifeq ($(CROSS32_COMPILE),) +CROSS32CC := $(CC) -m32 +CROSS32AS := $(AS) -a32 +CROSS32LD := $(LD) -m elf32ppc +CROSS32OBJCOPY := $(OBJCOPY) +endif AS := $(AS) -a64 LD := $(LD) -m elf64ppc CC := $(CC) -m64 endif +export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY + new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi) ifeq ($(new_nm),y) NM := $(NM) --synthetic + endif CHECKFLAGS += -m64 -D__powerpc__
arch/ppc64/boot/Makefile +5 -11
@@ -20,17 +20,11 @@ # CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE # in the toplevel makefile. -CROSS32_COMPILE ?= -#CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux- -BOOTCC := $(CROSS32_COMPILE)gcc HOSTCC := gcc BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin -BOOTAS := $(CROSS32_COMPILE)as BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -BOOTLD := $(CROSS32_COMPILE)ld BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds -BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy OBJCOPYFLAGS := contents,alloc,load,readonly,data src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S
@@ -38,10 +32,10 @@ src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) quiet_cmd_bootcc = BOOTCC $@ - cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< + cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< quiet_cmd_bootas = BOOTAS $@ - cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< + cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c $(call if_changed_dep,bootcc)
@@ -77,15 +71,15 @@ vmlinux.strip: vmlinux FORCE $(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE $(call if_changed,ramdisk) -addsection = $(BOOTOBJCOPY) $(1) \ +addsection = $(CROSS32OBJCOPY) $(1) \ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \ --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(OBJCOPYFLAGS) quiet_cmd_addnote = ADDNOTE $@ - cmd_addnote = $(BOOTLD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@ + cmd_addnote = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@ quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(BOOTAS) -o $@ + cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(CROSS32AS) -o $@ $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE $(call if_changed,gzip)
arch/ppc64/kernel/Makefile +2 -1
@@ -11,7 +11,8 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o rtc.o init_task.o \ lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ - iommu.o sysfs.o + iommu.o sysfs.o vdso.o +obj-y += vdso32/ vdso64/ obj-$(CONFIG_PPC_OF) += of_device.o
arch/ppc64/kernel/asm-offsets.c +22 -0
@@ -22,6 +22,7 @@#include <linux/types.h> #include <linux/mman.h> #include <linux/mm.h> +#include <linux/time.h> #include <linux/hardirq.h> #include <asm/io.h> #include <asm/page.h>
@@ -35,6 +36,8 @@#include <asm/rtas.h> #include <asm/cputable.h> #include <asm/cache.h> +#include <asm/systemcfg.h> +#include <asm/compat.h> #define DEFINE (sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -167,5 +170,24 @@ int main(void)DEFINE (CPU_SPEC_FEATURES , offsetof(struct cpu_spec , cpu_features));DEFINE (CPU_SPEC_SETUP , offsetof(struct cpu_spec , cpu_setup)); +/* systemcfg offsets for use by vdso */ +DEFINE (CFG_TB_ORIG_STAMP , offsetof(struct systemcfg , tb_orig_stamp)); +DEFINE (CFG_TB_TICKS_PER_SEC , offsetof(struct systemcfg , tb_ticks_per_sec)); +DEFINE (CFG_TB_TO_XS , offsetof(struct systemcfg , tb_to_xs)); +DEFINE (CFG_STAMP_XSEC , offsetof(struct systemcfg , stamp_xsec)); +DEFINE (CFG_TB_UPDATE_COUNT , offsetof(struct systemcfg , tb_update_count)); +DEFINE (CFG_TZ_MINUTEWEST , offsetof(struct systemcfg , tz_minuteswest)); +DEFINE (CFG_TZ_DSTTIME , offsetof(struct systemcfg , tz_dsttime)); +DEFINE (CFG_SYSCALL_MAP32 , offsetof(struct systemcfg , syscall_map_32)); +DEFINE (CFG_SYSCALL_MAP64 , offsetof(struct systemcfg , syscall_map_64)); + +/* timeval/timezone offsets for use by vdso */ +DEFINE (TVAL64_TV_SEC , offsetof(struct timeval , tv_sec)); +DEFINE (TVAL64_TV_USEC , offsetof(struct timeval , tv_usec)); +DEFINE (TVAL32_TV_SEC , offsetof(struct compat_timeval , tv_sec)); +DEFINE (TVAL32_TV_USEC , offsetof(struct compat_timeval , tv_usec)); +DEFINE (TZONE_TZ_MINWEST , offsetof(struct timezone , tz_minuteswest)); +DEFINE (TZONE_TZ_DSTTIME , offsetof(struct timezone , tz_dsttime)); +return 0 ; }
arch/ppc64/kernel/head.S +0 -1
@@ -54,7 +54,6 @@ * 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x3000 - 0x3fff : Interrupt support * 0x4000 - 0x4fff : NACA - * 0x5000 - 0x5fff : SystemCfg * 0x6000 : iSeries and common interrupt prologs * 0x9000 - 0x9fff : Initial segment table */
arch/ppc64/kernel/setup.c +31 -0
@@ -990,6 +990,34 @@ static void __init emergency_stack_init(void) limit)) + PAGE_SIZE; } +/* +* Called from setup_arch to initialize the bitmap of available +* syscalls in the systemcfg page +*/ +void __init setup_syscall_map (void ) +{ +unsigned int i, count64 =0 , count32 =0 ; +extern unsigned long *sys_call_table; +extern unsigned long *sys_call_table32; +extern unsigned long sys_ni_syscall; + + +for (i =0 ; i < __NR_syscalls; i++) { +if (sys_call_table[i] == sys_ni_syscall) +continue ; + count64++; + systemcfg->syscall_map_64[i >>5 ] |=0x80000000UL >> (i &0x1f ); + } +for (i =0 ; i < __NR_syscalls; i++) { +if (sys_call_table32[i] == sys_ni_syscall) +continue ; + count32++; + systemcfg->syscall_map_32[i >>5 ] |=0x80000000UL >> (i &0x1f ); + } +printk (KERN_INFO "Syscall map setup, %d 32 bits and %d 64 bits syscalls\n" , + count32, count64); +} +/* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until
@@ -1028,6 +1056,9 @@ void __init setup_arch(char **cmdline_p)/* set up the bootmem stuff with available memory */ do_init_bootmem (); +/* initialize the syscall map in systemcfg */ +setup_syscall_map (); + ppc_md.setup_arch ();/* Select the correct idle loop for the platform. */
arch/ppc64/kernel/signal.c +9 -5
@@ -36,6 +36,7 @@#include <asm/ppcdebug.h> #include <asm/unistd.h> #include <asm/cacheflush.h> +#include <asm/vdso.h> #define DEBUG_SIG 0
@@ -428,10 +429,14 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, goto badframe;/* Set up to return from userspace. */ - err |=setup_trampoline (__NR_rt_sigreturn, &frame->tramp[0 ]); -if (err) - goto badframe; - +if (vdso64_rt_sigtramp && current->thread.vdso_base) { + regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; + }else { + err |=setup_trampoline (__NR_rt_sigreturn, &frame->tramp[0 ]); +if (err) + goto badframe; + regs->link = (unsigned long ) &frame->tramp[0 ]; + } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;/* Allocate a dummy caller frame for the signal handler. */
@@ -440,7 +445,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,/* Set up "regs" so we "return" to the signal handler. */ err |=get_user (regs->nip, &funct_desc_ptr->entry); - regs->link = (unsigned long ) &frame->tramp[0 ]; regs->gpr[1 ] = newsp; err |=get_user (regs->gpr[2 ], &funct_desc_ptr->toc); regs->gpr[3 ] = signr;
arch/ppc64/kernel/signal32.c +20 -7
@@ -31,6 +31,7 @@#include <asm/ppcdebug.h> #include <asm/unistd.h> #include <asm/cacheflush.h> +#include <asm/vdso.h> #define DEBUG_SIG 0
@@ -656,18 +657,24 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,/* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; -if (save_user_regs (regs, frame, __NR_rt_sigreturn)) - goto badframe; -if (put_user (regs->gpr[1 ], (unsigned long __user *)newsp)) goto badframe; + +if (vdso32_rt_sigtramp && current->thread.vdso_base) { +if (save_user_regs (regs, frame,0 )) + goto badframe; + regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; + }else { +if (save_user_regs (regs, frame, __NR_rt_sigreturn)) + goto badframe; + regs->link = (unsigned long ) frame->tramp; + } regs->gpr[1 ] = (unsigned long ) newsp; regs->gpr[3 ] = sig; regs->gpr[4 ] = (unsigned long ) &rt_sf->info; regs->gpr[5 ] = (unsigned long ) &rt_sf->uc; regs->gpr[6 ] = (unsigned long ) rt_sf; regs->nip = (unsigned long ) ka->sa.sa_handler; - regs->link = (unsigned long ) frame->tramp; regs->trap =0 ; regs->result =0 ;
@@ -825,8 +832,15 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka, || __put_user(sig, &sc->signal)) goto badframe; -if (save_user_regs (regs, &frame->mctx, __NR_sigreturn)) - goto badframe; +if (vdso32_sigtramp && current->thread.vdso_base) { +if (save_user_regs (regs, &frame->mctx,0 )) + goto badframe; + regs->link = current->thread.vdso_base + vdso32_sigtramp; + }else { +if (save_user_regs (regs, &frame->mctx, __NR_sigreturn)) + goto badframe; + regs->link = (unsigned long ) frame->mctx.tramp; + }if (put_user (regs->gpr[1 ], (unsigned long __user *)newsp)) goto badframe;
@@ -834,7 +848,6 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->gpr[3 ] = sig; regs->gpr[4 ] = (unsigned long ) sc; regs->nip = (unsigned long ) ka->sa.sa_handler; - regs->link = (unsigned long ) frame->mctx.tramp; regs->trap =0 ; regs->result =0 ;
arch/ppc64/kernel/smp.c +1 -1
@@ -383,7 +383,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)* For now we leave it which means the time can be some * number of msecs off until someone does a settimeofday() */ - do_gtod.tb_orig_stamp = tb_last_stamp; + do_gtod.varp->tb_orig_stamp = tb_last_stamp; systemcfg->tb_orig_stamp = tb_last_stamp;#endif
arch/ppc64/kernel/time.c +58 -26
157 lines not on this page · raw message
arch/ppc64/kernel/vdso.c new file +614 -0
614 lines not on this page · raw message
arch/ppc64/kernel/vdso32/Makefile new file +36 -0
@@ -0,0 +1,36 @@ + +# List of files in the vdso, has to be asm only for now + +obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o + +# Build rules + +targets := $(obj-vdso32) vdso32.so +obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) + + +EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin +EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 +EXTRA_AFLAGS := -D__VDSO32__ -s + +obj-y += vdso32_wrapper.o +extra-y += vdso32.lds +CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) + +# Force dependency (incbin is bad) +$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so + +# link rule for the .so file, .lds has to be first +$(obj)/vdso32.so: $(src)/vdso32.lds $(obj-vdso32) + $(call if_changed,vdso32ld) + +# assembly rules for the .S files +$(obj-vdso32): %.o: %.S + $(call if_changed_dep,vdso32as) + +# actual build commands +quiet_cmd_vdso32ld = VDSO32L $@ + cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@ +quiet_cmd_vdso32as = VDSO32A $@ + cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $< +
arch/ppc64/kernel/vdso32/cacheflush.S new file +65 -0
65 lines not on this page · raw message
arch/ppc64/kernel/vdso32/datapage.S new file +68 -0
68 lines not on this page · raw message
arch/ppc64/kernel/vdso32/gettimeofday.S new file +139 -0
139 lines not on this page · raw message
arch/ppc64/kernel/vdso32/sigtramp.S new file +300 -0
300 lines not on this page · raw message
arch/ppc64/kernel/vdso32/vdso32.lds.S new file +111 -0
111 lines not on this page · raw message
arch/ppc64/kernel/vdso32/vdso32_wrapper.S new file +13 -0
@@ -0,0 +1,13 @@ +#include <linux/init.h> +#include <asm/page.h> + + .section ".data.page_aligned" + + .globl vdso32_start, vdso32_end + .balign PAGE_SIZE +vdso32_start: + .incbin "arch/ppc64/kernel/vdso32/vdso32.so" + .balign PAGE_SIZE +vdso32_end: + + .previous
arch/ppc64/kernel/vdso64/Makefile new file +35 -0
@@ -0,0 +1,35 @@ +# List of files in the vdso, has to be asm only for now + +obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o + +# Build rules + +targets := $(obj-vdso64) vdso64.so +obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) + +EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin +EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 +EXTRA_AFLAGS := -D__VDSO64__ -s + +obj-y += vdso64_wrapper.o +extra-y += vdso64.lds +CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) + +# Force dependency (incbin is bad) +$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so + +# link rule for the .so file, .lds has to be first +$(obj)/vdso64.so: $(src)/vdso64.lds $(obj-vdso64) + $(call if_changed,vdso64ld) + +# assembly rules for the .S files +$(obj-vdso64): %.o: %.S + $(call if_changed_dep,vdso64as) + +# actual build commands +quiet_cmd_vdso64ld = VDSO64L $@ + cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ +quiet_cmd_vdso64as = VDSO64A $@ + cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< + +
arch/ppc64/kernel/vdso64/cacheflush.S new file +64 -0
64 lines not on this page · raw message
arch/ppc64/kernel/vdso64/datapage.S new file +68 -0
68 lines not on this page · raw message
arch/ppc64/kernel/vdso64/gettimeofday.S new file +91 -0
91 lines not on this page · raw message
arch/ppc64/kernel/vdso64/sigtramp.S new file +294 -0
294 lines not on this page · raw message
arch/ppc64/kernel/vdso64/vdso64.lds.S new file +110 -0
110 lines not on this page · raw message
arch/ppc64/kernel/vdso64/vdso64_wrapper.S new file +13 -0
@@ -0,0 +1,13 @@ +#include <linux/init.h> +#include <asm/page.h> + + .section ".data.page_aligned" + + .globl vdso64_start, vdso64_end + .balign PAGE_SIZE +vdso64_start: + .incbin "arch/ppc64/kernel/vdso64/vdso64.so" + .balign PAGE_SIZE +vdso64_end: + + .previous
arch/ppc64/mm/init.c +3 -0
@@ -63,6 +63,7 @@#include <asm/system.h> #include <asm/iommu.h> #include <asm/abs_addr.h> +#include <asm/vdso.h> int mem_init_done;unsigned long ioremap_bot =IMALLOC_BASE ;
@@ -748,6 +749,8 @@ void __init mem_init(void)#ifdef CONFIG_PPC_ISERIES iommu_vio_init ();#endif +/* Initialize the vDSO */ +vdso_init (); }/*
fs/binfmt_elf.c +8 -0
@@ -782,6 +782,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) goto out_free_dentry; } +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES + retval =arch_setup_additional_pages (bprm, executable_stack); +if (retval <0 ) { +send_sig (SIGKILL , current,0 ); + goto out_free_dentry; + } +#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ + current->mm->start_stack = bprm->p;/* Now we do a little grungy work by mmaping the ELF image into
include/asm-ppc64/a.out.h +4 -7
@@ -30,14 +30,11 @@ struct exec#ifdef __KERNEL__ -#define STACK_TOP_USER64 (TASK_SIZE_USER64) +#define STACK_TOP_USER64 TASK_SIZE_USER64 +#define STACK_TOP_USER32 TASK_SIZE_USER32 -/* Give 32-bit user space a full 4G address space to live in. */ -#define STACK_TOP_USER32 (TASK_SIZE_USER32) - -#define STACK_TOP ((test_thread_flag(TIF_32BIT) || \ - (ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \ - STACK_TOP_USER32 : STACK_TOP_USER64) +#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ + STACK_TOP_USER32 : STACK_TOP_USER64)#endif /* __KERNEL__ */
include/asm-ppc64/elf.h +12 -0
@@ -238,10 +238,20 @@ do { \/* A special ignored type value for PPC, for glibc compatibility. */ #define AT_IGNOREPPC 22 +/* The vDSO location. We have to use the same value as x86 for glibc's +* sake :-) +*/ +#define AT_SYSINFO_EHDR 33 +extern int dcache_bsize;extern int icache_bsize;extern int ucache_bsize; +/* We do have an arch_setup_additional_pages for vDSO matters */ +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES +struct linux_binprm ; +extern int arch_setup_additional_pages (struct linux_binprm *bprm,int executable_stack); +/* * The requirements here are: * - keep the final alignment of sp (sp & 0xf)
@@ -260,6 +270,8 @@ do { \NEW_AUX_ENT (AT_DCACHEBSIZE , dcache_bsize); \NEW_AUX_ENT (AT_ICACHEBSIZE , icache_bsize); \NEW_AUX_ENT (AT_UCACHEBSIZE , ucache_bsize); \ +/* vDSO base */ \ +NEW_AUX_ENT (AT_SYSINFO_EHDR , current->thread.vdso_base); \ }while (0 )/* PowerPC64 relocations defined by the ABIs */
include/asm-ppc64/page.h +3 -0
@@ -185,6 +185,9 @@ extern int page_is_ram(unsigned long pfn);extern u64 ppc64_pft_size;/* Log 2 of page table size */ +/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ +#define __HAVE_ARCH_GATE_AREA 1 +#endif /* __ASSEMBLY__ */ #ifdef MODULE
include/asm-ppc64/processor.h +3 -3
@@ -544,8 +544,8 @@ extern struct task_struct *last_task_used_altivec;/* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(STACK_TOP_USER32 / 4)) -#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(STACK_TOP_USER64 / 4)) +#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4)) +#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)||(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \ TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
@@ -564,7 +564,7 @@ struct thread_struct {unsigned long fpexc_mode;/* Floating-point exception mode */ unsigned long start_tb;/* Start purr when proc switched in */ unsigned long accum_tb;/* Total accumilated purr for process */ -unsigned long pad;/* was saved_msr, saved_softe */ +unsigned long vdso_base;/* base of the vDSO library */ #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16)));
include/asm-ppc64/systemcfg.h +7 -1
@@ -20,10 +20,14 @@* Minor version changes are a hint. */ #define SYSTEMCFG_MAJOR 1 -#define SYSTEMCFG_MINOR 0 +#define SYSTEMCFG_MINOR 1 #ifndef __ASSEMBLY__ +#include <linux/unistd.h> + +#define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32) + struct systemcfg { __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ struct { /* Systemcfg version numbers */
@@ -47,6 +51,8 @@ struct systemcfg {__u32 dcache_line_size;/* L1 d-cache line size 0x64 */ __u32 icache_size;/* L1 i-cache size 0x68 */ __u32 icache_line_size;/* L1 i-cache line size 0x6C */ +__u32 syscall_map_64[SYSCALL_MAP_SIZE ];/* map of available syscalls 0x70 */ +__u32 syscall_map_32[SYSCALL_MAP_SIZE ];/* map of available syscalls */ };#ifdef __KERNEL__
include/asm-ppc64/time.h +1 -1
@@ -43,10 +43,10 @@ extern time_t last_rtc_update;struct gettimeofday_vars {unsigned long tb_to_xs;unsigned long stamp_xsec; +unsigned long tb_orig_stamp; };struct gettimeofday_struct { -unsigned long tb_orig_stamp;unsigned long tb_ticks_per_sec;struct gettimeofday_vars vars[2 ];struct gettimeofday_vars *volatile varp;
include/asm-ppc64/vdso.h new file +83 -0
83 lines not on this page · raw message
Michael Ellerman
AppliedRe: [PATCH] powerpc/vdso: remove deprecated VDS64_HAS_DESCRIPTORS references
In reply to Joe LawrenceQuoted 15 lines · Joe Lawrence
The original 2005 patch that introduced the powerpc vdso, pre-git ("ppc64: Implement a vDSO and use it for signal trampoline") notes that:
... symbols exposed by the vDSO aren't "normal" function symbols, apps can't be expected to link against them directly, the vDSO's are both seen as if they were linked at 0 and the symbols just contain offsets to the various functions. This is done on purpose to avoid a relocation step (ppc64 functions normally have descriptors with abs addresses in them). When glibc uses those functions, it's expected to use it's own trampolines that know how to reach them.
Despite that explanation, there remains dead #ifdef
VDS64_HAS_DESCRIPTORScode-blocks that provide alternate function definitions that setup function descriptors.
Quoted 7 lines
Since
VDS64_HAS_DESCRIPTORShas been unused for all these years, we might as well finally remove it from the codebase.html
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/ffd3eaf178b0f616a071e510e289d937330b0b35
cheers