Skip to contentSkip to conversation

ARM: vDSO gettimeofday using generic timer architecture

PATCH Superseded Nathan Lynch 4 participants 8 messages Feb 7, 2014 – Feb 11, 2014

Subsystems (3)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7. This follows the example of arm64 in conception but significantly differs in some aspects of the implementation (C vs assembly, mainly).

Clocks supported:
- CLOCK_REALTIME
- CLOCK_MONOTONIC
- CLOCK_REALTIME_COARSE
- CLOCK_MONOTONIC_COARSE

This also provides clock_getres (as arm64 does).

Tested on OMAP5, i.MX6, and qemu/versatilepb using a LD_PRELOAD shim to redirect system calls to the vDSO. I plan to undertake adding proper support to glibc if the overall approach is acceptable.

Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for clock_getres and coarse clocks is independent of the timer implementation and is provided unconditionally.

---

Changes since v1:
- update to 3.14-rc1
- ensure cache coherency for data page
- Document the kernel-to-userspace protocol for vdso data page updates, and note that the timekeeping core prevents concurrent updates.
- update wall-to-monotonic fields unconditionally
- move vdso_start, vdso_end declarations to vdso.h
- correctly build and run when CONFIG_ARM_ARCH_TIMER=n
- rearrange linker script to avoid overlapping sections when CONFIG_DEBUGINFO=n
- remove use_syscall checks from coarse clock paths
- crib BUG_INSTR (0xe7f001f2) from asm/bug.h for text fill

 arch/arm/Kconfig                     |   1 +
 arch/arm/include/asm/arch_timer.h    |   7 +-
 arch/arm/include/asm/auxvec.h        |   7 +
 arch/arm/include/asm/elf.h           |   6 +
 arch/arm/include/asm/mmu.h           |   1 +
 arch/arm/include/asm/vdso.h          |  28 ++++
 arch/arm/include/asm/vdso_datapage.h |  45 +++++
 arch/arm/kernel/Makefile             |   3 +-
 arch/arm/kernel/process.c            |  16 +-
 arch/arm/kernel/vdso.c               | 177 ++++++++++++++++++++
 arch/arm/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  46 ++++++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  87 ++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 312 +++++++++++++++++++++++++++++++++++
 15 files changed, 766 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/include/asm/auxvec.h
 create mode 100644 arch/arm/include/asm/vdso.h
 create mode 100644 arch/arm/include/asm/vdso_datapage.h
 create mode 100644 arch/arm/kernel/vdso.c
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c
arch/arm/Kconfig +1 -0
index e25419817791..556e5b616f61 100644
@@ -23,6 +23,7 @@ config ARM
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
 	select HAVE_ARCH_KGDB
arch/arm/include/asm/arch_timer.h +5 -2
index 0704e0cf5571..047c800b57f0 100644
@@ -103,13 +103,16 @@ static inline void arch_counter_set_user_access(void)
 {
 	u32 cntkctl = arch_timer_get_cntkctl();
 
-	/* Disable user access to both physical/virtual counters/timers */
+	/* Disable user access to the timers and the physical counter */
 	/* Also disable virtual event stream */
 	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
 			| ARCH_TIMER_USR_VT_ACCESS_EN
 			| ARCH_TIMER_VIRT_EVT_EN
-			| ARCH_TIMER_USR_VCT_ACCESS_EN
 			| ARCH_TIMER_USR_PCT_ACCESS_EN);
+
+	/* Enable user access to the virtual counter */
+	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+
 	arch_timer_set_cntkctl(cntkctl);
 }
 
arch/arm/include/asm/auxvec.h new file +7 -0
new file mode 100644
index 000000000000..f56936b97ec2
@@ -0,0 +1,7 @@
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* vDSO location */
+#define AT_SYSINFO_EHDR	33
+
+#endif
arch/arm/include/asm/elf.h +6 -0
index f4b46d39b9cf..b8d099264000 100644
@@ -1,6 +1,7 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <asm/auxvec.h>
 #include <asm/hwcap.h>
 
 /*
@@ -129,6 +130,11 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
 #ifdef CONFIG_MMU
+#define ARCH_DLINFO							\
+do {									\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
+		    (elf_addr_t)current->mm->context.vdso);		\
+} while (0)
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
 int arch_setup_additional_pages(struct linux_binprm *, int);
arch/arm/include/asm/mmu.h +1 -0
index 64fd15159b7d..1ee0f42a3b26 100644
@@ -11,6 +11,7 @@ typedef struct {
 #endif
 	unsigned int	vmalloc_seq;
 	unsigned long	sigpage;
+	unsigned long	vdso;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
arch/arm/include/asm/vdso.h new file +28 -0
new file mode 100644
index 000000000000..6c89ed88e689
@@ -0,0 +1,28 @@
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/mm_types.h>
+#include <asm/mmu.h>
+
+static inline bool vma_is_vdso(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso)
+		return true;
+	return false;
+}
+
+void arm_install_vdso(void);
+
+extern char vdso_start, vdso_end;
+
+#endif /* __ASSEMBLY__ */
+
+#define VDSO_LBASE	0x0
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
arch/arm/include/asm/vdso_datapage.h new file +45 -0

45 lines not on this page · raw message

arch/arm/kernel/Makefile +2 -1
index a30fc9be9e9e..9e785550b307 100644
@@ -18,7 +18,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 obj-y		:= elf.o entry-common.o irq.o opcodes.o \
 		   process.o ptrace.o return_address.o \
 		   setup.o signal.o sigreturn_codes.o \
-		   stacktrace.o sys_arm.o time.o traps.o
+		   stacktrace.o sys_arm.o time.o traps.o \
+		   vdso.o vdso/
 
 obj-$(CONFIG_ATAGS)		+= atags_parse.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags_proc.o
arch/arm/kernel/process.c +13 -3
index 92f7b15dd221..9907227adf92 100644
@@ -41,6 +41,7 @@
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
 #include <asm/tls.h>
+#include <asm/vdso.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -472,9 +473,16 @@ int in_gate_area_no_mm(unsigned long addr)
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-	return is_gate_vma(vma) ? "[vectors]" :
-		(vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
-		 "[sigpage]" : NULL;
+	if (is_gate_vma(vma))
+		return "[vectors]";
+
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage)
+		return "[sigpage]";
+
+	if (vma_is_vdso(vma))
+		return "[vdso]";
+
+	return NULL;
 }
 
 static struct page *signal_page;
@@ -505,6 +513,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (ret == 0)
 		mm->context.sigpage = addr;
 
+	arm_install_vdso();
+
  up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
arch/arm/kernel/vdso.c new file +177 -0

177 lines not on this page · raw message

arch/arm/kernel/vdso/.gitignore new file +1 -0
new file mode 100644
index 000000000000..f8b69d84238e
@@ -0,0 +1 @@
+vdso.lds
arch/arm/kernel/vdso/Makefile new file +46 -0

46 lines not on this page · raw message

arch/arm/kernel/vdso/vdso.S new file +35 -0
new file mode 100644
index 000000000000..aed16ff84c5f
@@ -0,0 +1,35 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_start, vdso_end
+	.balign PAGE_SIZE
+vdso_start:
+	.incbin "arch/arm/kernel/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
arch/arm/kernel/vdso/vdso.lds.S new file +87 -0

87 lines not on this page · raw message

arch/arm/kernel/vdso/vgettimeofday.c new file +312 -0

312 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#1 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

arch/arm/kernel/vdso.c line 79

Quoted 11 lines
arch/arm/kernel/vdso.c new file +11 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

arch/arm/kernel/vdso.c line 84

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+	/* Grab the vDSO data page. */
+	pg = virt_to_page(vdso_data);
+	get_page(pg);
+	vdso_pagelist[i] = pg;

Same goes for this.

arch/arm/kernel/vdso/vgettimeofday.c line 65

Quoted 8 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +8 -0
+static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_gettime;
+
+	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");

This isn't compatible with OABI, so either this must not be enabled when AEABI is disabled, or this needs to be fixed.

arch/arm/kernel/vdso/vgettimeofday.c line 244

Quoted 12 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +12 -0
+static long clock_getres_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_getres;
+
+	asm volatile(
+		"swi #0" :
+		"=r" (ret) :
+		"r" (clkid), "r" (ts), "r" (nr) :
+		"memory");

Same here.

arch/arm/kernel/vdso/vgettimeofday.c line 285

Quoted 8 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +8 -0
+static long gettimeofday_fallback(struct timeval *_tv, struct timezone *_tz)
+{
+	register struct timezone *tz asm("r1") = _tz;
+	register struct timeval *tv asm("r0") = _tv;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_gettimeofday;
+
+	asm("swi #0" : "=r" (ret) : "r" (tv), "r" (tz), "r" (nr) : "memory");

and here.

Signature · 3 lines
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
#2 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Hi Russell,

Quoted 12 lines · Russell King - ARM Linux

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

This looks like it was inherited from the PowerPC code where the behaviour of set_pte_at would change dependent on whether or not the page was reserved (set_pte_at->set_pte_filter->maybe_pte_to_page). I think we can safely remove this from ARM and ARM64.

Quoted 7 lines
Quoted 7 lines
arch/arm/kernel/vdso.c new file +7 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
Quoted 9 lines

arch/arm/kernel/vdso.c line 79

Quoted 4 lines
arch/arm/kernel/vdso.c new file +4 -0
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

This is a dress rehersal for install_special_mapping more than anything. If we map the page, and look at the first 4 bytes, are they what we expect?

Quoted 8 lines

arch/arm/kernel/vdso.c line 84

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+	/* Grab the vDSO data page. */
+	pg = virt_to_page(vdso_data);
+	get_page(pg);
+	vdso_pagelist[i] = pg;

Same goes for this.

We need the data page so we can remap it into user space via install_special_mapping.

Cheers,

Signature · 1 line
Steve
#3 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Quoted 16 lines · Steve Capper

Hi Russell,

Quoted 12 lines · Russell King - ARM Linux

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

Quoted 4 lines

This looks like it was inherited from the PowerPC code where the behaviour of set_pte_at would change dependent on whether or not the page was reserved (set_pte_at->set_pte_filter->maybe_pte_to_page). I think we can safely remove this from ARM and ARM64.

Great, so we can get rid of that and the get_page() on the vdso data page below.

Quoted 17 lines
Quoted 7 lines
Quoted 7 lines
arch/arm/kernel/vdso.c new file +7 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
Quoted 9 lines

arch/arm/kernel/vdso.c line 79

Quoted 4 lines
arch/arm/kernel/vdso.c new file +4 -0
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

Quoted 3 lines

This is a dress rehersal for install_special_mapping more than anything. If we map the page, and look at the first 4 bytes, are they what we expect?

My point is that we can already view this page directly by dereferencing vdso_start - do we really need to perform this apparant test of the MMU? If the MMU isn't working in this way, we have much bigger and more fundamental problems...

Signature · 3 lines
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
#4 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Quoted 42 lines · Russell King - ARM Linux
Quoted 16 lines · Steve Capper

Hi Russell,

Quoted 12 lines · Russell King - ARM Linux

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

Quoted 4 lines

This looks like it was inherited from the PowerPC code where the behaviour of set_pte_at would change dependent on whether or not the page was reserved (set_pte_at->set_pte_filter->maybe_pte_to_page). I think we can safely remove this from ARM and ARM64.

Great, so we can get rid of that and the get_page() on the vdso data page below.

Quoted 17 lines
Quoted 16 lines

arch/arm/kernel/vdso.c line 79

Quoted 11 lines
arch/arm/kernel/vdso.c new file +11 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

Quoted 9 lines
Quoted 3 lines

This is a dress rehersal for install_special_mapping more than anything. If we map the page, and look at the first 4 bytes, are they what we expect?

My point is that we can already view this page directly by dereferencing vdso_start - do we really need to perform this apparant test of the MMU? If the MMU isn't working in this way, we have much bigger and more fundamental problems...

I see, yes I think people would notice the MMU not working :-). This code also tests the alignment of vdso_start in a roundabout way. I'm not sure whether or not an explicit alignment check to PAGE_SIZE would be beneficial instead of the test mapping.

Cheers,

Signature · 1 line
Steve
#5 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

In reply to Russell King - ARM Linux
Quoted 12 lines · Russell King - ARM Linux

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

Quoted 15 lines

arch/arm/kernel/vdso.c line 79

Quoted 11 lines
arch/arm/kernel/vdso.c new file +11 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

Right, this stuff doesn't appear to be necessary. Removed the vmap, get_page, and ClearPageReserved calls for v3.

Quoted 11 lines

arch/arm/kernel/vdso/vgettimeofday.c line 65

Quoted 8 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +8 -0
+static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_gettime;
+
+	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");

This isn't compatible with OABI, so either this must not be enabled when AEABI is disabled, or this needs to be fixed.

Okay. I'll plan on making the vdso code depend on CONFIG_AEABI, likely indirectly via a CONFIG_VDSO Kconfig option. Since you'll need an updated C library to actually benefit from the vdso, I doubt any OABI support in this code would get any use.

Thanks for reviewing.

#6 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Quoted 29 lines · Nathan Lynch
Quoted 12 lines · Russell King - ARM Linux

arch/arm/kernel/vdso.c line 68

Quoted 7 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +7 -0
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}

Why do we want to clear the reserved status? This looks over complicated to me.

Quoted 15 lines

arch/arm/kernel/vdso.c line 79

Quoted 11 lines
arch/arm/kernel/vdso.c new file +11 -0
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}

Why do we need to vmap() pages which are already accessible - vdso_start must be part of the kernel image, and therefore will be accessible via standard mappings.

Quoted 2 lines

Right, this stuff doesn't appear to be necessary. Removed the vmap, get_page, and ClearPageReserved calls for v3.

Can you make the corresponding change for arm64 too, please?

Quoted 8 lines
Quoted 8 lines

arch/arm/kernel/vdso/vgettimeofday.c line 65

Quoted 8 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +8 -0
+static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_gettime;
+
+	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");

Might be worth making this volatile, rather than depend on the use of ret.

Also, placing both _clkid and ret into "r0" worries me slightly -- is GCC smart enough to realise that writing to ret kills _clkid?

Will

#7 lore raw

PATCH v2 1/1 ARM: vDSO gettimeofday using generic timer architecture

Quoted 6 lines · Will Deacon
Quoted 3 lines · Nathan Lynch

Right, this stuff doesn't appear to be necessary. Removed the vmap, get_page, and ClearPageReserved calls for v3.

Can you make the corresponding change for arm64 too, please?

Yes, will do.

Quoted 10 lines
Quoted 8 lines
Quoted 8 lines

arch/arm/kernel/vdso/vgettimeofday.c line 65

Quoted 8 lines
arch/arm/kernel/vdso/vgettimeofday.c new file +8 -0
+static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_gettime;
+
+	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");

Might be worth making this volatile, rather than depend on the use of ret.

Okay.

Quoted 2 lines

Also, placing both _clkid and ret into "r0" worries me slightly -- is GCC smart enough to realise that writing to ret kills _clkid?

I pretty much lifted this from an example in the GCC manual:

     register int *p1 asm ("r0") = ...;
     register int *p2 asm ("r1") = ...;
     register int *result asm ("r0");
     asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));

http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Extended-Asm.html

I guess it doesn't directly answer your concern, but it's an indication that GCC developers have this use case in mind.