From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:42
Hi,
This series adds support for a compat (AArch32) vDSO, providing two
userspace functionalities to compat processes:
* "Virtual" time syscalls (gettimeofday and clock_gettime). The
implementation is an adaptation of the arm vDSO (vgettimeofday.c),
sharing the data page with the 64-bit vDSO.
* sigreturn trampolines, following the example of the 64-bit vDSO
(sigreturn.S), but slightly more complicated because we provide A32
and T32 variants for both sigreturn and rt_sigreturn, and appropriate
arm-specific unwinding directives.
The first point brings the performance improvement expected of a vDSO,
by implementing time syscalls directly in userspace. The second point
allows to provide unwinding information for sigreturn trampolines,
achieving feature parity with the trampolines provided by glibc.
Unfortunately, this time we cannot escape using a 32-bit toolchain. To
build the compat VDSO, CONFIG_COMPAT_VDSO must be set *and*
CROSS_COMPILE_ARM32 must be defined to the prefix of a 32-bit compiler.
Failure to do so will not prevent building the kernel, but a warning
will be printed and the compat vDSO will not be built.
v3 is a major refactor of the series. The main change is that the kuser
helpers are no longer mutually exclusive with the 32-bit vDSO, and can
be disabled independently of the 32-bit vDSO (they are kept enabled by
default). To this end, the "old" sigreturn trampolines have been moved
out of the [vectors] page into an independent [sigreturn] page, similar
to [sigpage] on arm. The [vectors] page is now [kuserhelpers], and its
presence is controlled by CONFIG_KUSER_HELPERS. The [sigreturn] page is
only present when the 32-bit vDSO is not included (the latter provides
its own sigreturn trampolines with unwinding information). The following
table summarises which pages are now added in 32-bit processes:
+----------------+----------------+----------------+
| CONFIG | !VDSO32 | VDSO32 |
+----------------+----------------+----------------+
| !KUSER_HELPERS | [sigreturn] | [vvar] |
| | | [vdso] |
+----------------+----------------+----------------+
| KUSER_HELPERS | [sigreturn] | [vvar] |
| | [kuserhelpers] | [vdso] |
| | | [kuserhelpers] |
+----------------+----------------+----------------+
Additionally, the 32-bit vDSO no longer requires a 32-bit compiler
supporting ARMv8, any compiler supporting ARMv7-A can now be used. The
only code change is to introduce separate AArch32 barriers, to stop
generating dmb ishld when using an ARMv7 assembler. However, a major
rework of the 32-bit vDSO Makefile was necessary, because mismatching
32/64-bit compiler versions prevent sharing flags (e.g. recently
introduced warning flags). Copy/pasting flags is not nice or beautiful,
but filtering out flags is not practicable and may break when top-level
Makefiles are changed.
Patches overview:
* 1..3: split [vectors] -> [sigreturn] + [kuserhelpers], add
CONFIG_KUSER_HELPERS
* 4..6: preparation patches
* 7: the 32-bit vDSO itself
* 8..10: plumbing for the 32-bit vDSO
* 11: Kconfig/Makefile wiring
Thanks,
Kevin
Changelog v2..v3:
* kuser helpers / sigreturn split.
* Rework/debug of the sigreturn trampolines in the 32-bit vDSO. The CFI
directives have been removed, as they only provide debug information
on arm (which is stripped from vdso.so). After adding a missing nop,
unwinding now works properly with all the trampolines (see comment in
patch 7).
* Some cleanup in vdso.c, to make the 32-bit and 64-bit setup more
consistent.
* 32-bit vDSO Makefile refactor.
* AArch32 barriers, selected by the 32-bit compiler mode
(armv7-a/armv8-a).
* Use PROVIDE_HIDDEN() instead of HIDDEN() in vdso32/vdso.lds.S, as
HIDDEN() only exists since ld 2.23.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Kevin Brodsky (11):
arm64: compat: Remove leftover variable declaration
arm64: compat: Split the sigreturn trampolines and kuser helpers
arm64: compat: Add CONFIG_KUSER_HELPERS
arm64: Refactor vDSO init/setup
arm64: compat: Add time-related syscall numbers
arm64: compat: Expose offset to registers in sigframes
arm64: compat: Add a 32-bit vDSO
arm64: compat: 32-bit vDSO setup
arm64: elf: Set AT_SYSINFO_EHDR in compat processes
arm64: compat: Use vDSO sigreturn trampolines if available
arm64: Wire up and expose the new compat vDSO
arch/arm64/Kconfig | 52 +++++
arch/arm64/Makefile | 28 ++-
arch/arm64/include/asm/elf.h | 15 +-
arch/arm64/include/asm/processor.h | 4 +-
arch/arm64/include/asm/signal32.h | 46 ++++-
arch/arm64/include/asm/unistd.h | 2 +
arch/arm64/include/asm/vdso.h | 3 +
arch/arm64/kernel/Makefile | 9 +-
arch/arm64/kernel/asm-offsets.c | 13 ++
arch/arm64/kernel/kuser32.S | 48 +----
arch/arm64/kernel/signal32.c | 66 ++----
arch/arm64/kernel/sigreturn32.S | 59 ++++++
arch/arm64/kernel/vdso.c | 315 ++++++++++++++++++++---------
arch/arm64/kernel/vdso32/Makefile | 166 +++++++++++++++
arch/arm64/kernel/vdso32/aarch32-barrier.h | 33 +++
arch/arm64/kernel/vdso32/sigreturn.S | 76 +++++++
arch/arm64/kernel/vdso32/vdso.S | 32 +++
arch/arm64/kernel/vdso32/vdso.lds.S | 93 +++++++++
arch/arm64/kernel/vdso32/vgettimeofday.c | 295 +++++++++++++++++++++++++++
19 files changed, 1147 insertions(+), 208 deletions(-)
create mode 100644 arch/arm64/kernel/sigreturn32.S
create mode 100644 arch/arm64/kernel/vdso32/Makefile
create mode 100644 arch/arm64/kernel/vdso32/aarch32-barrier.h
create mode 100644 arch/arm64/kernel/vdso32/sigreturn.S
create mode 100644 arch/arm64/kernel/vdso32/vdso.S
create mode 100644 arch/arm64/kernel/vdso32/vdso.lds.S
create mode 100644 arch/arm64/kernel/vdso32/vgettimeofday.c
--
2.10.2
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:43
Commit a1d5ebaf8ccd ("arm64: big-endian: don't treat code as data when
copying sigret code") moved the 32-bit sigreturn trampoline code from
the aarch32_sigret_code array to kuser32.S. The commit removed the
array definition from signal32.c, but not its declaration in
signal32.h. Remove the leftover declaration.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/include/asm/signal32.h | 2 --
1 file changed, 2 deletions(-)
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:44
AArch32 processes are currently installed a special [vectors] page that
contains the sigreturn trampolines and the kuser helpers, at the fixed
address mandated by the kuser helpers ABI.
Having both functionalities in the same page is becoming problematic,
because:
* It makes it impossible to disable the kuser helpers (the sigreturn
trampolines cannot be removed), which is possible in arm.
* A future 32-bit vDSO would provide the sigreturn trampolines itself,
making those in [vectors] redundant.
This patch addresses the problem by moving the sigreturn trampolines to
a separate [sigreturn] page, in similar fashion to [sigpage] in arm.
[vectors] has always been a misnomer on arm64/compat, as there is no
AArch32 vector there. Now that only the kuser helpers are left there,
we can rename it to [kuserhelpers].
mm->context.vdso used to point to the [vectors] page, which is
unnecessary (as its address is fixed). It now points to the [sigreturn]
page (whose address is randomized like a vDSO).
Finally aarch32_setup_vectors_page() has been renamed to the more
generic aarch32_setup_additional_pages().
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/include/asm/elf.h | 6 +-
arch/arm64/include/asm/processor.h | 4 +-
arch/arm64/include/asm/signal32.h | 2 -
arch/arm64/kernel/signal32.c | 5 +-
arch/arm64/kernel/vdso.c | 135 ++++++++++++++++++++++++++-----------
5 files changed, 104 insertions(+), 48 deletions(-)
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:45
Make it possible to disable the kuser helpers by adding a KUSER_HELPERS
config option (enabled by default). When disabled, all kuser
helpers-related code is removed from the kernel and no mapping is done
at the fixed high address (0xffff0000); any attempt to use a kuser
helper from a 32-bit process will result in a segfault.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/Kconfig | 29 ++++++++++++++++++++
arch/arm64/kernel/Makefile | 3 ++-
arch/arm64/kernel/kuser32.S | 48 +++------------------------------
arch/arm64/kernel/sigreturn32.S | 59 +++++++++++++++++++++++++++++++++++++++++
arch/arm64/kernel/vdso.c | 6 +++++
5 files changed, 99 insertions(+), 46 deletions(-)
create mode 100644 arch/arm64/kernel/sigreturn32.S
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:46
Move the logic for setting up mappings and pages for the vDSO into
static functions. This makes the vDSO setup code more consistent with
the compat side and will allow to reuse it for the future compat vDSO.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/kernel/vdso.c | 170 +++++++++++++++++++++++++++--------------------
1 file changed, 99 insertions(+), 71 deletions(-)
@@ -51,6 +53,93 @@ static union {}vdso_data_store__page_aligned_data;structvdso_data*vdso_data=&vdso_data_store.data;+staticint__initvdso_mappings_init(constchar*name,+constchar*code_start,+constchar*code_end,+structvdso_mappings*mappings)+{+unsignedlongi,num_code_pages;+structpage**pages;++if(memcmp(code_start,"\177ELF",4)){+pr_err("%s is not a valid ELF object!\n",name);+return-EINVAL;+}++num_code_pages=(code_end-code_start)>>PAGE_SHIFT;+pr_info("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n",+name,num_code_pages+1,num_code_pages,code_start,1L,+vdso_data);++/*+*AllocatespaceforstoringpointerstothevDSOcodepages+the+*datapage.Thepointersmusthavethesamelifetimeasthemappings,+*whicharestatic,sothereisnoneedtokeeptrackofthepointer+*arraytofreeit.+*/+pages=kmalloc_array(num_code_pages+1,sizeof(structpage*),+GFP_KERNEL);+if(pages==NULL)+return-ENOMEM;++/* Grab the vDSO data page */+pages[0]=pfn_to_page(PHYS_PFN(__pa(vdso_data)));++/* Grab the vDSO code pages */+for(i=0;i<num_code_pages;i++)+pages[i+1]=pfn_to_page(PHYS_PFN(__pa(code_start))+i);++/* Populate the special mapping structures */+mappings->data_mapping=(structvm_special_mapping){+.name="[vvar]",+.pages=&pages[0],+};++mappings->code_mapping=(structvm_special_mapping){+.name="[vdso]",+.pages=&pages[1],+};++mappings->num_code_pages=num_code_pages;+return0;+}++staticintvdso_setup(structmm_struct*mm,+conststructvdso_mappings*mappings)+{+unsignedlongvdso_base,vdso_text_len,vdso_mapping_len;+void*ret;++vdso_text_len=mappings->num_code_pages<<PAGE_SHIFT;+/* Be sure to map the data page */+vdso_mapping_len=vdso_text_len+PAGE_SIZE;++vdso_base=get_unmapped_area(NULL,0,vdso_mapping_len,0,0);+if(IS_ERR_VALUE(vdso_base)){+ret=ERR_PTR(vdso_base);+gotoout;+}++ret=_install_special_mapping(mm,vdso_base,PAGE_SIZE,+VM_READ|VM_MAYREAD,+&mappings->data_mapping);+if(IS_ERR(ret))+gotoout;++vdso_base+=PAGE_SIZE;+ret=_install_special_mapping(mm,vdso_base,vdso_text_len,+VM_READ|VM_EXEC|+VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,+&mappings->code_mapping);+if(IS_ERR(ret))+gotoout;++mm->context.vdso=(void*)vdso_base;++out:+returnPTR_ERR_OR_ZERO(ret);+}+#ifdef CONFIG_COMPAT/* sigreturn trampolines page */
@@ -175,90 +264,29 @@ int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)#endif /* CONFIG_COMPAT */-staticstructvm_special_mappingvdso_spec[2]__ro_after_init={-{-.name="[vvar]",-},-{-.name="[vdso]",-},-};+staticstructvdso_mappingsvdso_mappings__ro_after_init;staticint__initvdso_init(void){-inti;-structpage**vdso_pagelist;--if(memcmp(&vdso_start,"\177ELF",4)){-pr_err("vDSO is not a valid ELF object!\n");-return-EINVAL;-}+externcharvdso_start,vdso_end;-vdso_pages=(&vdso_end-&vdso_start)>>PAGE_SHIFT;-pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",-vdso_pages+1,vdso_pages,&vdso_start,1L,vdso_data);--/* Allocate the vDSO pagelist, plus a page for the data. */-vdso_pagelist=kcalloc(vdso_pages+1,sizeof(structpage*),-GFP_KERNEL);-if(vdso_pagelist==NULL)-return-ENOMEM;--/* Grab the vDSO data page. */-vdso_pagelist[0]=pfn_to_page(PHYS_PFN(__pa(vdso_data)));--/* Grab the vDSO code pages. */-for(i=0;i<vdso_pages;i++)-vdso_pagelist[i+1]=pfn_to_page(PHYS_PFN(__pa(&vdso_start))+i);--vdso_spec[0].pages=&vdso_pagelist[0];-vdso_spec[1].pages=&vdso_pagelist[1];--return0;+returnvdso_mappings_init("vdso",&vdso_start,&vdso_end,+&vdso_mappings);}arch_initcall(vdso_init);-intarch_setup_additional_pages(structlinux_binprm*bprm,-intuses_interp)+intarch_setup_additional_pages(structlinux_binprm*bprm,intuses_interp){structmm_struct*mm=current->mm;-unsignedlongvdso_base,vdso_text_len,vdso_mapping_len;-void*ret;--vdso_text_len=vdso_pages<<PAGE_SHIFT;-/* Be sure to map the data page */-vdso_mapping_len=vdso_text_len+PAGE_SIZE;+intret;if(down_write_killable(&mm->mmap_sem))return-EINTR;-vdso_base=get_unmapped_area(NULL,0,vdso_mapping_len,0,0);-if(IS_ERR_VALUE(vdso_base)){-ret=ERR_PTR(vdso_base);-gotoup_fail;-}-ret=_install_special_mapping(mm,vdso_base,PAGE_SIZE,-VM_READ|VM_MAYREAD,-&vdso_spec[0]);-if(IS_ERR(ret))-gotoup_fail;--vdso_base+=PAGE_SIZE;-mm->context.vdso=(void*)vdso_base;-ret=_install_special_mapping(mm,vdso_base,vdso_text_len,-VM_READ|VM_EXEC|-VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,-&vdso_spec[1]);-if(IS_ERR(ret))-gotoup_fail;+ret=vdso_setup(mm,&vdso_mappings);up_write(&mm->mmap_sem);-return0;--up_fail:-mm->context.vdso=NULL;-up_write(&mm->mmap_sem);-returnPTR_ERR(ret);+returnret;}/*
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:47
They will be used by the future compat vDSO.
The compat syscall numbers correspond to the arm syscall numbers, see
arch/arm/include/uapi/asm/unistd.h.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/include/asm/unistd.h | 2 ++
1 file changed, 2 insertions(+)
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:48
This will be needed to provide unwinding information in compat
sigreturn trampolines, part of the future compat vDSO. There is no
obvious header the compat_sig* struct's should be moved to, so let's
put them in signal32.h.
Also fix minor style issues reported by checkpatch.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/include/asm/signal32.h | 46 +++++++++++++++++++++++++++++++++++++++
arch/arm64/kernel/asm-offsets.c | 13 +++++++++++
arch/arm64/kernel/signal32.c | 46 ---------------------------------------
3 files changed, 59 insertions(+), 46 deletions(-)
@@ -20,6 +20,52 @@#ifdef CONFIG_COMPAT#include<linux/compat.h>+structcompat_sigcontext{+/* We always set these two fields to 0 */+compat_ulong_ttrap_no;+compat_ulong_terror_code;++compat_ulong_toldmask;+compat_ulong_tarm_r0;+compat_ulong_tarm_r1;+compat_ulong_tarm_r2;+compat_ulong_tarm_r3;+compat_ulong_tarm_r4;+compat_ulong_tarm_r5;+compat_ulong_tarm_r6;+compat_ulong_tarm_r7;+compat_ulong_tarm_r8;+compat_ulong_tarm_r9;+compat_ulong_tarm_r10;+compat_ulong_tarm_fp;+compat_ulong_tarm_ip;+compat_ulong_tarm_sp;+compat_ulong_tarm_lr;+compat_ulong_tarm_pc;+compat_ulong_tarm_cpsr;+compat_ulong_tfault_address;+};++structcompat_ucontext{+compat_ulong_tuc_flags;+compat_uptr_tuc_link;+compat_stack_tuc_stack;+structcompat_sigcontextuc_mcontext;+compat_sigset_tuc_sigmask;+int__unused[32-(sizeof(compat_sigset_t)/sizeof(int))];+compat_ulong_tuc_regspace[128]__aligned(8);+};++structcompat_sigframe{+structcompat_ucontextuc;+compat_ulong_tretcode[2];+};++structcompat_rt_sigframe{+structcompat_siginfoinfo;+structcompat_sigframesig;+};+intcompat_setup_frame(intusig,structksignal*ksig,sigset_t*set,structpt_regs*regs);intcompat_setup_rt_frame(intusig,structksignal*ksig,sigset_t*set,
@@ -29,42 +29,6 @@#include<asm/uaccess.h>#include<asm/unistd.h>-structcompat_sigcontext{-/* We always set these two fields to 0 */-compat_ulong_ttrap_no;-compat_ulong_terror_code;--compat_ulong_toldmask;-compat_ulong_tarm_r0;-compat_ulong_tarm_r1;-compat_ulong_tarm_r2;-compat_ulong_tarm_r3;-compat_ulong_tarm_r4;-compat_ulong_tarm_r5;-compat_ulong_tarm_r6;-compat_ulong_tarm_r7;-compat_ulong_tarm_r8;-compat_ulong_tarm_r9;-compat_ulong_tarm_r10;-compat_ulong_tarm_fp;-compat_ulong_tarm_ip;-compat_ulong_tarm_sp;-compat_ulong_tarm_lr;-compat_ulong_tarm_pc;-compat_ulong_tarm_cpsr;-compat_ulong_tfault_address;-};--structcompat_ucontext{-compat_ulong_tuc_flags;-compat_uptr_tuc_link;-compat_stack_tuc_stack;-structcompat_sigcontextuc_mcontext;-compat_sigset_tuc_sigmask;-int__unused[32-(sizeof(compat_sigset_t)/sizeof(int))];-compat_ulong_tuc_regspace[128]__attribute__((__aligned__(8)));-};-structcompat_vfp_sigframe{compat_ulong_tmagic;compat_ulong_tsize;
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:49
Provide the files necessary for building a compat (AArch32) vDSO in
kernel/vdso32.
This is mostly an adaptation of the arm vDSO. The most significant
change in vgettimeofday.c is the use of the arm64 vdso_data struct,
allowing the vDSO data page to be shared between the 32 and 64-bit
vDSOs. Additionally, a different set of barrier macros is used (see
aarch32-barrier.h), as we want to support old 32-bit compilers that
may not support ARMv8 and its new barrier arguments (*ld).
In addition to the time functions, sigreturn trampolines are also
provided, aiming at replacing those in the sigreturn page as the
latter don't provide any unwinding information (and it's easier to
have just one "user code" page). arm-specific unwinding directives are
used, based on glibc's implementation. Symbol offsets are made
available to the kernel using the same method as the 64-bit vDSO.
There is unfortunately an important caveat: we cannot get away with
hand-coding 32-bit instructions like in kernel/kuser32.S, this time we
really need a 32-bit compiler. The compat vDSO Makefile relies on
CROSS_COMPILE_ARM32 to provide a 32-bit compiler, appropriate logic
will be added to the arm64 Makefile later on to ensure that an attempt
to build the compat vDSO is made only if this variable has been set
properly.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
Note regarding the sigreturn trampolines: they should now have proper unwinding
information. I tested them by recompiling glibc to make it use the kernel
sigreturn (instead of setting its own sa_restorer), and then use glibc's
backtrace() inside a signal handler, or in C++ throw an exception from a signal
handler (hopefully nobody actually uses this "feature", but who knows...). Note
that in C, you must compile your application with -fasynchronous-unwind-tables
(which is the default on x86 but not arm), so that backtrace() actually uses the
unwinder to derive the stack trace. gdb is not very useful in this case, because
it has some magic to detect sigreturn trampolines based on the exact sequence of
instructions, and can derive the stack trace from there, without debug/unwinding
information.
The only remaining issue (AFAIK) is that backtrace() doesn't manage to print
the name of the Thumb trampolines, and gdb is also confused (the frame shows up
as "#1 0x... in ?? ()"). This seems to be a bug somewhere in the unwinder (and
gdb can't use its magic instruction matching because it expects slightly
different instructions), but I can't tell for sure. Given their limited use, an
option would be to only keep the ARM trampolines; but for now they will remain
there for compatibility with arch/arm.
arch/arm64/kernel/vdso32/Makefile | 166 ++++++++++++++++
arch/arm64/kernel/vdso32/aarch32-barrier.h | 33 ++++
arch/arm64/kernel/vdso32/sigreturn.S | 76 ++++++++
arch/arm64/kernel/vdso32/vdso.S | 32 ++++
arch/arm64/kernel/vdso32/vdso.lds.S | 93 +++++++++
arch/arm64/kernel/vdso32/vgettimeofday.c | 295 +++++++++++++++++++++++++++++
6 files changed, 695 insertions(+)
create mode 100644 arch/arm64/kernel/vdso32/Makefile
create mode 100644 arch/arm64/kernel/vdso32/aarch32-barrier.h
create mode 100644 arch/arm64/kernel/vdso32/sigreturn.S
create mode 100644 arch/arm64/kernel/vdso32/vdso.S
create mode 100644 arch/arm64/kernel/vdso32/vdso.lds.S
create mode 100644 arch/arm64/kernel/vdso32/vgettimeofday.c
@@ -0,0 +1,166 @@+#+# Building a vDSO image for AArch32.+#+# Author: Kevin Brodsky <kevin.brodsky@arm.com>+# A mix between the arm64 and arm vDSO Makefiles.++CC_ARM32:=$(CROSS_COMPILE_ARM32)gcc++# Same as cc-*option, but using CC_ARM32 instead of CC+cc32-option=$(calltry-run,\+$(CC_ARM32)$(1)-c-xc/dev/null-o"$$TMP",$(1),$(2))+cc32-disable-warning=$(calltry-run,\+$(CC_ARM32)-W$(strip$(1))-c-xc/dev/null-o"$$TMP",-Wno-$(strip$(1)))+cc32-ldoption=$(calltry-run,\+$(CC_ARM32)$(1)-nostdlib-xc/dev/null-o"$$TMP",$(1),$(2))++# We cannot use the global flags to compile the vDSO files, the main reason+# being that the 32-bit compiler may be older than the main (64-bit) compiler+# and therefore may not understand flags set using $(cc-option ...). Besides,+# arch-specific options should be taken from the arm Makefile instead of the+# arm64 one.+# As a result we set our own flags here.++# From top-level Makefile+# NOSTDINC_FLAGS+VDSO_CPPFLAGS:=-nostdinc-isystem$(shell$(CC_ARM32)-print-file-name=include)+VDSO_CPPFLAGS+=$(LINUXINCLUDE)+VDSO_CPPFLAGS+=$(KBUILD_CPPFLAGS)++# Common C and assembly flags+# From top-level Makefile+VDSO_CAFLAGS:=$(VDSO_CPPFLAGS)+VDSO_CAFLAGS+=$(callcc32-option,-fno-PIE)+ifdef CONFIG_DEBUG_INFO+VDSO_CAFLAGS+=-g+endif+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC_ARM32)), y)+VDSO_CAFLAGS+=-DCC_HAVE_ASM_GOTO+endif++# From arm Makefile+VDSO_CAFLAGS+=$(callcc32-option,-fno-dwarf2-cfi-asm)+VDSO_CAFLAGS+=-mabi=aapcs-linux-mfloat-abi=soft+ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)+VDSO_CAFLAGS+=-mbig-endian+else+VDSO_CAFLAGS+=-mlittle-endian+endif++# From arm vDSO Makefile+VDSO_CAFLAGS+=-fPIC-fno-builtin-fno-stack-protector+VDSO_CAFLAGS+=-DDISABLE_BRANCH_PROFILING++# Try to compile for ARMv8. If the compiler is too old and doesn't support it,+# fall back to v7. There is no easy way to check for what architecture the code+# is being compiled, so define a macro specifying that (see arch/arm/Makefile).+VDSO_CAFLAGS+=$(callcc32-option,-march=armv8-a-D__LINUX_ARM_ARCH__=8,\+-march=armv7-a-D__LINUX_ARM_ARCH__=7)++VDSO_CFLAGS:=$(VDSO_CAFLAGS)+# KBUILD_CFLAGS from top-level Makefile+VDSO_CFLAGS+=-Wall-Wundef-Wstrict-prototypes-Wno-trigraphs\+-fno-strict-aliasing-fno-common\+-Werror-implicit-function-declaration\+-Wno-format-security\+-std=gnu89+VDSO_CFLAGS+=-O2+# Some useful compiler-dependent flags from top-level Makefile+VDSO_CFLAGS+=$(callcc32-option,-Wdeclaration-after-statement,)+VDSO_CFLAGS+=$(callcc32-option,-Wno-pointer-sign)+VDSO_CFLAGS+=$(callcc32-option,-fno-strict-overflow)+VDSO_CFLAGS+=$(callcc32-option,-Werror=strict-prototypes)+VDSO_CFLAGS+=$(callcc32-option,-Werror=date-time)+VDSO_CFLAGS+=$(callcc32-option,-Werror=incompatible-pointer-types)++# The 32-bit compiler does not provide 128-bit integers, which are used in+# some headers that are indirectly included from the vDSO code.+# This hack makes the compiler happy and should trigger a warning/error if+# variables of such type are referenced.+VDSO_CFLAGS+=-D__uint128_t='void*'+# Silence some warnings coming from headers that operate on long's+# (on GCC 4.8 or older, there is unfortunately no way to silence this warning)+VDSO_CFLAGS+=$(callcc32-disable-warning,shift-count-overflow)+VDSO_CFLAGS+=-Wno-int-to-pointer-cast++VDSO_AFLAGS:=$(VDSO_CAFLAGS)+VDSO_AFLAGS+=-D__ASSEMBLY__++VDSO_LDFLAGS:=$(VDSO_CPPFLAGS)+# From arm vDSO Makefile+VDSO_LDFLAGS+=-Wl,-Bsymbolic-Wl,--no-undefined-Wl,-soname=linux-vdso.so.1+VDSO_LDFLAGS+=-Wl,-z,max-page-size=4096-Wl,-z,common-page-size=4096+VDSO_LDFLAGS+=-nostdlib-shared-mfloat-abi=soft+VDSO_LDFLAGS+=$(callcc32-ldoption,-Wl$(comma)--hash-style=sysv)+VDSO_LDFLAGS+=$(callcc32-ldoption,-Wl$(comma)--build-id)+VDSO_LDFLAGS+=$(callcc32-ldoption,-fuse-ld=bfd)+++# Borrow vdsomunge.c from the arm vDSO+munge:=arch/arm/vdso/vdsomunge+hostprogs-y:=$(srctree)/$(munge)++c-obj-vdso:=vgettimeofday.o+asm-obj-vdso:=sigreturn.o++# Build rules+targets:=$(c-obj-vdso)$(asm-obj-vdso)vdso.sovdso.so.dbgvdso.so.raw+c-obj-vdso:=$(addprefix$(obj)/,$(c-obj-vdso))+asm-obj-vdso:=$(addprefix$(obj)/,$(asm-obj-vdso))+obj-vdso:=$(c-obj-vdso)$(asm-obj-vdso)++obj-y+=vdso.o+extra-y+=vdso.lds+CPPFLAGS_vdso.lds+=-P-C-U$(ARCH)++# Force dependency (vdso.s includes vdso.so through incbin)+$(obj)/vdso.o:$(obj)/vdso.so++include/generated/vdso32-offsets.h:$(obj)/vdso.so.dbgFORCE+$(callif_changed,vdsosym)++# Strip rule for vdso.so+$(obj)/vdso.so:OBJCOPYFLAGS := -S+$(obj)/vdso.so:$(obj)/vdso.so.dbgFORCE+$(callif_changed,objcopy)++$(obj)/vdso.so.dbg:$(obj)/vdso.so.raw$(objtree)/$(munge)FORCE+$(callif_changed,vdsomunge)++# Link rule for the .so file, .lds has to be first+$(obj)/vdso.so.raw:$(src)/vdso.lds$(obj-vdso)FORCE+$(callif_changed,vdsold)++# Compilation rules for the vDSO sources+$(c-obj-vdso):%.o: %.cFORCE+$(callif_changed_dep,vdsocc)+$(asm-obj-vdso):%.o: %.SFORCE+$(callif_changed_dep,vdsoas)++# Actual build commands+quiet_cmd_vdsold=VDSOL$@+cmd_vdsold=$(CC_ARM32)-Wp,-MD,$(depfile)$(VDSO_LDFLAGS)\+-Wl,-T$(filter%.lds,$^)$(filter%.o,$^)-o$@+quiet_cmd_vdsocc=VDSOC$@+cmd_vdsocc=$(CC_ARM32)-Wp,-MD,$(depfile)$(VDSO_CFLAGS)-c-o$@$<+quiet_cmd_vdsoas=VDSOA$@+cmd_vdsoas=$(CC_ARM32)-Wp,-MD,$(depfile)$(VDSO_AFLAGS)-c-o$@$<++quiet_cmd_vdsomunge=MUNGE$@+cmd_vdsomunge=$(objtree)/$(munge)$<$@++# Generate vDSO offsets using helper script (borrowed from the 64-bit vDSO)+gen-vdsosym:=$(srctree)/$(src)/../vdso/gen_vdso_offsets.sh+quiet_cmd_vdsosym=VDSOSYM$@+# The AArch64 nm should be able to read an AArch32 binary+cmd_vdsosym=$(NM)$<|$(gen-vdsosym)|LC_ALL=Csort>$@++# Install commands for the unstripped file+quiet_cmd_vdso_install=INSTALL$@+cmd_vdso_install=cp$(obj)/$@.dbg$(MODLIB)/vdso/vdso32.so++vdso.so:$(obj)/vdso.so.dbg+@mkdir-p$(MODLIB)/vdso+$(callcmd,vdso_install)++vdso_install:vdso.so
@@ -0,0 +1,76 @@+/*+*SigreturntrampolinesforreturningfromasignalwhentheSA_RESTORER+*flagisnotset.+*+*Copyright (C)2016ARMLimited+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*+*Basedonglibc's arm sa_restorer. While this is not strictly necessary, we+*providebothA32andT32versions,inaccordancewiththearmsigreturn+*code.+*/++#include <linux/linkage.h>+#include <asm/asm-offsets.h>+#include <asm/unistd.h>++.macrosigreturn_trampolinename,syscall,regs_offset+/*+*Weprovidedirectivesforenablingstackunwindingthroughthe+*trampoline.Onarm,CFIdirectivesareonlyusedfordebugging (and+*thevDSOisstrippedofdebuginformation),soonlythearm-specific+*unwindingdirectivesareusefulhere.+*/+.fnstart+.save{r0-r15}+.pad#\regs_offset+/*+*Itisnecessarytostarttheunwindtablesatleastoneinstruction+*beforethetrampoline,astheunwinderwillassumethatthesignal+*handlerhasbeencalledfromthetrampoline,thatisjustbefore+*wherethesignalhandlerreturns (movr7,...).+*/+nop+ENTRY(\name)+movr7,#\syscall+svc#0+.fnend+/*+*WewouldliketouseENDPROC,butthemacrouses@whichisa+*commentsymbolforarmassemblers,sodirectlyuse.typewith%+*instead.+*/+.type\name,%function+END(\name)+.endm++.text++.arm+sigreturn_trampoline__kernel_sigreturn_arm,\+__NR_compat_sigreturn,\+COMPAT_SIGFRAME_REGS_OFFSET++sigreturn_trampoline__kernel_rt_sigreturn_arm,\+__NR_compat_rt_sigreturn,\+COMPAT_RT_SIGFRAME_REGS_OFFSET++.thumb+sigreturn_trampoline__kernel_sigreturn_thumb,\+__NR_compat_sigreturn,\+COMPAT_SIGFRAME_REGS_OFFSET++sigreturn_trampoline__kernel_rt_sigreturn_thumb,\+__NR_compat_rt_sigreturn,\+COMPAT_RT_SIGFRAME_REGS_OFFSET
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:50
If the compat vDSO is enabled, install it in compat processes. In this
case, the compat vDSO replaces the sigreturn page (it provides its own
sigreturn trampolines).
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/kernel/vdso.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:51
If the compat vDSO is enabled, we need to set AT_SYSINFO_EHDR in the
auxiliary vector of compat processes to the address of the vDSO code
page, so that the dynamic linker can find it (just like the regular vDSO).
Note that we cast context.vdso to unsigned long, instead of elf_addr_t,
because elf_addr_t is 32-bit in compat_binfmt_elf.c, and casting to u32
would trigger a pointer narrowing warning.
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/include/asm/elf.h | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
From: Kevin Brodsky <hidden> Date: 2016-12-06 16:03:53
Expose the new compat vDSO via the COMPAT_VDSO config option.
The option is not enabled in defconfig because we really need a 32-bit
compiler this time, and we rely on the user to provide it themselves
by setting CROSS_COMPILE_ARM32. Therefore enabling the option by
default would make little sense, since the user must explicitly set a
non-standard environment variable anyway.
CONFIG_COMPAT_VDSO is not directly used in the code, because we want
to ignore it (build as if it were not set) if the user didn't set
CROSS_COMPILE_ARM32 properly. If the variable has been set to a valid
prefix, CONFIG_VDSO32 will be set; this is the option that the code
and Makefiles test.
For more flexibility, like CROSS_COMPILE, CROSS_COMPILE_ARM32 can also
be set via CONFIG_CROSS_COMPILE_ARM32 (the environment variable
overrides the config option, as expected).
Cc: Will Deacon <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Lynch <redacted>
Cc: Christopher Covington <redacted>
Cc: Dmitry Safonov <redacted>
Cc: Jisheng Zhang <redacted>
Signed-off-by: Kevin Brodsky <redacted>
---
arch/arm64/Kconfig | 23 +++++++++++++++++++++++
arch/arm64/Makefile | 28 ++++++++++++++++++++++++++--
arch/arm64/kernel/Makefile | 8 ++++++--
3 files changed, 55 insertions(+), 4 deletions(-)
@@ -37,10 +37,32 @@ $(warning LSE atomics not supported by binutils) endifendif-KBUILD_CFLAGS+=-mgeneral-regs-only$(lseinstr)+ifeq ($(CONFIG_COMPAT_VDSO), y)+CROSS_COMPILE_ARM32?=$(CONFIG_CROSS_COMPILE_ARM32:"%"=%)++ # Check that the user has provided a valid prefix for the 32-bit toolchain.+ # To prevent selecting the system gcc by default, the prefix is not allowed to+ # be empty, unlike CROSS_COMPILE. In the unlikely event that the system gcc+ # is actually the 32-bit ARM compiler to be used, the variable can be set to+ # the dirname (e.g. CROSS_COMPILE_ARM32=/usr/bin/).+ # Note: this Makefile is read both before and after regenerating the+ # config (if needed). Any warning appearing before the config has been+ # regenerated should be ignored.+ ifeq ($(CROSS_COMPILE_ARM32),)+$(warningCROSS_COMPILE_ARM32notdefinedorempty,thecompatvDSOwillnotbebuilt)+ else ifeq ($(shell which $(CROSS_COMPILE_ARM32)gcc 2> /dev/null),)+$(warning$(CROSS_COMPILE_ARM32)gccnotfound,thecompatvDSOwillnotbebuilt)+ else+exportCROSS_COMPILE_ARM32+exportCONFIG_VDSO32:=y+vdso32:=-DCONFIG_VDSO32=1+ endif+endif++KBUILD_CFLAGS+=-mgeneral-regs-only$(lseinstr)$(vdso32)KBUILD_CFLAGS+=-fno-asynchronous-unwind-tablesKBUILD_CFLAGS+=$(callcc-option,-mpc-relative-literal-loads)-KBUILD_AFLAGS+=$(lseinstr)+KBUILD_AFLAGS+=$(lseinstr)$(vdso32)ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)KBUILD_CPPFLAGS+=-mbig-endian
As I said at LPC last month, I'm not excited to have arch/arm's
vgettimeofday.c copied into arch/arm64 and tweaked; I'd rather see this
part of the implementation shared between arch/arm and arch/arm64
somehow, even if there's not an elegant way to do so.
The situation which must be avoided is one where the arch/arm64 compat
VDSO incompatibly diverges from the arch/arm VDSO. That becomes much
less likely if there's only one copy of the userspace-exposed code to
maintain.
[...]
quoted hunk
+/*+ * We use the hidden visibility to prevent the compiler from generating a GOT+ * relocation. Not only is going through a GOT useless (the entry couldn't and+ * musn't be overridden by another library), it does not even work: the linker+ * cannot generate an absolute address to the data page.+ *+ * With the hidden visibility, the compiler simply generates a PC-relative+ * relocation (R_ARM_REL32), and this is what we need.+ */+extern const struct vdso_data _vdso_data __attribute__((visibility("hidden")));++static inline const struct vdso_data *get_vdso_data(void)+{+ const struct vdso_data *ret;+ /*+ * This simply puts &_vdso_data into ret. The reason why we don't use+ * `ret = &_vdso_data` is that the compiler tends to optimise this in a+ * very suboptimal way: instead of keeping &_vdso_data in a register,+ * it goes through a relocation almost every time _vdso_data must be+ * accessed (even in subfunctions). This is both time and space+ * consuming: each relocation uses a word in the code section, and it+ * has to be loaded at runtime.+ *+ * This trick hides the assignment from the compiler. Since it cannot+ * track where the pointer comes from, it will only use one relocation+ * where get_vdso_data() is called, and then keep the result in a+ * register.+ */+ asm("mov %0, %1" : "=r"(ret) : "r"(&_vdso_data));+ return ret;+}
I think this is an instructive case: this code looks like an improvement
over how the arch/arm VDSO accesses the data page. Enhancements like
this (not to mention fixes) shouldn't require a patch-per-architecture;
things inevitably get out of sync and it's more of a maintenance burden
in the long term.
As I said at LPC last month, I'm not excited to have arch/arm's
vgettimeofday.c copied into arch/arm64 and tweaked; I'd rather see this
part of the implementation shared between arch/arm and arch/arm64
somehow, even if there's not an elegant way to do so.
The situation which must be avoided is one where the arch/arm64 compat
VDSO incompatibly diverges from the arch/arm VDSO. That becomes much
less likely if there's only one copy of the userspace-exposed code to
maintain.
I still agree this is very suboptimal. However, I also think this is by far the most
straightforward solution, and I would like to stick to it *as a first step*. If you
diff this "tweaked" vgettimeofday.c with the original one, you'll see that it is
really not obvious to share even parts of vgettimeofday.c in the current state of arm
and arm64. Besides, arm's vDSO hasn't changed much since it has been introduced last
year, and vgettimeofday.c hasn't changed at all, so I think it's fair to say
divergences are unlikely to happen in the near future.
Nevertheless, I completely agree this is not a good situation in the long run, and I
am not happy with leaving things in this state. After this series is merged, my plan
is to try and align arm and arm64 both in terms of vDSO features and kernel-vDSO
interface. This would notably involve:
* Aligning the vDSO data struct's (especially vdso_data's member names), so that
vgettimeofday.c can be (mostly) shared.
* Non-trivial Makefile work to share the same one between the arm and arm64 compat
vDSOs. The refactoring I did in v3 is a first step, as not using top-level flags
makes it more feasible to share the same Makefile.
* Adding support for CLOCK_MONOTONIC_RAW, as I did in the 64-bit vDSO.
* Moving arm's sigreturn trampolines to its vDSO (if enabled), and convince glibc to
use the kernel's trampolines like on arm64.
This represents a substantial amount of work, which I think should be in a separate
series (this one has already grown bigger than I expected).
The final step would be to investigate whether the 64-bit vDSO could reasonably move
to a C implementation, and if it is the case unify the 3 vDSOs.
[...]
quoted
+/*+ * We use the hidden visibility to prevent the compiler from generating a GOT+ * relocation. Not only is going through a GOT useless (the entry couldn't and+ * musn't be overridden by another library), it does not even work: the linker+ * cannot generate an absolute address to the data page.+ *+ * With the hidden visibility, the compiler simply generates a PC-relative+ * relocation (R_ARM_REL32), and this is what we need.+ */+extern const struct vdso_data _vdso_data __attribute__((visibility("hidden")));++static inline const struct vdso_data *get_vdso_data(void)+{+ const struct vdso_data *ret;+ /*+ * This simply puts &_vdso_data into ret. The reason why we don't use+ * `ret = &_vdso_data` is that the compiler tends to optimise this in a+ * very suboptimal way: instead of keeping &_vdso_data in a register,+ * it goes through a relocation almost every time _vdso_data must be+ * accessed (even in subfunctions). This is both time and space+ * consuming: each relocation uses a word in the code section, and it+ * has to be loaded at runtime.+ *+ * This trick hides the assignment from the compiler. Since it cannot+ * track where the pointer comes from, it will only use one relocation+ * where get_vdso_data() is called, and then keep the result in a+ * register.+ */+ asm("mov %0, %1" : "=r"(ret) : "r"(&_vdso_data));+ return ret;+}
I think this is an instructive case: this code looks like an improvement
over how the arch/arm VDSO accesses the data page. Enhancements like
this (not to mention fixes) shouldn't require a patch-per-architecture;
things inevitably get out of sync and it's more of a maintenance burden
in the long term.
What arm does is suboptimal indeed, as it uses a whole function to derive vdso_data's
address instead of a simple relocation. However both methods are functionally
equivalent. The approach I used here is simply consistent with how vdso_data is
accessed in the 64-bit vDSO (with those two tricks because of both an assembler
difference and the fact we are using C here, and GCC is not being smart). Again, I
agree the arm vDSO should use the same approach, but unification requires other
changes beyond the scope of this first series.
Thanks,
Kevin
As I said at LPC last month, I'm not excited to have arch/arm's
vgettimeofday.c copied into arch/arm64 and tweaked; I'd rather see this
part of the implementation shared between arch/arm and arch/arm64
somehow, even if there's not an elegant way to do so.
The situation which must be avoided is one where the arch/arm64 compat
VDSO incompatibly diverges from the arch/arm VDSO. That becomes much
less likely if there's only one copy of the userspace-exposed code to
maintain.
I still agree this is very suboptimal. However, I also think this is by far the most
straightforward solution, and I would like to stick to it *as a first step*. If you
diff this "tweaked" vgettimeofday.c with the original one, you'll see that it is
really not obvious to share even parts of vgettimeofday.c in the current state of arm
and arm64.
After adapting your get_vdso_data() to arch/arm/vdso, I come up with the
differences below, which seems surmountable mostly with the addition of
appropriate accessor functions for the data page, or changing the field
names to match. So I can't say I'm persuaded.
I'm happy to review and facilitate changes to code in arch/arm/vdso to
make it possible to share it with arm64 for its compat VDSO.
vgettimeofday.c | 84 ++++++++++++++++++++++++--------------------------------
1 file changed, 37 insertions(+), 47 deletions(-)
@@ -15,20 +15,23 @@*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.*/+#include<linux/clocksource.h>#include<linux/compiler.h>-#include<linux/hrtimer.h>#include<linux/time.h>-#include<asm/arch_timer.h>-#include<asm/barrier.h>-#include<asm/bug.h>-#include<asm/page.h>#include<asm/unistd.h>#include<asm/vdso_datapage.h>-#ifndef CONFIG_AEABI-#error This code depends on AEABI system call conventions-#endif+#include"aarch32-barrier.h"+/*+*WeusethehiddenvisibilitytopreventthecompilerfromgeneratingaGOT+*relocation.NotonlyisgoingthroughaGOTuseless(theentrycouldn'tand+*musn'tbeoverriddenbyanotherlibrary),itdoesnotevenwork:thelinker+*cannotgenerateanabsoluteaddresstothedatapage.+*+*Withthehiddenvisibility,thecompilersimplygeneratesaPC-relative+*relocation(R_ARM_REL32),andthisiswhatweneed.+*/externconststructvdso_data_vdso_data__attribute__((visibility("hidden")));staticinlineconststructvdso_data*get_vdso_data(void)
@@ -72,26 +73,30 @@seq=__vdso_read_begin(vdata);-smp_rmb();/* Pairs with smp_wmb in vdso_write_end */+aarch32_smp_rmb();returnseq;}staticnotraceintvdso_read_retry(conststructvdso_data*vdata,u32start){-smp_rmb();/* Pairs with smp_wmb in vdso_write_begin */-returnvdata->seq_count!=start;+aarch32_smp_rmb();+returnvdata->tb_seq_count!=start;}+/*+*Note:onlyAEABIissupportedbythecompatlayer,wecanassumeAEABI+*syscallconventionsareused.+*/staticnotracelongclock_gettime_fallback(clockid_t_clkid,structtimespec*_ts){registerstructtimespec*tsasm("r1")=_ts;registerclockid_tclkidasm("r0")=_clkid;registerlongretasm("r0");-registerlongnrasm("r7")=__NR_clock_gettime;+registerlongnrasm("r7")=__NR_compat_clock_gettime;asmvolatile(-" swi #0\n"+" svc #0\n":"=r"(ret):"r"(clkid),"r"(ts),"r"(nr):"memory");
From: Will Deacon <hidden> Date: 2017-02-17 17:16:34
On Tue, Dec 06, 2016 at 04:03:42PM +0000, Kevin Brodsky wrote:
Hi,
Hi Kevin,
This series adds support for a compat (AArch32) vDSO, providing two
userspace functionalities to compat processes:
* "Virtual" time syscalls (gettimeofday and clock_gettime). The
implementation is an adaptation of the arm vDSO (vgettimeofday.c),
sharing the data page with the 64-bit vDSO.
* sigreturn trampolines, following the example of the 64-bit vDSO
(sigreturn.S), but slightly more complicated because we provide A32
and T32 variants for both sigreturn and rt_sigreturn, and appropriate
arm-specific unwinding directives.
The first point brings the performance improvement expected of a vDSO,
by implementing time syscalls directly in userspace. The second point
allows to provide unwinding information for sigreturn trampolines,
achieving feature parity with the trampolines provided by glibc.
Unfortunately, this time we cannot escape using a 32-bit toolchain. To
build the compat VDSO, CONFIG_COMPAT_VDSO must be set *and*
CROSS_COMPILE_ARM32 must be defined to the prefix of a 32-bit compiler.
Failure to do so will not prevent building the kernel, but a warning
will be printed and the compat vDSO will not be built.
v3 is a major refactor of the series. The main change is that the kuser
helpers are no longer mutually exclusive with the 32-bit vDSO, and can
be disabled independently of the 32-bit vDSO (they are kept enabled by
default). To this end, the "old" sigreturn trampolines have been moved
out of the [vectors] page into an independent [sigreturn] page, similar
to [sigpage] on arm. The [vectors] page is now [kuserhelpers], and its
presence is controlled by CONFIG_KUSER_HELPERS. The [sigreturn] page is
only present when the 32-bit vDSO is not included (the latter provides
its own sigreturn trampolines with unwinding information). The following
table summarises which pages are now added in 32-bit processes:
+----------------+----------------+----------------+
| CONFIG | !VDSO32 | VDSO32 |
+----------------+----------------+----------------+
| !KUSER_HELPERS | [sigreturn] | [vvar] |
| | | [vdso] |
+----------------+----------------+----------------+
| KUSER_HELPERS | [sigreturn] | [vvar] |
| | [kuserhelpers] | [vdso] |
| | | [kuserhelpers] |
+----------------+----------------+----------------+
Why is this different to arch/arm/? The idea of the COMPAT layer is to
do the same thing as arch/arm, so we should use [sigpage] and [vectors]
instead of [sigreturn] and [kuserhelpers]. I also think that the /proc/maps
code assumes the "gate vma" is at the end, but that's more of a niggle
than anything else.
The big issue with this series is that I share Nathan's concerns that we're
needlessly forking code from arch/arm/, without a commitment to follow up
with the refactoring effort. So, whilst I can see that technically this is
looking pretty solid, it's a big ask to merge this into mainline as-is.
Will