* [PATCH v6 01/14] vdso/datastore: Reduce scope of some variables in vvar_fault()
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
@ 2026-03-04 7:48 ` Thomas Weißschuh
2026-03-04 8:10 ` Christophe Leroy (CS GROUP)
2026-03-04 7:48 ` [PATCH v6 02/14] vdso/datastore: Drop inclusion of linux/mmap_lock.h Thomas Weißschuh
` (13 subsequent siblings)
14 siblings, 1 reply; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:48 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
These variables are only used inside a single branch.
Move their declarations there.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
---
lib/vdso/datastore.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index a565c30c71a0..2cca4e84e5b5 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -41,8 +41,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct page *timens_page = find_timens_vvar_page(vma);
- unsigned long addr, pfn;
- vm_fault_t err;
+ unsigned long pfn;
switch (vmf->pgoff) {
case VDSO_TIME_PAGE_OFFSET:
@@ -54,6 +53,9 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
* Fault in VVAR page too, since it will be accessed
* to get clock data anyway.
*/
+ unsigned long addr;
+ vm_fault_t err;
+
addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE;
err = vmf_insert_pfn(vma, addr, pfn);
if (unlikely(err & VM_FAULT_ERROR))
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 01/14] vdso/datastore: Reduce scope of some variables in vvar_fault()
2026-03-04 7:48 ` [PATCH v6 01/14] vdso/datastore: Reduce scope of some variables in vvar_fault() Thomas Weißschuh
@ 2026-03-04 8:10 ` Christophe Leroy (CS GROUP)
0 siblings, 0 replies; 19+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-04 8:10 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Vincenzo Frascino,
Arnd Bergmann, David S. Miller, Andreas Larsson, Nick Alcock,
John Stultz, Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390
Le 04/03/2026 à 08:48, Thomas Weißschuh a écrit :
> These variables are only used inside a single branch.
>
> Move their declarations there.
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> Tested-by: Andreas Larsson <andreas@gaisler.com>
> Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> lib/vdso/datastore.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
> index a565c30c71a0..2cca4e84e5b5 100644
> --- a/lib/vdso/datastore.c
> +++ b/lib/vdso/datastore.c
> @@ -41,8 +41,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> struct page *timens_page = find_timens_vvar_page(vma);
> - unsigned long addr, pfn;
> - vm_fault_t err;
> + unsigned long pfn;
>
> switch (vmf->pgoff) {
> case VDSO_TIME_PAGE_OFFSET:
> @@ -54,6 +53,9 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> * Fault in VVAR page too, since it will be accessed
> * to get clock data anyway.
> */
> + unsigned long addr;
> + vm_fault_t err;
> +
> addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE;
> err = vmf_insert_pfn(vma, addr, pfn);
> if (unlikely(err & VM_FAULT_ERROR))
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 02/14] vdso/datastore: Drop inclusion of linux/mmap_lock.h
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
2026-03-04 7:48 ` [PATCH v6 01/14] vdso/datastore: Reduce scope of some variables in vvar_fault() Thomas Weißschuh
@ 2026-03-04 7:48 ` Thomas Weißschuh
2026-03-04 8:11 ` Christophe Leroy (CS GROUP)
2026-03-04 7:49 ` [PATCH v6 03/14] vdso/datastore: Allocate data pages dynamically Thomas Weißschuh
` (12 subsequent siblings)
14 siblings, 1 reply; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:48 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
This header is unnecessary and together with some upcoming changes would
introduce compiler warnings.
Link: https://lore.kernel.org/lkml/20250916-mm-rcuwait-v1-1-39a3beea6ec3@linutronix.de/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
---
lib/vdso/datastore.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index 2cca4e84e5b5..7377fcb6e1df 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/linkage.h>
-#include <linux/mmap_lock.h>
#include <linux/mm.h>
#include <linux/time_namespace.h>
#include <linux/types.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 02/14] vdso/datastore: Drop inclusion of linux/mmap_lock.h
2026-03-04 7:48 ` [PATCH v6 02/14] vdso/datastore: Drop inclusion of linux/mmap_lock.h Thomas Weißschuh
@ 2026-03-04 8:11 ` Christophe Leroy (CS GROUP)
0 siblings, 0 replies; 19+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-04 8:11 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Vincenzo Frascino,
Arnd Bergmann, David S. Miller, Andreas Larsson, Nick Alcock,
John Stultz, Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390
Le 04/03/2026 à 08:48, Thomas Weißschuh a écrit :
> This header is unnecessary and together with some upcoming changes would
> introduce compiler warnings.
>
> Link: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Flkml%2F20250916-mm-rcuwait-v1-1-39a3beea6ec3%40linutronix.de%2F&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C8f791d1218bb4befc3d908de79c289b8%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C639082073628618434%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=xxp2D4fWK%2Fd9%2BhcwfbD7s7ft5l773T3LhRdnchXga28%3D&reserved=0
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> Tested-by: Andreas Larsson <andreas@gaisler.com>
> Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> lib/vdso/datastore.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
> index 2cca4e84e5b5..7377fcb6e1df 100644
> --- a/lib/vdso/datastore.c
> +++ b/lib/vdso/datastore.c
> @@ -1,7 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0-only
>
> #include <linux/linkage.h>
> -#include <linux/mmap_lock.h>
> #include <linux/mm.h>
> #include <linux/time_namespace.h>
> #include <linux/types.h>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 03/14] vdso/datastore: Allocate data pages dynamically
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
2026-03-04 7:48 ` [PATCH v6 01/14] vdso/datastore: Reduce scope of some variables in vvar_fault() Thomas Weißschuh
2026-03-04 7:48 ` [PATCH v6 02/14] vdso/datastore: Drop inclusion of linux/mmap_lock.h Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 8:49 ` Christophe Leroy (CS GROUP)
2026-03-04 7:49 ` [PATCH v6 04/14] sparc64: vdso: Link with -z noexecstack Thomas Weißschuh
` (11 subsequent siblings)
14 siblings, 1 reply; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
Allocating the data pages as part of the kernel image does not work on
SPARC. The MMU will through a fault when userspace tries to access them.
Allocate the data pages through the page allocator instead.
Unused pages in the vDSO VMA are still allocated to keep the virtual
addresses aligned. Switch the mapping from PFNs to 'struct page' as that
is required for dynamically allocated pages.
This also aligns the allocation of the datapages with the code
pages and is a prerequisite for mlockall() support.
VM_MIXEDMAP is necessary for the call to vmf_insert_page() in the timens
prefault path to work.
The data pages need to be order-0, non-compound pages so that the
mapping to userspace and the different orderings work.
These pages are also used by the timekeeping, random pool and
architecture initialization code. Some of these are running before the
page allocator is available. To keep these subsytems working without
changes, introduce early, statically data storage which will then
replaced by the real one as soon as that is available.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
include/linux/vdso_datastore.h | 6 +++
init/main.c | 2 +
lib/vdso/datastore.c | 92 +++++++++++++++++++++++++++---------------
3 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/include/linux/vdso_datastore.h b/include/linux/vdso_datastore.h
index a91fa24b06e0..0b530428db71 100644
--- a/include/linux/vdso_datastore.h
+++ b/include/linux/vdso_datastore.h
@@ -2,9 +2,15 @@
#ifndef _LINUX_VDSO_DATASTORE_H
#define _LINUX_VDSO_DATASTORE_H
+#ifdef CONFIG_HAVE_GENERIC_VDSO
#include <linux/mm_types.h>
extern const struct vm_special_mapping vdso_vvar_mapping;
struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned long addr);
+void __init vdso_setup_data_pages(void);
+#else /* !CONFIG_HAVE_GENERIC_VDSO */
+static inline void vdso_setup_data_pages(void) { }
+#endif /* CONFIG_HAVE_GENERIC_VDSO */
+
#endif /* _LINUX_VDSO_DATASTORE_H */
diff --git a/init/main.c b/init/main.c
index 1cb395dd94e4..de867b2693d2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -105,6 +105,7 @@
#include <linux/ptdump.h>
#include <linux/time_namespace.h>
#include <linux/unaligned.h>
+#include <linux/vdso_datastore.h>
#include <net/net_namespace.h>
#include <asm/io.h>
@@ -1119,6 +1120,7 @@ void start_kernel(void)
srcu_init();
hrtimers_init();
softirq_init();
+ vdso_setup_data_pages();
timekeeping_init();
time_init();
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index 7377fcb6e1df..faebf5b7cd6e 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -1,52 +1,79 @@
// SPDX-License-Identifier: GPL-2.0-only
-#include <linux/linkage.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
#include <linux/mm.h>
#include <linux/time_namespace.h>
#include <linux/types.h>
#include <linux/vdso_datastore.h>
#include <vdso/datapage.h>
-/*
- * The vDSO data page.
- */
+static u8 vdso_initdata[VDSO_NR_PAGES * PAGE_SIZE] __aligned(PAGE_SIZE) __initdata = {};
+
#ifdef CONFIG_GENERIC_GETTIMEOFDAY
-static union {
- struct vdso_time_data data;
- u8 page[PAGE_SIZE];
-} vdso_time_data_store __page_aligned_data;
-struct vdso_time_data *vdso_k_time_data = &vdso_time_data_store.data;
-static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE);
+struct vdso_time_data *vdso_k_time_data __refdata =
+ (void *)&vdso_initdata[VDSO_TIME_PAGE_OFFSET * PAGE_SIZE];
+
+static_assert(sizeof(struct vdso_time_data) <= PAGE_SIZE);
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
#ifdef CONFIG_VDSO_GETRANDOM
-static union {
- struct vdso_rng_data data;
- u8 page[PAGE_SIZE];
-} vdso_rng_data_store __page_aligned_data;
-struct vdso_rng_data *vdso_k_rng_data = &vdso_rng_data_store.data;
-static_assert(sizeof(vdso_rng_data_store) == PAGE_SIZE);
+struct vdso_rng_data *vdso_k_rng_data __refdata =
+ (void *)&vdso_initdata[VDSO_RNG_PAGE_OFFSET * PAGE_SIZE];
+
+static_assert(sizeof(struct vdso_rng_data) <= PAGE_SIZE);
#endif /* CONFIG_VDSO_GETRANDOM */
#ifdef CONFIG_ARCH_HAS_VDSO_ARCH_DATA
-static union {
- struct vdso_arch_data data;
- u8 page[VDSO_ARCH_DATA_SIZE];
-} vdso_arch_data_store __page_aligned_data;
-struct vdso_arch_data *vdso_k_arch_data = &vdso_arch_data_store.data;
+struct vdso_arch_data *vdso_k_arch_data __refdata =
+ (void *)&vdso_initdata[VDSO_ARCH_PAGES_START * PAGE_SIZE];
#endif /* CONFIG_ARCH_HAS_VDSO_ARCH_DATA */
+void __init vdso_setup_data_pages(void)
+{
+ unsigned int order = get_order(VDSO_NR_PAGES * PAGE_SIZE);
+ struct page *pages;
+
+ /*
+ * Allocate the data pages dynamically. SPARC does not support mapping
+ * static pages to be mapped into userspace.
+ * It is also a requirement for mlockall() support.
+ *
+ * Do not use folios. In time namespaces the pages are mapped in a different order
+ * to userspace, which is not handled by the folio optimizations in finish_fault().
+ */
+ pages = alloc_pages(GFP_KERNEL, order);
+ if (!pages)
+ panic("Unable to allocate VDSO storage pages");
+
+ /* The pages are mapped one-by-one into userspace and each one needs to be refcounted. */
+ split_page(pages, order);
+
+ /* Move the data already written by other subsystems to the new pages */
+ memcpy(page_address(pages), vdso_initdata, VDSO_NR_PAGES * PAGE_SIZE);
+
+ if (IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY))
+ vdso_k_time_data = page_address(pages + VDSO_TIME_PAGE_OFFSET);
+
+ if (IS_ENABLED(CONFIG_VDSO_GETRANDOM))
+ vdso_k_rng_data = page_address(pages + VDSO_RNG_PAGE_OFFSET);
+
+ if (IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA))
+ vdso_k_arch_data = page_address(pages + VDSO_ARCH_PAGES_START);
+}
+
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
struct vm_area_struct *vma, struct vm_fault *vmf)
{
- struct page *timens_page = find_timens_vvar_page(vma);
- unsigned long pfn;
+ struct page *page, *timens_page;
+
+ timens_page = find_timens_vvar_page(vma);
switch (vmf->pgoff) {
case VDSO_TIME_PAGE_OFFSET:
if (!IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY))
return VM_FAULT_SIGBUS;
- pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
+ page = virt_to_page(vdso_k_time_data);
if (timens_page) {
/*
* Fault in VVAR page too, since it will be accessed
@@ -56,10 +83,10 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
vm_fault_t err;
addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE;
- err = vmf_insert_pfn(vma, addr, pfn);
+ err = vmf_insert_page(vma, addr, page);
if (unlikely(err & VM_FAULT_ERROR))
return err;
- pfn = page_to_pfn(timens_page);
+ page = timens_page;
}
break;
case VDSO_TIMENS_PAGE_OFFSET:
@@ -72,24 +99,25 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
*/
if (!IS_ENABLED(CONFIG_TIME_NS) || !timens_page)
return VM_FAULT_SIGBUS;
- pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
+ page = virt_to_page(vdso_k_time_data);
break;
case VDSO_RNG_PAGE_OFFSET:
if (!IS_ENABLED(CONFIG_VDSO_GETRANDOM))
return VM_FAULT_SIGBUS;
- pfn = __phys_to_pfn(__pa_symbol(vdso_k_rng_data));
+ page = virt_to_page(vdso_k_rng_data);
break;
case VDSO_ARCH_PAGES_START ... VDSO_ARCH_PAGES_END:
if (!IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA))
return VM_FAULT_SIGBUS;
- pfn = __phys_to_pfn(__pa_symbol(vdso_k_arch_data)) +
- vmf->pgoff - VDSO_ARCH_PAGES_START;
+ page = virt_to_page(vdso_k_arch_data) + vmf->pgoff - VDSO_ARCH_PAGES_START;
break;
default:
return VM_FAULT_SIGBUS;
}
- return vmf_insert_pfn(vma, vmf->address, pfn);
+ get_page(page);
+ vmf->page = page;
+ return 0;
}
const struct vm_special_mapping vdso_vvar_mapping = {
@@ -101,7 +129,7 @@ struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned
{
return _install_special_mapping(mm, addr, VDSO_NR_PAGES * PAGE_SIZE,
VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP |
- VM_PFNMAP | VM_SEALED_SYSMAP,
+ VM_MIXEDMAP | VM_SEALED_SYSMAP,
&vdso_vvar_mapping);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 03/14] vdso/datastore: Allocate data pages dynamically
2026-03-04 7:49 ` [PATCH v6 03/14] vdso/datastore: Allocate data pages dynamically Thomas Weißschuh
@ 2026-03-04 8:49 ` Christophe Leroy (CS GROUP)
0 siblings, 0 replies; 19+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-04 8:49 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Vincenzo Frascino,
Arnd Bergmann, David S. Miller, Andreas Larsson, Nick Alcock,
John Stultz, Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390
Le 04/03/2026 à 08:49, Thomas Weißschuh a écrit :
> Allocating the data pages as part of the kernel image does not work on
> SPARC. The MMU will through a fault when userspace tries to access them.
>
> Allocate the data pages through the page allocator instead.
> Unused pages in the vDSO VMA are still allocated to keep the virtual
> addresses aligned. Switch the mapping from PFNs to 'struct page' as that
> is required for dynamically allocated pages.
> This also aligns the allocation of the datapages with the code
> pages and is a prerequisite for mlockall() support.
>
> VM_MIXEDMAP is necessary for the call to vmf_insert_page() in the timens
> prefault path to work.
>
> The data pages need to be order-0, non-compound pages so that the
> mapping to userspace and the different orderings work.
>
> These pages are also used by the timekeeping, random pool and
> architecture initialization code. Some of these are running before the
> page allocator is available. To keep these subsytems working without
> changes, introduce early, statically data storage which will then
> replaced by the real one as soon as that is available.
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> include/linux/vdso_datastore.h | 6 +++
> init/main.c | 2 +
> lib/vdso/datastore.c | 92 +++++++++++++++++++++++++++---------------
> 3 files changed, 68 insertions(+), 32 deletions(-)
>
> diff --git a/include/linux/vdso_datastore.h b/include/linux/vdso_datastore.h
> index a91fa24b06e0..0b530428db71 100644
> --- a/include/linux/vdso_datastore.h
> +++ b/include/linux/vdso_datastore.h
> @@ -2,9 +2,15 @@
> #ifndef _LINUX_VDSO_DATASTORE_H
> #define _LINUX_VDSO_DATASTORE_H
>
> +#ifdef CONFIG_HAVE_GENERIC_VDSO
> #include <linux/mm_types.h>
>
> extern const struct vm_special_mapping vdso_vvar_mapping;
> struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned long addr);
>
> +void __init vdso_setup_data_pages(void);
> +#else /* !CONFIG_HAVE_GENERIC_VDSO */
> +static inline void vdso_setup_data_pages(void) { }
> +#endif /* CONFIG_HAVE_GENERIC_VDSO */
> +
> #endif /* _LINUX_VDSO_DATASTORE_H */
> diff --git a/init/main.c b/init/main.c
> index 1cb395dd94e4..de867b2693d2 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -105,6 +105,7 @@
> #include <linux/ptdump.h>
> #include <linux/time_namespace.h>
> #include <linux/unaligned.h>
> +#include <linux/vdso_datastore.h>
> #include <net/net_namespace.h>
>
> #include <asm/io.h>
> @@ -1119,6 +1120,7 @@ void start_kernel(void)
> srcu_init();
> hrtimers_init();
> softirq_init();
> + vdso_setup_data_pages();
> timekeeping_init();
> time_init();
>
> diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
> index 7377fcb6e1df..faebf5b7cd6e 100644
> --- a/lib/vdso/datastore.c
> +++ b/lib/vdso/datastore.c
> @@ -1,52 +1,79 @@
> // SPDX-License-Identifier: GPL-2.0-only
>
> -#include <linux/linkage.h>
> +#include <linux/gfp.h>
> +#include <linux/init.h>
> #include <linux/mm.h>
> #include <linux/time_namespace.h>
> #include <linux/types.h>
> #include <linux/vdso_datastore.h>
> #include <vdso/datapage.h>
>
> -/*
> - * The vDSO data page.
> - */
> +static u8 vdso_initdata[VDSO_NR_PAGES * PAGE_SIZE] __aligned(PAGE_SIZE) __initdata = {};
> +
> #ifdef CONFIG_GENERIC_GETTIMEOFDAY
> -static union {
> - struct vdso_time_data data;
> - u8 page[PAGE_SIZE];
> -} vdso_time_data_store __page_aligned_data;
> -struct vdso_time_data *vdso_k_time_data = &vdso_time_data_store.data;
> -static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE);
> +struct vdso_time_data *vdso_k_time_data __refdata =
> + (void *)&vdso_initdata[VDSO_TIME_PAGE_OFFSET * PAGE_SIZE];
> +
> +static_assert(sizeof(struct vdso_time_data) <= PAGE_SIZE);
> #endif /* CONFIG_GENERIC_GETTIMEOFDAY */
>
> #ifdef CONFIG_VDSO_GETRANDOM
> -static union {
> - struct vdso_rng_data data;
> - u8 page[PAGE_SIZE];
> -} vdso_rng_data_store __page_aligned_data;
> -struct vdso_rng_data *vdso_k_rng_data = &vdso_rng_data_store.data;
> -static_assert(sizeof(vdso_rng_data_store) == PAGE_SIZE);
> +struct vdso_rng_data *vdso_k_rng_data __refdata =
> + (void *)&vdso_initdata[VDSO_RNG_PAGE_OFFSET * PAGE_SIZE];
> +
> +static_assert(sizeof(struct vdso_rng_data) <= PAGE_SIZE);
> #endif /* CONFIG_VDSO_GETRANDOM */
>
> #ifdef CONFIG_ARCH_HAS_VDSO_ARCH_DATA
> -static union {
> - struct vdso_arch_data data;
> - u8 page[VDSO_ARCH_DATA_SIZE];
> -} vdso_arch_data_store __page_aligned_data;
> -struct vdso_arch_data *vdso_k_arch_data = &vdso_arch_data_store.data;
> +struct vdso_arch_data *vdso_k_arch_data __refdata =
> + (void *)&vdso_initdata[VDSO_ARCH_PAGES_START * PAGE_SIZE];
> #endif /* CONFIG_ARCH_HAS_VDSO_ARCH_DATA */
>
> +void __init vdso_setup_data_pages(void)
> +{
> + unsigned int order = get_order(VDSO_NR_PAGES * PAGE_SIZE);
> + struct page *pages;
> +
> + /*
> + * Allocate the data pages dynamically. SPARC does not support mapping
> + * static pages to be mapped into userspace.
> + * It is also a requirement for mlockall() support.
> + *
> + * Do not use folios. In time namespaces the pages are mapped in a different order
> + * to userspace, which is not handled by the folio optimizations in finish_fault().
> + */
> + pages = alloc_pages(GFP_KERNEL, order);
> + if (!pages)
> + panic("Unable to allocate VDSO storage pages");
> +
> + /* The pages are mapped one-by-one into userspace and each one needs to be refcounted. */
> + split_page(pages, order);
> +
> + /* Move the data already written by other subsystems to the new pages */
> + memcpy(page_address(pages), vdso_initdata, VDSO_NR_PAGES * PAGE_SIZE);
> +
> + if (IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY))
> + vdso_k_time_data = page_address(pages + VDSO_TIME_PAGE_OFFSET);
> +
> + if (IS_ENABLED(CONFIG_VDSO_GETRANDOM))
> + vdso_k_rng_data = page_address(pages + VDSO_RNG_PAGE_OFFSET);
> +
> + if (IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA))
> + vdso_k_arch_data = page_address(pages + VDSO_ARCH_PAGES_START);
> +}
> +
> static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> - struct page *timens_page = find_timens_vvar_page(vma);
> - unsigned long pfn;
> + struct page *page, *timens_page;
> +
> + timens_page = find_timens_vvar_page(vma);
>
> switch (vmf->pgoff) {
> case VDSO_TIME_PAGE_OFFSET:
> if (!IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY))
> return VM_FAULT_SIGBUS;
> - pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
> + page = virt_to_page(vdso_k_time_data);
> if (timens_page) {
> /*
> * Fault in VVAR page too, since it will be accessed
> @@ -56,10 +83,10 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> vm_fault_t err;
>
> addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE;
> - err = vmf_insert_pfn(vma, addr, pfn);
> + err = vmf_insert_page(vma, addr, page);
> if (unlikely(err & VM_FAULT_ERROR))
> return err;
> - pfn = page_to_pfn(timens_page);
> + page = timens_page;
> }
> break;
> case VDSO_TIMENS_PAGE_OFFSET:
> @@ -72,24 +99,25 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> */
> if (!IS_ENABLED(CONFIG_TIME_NS) || !timens_page)
> return VM_FAULT_SIGBUS;
> - pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
> + page = virt_to_page(vdso_k_time_data);
> break;
> case VDSO_RNG_PAGE_OFFSET:
> if (!IS_ENABLED(CONFIG_VDSO_GETRANDOM))
> return VM_FAULT_SIGBUS;
> - pfn = __phys_to_pfn(__pa_symbol(vdso_k_rng_data));
> + page = virt_to_page(vdso_k_rng_data);
> break;
> case VDSO_ARCH_PAGES_START ... VDSO_ARCH_PAGES_END:
> if (!IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA))
> return VM_FAULT_SIGBUS;
> - pfn = __phys_to_pfn(__pa_symbol(vdso_k_arch_data)) +
> - vmf->pgoff - VDSO_ARCH_PAGES_START;
> + page = virt_to_page(vdso_k_arch_data) + vmf->pgoff - VDSO_ARCH_PAGES_START;
> break;
> default:
> return VM_FAULT_SIGBUS;
> }
>
> - return vmf_insert_pfn(vma, vmf->address, pfn);
> + get_page(page);
> + vmf->page = page;
> + return 0;
> }
>
> const struct vm_special_mapping vdso_vvar_mapping = {
> @@ -101,7 +129,7 @@ struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned
> {
> return _install_special_mapping(mm, addr, VDSO_NR_PAGES * PAGE_SIZE,
> VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP |
> - VM_PFNMAP | VM_SEALED_SYSMAP,
> + VM_MIXEDMAP | VM_SEALED_SYSMAP,
> &vdso_vvar_mapping);
> }
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 04/14] sparc64: vdso: Link with -z noexecstack
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (2 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 03/14] vdso/datastore: Allocate data pages dynamically Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 05/14] sparc64: vdso: Remove obsolete "fake section table" reservation Thomas Weißschuh
` (10 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh, Arnd Bergmann
The vDSO stack does not need to be executable. Prevent the linker from
creating executable. For more background see commit ffcf9c5700e4 ("x86:
link vdso and boot with -z noexecstack --no-warn-rwx-segments").
Also prevent the following warning from the linker:
sparc64-linux-ld: warning: arch/sparc/vdso/vdso-note.o: missing .note.GNU-stack section implies executable stack
sparc64-linux-ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
Suggested-by: Arnd Bergmann <arnd@kernel.org>
Link: https://lore.kernel.org/lkml/20250707144726.4008707-1-arnd@kernel.org/
Fixes: 9a08862a5d2e ("vDSO for sparc")
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/vdso/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index 1a4e585c91d7..2e911ccc9db7 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -107,4 +107,4 @@ quiet_cmd_vdso = VDSO $@
$(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-T $(filter %.lds,$^) $(filter %.o,$^)
-VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 -Bsymbolic --no-undefined
+VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 -Bsymbolic --no-undefined -z noexecstack
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 05/14] sparc64: vdso: Remove obsolete "fake section table" reservation
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (3 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 04/14] sparc64: vdso: Link with -z noexecstack Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 06/14] sparc64: vdso: Replace code patching with runtime conditional Thomas Weißschuh
` (9 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
When the vDSO logic was copied from x86 to SPARC some unused remnants of
the fake section handling were copied, too. In x86 the original fake
section handling had already been removed incompletely in commit
da861e18eccc ("x86, vdso: Get rid of the fake section mechanism").
On x86 the reservation was only cleaned up in commit 24b7c77bbb24
("x86/vdso: Remove obsolete "fake section table" reservation").
Remove the reservation for SPARC, too.
Fixes: 9a08862a5d2e ("vDSO for sparc")
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/vdso/vdso-layout.lds.S | 21 ---------------------
arch/sparc/vdso/vdso2c.c | 8 --------
2 files changed, 29 deletions(-)
diff --git a/arch/sparc/vdso/vdso-layout.lds.S b/arch/sparc/vdso/vdso-layout.lds.S
index d31e57e8a3bb..9e0804789d11 100644
--- a/arch/sparc/vdso/vdso-layout.lds.S
+++ b/arch/sparc/vdso/vdso-layout.lds.S
@@ -4,16 +4,6 @@
* This script controls its layout.
*/
-#if defined(BUILD_VDSO64)
-# define SHDR_SIZE 64
-#elif defined(BUILD_VDSO32)
-# define SHDR_SIZE 40
-#else
-# error unknown VDSO target
-#endif
-
-#define NUM_FAKE_SHDRS 7
-
SECTIONS
{
/*
@@ -47,19 +37,8 @@ SECTIONS
*(.bss*)
*(.dynbss*)
*(.gnu.linkonce.b.*)
-
- /*
- * Ideally this would live in a C file: kept in here for
- * compatibility with x86-64.
- */
- VDSO_FAKE_SECTION_TABLE_START = .;
- . = . + NUM_FAKE_SHDRS * SHDR_SIZE;
- VDSO_FAKE_SECTION_TABLE_END = .;
} :text
- .fake_shstrtab : { *(.fake_shstrtab) } :text
-
-
.note : { *(.note.*) } :text :note
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
diff --git a/arch/sparc/vdso/vdso2c.c b/arch/sparc/vdso/vdso2c.c
index dc81240aab6f..b97af5ec9f35 100644
--- a/arch/sparc/vdso/vdso2c.c
+++ b/arch/sparc/vdso/vdso2c.c
@@ -61,8 +61,6 @@ const char *outfilename;
/* Symbols that we need in vdso2c. */
enum {
sym_vvar_start,
- sym_VDSO_FAKE_SECTION_TABLE_START,
- sym_VDSO_FAKE_SECTION_TABLE_END,
};
struct vdso_sym {
@@ -72,12 +70,6 @@ struct vdso_sym {
struct vdso_sym required_syms[] = {
[sym_vvar_start] = {"vvar_start", 1},
- [sym_VDSO_FAKE_SECTION_TABLE_START] = {
- "VDSO_FAKE_SECTION_TABLE_START", 0
- },
- [sym_VDSO_FAKE_SECTION_TABLE_END] = {
- "VDSO_FAKE_SECTION_TABLE_END", 0
- },
};
__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 06/14] sparc64: vdso: Replace code patching with runtime conditional
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (4 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 05/14] sparc64: vdso: Remove obsolete "fake section table" reservation Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 07/14] sparc64: vdso: Move hardware counter read into header Thomas Weißschuh
` (8 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh, Thomas Gleixner
The patching logic is unnecessarily complicated and stands in the way of
the adoption of the generic vDSO framework.
Replace it by a simple runtime switch, similar to other architectures.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/lkml/87ecu9tfhw.ffs@tglx/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/vdso/vclock_gettime.c | 112 +-------------------
arch/sparc/vdso/vdso.lds.S | 2 -
arch/sparc/vdso/vdso32/vdso32.lds.S | 2 -
arch/sparc/vdso/vma.c | 204 ------------------------------------
4 files changed, 4 insertions(+), 316 deletions(-)
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index 79607804ea1b..643608bffe13 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -148,17 +148,11 @@ notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
u64 v;
u64 cycles;
- cycles = vread_tick();
- v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
- return v * vvar->clock.mult;
-}
-
-notrace static __always_inline u64 vgetsns_stick(struct vvar_data *vvar)
-{
- u64 v;
- u64 cycles;
+ if (likely(vvar->vclock_mode == VCLOCK_STICK))
+ cycles = vread_tick_stick();
+ else
+ cycles = vread_tick();
- cycles = vread_tick_stick();
v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
return v * vvar->clock.mult;
}
@@ -183,26 +177,6 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar,
return 0;
}
-notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
-{
- unsigned long seq;
- u64 ns;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->wall_time_sec;
- ns = vvar->wall_time_snsec;
- ns += vgetsns_stick(vvar);
- ns = __shr64(ns, vvar->clock.shift);
- } while (unlikely(vvar_read_retry(vvar, seq)));
-
- ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
- ts->tv_nsec = ns;
-
- return 0;
-}
-
notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
struct __kernel_old_timespec *ts)
{
@@ -223,26 +197,6 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
return 0;
}
-notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
-{
- unsigned long seq;
- u64 ns;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->monotonic_time_sec;
- ns = vvar->monotonic_time_snsec;
- ns += vgetsns_stick(vvar);
- ns = __shr64(ns, vvar->clock.shift);
- } while (unlikely(vvar_read_retry(vvar, seq)));
-
- ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
- ts->tv_nsec = ns;
-
- return 0;
-}
-
notrace static int do_realtime_coarse(struct vvar_data *vvar,
struct __kernel_old_timespec *ts)
{
@@ -298,31 +252,6 @@ int
clock_gettime(clockid_t, struct __kernel_old_timespec *)
__attribute__((weak, alias("__vdso_clock_gettime")));
-notrace int
-__vdso_clock_gettime_stick(clockid_t clock, struct __kernel_old_timespec *ts)
-{
- struct vvar_data *vvd = get_vvar_data();
-
- switch (clock) {
- case CLOCK_REALTIME:
- if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
- break;
- return do_realtime_stick(vvd, ts);
- case CLOCK_MONOTONIC:
- if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
- break;
- return do_monotonic_stick(vvd, ts);
- case CLOCK_REALTIME_COARSE:
- return do_realtime_coarse(vvd, ts);
- case CLOCK_MONOTONIC_COARSE:
- return do_monotonic_coarse(vvd, ts);
- }
- /*
- * Unknown clock ID ? Fall back to the syscall.
- */
- return vdso_fallback_gettime(clock, ts);
-}
-
notrace int
__vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
{
@@ -358,36 +287,3 @@ __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
int
gettimeofday(struct __kernel_old_timeval *, struct timezone *)
__attribute__((weak, alias("__vdso_gettimeofday")));
-
-notrace int
-__vdso_gettimeofday_stick(struct __kernel_old_timeval *tv, struct timezone *tz)
-{
- struct vvar_data *vvd = get_vvar_data();
-
- if (likely(vvd->vclock_mode != VCLOCK_NONE)) {
- if (likely(tv != NULL)) {
- union tstv_t {
- struct __kernel_old_timespec ts;
- struct __kernel_old_timeval tv;
- } *tstv = (union tstv_t *) tv;
- do_realtime_stick(vvd, &tstv->ts);
- /*
- * Assign before dividing to ensure that the division is
- * done in the type of tv_usec, not tv_nsec.
- *
- * There cannot be > 1 billion usec in a second:
- * do_realtime() has already distributed such overflow
- * into tv_sec. So we can assign it to an int safely.
- */
- tstv->tv.tv_usec = tstv->ts.tv_nsec;
- tstv->tv.tv_usec /= 1000;
- }
- if (unlikely(tz != NULL)) {
- /* Avoid memcpy. Some old compilers fail to inline it */
- tz->tz_minuteswest = vvd->tz_minuteswest;
- tz->tz_dsttime = vvd->tz_dsttime;
- }
- return 0;
- }
- return vdso_fallback_gettimeofday(tv, tz);
-}
diff --git a/arch/sparc/vdso/vdso.lds.S b/arch/sparc/vdso/vdso.lds.S
index 629ab6900df7..f3caa29a331c 100644
--- a/arch/sparc/vdso/vdso.lds.S
+++ b/arch/sparc/vdso/vdso.lds.S
@@ -18,10 +18,8 @@ VERSION {
global:
clock_gettime;
__vdso_clock_gettime;
- __vdso_clock_gettime_stick;
gettimeofday;
__vdso_gettimeofday;
- __vdso_gettimeofday_stick;
local: *;
};
}
diff --git a/arch/sparc/vdso/vdso32/vdso32.lds.S b/arch/sparc/vdso/vdso32/vdso32.lds.S
index 218930fdff03..53575ee154c4 100644
--- a/arch/sparc/vdso/vdso32/vdso32.lds.S
+++ b/arch/sparc/vdso/vdso32/vdso32.lds.S
@@ -17,10 +17,8 @@ VERSION {
global:
clock_gettime;
__vdso_clock_gettime;
- __vdso_clock_gettime_stick;
gettimeofday;
__vdso_gettimeofday;
- __vdso_gettimeofday_stick;
local: *;
};
}
diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c
index c454689ce5fa..1f47d8341e43 100644
--- a/arch/sparc/vdso/vma.c
+++ b/arch/sparc/vdso/vma.c
@@ -42,203 +42,6 @@ static struct vm_special_mapping vdso_mapping32 = {
struct vvar_data *vvar_data;
-struct vdso_elfinfo32 {
- Elf32_Ehdr *hdr;
- Elf32_Sym *dynsym;
- unsigned long dynsymsize;
- const char *dynstr;
- unsigned long text;
-};
-
-struct vdso_elfinfo64 {
- Elf64_Ehdr *hdr;
- Elf64_Sym *dynsym;
- unsigned long dynsymsize;
- const char *dynstr;
- unsigned long text;
-};
-
-struct vdso_elfinfo {
- union {
- struct vdso_elfinfo32 elf32;
- struct vdso_elfinfo64 elf64;
- } u;
-};
-
-static void *one_section64(struct vdso_elfinfo64 *e, const char *name,
- unsigned long *size)
-{
- const char *snames;
- Elf64_Shdr *shdrs;
- unsigned int i;
-
- shdrs = (void *)e->hdr + e->hdr->e_shoff;
- snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset;
- for (i = 1; i < e->hdr->e_shnum; i++) {
- if (!strcmp(snames+shdrs[i].sh_name, name)) {
- if (size)
- *size = shdrs[i].sh_size;
- return (void *)e->hdr + shdrs[i].sh_offset;
- }
- }
- return NULL;
-}
-
-static int find_sections64(const struct vdso_image *image, struct vdso_elfinfo *_e)
-{
- struct vdso_elfinfo64 *e = &_e->u.elf64;
-
- e->hdr = image->data;
- e->dynsym = one_section64(e, ".dynsym", &e->dynsymsize);
- e->dynstr = one_section64(e, ".dynstr", NULL);
-
- if (!e->dynsym || !e->dynstr) {
- pr_err("VDSO64: Missing symbol sections.\n");
- return -ENODEV;
- }
- return 0;
-}
-
-static Elf64_Sym *find_sym64(const struct vdso_elfinfo64 *e, const char *name)
-{
- unsigned int i;
-
- for (i = 0; i < (e->dynsymsize / sizeof(Elf64_Sym)); i++) {
- Elf64_Sym *s = &e->dynsym[i];
- if (s->st_name == 0)
- continue;
- if (!strcmp(e->dynstr + s->st_name, name))
- return s;
- }
- return NULL;
-}
-
-static int patchsym64(struct vdso_elfinfo *_e, const char *orig,
- const char *new)
-{
- struct vdso_elfinfo64 *e = &_e->u.elf64;
- Elf64_Sym *osym = find_sym64(e, orig);
- Elf64_Sym *nsym = find_sym64(e, new);
-
- if (!nsym || !osym) {
- pr_err("VDSO64: Missing symbols.\n");
- return -ENODEV;
- }
- osym->st_value = nsym->st_value;
- osym->st_size = nsym->st_size;
- osym->st_info = nsym->st_info;
- osym->st_other = nsym->st_other;
- osym->st_shndx = nsym->st_shndx;
-
- return 0;
-}
-
-static void *one_section32(struct vdso_elfinfo32 *e, const char *name,
- unsigned long *size)
-{
- const char *snames;
- Elf32_Shdr *shdrs;
- unsigned int i;
-
- shdrs = (void *)e->hdr + e->hdr->e_shoff;
- snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset;
- for (i = 1; i < e->hdr->e_shnum; i++) {
- if (!strcmp(snames+shdrs[i].sh_name, name)) {
- if (size)
- *size = shdrs[i].sh_size;
- return (void *)e->hdr + shdrs[i].sh_offset;
- }
- }
- return NULL;
-}
-
-static int find_sections32(const struct vdso_image *image, struct vdso_elfinfo *_e)
-{
- struct vdso_elfinfo32 *e = &_e->u.elf32;
-
- e->hdr = image->data;
- e->dynsym = one_section32(e, ".dynsym", &e->dynsymsize);
- e->dynstr = one_section32(e, ".dynstr", NULL);
-
- if (!e->dynsym || !e->dynstr) {
- pr_err("VDSO32: Missing symbol sections.\n");
- return -ENODEV;
- }
- return 0;
-}
-
-static Elf32_Sym *find_sym32(const struct vdso_elfinfo32 *e, const char *name)
-{
- unsigned int i;
-
- for (i = 0; i < (e->dynsymsize / sizeof(Elf32_Sym)); i++) {
- Elf32_Sym *s = &e->dynsym[i];
- if (s->st_name == 0)
- continue;
- if (!strcmp(e->dynstr + s->st_name, name))
- return s;
- }
- return NULL;
-}
-
-static int patchsym32(struct vdso_elfinfo *_e, const char *orig,
- const char *new)
-{
- struct vdso_elfinfo32 *e = &_e->u.elf32;
- Elf32_Sym *osym = find_sym32(e, orig);
- Elf32_Sym *nsym = find_sym32(e, new);
-
- if (!nsym || !osym) {
- pr_err("VDSO32: Missing symbols.\n");
- return -ENODEV;
- }
- osym->st_value = nsym->st_value;
- osym->st_size = nsym->st_size;
- osym->st_info = nsym->st_info;
- osym->st_other = nsym->st_other;
- osym->st_shndx = nsym->st_shndx;
-
- return 0;
-}
-
-static int find_sections(const struct vdso_image *image, struct vdso_elfinfo *e,
- bool elf64)
-{
- if (elf64)
- return find_sections64(image, e);
- else
- return find_sections32(image, e);
-}
-
-static int patch_one_symbol(struct vdso_elfinfo *e, const char *orig,
- const char *new_target, bool elf64)
-{
- if (elf64)
- return patchsym64(e, orig, new_target);
- else
- return patchsym32(e, orig, new_target);
-}
-
-static int stick_patch(const struct vdso_image *image, struct vdso_elfinfo *e, bool elf64)
-{
- int err;
-
- err = find_sections(image, e, elf64);
- if (err)
- return err;
-
- err = patch_one_symbol(e,
- "__vdso_gettimeofday",
- "__vdso_gettimeofday_stick", elf64);
- if (err)
- return err;
-
- return patch_one_symbol(e,
- "__vdso_clock_gettime",
- "__vdso_clock_gettime_stick", elf64);
- return 0;
-}
-
/*
* Allocate pages for the vdso and vvar, and copy in the vdso text from the
* kernel image.
@@ -250,15 +53,8 @@ static int __init init_vdso_image(const struct vdso_image *image,
int cnpages = (image->size) / PAGE_SIZE;
struct page *dp, **dpp = NULL;
struct page *cp, **cpp = NULL;
- struct vdso_elfinfo ei;
int i, dnpages = 0;
- if (tlb_type != spitfire) {
- int err = stick_patch(image, &ei, elf64);
- if (err)
- return err;
- }
-
/*
* First, the vdso text. This is initialied data, an integral number of
* pages long.
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 07/14] sparc64: vdso: Move hardware counter read into header
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (5 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 06/14] sparc64: vdso: Replace code patching with runtime conditional Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 08/14] sparc64: vdso: Move syscall fallbacks " Thomas Weißschuh
` (7 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
The generic vDSO libraries expected the architecture glue around hardware
counter reading in asm/vdso/gettimeofday.h. To prepare the adoption of the
generic library, move the existing functions there.
While at it, perform some trivial alignment with the generic vDSO library:
* Drop 'notrace', as the functions are __always_inline anyways
* Use the same parameter types
* Use the same function names
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/include/asm/vdso/gettimeofday.h | 78 ++++++++++++++++++++++++++++++
arch/sparc/vdso/vclock_gettime.c | 70 ++-------------------------
2 files changed, 82 insertions(+), 66 deletions(-)
diff --git a/arch/sparc/include/asm/vdso/gettimeofday.h b/arch/sparc/include/asm/vdso/gettimeofday.h
new file mode 100644
index 000000000000..31f6505d3ab5
--- /dev/null
+++ b/arch/sparc/include/asm/vdso/gettimeofday.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2006 Andi Kleen, SUSE Labs.
+ */
+
+#ifndef _ASM_SPARC_VDSO_GETTIMEOFDAY_H
+#define _ASM_SPARC_VDSO_GETTIMEOFDAY_H
+
+#include <linux/types.h>
+#include <asm/vvar.h>
+
+#ifdef CONFIG_SPARC64
+static __always_inline u64 vdso_shift_ns(u64 val, u32 amt)
+{
+ return val >> amt;
+}
+
+static __always_inline u64 vread_tick(void)
+{
+ u64 ret;
+
+ __asm__ __volatile__("rd %%tick, %0" : "=r" (ret));
+ return ret;
+}
+
+static __always_inline u64 vread_tick_stick(void)
+{
+ u64 ret;
+
+ __asm__ __volatile__("rd %%asr24, %0" : "=r" (ret));
+ return ret;
+}
+#else
+static __always_inline u64 vdso_shift_ns(u64 val, u32 amt)
+{
+ u64 ret;
+
+ __asm__ __volatile__("sllx %H1, 32, %%g1\n\t"
+ "srl %L1, 0, %L1\n\t"
+ "or %%g1, %L1, %%g1\n\t"
+ "srlx %%g1, %2, %L0\n\t"
+ "srlx %L0, 32, %H0"
+ : "=r" (ret)
+ : "r" (val), "r" (amt)
+ : "g1");
+ return ret;
+}
+
+static __always_inline u64 vread_tick(void)
+{
+ register unsigned long long ret asm("o4");
+
+ __asm__ __volatile__("rd %%tick, %L0\n\t"
+ "srlx %L0, 32, %H0"
+ : "=r" (ret));
+ return ret;
+}
+
+static __always_inline u64 vread_tick_stick(void)
+{
+ register unsigned long long ret asm("o4");
+
+ __asm__ __volatile__("rd %%asr24, %L0\n\t"
+ "srlx %L0, 32, %H0"
+ : "=r" (ret));
+ return ret;
+}
+#endif
+
+static __always_inline u64 __arch_get_hw_counter(struct vvar_data *vvar)
+{
+ if (likely(vvar->vclock_mode == VCLOCK_STICK))
+ return vread_tick_stick();
+ else
+ return vread_tick();
+}
+
+#endif /* _ASM_SPARC_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index 643608bffe13..16ac80982a00 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -19,6 +19,7 @@
#include <asm/unistd.h>
#include <asm/timex.h>
#include <asm/clocksource.h>
+#include <asm/vdso/gettimeofday.h>
#include <asm/vvar.h>
#ifdef CONFIG_SPARC64
@@ -85,73 +86,10 @@ notrace static long vdso_fallback_gettimeofday(struct __kernel_old_timeval *tv,
return o0;
}
-#ifdef CONFIG_SPARC64
-notrace static __always_inline u64 __shr64(u64 val, int amt)
-{
- return val >> amt;
-}
-
-notrace static __always_inline u64 vread_tick(void)
-{
- u64 ret;
-
- __asm__ __volatile__("rd %%tick, %0" : "=r" (ret));
- return ret;
-}
-
-notrace static __always_inline u64 vread_tick_stick(void)
-{
- u64 ret;
-
- __asm__ __volatile__("rd %%asr24, %0" : "=r" (ret));
- return ret;
-}
-#else
-notrace static __always_inline u64 __shr64(u64 val, int amt)
-{
- u64 ret;
-
- __asm__ __volatile__("sllx %H1, 32, %%g1\n\t"
- "srl %L1, 0, %L1\n\t"
- "or %%g1, %L1, %%g1\n\t"
- "srlx %%g1, %2, %L0\n\t"
- "srlx %L0, 32, %H0"
- : "=r" (ret)
- : "r" (val), "r" (amt)
- : "g1");
- return ret;
-}
-
-notrace static __always_inline u64 vread_tick(void)
-{
- register unsigned long long ret asm("o4");
-
- __asm__ __volatile__("rd %%tick, %L0\n\t"
- "srlx %L0, 32, %H0"
- : "=r" (ret));
- return ret;
-}
-
-notrace static __always_inline u64 vread_tick_stick(void)
-{
- register unsigned long long ret asm("o4");
-
- __asm__ __volatile__("rd %%asr24, %L0\n\t"
- "srlx %L0, 32, %H0"
- : "=r" (ret));
- return ret;
-}
-#endif
-
notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
{
u64 v;
- u64 cycles;
-
- if (likely(vvar->vclock_mode == VCLOCK_STICK))
- cycles = vread_tick_stick();
- else
- cycles = vread_tick();
+ u64 cycles = __arch_get_hw_counter(vvar);
v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
return v * vvar->clock.mult;
@@ -168,7 +106,7 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar,
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns(vvar);
- ns = __shr64(ns, vvar->clock.shift);
+ ns = vdso_shift_ns(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -188,7 +126,7 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns(vvar);
- ns = __shr64(ns, vvar->clock.shift);
+ ns = vdso_shift_ns(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 08/14] sparc64: vdso: Move syscall fallbacks into header
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (6 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 07/14] sparc64: vdso: Move hardware counter read into header Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 09/14] sparc64: vdso: Introduce vdso/processor.h Thomas Weißschuh
` (6 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
The generic vDSO libraries expected the syscall fallbacks in
asm/vdso/gettimeofday.h. To prepare the adoption of the generic library,
move the existing functions there.
While at it, rename them so they match what the generic library expects.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/include/asm/vdso/gettimeofday.h | 50 +++++++++++++++++++++++++++++
arch/sparc/vdso/vclock_gettime.c | 51 ++----------------------------
2 files changed, 52 insertions(+), 49 deletions(-)
diff --git a/arch/sparc/include/asm/vdso/gettimeofday.h b/arch/sparc/include/asm/vdso/gettimeofday.h
index 31f6505d3ab5..429dc080568f 100644
--- a/arch/sparc/include/asm/vdso/gettimeofday.h
+++ b/arch/sparc/include/asm/vdso/gettimeofday.h
@@ -6,6 +6,9 @@
#ifndef _ASM_SPARC_VDSO_GETTIMEOFDAY_H
#define _ASM_SPARC_VDSO_GETTIMEOFDAY_H
+#include <uapi/linux/time.h>
+#include <uapi/linux/unistd.h>
+
#include <linux/types.h>
#include <asm/vvar.h>
@@ -75,4 +78,51 @@ static __always_inline u64 __arch_get_hw_counter(struct vvar_data *vvar)
return vread_tick();
}
+#ifdef CONFIG_SPARC64
+#define SYSCALL_STRING \
+ "ta 0x6d;" \
+ "bcs,a 1f;" \
+ " sub %%g0, %%o0, %%o0;" \
+ "1:"
+#else
+#define SYSCALL_STRING \
+ "ta 0x10;" \
+ "bcs,a 1f;" \
+ " sub %%g0, %%o0, %%o0;" \
+ "1:"
+#endif
+
+#define SYSCALL_CLOBBERS \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
+ "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", \
+ "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", \
+ "cc", "memory"
+
+static __always_inline
+long clock_gettime_fallback(clockid_t clock, struct __kernel_old_timespec *ts)
+{
+ register long num __asm__("g1") = __NR_clock_gettime;
+ register long o0 __asm__("o0") = clock;
+ register long o1 __asm__("o1") = (long) ts;
+
+ __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
+ "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
+ return o0;
+}
+
+static __always_inline
+long gettimeofday_fallback(struct __kernel_old_timeval *tv, struct timezone *tz)
+{
+ register long num __asm__("g1") = __NR_gettimeofday;
+ register long o0 __asm__("o0") = (long) tv;
+ register long o1 __asm__("o1") = (long) tz;
+
+ __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
+ "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
+ return o0;
+}
+
#endif /* _ASM_SPARC_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index 16ac80982a00..e768c0b84b34 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -13,38 +13,13 @@
*/
#include <linux/kernel.h>
-#include <linux/time.h>
#include <linux/string.h>
#include <asm/io.h>
-#include <asm/unistd.h>
#include <asm/timex.h>
#include <asm/clocksource.h>
#include <asm/vdso/gettimeofday.h>
#include <asm/vvar.h>
-#ifdef CONFIG_SPARC64
-#define SYSCALL_STRING \
- "ta 0x6d;" \
- "bcs,a 1f;" \
- " sub %%g0, %%o0, %%o0;" \
- "1:"
-#else
-#define SYSCALL_STRING \
- "ta 0x10;" \
- "bcs,a 1f;" \
- " sub %%g0, %%o0, %%o0;" \
- "1:"
-#endif
-
-#define SYSCALL_CLOBBERS \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
- "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", \
- "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", \
- "cc", "memory"
-
/*
* Compute the vvar page's address in the process address space, and return it
* as a pointer to the vvar_data.
@@ -64,28 +39,6 @@ notrace static __always_inline struct vvar_data *get_vvar_data(void)
return (struct vvar_data *) ret;
}
-notrace static long vdso_fallback_gettime(long clock, struct __kernel_old_timespec *ts)
-{
- register long num __asm__("g1") = __NR_clock_gettime;
- register long o0 __asm__("o0") = clock;
- register long o1 __asm__("o1") = (long) ts;
-
- __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
- "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
- return o0;
-}
-
-notrace static long vdso_fallback_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
-{
- register long num __asm__("g1") = __NR_gettimeofday;
- register long o0 __asm__("o0") = (long) tv;
- register long o1 __asm__("o1") = (long) tz;
-
- __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
- "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
- return o0;
-}
-
notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
{
u64 v;
@@ -184,7 +137,7 @@ __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts)
/*
* Unknown clock ID ? Fall back to the syscall.
*/
- return vdso_fallback_gettime(clock, ts);
+ return clock_gettime_fallback(clock, ts);
}
int
clock_gettime(clockid_t, struct __kernel_old_timespec *)
@@ -220,7 +173,7 @@ __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
}
return 0;
}
- return vdso_fallback_gettimeofday(tv, tz);
+ return gettimeofday_fallback(tv, tz);
}
int
gettimeofday(struct __kernel_old_timeval *, struct timezone *)
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 09/14] sparc64: vdso: Introduce vdso/processor.h
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (7 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 08/14] sparc64: vdso: Move syscall fallbacks " Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 10/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (5 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
The generic vDSO library expects a vdso/processor.h with an definition of
cpu_relax().
Split out cpu_relax() into this dedicated header.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/include/asm/processor.h | 3 +++
arch/sparc/include/asm/processor_32.h | 2 --
arch/sparc/include/asm/processor_64.h | 25 --------------------
arch/sparc/include/asm/vdso/processor.h | 41 +++++++++++++++++++++++++++++++++
4 files changed, 44 insertions(+), 27 deletions(-)
diff --git a/arch/sparc/include/asm/processor.h b/arch/sparc/include/asm/processor.h
index 18295ea625dd..e34de956519a 100644
--- a/arch/sparc/include/asm/processor.h
+++ b/arch/sparc/include/asm/processor.h
@@ -1,6 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ___ASM_SPARC_PROCESSOR_H
#define ___ASM_SPARC_PROCESSOR_H
+
+#include <asm/vdso/processor.h>
+
#if defined(__sparc__) && defined(__arch64__)
#include <asm/processor_64.h>
#else
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index ba8b70ffec08..a074d313f4f8 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -91,8 +91,6 @@ unsigned long __get_wchan(struct task_struct *);
extern struct task_struct *last_task_used_math;
int do_mathemu(struct pt_regs *regs, struct task_struct *fpt);
-#define cpu_relax() barrier()
-
extern void (*sparc_idle)(void);
#endif
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 321859454ca4..485070495263 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -182,31 +182,6 @@ unsigned long __get_wchan(struct task_struct *task);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc)
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP])
-/* Please see the commentary in asm/backoff.h for a description of
- * what these instructions are doing and how they have been chosen.
- * To make a long story short, we are trying to yield the current cpu
- * strand during busy loops.
- */
-#ifdef BUILD_VDSO
-#define cpu_relax() asm volatile("\n99:\n\t" \
- "rd %%ccr, %%g0\n\t" \
- "rd %%ccr, %%g0\n\t" \
- "rd %%ccr, %%g0\n\t" \
- ::: "memory")
-#else /* ! BUILD_VDSO */
-#define cpu_relax() asm volatile("\n99:\n\t" \
- "rd %%ccr, %%g0\n\t" \
- "rd %%ccr, %%g0\n\t" \
- "rd %%ccr, %%g0\n\t" \
- ".section .pause_3insn_patch,\"ax\"\n\t"\
- ".word 99b\n\t" \
- "wr %%g0, 128, %%asr27\n\t" \
- "nop\n\t" \
- "nop\n\t" \
- ".previous" \
- ::: "memory")
-#endif
-
/* Prefetch support. This is tuned for UltraSPARC-III and later.
* UltraSPARC-I will treat these as nops, and UltraSPARC-II has
* a shallower prefetch queue than later chips.
diff --git a/arch/sparc/include/asm/vdso/processor.h b/arch/sparc/include/asm/vdso/processor.h
new file mode 100644
index 000000000000..f7a9adc807f7
--- /dev/null
+++ b/arch/sparc/include/asm/vdso/processor.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_SPARC_VDSO_PROCESSOR_H
+#define _ASM_SPARC_VDSO_PROCESSOR_H
+
+#include <linux/compiler.h>
+
+#if defined(__arch64__)
+
+/* Please see the commentary in asm/backoff.h for a description of
+ * what these instructions are doing and how they have been chosen.
+ * To make a long story short, we are trying to yield the current cpu
+ * strand during busy loops.
+ */
+#ifdef BUILD_VDSO
+#define cpu_relax() asm volatile("\n99:\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ ::: "memory")
+#else /* ! BUILD_VDSO */
+#define cpu_relax() asm volatile("\n99:\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ ".section .pause_3insn_patch,\"ax\"\n\t"\
+ ".word 99b\n\t" \
+ "wr %%g0, 128, %%asr27\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ ".previous" \
+ ::: "memory")
+#endif /* BUILD_VDSO */
+
+#else /* ! __arch64__ */
+
+#define cpu_relax() barrier()
+
+#endif /* __arch64__ */
+
+#endif /* _ASM_SPARC_VDSO_PROCESSOR_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 10/14] sparc64: vdso: Switch to the generic vDSO library
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (8 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 09/14] sparc64: vdso: Introduce vdso/processor.h Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 11/14] sparc64: vdso2c: Drop sym_vvar_start handling Thomas Weißschuh
` (4 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
The generic vDSO provides a lot common functionality shared between
different architectures. SPARC is the last architecture not using it,
preventing some necessary code cleanup.
Make use of the generic infrastructure.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/Kconfig | 3 +-
arch/sparc/include/asm/clocksource.h | 9 --
arch/sparc/include/asm/vdso/clocksource.h | 10 ++
arch/sparc/include/asm/vdso/gettimeofday.h | 58 ++++++++--
arch/sparc/include/asm/vdso/vsyscall.h | 10 ++
arch/sparc/include/asm/vvar.h | 75 -------------
arch/sparc/kernel/Makefile | 1 -
arch/sparc/kernel/time_64.c | 6 +-
arch/sparc/kernel/vdso.c | 69 ------------
arch/sparc/vdso/Makefile | 6 +-
arch/sparc/vdso/vclock_gettime.c | 169 ++++-------------------------
arch/sparc/vdso/vdso-layout.lds.S | 7 +-
arch/sparc/vdso/vma.c | 70 +++---------
13 files changed, 118 insertions(+), 375 deletions(-)
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 8699be91fca9..a6b787efc2c4 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -104,7 +104,6 @@ config SPARC64
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select GENERIC_TIME_VSYSCALL
- select ARCH_CLOCKSOURCE_DATA
select ARCH_HAS_PTE_SPECIAL
select PCI_DOMAINS if PCI
select ARCH_HAS_GIGANTIC_PAGE
@@ -115,6 +114,8 @@ config SPARC64
select ARCH_SUPPORTS_SCHED_SMT if SMP
select ARCH_SUPPORTS_SCHED_MC if SMP
select ARCH_HAS_LAZY_MMU_MODE
+ select HAVE_GENERIC_VDSO
+ select GENERIC_GETTIMEOFDAY
config ARCH_PROC_KCORE_TEXT
def_bool y
diff --git a/arch/sparc/include/asm/clocksource.h b/arch/sparc/include/asm/clocksource.h
index d63ef224befe..68303ad26eb2 100644
--- a/arch/sparc/include/asm/clocksource.h
+++ b/arch/sparc/include/asm/clocksource.h
@@ -5,13 +5,4 @@
#ifndef _ASM_SPARC_CLOCKSOURCE_H
#define _ASM_SPARC_CLOCKSOURCE_H
-/* VDSO clocksources */
-#define VCLOCK_NONE 0 /* Nothing userspace can do. */
-#define VCLOCK_TICK 1 /* Use %tick. */
-#define VCLOCK_STICK 2 /* Use %stick. */
-
-struct arch_clocksource_data {
- int vclock_mode;
-};
-
#endif /* _ASM_SPARC_CLOCKSOURCE_H */
diff --git a/arch/sparc/include/asm/vdso/clocksource.h b/arch/sparc/include/asm/vdso/clocksource.h
new file mode 100644
index 000000000000..007aa8ceaf52
--- /dev/null
+++ b/arch/sparc/include/asm/vdso/clocksource.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_VDSO_CLOCKSOURCE_H
+#define __ASM_VDSO_CLOCKSOURCE_H
+
+/* VDSO clocksources */
+#define VDSO_ARCH_CLOCKMODES \
+ VDSO_CLOCKMODE_TICK, \
+ VDSO_CLOCKMODE_STICK
+
+#endif /* __ASM_VDSO_CLOCKSOURCE_H */
diff --git a/arch/sparc/include/asm/vdso/gettimeofday.h b/arch/sparc/include/asm/vdso/gettimeofday.h
index 429dc080568f..a35875fba454 100644
--- a/arch/sparc/include/asm/vdso/gettimeofday.h
+++ b/arch/sparc/include/asm/vdso/gettimeofday.h
@@ -9,15 +9,14 @@
#include <uapi/linux/time.h>
#include <uapi/linux/unistd.h>
+#include <vdso/align.h>
+#include <vdso/clocksource.h>
+#include <vdso/datapage.h>
+#include <vdso/page.h>
+
#include <linux/types.h>
-#include <asm/vvar.h>
#ifdef CONFIG_SPARC64
-static __always_inline u64 vdso_shift_ns(u64 val, u32 amt)
-{
- return val >> amt;
-}
-
static __always_inline u64 vread_tick(void)
{
u64 ret;
@@ -48,6 +47,7 @@ static __always_inline u64 vdso_shift_ns(u64 val, u32 amt)
: "g1");
return ret;
}
+#define vdso_shift_ns vdso_shift_ns
static __always_inline u64 vread_tick(void)
{
@@ -70,9 +70,9 @@ static __always_inline u64 vread_tick_stick(void)
}
#endif
-static __always_inline u64 __arch_get_hw_counter(struct vvar_data *vvar)
+static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, const struct vdso_time_data *vd)
{
- if (likely(vvar->vclock_mode == VCLOCK_STICK))
+ if (likely(clock_mode == VDSO_CLOCKMODE_STICK))
return vread_tick_stick();
else
return vread_tick();
@@ -102,7 +102,20 @@ static __always_inline u64 __arch_get_hw_counter(struct vvar_data *vvar)
"cc", "memory"
static __always_inline
-long clock_gettime_fallback(clockid_t clock, struct __kernel_old_timespec *ts)
+long clock_gettime_fallback(clockid_t clock, struct __kernel_timespec *ts)
+{
+ register long num __asm__("g1") = __NR_clock_gettime;
+ register long o0 __asm__("o0") = clock;
+ register long o1 __asm__("o1") = (long) ts;
+
+ __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
+ "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
+ return o0;
+}
+
+#ifndef CONFIG_SPARC64
+static __always_inline
+long clock_gettime32_fallback(clockid_t clock, struct old_timespec32 *ts)
{
register long num __asm__("g1") = __NR_clock_gettime;
register long o0 __asm__("o0") = clock;
@@ -112,6 +125,7 @@ long clock_gettime_fallback(clockid_t clock, struct __kernel_old_timespec *ts)
"0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
return o0;
}
+#endif
static __always_inline
long gettimeofday_fallback(struct __kernel_old_timeval *tv, struct timezone *tz)
@@ -125,4 +139,30 @@ long gettimeofday_fallback(struct __kernel_old_timeval *tv, struct timezone *tz)
return o0;
}
+static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
+{
+ unsigned long ret;
+
+ /*
+ * SPARC does not support native PC-relative code relocations.
+ * Calculate the address manually, works for 32 and 64 bit code.
+ */
+ __asm__ __volatile__(
+ "1:\n"
+ "call 3f\n" // Jump over the embedded data and set up %o7
+ "nop\n" // Delay slot
+ "2:\n"
+ ".word vdso_u_time_data - .\n" // Embedded offset to external symbol
+ "3:\n"
+ "add %%o7, 2b - 1b, %%o7\n" // Point %o7 to the embedded offset
+ "ldsw [%%o7], %0\n" // Load the offset
+ "add %0, %%o7, %0\n" // Calculate the absolute address
+ : "=r" (ret)
+ :
+ : "o7");
+
+ return (const struct vdso_time_data *)ret;
+}
+#define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data
+
#endif /* _ASM_SPARC_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/sparc/include/asm/vdso/vsyscall.h b/arch/sparc/include/asm/vdso/vsyscall.h
new file mode 100644
index 000000000000..8bfe703fedc5
--- /dev/null
+++ b/arch/sparc/include/asm/vdso/vsyscall.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_SPARC_VDSO_VSYSCALL_H
+#define _ASM_SPARC_VDSO_VSYSCALL_H
+
+#define __VDSO_PAGES 4
+
+#include <asm-generic/vdso/vsyscall.h>
+
+#endif /* _ASM_SPARC_VDSO_VSYSCALL_H */
diff --git a/arch/sparc/include/asm/vvar.h b/arch/sparc/include/asm/vvar.h
deleted file mode 100644
index 6eaf5cfcaae1..000000000000
--- a/arch/sparc/include/asm/vvar.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _ASM_SPARC_VVAR_DATA_H
-#define _ASM_SPARC_VVAR_DATA_H
-
-#include <asm/clocksource.h>
-#include <asm/processor.h>
-#include <asm/barrier.h>
-#include <linux/time.h>
-#include <linux/types.h>
-
-struct vvar_data {
- unsigned int seq;
-
- int vclock_mode;
- struct { /* extract of a clocksource struct */
- u64 cycle_last;
- u64 mask;
- int mult;
- int shift;
- } clock;
- /* open coded 'struct timespec' */
- u64 wall_time_sec;
- u64 wall_time_snsec;
- u64 monotonic_time_snsec;
- u64 monotonic_time_sec;
- u64 monotonic_time_coarse_sec;
- u64 monotonic_time_coarse_nsec;
- u64 wall_time_coarse_sec;
- u64 wall_time_coarse_nsec;
-
- int tz_minuteswest;
- int tz_dsttime;
-};
-
-extern struct vvar_data *vvar_data;
-extern int vdso_fix_stick;
-
-static inline unsigned int vvar_read_begin(const struct vvar_data *s)
-{
- unsigned int ret;
-
-repeat:
- ret = READ_ONCE(s->seq);
- if (unlikely(ret & 1)) {
- cpu_relax();
- goto repeat;
- }
- smp_rmb(); /* Finish all reads before we return seq */
- return ret;
-}
-
-static inline int vvar_read_retry(const struct vvar_data *s,
- unsigned int start)
-{
- smp_rmb(); /* Finish all reads before checking the value of seq */
- return unlikely(s->seq != start);
-}
-
-static inline void vvar_write_begin(struct vvar_data *s)
-{
- ++s->seq;
- smp_wmb(); /* Makes sure that increment of seq is reflected */
-}
-
-static inline void vvar_write_end(struct vvar_data *s)
-{
- smp_wmb(); /* Makes the value of seq current before we increment */
- ++s->seq;
-}
-
-
-#endif /* _ASM_SPARC_VVAR_DATA_H */
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 22170d4f8e06..497b5714fa8f 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_SPARC32) += systbls_32.o
obj-y += time_$(BITS).o
obj-$(CONFIG_SPARC32) += windows.o
obj-y += cpu.o
-obj-$(CONFIG_SPARC64) += vdso.o
obj-$(CONFIG_SPARC32) += devices.o
obj-y += ptrace_$(BITS).o
obj-y += unaligned_$(BITS).o
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index b32f27f929d1..87b267043ccd 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -838,14 +838,14 @@ void __init time_init_early(void)
if (tlb_type == spitfire) {
if (is_hummingbird()) {
init_tick_ops(&hbtick_operations);
- clocksource_tick.archdata.vclock_mode = VCLOCK_NONE;
+ clocksource_tick.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
} else {
init_tick_ops(&tick_operations);
- clocksource_tick.archdata.vclock_mode = VCLOCK_TICK;
+ clocksource_tick.vdso_clock_mode = VDSO_CLOCKMODE_TICK;
}
} else {
init_tick_ops(&stick_operations);
- clocksource_tick.archdata.vclock_mode = VCLOCK_STICK;
+ clocksource_tick.vdso_clock_mode = VDSO_CLOCKMODE_STICK;
}
}
diff --git a/arch/sparc/kernel/vdso.c b/arch/sparc/kernel/vdso.c
deleted file mode 100644
index 0e27437eb97b..000000000000
--- a/arch/sparc/kernel/vdso.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
- * Copyright 2003 Andi Kleen, SuSE Labs.
- *
- * Thanks to hpa@transmeta.com for some useful hint.
- * Special thanks to Ingo Molnar for his early experience with
- * a different vsyscall implementation for Linux/IA32 and for the name.
- */
-
-#include <linux/time.h>
-#include <linux/timekeeper_internal.h>
-
-#include <asm/vvar.h>
-
-void update_vsyscall_tz(void)
-{
- if (unlikely(vvar_data == NULL))
- return;
-
- vvar_data->tz_minuteswest = sys_tz.tz_minuteswest;
- vvar_data->tz_dsttime = sys_tz.tz_dsttime;
-}
-
-void update_vsyscall(struct timekeeper *tk)
-{
- struct vvar_data *vdata = vvar_data;
-
- if (unlikely(vdata == NULL))
- return;
-
- vvar_write_begin(vdata);
- vdata->vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode;
- vdata->clock.cycle_last = tk->tkr_mono.cycle_last;
- vdata->clock.mask = tk->tkr_mono.mask;
- vdata->clock.mult = tk->tkr_mono.mult;
- vdata->clock.shift = tk->tkr_mono.shift;
-
- vdata->wall_time_sec = tk->xtime_sec;
- vdata->wall_time_snsec = tk->tkr_mono.xtime_nsec;
-
- vdata->monotonic_time_sec = tk->xtime_sec +
- tk->wall_to_monotonic.tv_sec;
- vdata->monotonic_time_snsec = tk->tkr_mono.xtime_nsec +
- (tk->wall_to_monotonic.tv_nsec <<
- tk->tkr_mono.shift);
-
- while (vdata->monotonic_time_snsec >=
- (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
- vdata->monotonic_time_snsec -=
- ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift;
- vdata->monotonic_time_sec++;
- }
-
- vdata->wall_time_coarse_sec = tk->xtime_sec;
- vdata->wall_time_coarse_nsec =
- (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
-
- vdata->monotonic_time_coarse_sec =
- vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
- vdata->monotonic_time_coarse_nsec =
- vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec;
-
- while (vdata->monotonic_time_coarse_nsec >= NSEC_PER_SEC) {
- vdata->monotonic_time_coarse_nsec -= NSEC_PER_SEC;
- vdata->monotonic_time_coarse_sec++;
- }
-
- vvar_write_end(vdata);
-}
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index 2e911ccc9db7..1822676b4ebd 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -3,6 +3,9 @@
# Building vDSO images for sparc.
#
+# Include the generic Makefile to check the built vDSO:
+include $(srctree)/lib/vdso/Makefile.include
+
# files to link into the vdso
vobjs-y := vdso-note.o vclock_gettime.o
@@ -105,6 +108,7 @@ $(obj)/vdso32.so.dbg: FORCE \
quiet_cmd_vdso = VDSO $@
cmd_vdso = $(LD) -nostdlib -o $@ \
$(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
- -T $(filter %.lds,$^) $(filter %.o,$^)
+ -T $(filter %.lds,$^) $(filter %.o,$^); \
+ $(cmd_vdso_check)
VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 -Bsymbolic --no-undefined -z noexecstack
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index e768c0b84b34..093a7ff4dafc 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -12,169 +12,40 @@
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
*/
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/io.h>
-#include <asm/timex.h>
-#include <asm/clocksource.h>
-#include <asm/vdso/gettimeofday.h>
-#include <asm/vvar.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
-/*
- * Compute the vvar page's address in the process address space, and return it
- * as a pointer to the vvar_data.
- */
-notrace static __always_inline struct vvar_data *get_vvar_data(void)
-{
- unsigned long ret;
+#include <vdso/gettime.h>
- /*
- * vdso data page is the first vDSO page so grab the PC
- * and move up a page to get to the data page.
- */
- __asm__("rd %%pc, %0" : "=r" (ret));
- ret &= ~(8192 - 1);
- ret -= 8192;
+#include <asm/vdso/gettimeofday.h>
- return (struct vvar_data *) ret;
-}
+#include "../../../../lib/vdso/gettimeofday.c"
-notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
{
- u64 v;
- u64 cycles = __arch_get_hw_counter(vvar);
-
- v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
- return v * vvar->clock.mult;
+ return __cvdso_gettimeofday(tv, tz);
}
-notrace static __always_inline int do_realtime(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
-{
- unsigned long seq;
- u64 ns;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->wall_time_sec;
- ns = vvar->wall_time_snsec;
- ns += vgetsns(vvar);
- ns = vdso_shift_ns(ns, vvar->clock.shift);
- } while (unlikely(vvar_read_retry(vvar, seq)));
-
- ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
- ts->tv_nsec = ns;
+int gettimeofday(struct __kernel_old_timeval *, struct timezone *)
+ __weak __alias(__vdso_gettimeofday);
- return 0;
-}
-
-notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
+#if defined(CONFIG_SPARC64)
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
{
- unsigned long seq;
- u64 ns;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->monotonic_time_sec;
- ns = vvar->monotonic_time_snsec;
- ns += vgetsns(vvar);
- ns = vdso_shift_ns(ns, vvar->clock.shift);
- } while (unlikely(vvar_read_retry(vvar, seq)));
-
- ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
- ts->tv_nsec = ns;
-
- return 0;
-}
-
-notrace static int do_realtime_coarse(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
-{
- unsigned long seq;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->wall_time_coarse_sec;
- ts->tv_nsec = vvar->wall_time_coarse_nsec;
- } while (unlikely(vvar_read_retry(vvar, seq)));
- return 0;
+ return __cvdso_clock_gettime(clock, ts);
}
-notrace static int do_monotonic_coarse(struct vvar_data *vvar,
- struct __kernel_old_timespec *ts)
-{
- unsigned long seq;
-
- do {
- seq = vvar_read_begin(vvar);
- ts->tv_sec = vvar->monotonic_time_coarse_sec;
- ts->tv_nsec = vvar->monotonic_time_coarse_nsec;
- } while (unlikely(vvar_read_retry(vvar, seq)));
+int clock_gettime(clockid_t, struct __kernel_timespec *)
+ __weak __alias(__vdso_clock_gettime);
- return 0;
-}
+#else
-notrace int
-__vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts)
+int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts)
{
- struct vvar_data *vvd = get_vvar_data();
-
- switch (clock) {
- case CLOCK_REALTIME:
- if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
- break;
- return do_realtime(vvd, ts);
- case CLOCK_MONOTONIC:
- if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
- break;
- return do_monotonic(vvd, ts);
- case CLOCK_REALTIME_COARSE:
- return do_realtime_coarse(vvd, ts);
- case CLOCK_MONOTONIC_COARSE:
- return do_monotonic_coarse(vvd, ts);
- }
- /*
- * Unknown clock ID ? Fall back to the syscall.
- */
- return clock_gettime_fallback(clock, ts);
+ return __cvdso_clock_gettime32(clock, ts);
}
-int
-clock_gettime(clockid_t, struct __kernel_old_timespec *)
- __attribute__((weak, alias("__vdso_clock_gettime")));
-notrace int
-__vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
-{
- struct vvar_data *vvd = get_vvar_data();
+int clock_gettime(clockid_t, struct old_timespec32 *)
+ __weak __alias(__vdso_clock_gettime);
- if (likely(vvd->vclock_mode != VCLOCK_NONE)) {
- if (likely(tv != NULL)) {
- union tstv_t {
- struct __kernel_old_timespec ts;
- struct __kernel_old_timeval tv;
- } *tstv = (union tstv_t *) tv;
- do_realtime(vvd, &tstv->ts);
- /*
- * Assign before dividing to ensure that the division is
- * done in the type of tv_usec, not tv_nsec.
- *
- * There cannot be > 1 billion usec in a second:
- * do_realtime() has already distributed such overflow
- * into tv_sec. So we can assign it to an int safely.
- */
- tstv->tv.tv_usec = tstv->ts.tv_nsec;
- tstv->tv.tv_usec /= 1000;
- }
- if (unlikely(tz != NULL)) {
- /* Avoid memcpy. Some old compilers fail to inline it */
- tz->tz_minuteswest = vvd->tz_minuteswest;
- tz->tz_dsttime = vvd->tz_dsttime;
- }
- return 0;
- }
- return gettimeofday_fallback(tv, tz);
-}
-int
-gettimeofday(struct __kernel_old_timeval *, struct timezone *)
- __attribute__((weak, alias("__vdso_gettimeofday")));
+#endif
diff --git a/arch/sparc/vdso/vdso-layout.lds.S b/arch/sparc/vdso/vdso-layout.lds.S
index 9e0804789d11..180e5d0ee071 100644
--- a/arch/sparc/vdso/vdso-layout.lds.S
+++ b/arch/sparc/vdso/vdso-layout.lds.S
@@ -4,6 +4,10 @@
* This script controls its layout.
*/
+#include <vdso/datapage.h>
+#include <vdso/page.h>
+#include <asm/vdso/vsyscall.h>
+
SECTIONS
{
/*
@@ -13,8 +17,7 @@ SECTIONS
* segment. Page size is 8192 for both 64-bit and 32-bit vdso binaries
*/
- vvar_start = . -8192;
- vvar_data = vvar_start;
+ VDSO_VVAR_SYMS
. = SIZEOF_HEADERS;
diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c
index 1f47d8341e43..60029d60f4d3 100644
--- a/arch/sparc/vdso/vma.c
+++ b/arch/sparc/vdso/vma.c
@@ -16,17 +16,16 @@
#include <linux/linkage.h>
#include <linux/random.h>
#include <linux/elf.h>
+#include <linux/vdso_datastore.h>
#include <asm/cacheflush.h>
#include <asm/spitfire.h>
#include <asm/vdso.h>
-#include <asm/vvar.h>
#include <asm/page.h>
-unsigned int __read_mostly vdso_enabled = 1;
+#include <vdso/datapage.h>
+#include <asm/vdso/vsyscall.h>
-static struct vm_special_mapping vvar_mapping = {
- .name = "[vvar]"
-};
+unsigned int __read_mostly vdso_enabled = 1;
#ifdef CONFIG_SPARC64
static struct vm_special_mapping vdso_mapping64 = {
@@ -40,10 +39,8 @@ static struct vm_special_mapping vdso_mapping32 = {
};
#endif
-struct vvar_data *vvar_data;
-
/*
- * Allocate pages for the vdso and vvar, and copy in the vdso text from the
+ * Allocate pages for the vdso and copy in the vdso text from the
* kernel image.
*/
static int __init init_vdso_image(const struct vdso_image *image,
@@ -51,9 +48,8 @@ static int __init init_vdso_image(const struct vdso_image *image,
bool elf64)
{
int cnpages = (image->size) / PAGE_SIZE;
- struct page *dp, **dpp = NULL;
struct page *cp, **cpp = NULL;
- int i, dnpages = 0;
+ int i;
/*
* First, the vdso text. This is initialied data, an integral number of
@@ -76,31 +72,6 @@ static int __init init_vdso_image(const struct vdso_image *image,
copy_page(page_address(cp), image->data + i * PAGE_SIZE);
}
- /*
- * Now the vvar page. This is uninitialized data.
- */
-
- if (vvar_data == NULL) {
- dnpages = (sizeof(struct vvar_data) / PAGE_SIZE) + 1;
- if (WARN_ON(dnpages != 1))
- goto oom;
- dpp = kzalloc_objs(struct page *, dnpages);
- vvar_mapping.pages = dpp;
-
- if (!dpp)
- goto oom;
-
- dp = alloc_page(GFP_KERNEL);
- if (!dp)
- goto oom;
-
- dpp[0] = dp;
- vvar_data = page_address(dp);
- memset(vvar_data, 0, PAGE_SIZE);
-
- vvar_data->seq = 0;
- }
-
return 0;
oom:
if (cpp != NULL) {
@@ -112,15 +83,6 @@ static int __init init_vdso_image(const struct vdso_image *image,
vdso_mapping->pages = NULL;
}
- if (dpp != NULL) {
- for (i = 0; i < dnpages; i++) {
- if (dpp[i] != NULL)
- __free_page(dpp[i]);
- }
- kfree(dpp);
- vvar_mapping.pages = NULL;
- }
-
pr_warn("Cannot allocate vdso\n");
vdso_enabled = 0;
return -ENOMEM;
@@ -155,9 +117,12 @@ static unsigned long vdso_addr(unsigned long start, unsigned int len)
return start + (offset << PAGE_SHIFT);
}
+static_assert(VDSO_NR_PAGES == __VDSO_PAGES);
+
static int map_vdso(const struct vdso_image *image,
struct vm_special_mapping *vdso_mapping)
{
+ const size_t area_size = image->size + VDSO_NR_PAGES * PAGE_SIZE;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned long text_start, addr = 0;
@@ -170,23 +135,20 @@ static int map_vdso(const struct vdso_image *image,
* region is free.
*/
if (current->flags & PF_RANDOMIZE) {
- addr = get_unmapped_area(NULL, 0,
- image->size - image->sym_vvar_start,
- 0, 0);
+ addr = get_unmapped_area(NULL, 0, area_size, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
}
- addr = vdso_addr(addr, image->size - image->sym_vvar_start);
+ addr = vdso_addr(addr, area_size);
}
- addr = get_unmapped_area(NULL, addr,
- image->size - image->sym_vvar_start, 0, 0);
+ addr = get_unmapped_area(NULL, addr, area_size, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
}
- text_start = addr - image->sym_vvar_start;
+ text_start = addr + VDSO_NR_PAGES * PAGE_SIZE;
current->mm->context.vdso = (void __user *)text_start;
/*
@@ -204,11 +166,7 @@ static int map_vdso(const struct vdso_image *image,
goto up_fail;
}
- vma = _install_special_mapping(mm,
- addr,
- -image->sym_vvar_start,
- VM_READ|VM_MAYREAD,
- &vvar_mapping);
+ vma = vdso_install_vvar_mapping(mm, addr);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 11/14] sparc64: vdso2c: Drop sym_vvar_start handling
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (9 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 10/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 12/14] sparc64: vdso2c: Remove symbol handling Thomas Weißschuh
` (3 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
After the adoption of the generic vDSO library this symbol does not exist.
The alignment invariant is now guaranteed by the generic code.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/include/asm/vdso.h | 2 --
arch/sparc/vdso/vdso2c.c | 6 ------
arch/sparc/vdso/vdso2c.h | 4 ----
3 files changed, 12 deletions(-)
diff --git a/arch/sparc/include/asm/vdso.h b/arch/sparc/include/asm/vdso.h
index 59e79d35cd73..f08562d10215 100644
--- a/arch/sparc/include/asm/vdso.h
+++ b/arch/sparc/include/asm/vdso.h
@@ -8,8 +8,6 @@
struct vdso_image {
void *data;
unsigned long size; /* Always a multiple of PAGE_SIZE */
-
- long sym_vvar_start; /* Negative offset to the vvar area */
};
#ifdef CONFIG_SPARC64
diff --git a/arch/sparc/vdso/vdso2c.c b/arch/sparc/vdso/vdso2c.c
index b97af5ec9f35..70b14a436fe2 100644
--- a/arch/sparc/vdso/vdso2c.c
+++ b/arch/sparc/vdso/vdso2c.c
@@ -58,18 +58,12 @@
const char *outfilename;
-/* Symbols that we need in vdso2c. */
-enum {
- sym_vvar_start,
-};
-
struct vdso_sym {
const char *name;
int export;
};
struct vdso_sym required_syms[] = {
- [sym_vvar_start] = {"vvar_start", 1},
};
__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
diff --git a/arch/sparc/vdso/vdso2c.h b/arch/sparc/vdso/vdso2c.h
index 60d69acc748f..ba0794659eb5 100644
--- a/arch/sparc/vdso/vdso2c.h
+++ b/arch/sparc/vdso/vdso2c.h
@@ -104,10 +104,6 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
}
}
- /* Validate mapping addresses. */
- if (syms[sym_vvar_start] % 8192)
- fail("vvar_begin must be a multiple of 8192\n");
-
if (!name) {
fwrite(stripped_addr, stripped_len, 1, outfile);
return;
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 12/14] sparc64: vdso2c: Remove symbol handling
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (10 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 11/14] sparc64: vdso2c: Drop sym_vvar_start handling Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 13/14] sparc64: vdso: Implement clock_gettime64() Thomas Weißschuh
` (2 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
There are no handled symbols left.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/vdso/vdso2c.c | 10 ----------
arch/sparc/vdso/vdso2c.h | 41 +----------------------------------------
2 files changed, 1 insertion(+), 50 deletions(-)
diff --git a/arch/sparc/vdso/vdso2c.c b/arch/sparc/vdso/vdso2c.c
index 70b14a436fe2..e5c61214a0e2 100644
--- a/arch/sparc/vdso/vdso2c.c
+++ b/arch/sparc/vdso/vdso2c.c
@@ -58,14 +58,6 @@
const char *outfilename;
-struct vdso_sym {
- const char *name;
- int export;
-};
-
-struct vdso_sym required_syms[] = {
-};
-
__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
static void fail(const char *format, ...)
{
@@ -105,8 +97,6 @@ static void fail(const char *format, ...)
#define PUT_BE(x, val) \
PBE(x, val, 64, PBE(x, val, 32, PBE(x, val, 16, LAST_PBE(x, val))))
-#define NSYMS ARRAY_SIZE(required_syms)
-
#define BITSFUNC3(name, bits, suffix) name##bits##suffix
#define BITSFUNC2(name, bits, suffix) BITSFUNC3(name, bits, suffix)
#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS, )
diff --git a/arch/sparc/vdso/vdso2c.h b/arch/sparc/vdso/vdso2c.h
index ba0794659eb5..bad6a0593f4c 100644
--- a/arch/sparc/vdso/vdso2c.h
+++ b/arch/sparc/vdso/vdso2c.h
@@ -17,11 +17,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
unsigned long mapping_size;
int i;
unsigned long j;
- ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr;
+ ELF(Shdr) *symtab_hdr = NULL;
ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
ELF(Dyn) *dyn = 0, *dyn_end = 0;
- INT_BITS syms[NSYMS] = {};
-
ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff));
/* Walk the segment table. */
@@ -72,38 +70,6 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
if (!symtab_hdr)
fail("no symbol table\n");
- strtab_hdr = raw_addr + GET_BE(&hdr->e_shoff) +
- GET_BE(&hdr->e_shentsize) * GET_BE(&symtab_hdr->sh_link);
-
- /* Walk the symbol table */
- for (i = 0;
- i < GET_BE(&symtab_hdr->sh_size) / GET_BE(&symtab_hdr->sh_entsize);
- i++) {
- int k;
-
- ELF(Sym) *sym = raw_addr + GET_BE(&symtab_hdr->sh_offset) +
- GET_BE(&symtab_hdr->sh_entsize) * i;
- const char *name = raw_addr + GET_BE(&strtab_hdr->sh_offset) +
- GET_BE(&sym->st_name);
-
- for (k = 0; k < NSYMS; k++) {
- if (!strcmp(name, required_syms[k].name)) {
- if (syms[k]) {
- fail("duplicate symbol %s\n",
- required_syms[k].name);
- }
-
- /*
- * Careful: we use negative addresses, but
- * st_value is unsigned, so we rely
- * on syms[k] being a signed type of the
- * correct width.
- */
- syms[k] = GET_BE(&sym->st_value);
- }
- }
- }
-
if (!name) {
fwrite(stripped_addr, stripped_len, 1, outfile);
return;
@@ -129,10 +95,5 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name);
fprintf(outfile, "\t.data = raw_data,\n");
fprintf(outfile, "\t.size = %lu,\n", mapping_size);
- for (i = 0; i < NSYMS; i++) {
- if (required_syms[i].export && syms[i])
- fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
- required_syms[i].name, (int64_t)syms[i]);
- }
fprintf(outfile, "};\n");
}
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 13/14] sparc64: vdso: Implement clock_gettime64()
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (11 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 12/14] sparc64: vdso2c: Remove symbol handling Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-04 7:49 ` [PATCH v6 14/14] clocksource: remove ARCH_CLOCKSOURCE_DATA Thomas Weißschuh
2026-03-05 15:17 ` [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Nathaniel Roach
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
To be y2038-safe, 32-bit userspace needs to explicitly call the 64-bit safe
time APIs.
Implement clock_gettime64() in the 32-bit vDSO.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Andreas Larsson <andreas@gaisler.com>
---
arch/sparc/include/asm/vdso/gettimeofday.h | 20 ++++++++++++++++++--
arch/sparc/vdso/vclock_gettime.c | 8 ++++++++
arch/sparc/vdso/vdso32/vdso32.lds.S | 2 ++
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/arch/sparc/include/asm/vdso/gettimeofday.h b/arch/sparc/include/asm/vdso/gettimeofday.h
index a35875fba454..b0c80c8a28bb 100644
--- a/arch/sparc/include/asm/vdso/gettimeofday.h
+++ b/arch/sparc/include/asm/vdso/gettimeofday.h
@@ -101,6 +101,8 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, const struct vd
"f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", \
"cc", "memory"
+#ifdef CONFIG_SPARC64
+
static __always_inline
long clock_gettime_fallback(clockid_t clock, struct __kernel_timespec *ts)
{
@@ -113,7 +115,20 @@ long clock_gettime_fallback(clockid_t clock, struct __kernel_timespec *ts)
return o0;
}
-#ifndef CONFIG_SPARC64
+#else /* !CONFIG_SPARC64 */
+
+static __always_inline
+long clock_gettime_fallback(clockid_t clock, struct __kernel_timespec *ts)
+{
+ register long num __asm__("g1") = __NR_clock_gettime64;
+ register long o0 __asm__("o0") = clock;
+ register long o1 __asm__("o1") = (long) ts;
+
+ __asm__ __volatile__(SYSCALL_STRING : "=r" (o0) : "r" (num),
+ "0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
+ return o0;
+}
+
static __always_inline
long clock_gettime32_fallback(clockid_t clock, struct old_timespec32 *ts)
{
@@ -125,7 +140,8 @@ long clock_gettime32_fallback(clockid_t clock, struct old_timespec32 *ts)
"0" (o0), "r" (o1) : SYSCALL_CLOBBERS);
return o0;
}
-#endif
+
+#endif /* CONFIG_SPARC64 */
static __always_inline
long gettimeofday_fallback(struct __kernel_old_timeval *tv, struct timezone *tz)
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index 093a7ff4dafc..1d9859392e4c 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -48,4 +48,12 @@ int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts)
int clock_gettime(clockid_t, struct old_timespec32 *)
__weak __alias(__vdso_clock_gettime);
+int __vdso_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts)
+{
+ return __cvdso_clock_gettime(clock, ts);
+}
+
+int clock_gettime64(clockid_t, struct __kernel_timespec *)
+ __weak __alias(__vdso_clock_gettime64);
+
#endif
diff --git a/arch/sparc/vdso/vdso32/vdso32.lds.S b/arch/sparc/vdso/vdso32/vdso32.lds.S
index 53575ee154c4..a14e4f77e6f2 100644
--- a/arch/sparc/vdso/vdso32/vdso32.lds.S
+++ b/arch/sparc/vdso/vdso32/vdso32.lds.S
@@ -17,6 +17,8 @@ VERSION {
global:
clock_gettime;
__vdso_clock_gettime;
+ clock_gettime64;
+ __vdso_clock_gettime64;
gettimeofday;
__vdso_gettimeofday;
local: *;
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v6 14/14] clocksource: remove ARCH_CLOCKSOURCE_DATA
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (12 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 13/14] sparc64: vdso: Implement clock_gettime64() Thomas Weißschuh
@ 2026-03-04 7:49 ` Thomas Weißschuh
2026-03-05 15:17 ` [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Nathaniel Roach
14 siblings, 0 replies; 19+ messages in thread
From: Thomas Weißschuh @ 2026-03-04 7:49 UTC (permalink / raw)
To: Andy Lutomirski, Vincenzo Frascino, Arnd Bergmann,
David S. Miller, Andreas Larsson, Nick Alcock, John Stultz,
Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390,
Thomas Weißschuh
From: Arnd Bergmann <arnd@arndb.de>
After sparc64, there are no remaining users of ARCH_CLOCKSOURCE_DATA
and it can just be removed.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: John Stultz <jstultz@google.com>
[Thomas: drop sparc64 bits from the patch]
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Andreas Larsson <andreas@gaisler.com>
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
---
include/linux/clocksource.h | 6 +-----
kernel/time/Kconfig | 4 ----
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 65b7c41471c3..12d853b18832 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -25,8 +25,7 @@ struct clocksource_base;
struct clocksource;
struct module;
-#if defined(CONFIG_ARCH_CLOCKSOURCE_DATA) || \
- defined(CONFIG_GENERIC_GETTIMEOFDAY)
+#if defined(CONFIG_GENERIC_GETTIMEOFDAY)
#include <asm/clocksource.h>
#endif
@@ -106,9 +105,6 @@ struct clocksource {
u64 max_idle_ns;
u32 maxadj;
u32 uncertainty_margin;
-#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
- struct arch_clocksource_data archdata;
-#endif
u64 max_cycles;
u64 max_raw_delta;
const char *name;
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index 7c6a52f7836c..fe3311877097 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -9,10 +9,6 @@
config CLOCKSOURCE_WATCHDOG
bool
-# Architecture has extra clocksource data
-config ARCH_CLOCKSOURCE_DATA
- bool
-
# Architecture has extra clocksource init called from registration
config ARCH_CLOCKSOURCE_INIT
bool
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library
2026-03-04 7:48 [PATCH v6 00/14] sparc64: vdso: Switch to the generic vDSO library Thomas Weißschuh
` (13 preceding siblings ...)
2026-03-04 7:49 ` [PATCH v6 14/14] clocksource: remove ARCH_CLOCKSOURCE_DATA Thomas Weißschuh
@ 2026-03-05 15:17 ` Nathaniel Roach
14 siblings, 0 replies; 19+ messages in thread
From: Nathaniel Roach @ 2026-03-05 15:17 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Vincenzo Frascino,
Arnd Bergmann, David S. Miller, Andreas Larsson, Nick Alcock,
John Stultz, Stephen Boyd, John Paul Adrian Glaubitz, Shuah Khan,
Catalin Marinas, Will Deacon, Theodore Ts'o,
Jason A. Donenfeld, Russell King, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Huacai Chen, WANG Xuerui,
Thomas Bogendoerfer, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Shannon Nelson, Thomas Gleixner, Christophe Leroy
Cc: linux-kernel, sparclinux, linux-kselftest, linux-arm-kernel,
linuxppc-dev, loongarch, linux-mips, linux-s390, Arnd Bergmann
No (new) issues seen on SPARC T5-2.
On 4/3/26 15:48, Thomas Weißschuh wrote:
> The generic vDSO provides a lot common functionality shared between
> different architectures. SPARC is the last architecture not using it,
> preventing some necessary code cleanup.
>
> Make use of the generic infrastructure.
>
> Follow-up to and replacement for Arnd's SPARC vDSO removal patches:
> https://lore.kernel.org/lkml/20250707144726.4008707-1-arnd@kernel.org/
>
> SPARC64 can not map .bss into userspace, so the vDSO datapages are
> switched over to be allocated dynamically.
>
> Tested on a Niagara T4 and QEMU.
>
> This has emantic conflicts with
> * "vdso: Reject absolute relocations during build" [0]
> * "vDSO: Respect COMPAT_32BIT_TIME" [1]
>
> But I expect both other serieses to need more discussions.
>
> [0] https://lore.kernel.org/lkml/20250812-vdso-absolute-reloc-v4-0-61a8b615e5ec@linutronix.de/
> [1] https://lore.kernel.org/lkml/20260227-vdso-compat_32bit_time-v1-0-3f0286a7bac3@linutronix.de/
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Tested-by: Nathaniel Roach <nroach44@nroach44.id.au> # SPARC T5-2
> ---
> Changes in v6:
> - Provide statically allocated during early boot to avoid canges to the rng core
> - Use non-compound data pages
> - Reword commit messages
> - Rebase on v7.0-rc1
> - Link to v5: https://lore.kernel.org/r/20251106-vdso-sparc64-generic-2-v5-0-97ff2b6542f7@linutronix.de
>
> Changes in v5:
> - Merge the patches for 'struct page' mapping and dynamic allocation
> - Zero out newly-allocated data pages
> - Pick up review tags
> - Link to v4: https://lore.kernel.org/r/20251014-vdso-sparc64-generic-2-v4-0-e0607bf49dea@linutronix.de
>
> Changes in v4:
> - Rebase on v6.18-rc1.
> - Keep inclusion of asm/clocksource.h from linux/clocksource.h
> - Reword description of "s390/time: Set up vDSO datapage later"
> - Link to v3: https://lore.kernel.org/r/20250917-vdso-sparc64-generic-2-v3-0-3679b1bc8ee8@linutronix.de
>
> Changes in v3:
> - Allocate vDSO data pages dynamically (and lots of preparations for that)
> - Drop clock_getres()
> - Fix 32bit clock_gettime() syscall fallback
> - Link to v2: https://lore.kernel.org/r/20250815-vdso-sparc64-generic-2-v2-0-b5ff80672347@linutronix.de
>
> Changes in v2:
> - Rebase on v6.17-rc1
> - Drop RFC state
> - Fix typo in commit message
> - Drop duplicate 'select GENERIC_TIME_VSYSCALL'
> - Merge "sparc64: time: Remove architecture-specific clocksource data" into the
> main conversion patch. It violated the check in __clocksource_register_scale()
> - Link to v1: https://lore.kernel.org/r/20250724-vdso-sparc64-generic-2-v1-0-e376a3bd24d1@linutronix.de
>
> ---
> Arnd Bergmann (1):
> clocksource: remove ARCH_CLOCKSOURCE_DATA
>
> Thomas Weißschuh (13):
> vdso/datastore: Reduce scope of some variables in vvar_fault()
> vdso/datastore: Drop inclusion of linux/mmap_lock.h
> vdso/datastore: Allocate data pages dynamically
> sparc64: vdso: Link with -z noexecstack
> sparc64: vdso: Remove obsolete "fake section table" reservation
> sparc64: vdso: Replace code patching with runtime conditional
> sparc64: vdso: Move hardware counter read into header
> sparc64: vdso: Move syscall fallbacks into header
> sparc64: vdso: Introduce vdso/processor.h
> sparc64: vdso: Switch to the generic vDSO library
> sparc64: vdso2c: Drop sym_vvar_start handling
> sparc64: vdso2c: Remove symbol handling
> sparc64: vdso: Implement clock_gettime64()
>
> arch/sparc/Kconfig | 3 +-
> arch/sparc/include/asm/clocksource.h | 9 -
> arch/sparc/include/asm/processor.h | 3 +
> arch/sparc/include/asm/processor_32.h | 2 -
> arch/sparc/include/asm/processor_64.h | 25 --
> arch/sparc/include/asm/vdso.h | 2 -
> arch/sparc/include/asm/vdso/clocksource.h | 10 +
> arch/sparc/include/asm/vdso/gettimeofday.h | 184 ++++++++++++++
> arch/sparc/include/asm/vdso/processor.h | 41 ++++
> arch/sparc/include/asm/vdso/vsyscall.h | 10 +
> arch/sparc/include/asm/vvar.h | 75 ------
> arch/sparc/kernel/Makefile | 1 -
> arch/sparc/kernel/time_64.c | 6 +-
> arch/sparc/kernel/vdso.c | 69 ------
> arch/sparc/vdso/Makefile | 8 +-
> arch/sparc/vdso/vclock_gettime.c | 380 ++---------------------------
> arch/sparc/vdso/vdso-layout.lds.S | 26 +-
> arch/sparc/vdso/vdso.lds.S | 2 -
> arch/sparc/vdso/vdso2c.c | 24 --
> arch/sparc/vdso/vdso2c.h | 45 +---
> arch/sparc/vdso/vdso32/vdso32.lds.S | 4 +-
> arch/sparc/vdso/vma.c | 274 ++-------------------
> include/linux/clocksource.h | 6 +-
> include/linux/vdso_datastore.h | 6 +
> init/main.c | 2 +
> kernel/time/Kconfig | 4 -
> lib/vdso/datastore.c | 97 +++++---
> 27 files changed, 375 insertions(+), 943 deletions(-)
> ---
> base-commit: f02e02079ac56b44ff89d4c2189cf7185ab794f3
> change-id: 20250722-vdso-sparc64-generic-2-25f2e058e92c
>
> Best regards,
^ permalink raw reply [flat|nested] 19+ messages in thread