Skip to content

Commit

Permalink
From patchwork series 436945
Browse files Browse the repository at this point in the history
  • Loading branch information
Fox Snowpatch committed Dec 16, 2024
1 parent 2dd0957 commit 2d685b7
Show file tree
Hide file tree
Showing 90 changed files with 581 additions and 1,231 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -9679,6 +9679,7 @@ F: include/asm-generic/vdso/vsyscall.h
F: include/vdso/
F: kernel/time/vsyscall.c
F: lib/vdso/
F: lib/vdso_kernel/

GENWQE (IBM Generic Workqueue Card)
M: Frank Haverkamp <[email protected]>
Expand Down
4 changes: 4 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,10 @@ config HAVE_SPARSE_SYSCALL_NR
entries at 4000, 5000 and 6000 locations. This option turns on syscall
related optimizations for a given architecture.

config ARCH_HAS_VDSO_ARCH_DATA
depends on HAVE_GENERIC_VDSO
bool

config ARCH_HAS_VDSO_TIME_DATA
bool

Expand Down
2 changes: 2 additions & 0 deletions arch/arm/include/asm/vdso.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#ifdef __KERNEL__

#define __VDSO_PAGES 4

#ifndef __ASSEMBLY__

struct mm_struct;
Expand Down
7 changes: 1 addition & 6 deletions arch/arm/include/asm/vdso/gettimeofday.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static inline bool arm_vdso_hres_capable(void)
#define __arch_vdso_hres_capable arm_vdso_hres_capable

static __always_inline u64 __arch_get_hw_counter(int clock_mode,
const struct vdso_data *vd)
const struct vdso_time_data *vd)
{
#ifdef CONFIG_ARM_ARCH_TIMER
u64 cycle_now;
Expand All @@ -135,11 +135,6 @@ static __always_inline u64 __arch_get_hw_counter(int clock_mode,
#endif
}

static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
return _vdso_data;
}

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
12 changes: 2 additions & 10 deletions arch/arm/include/asm/vdso/vsyscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,14 @@
#include <vdso/datapage.h>
#include <asm/cacheflush.h>

extern struct vdso_data *vdso_data;
extern bool cntvct_ok;

static __always_inline
struct vdso_data *__arm_get_k_vdso_data(void)
{
return vdso_data;
}
#define __arch_get_k_vdso_data __arm_get_k_vdso_data

static __always_inline
void __arm_sync_vdso_data(struct vdso_data *vdata)
void __arm_sync_vdso_time_data(struct vdso_time_data *vdata)
{
flush_dcache_page(virt_to_page(vdata));
}
#define __arch_sync_vdso_data __arm_sync_vdso_data
#define __arch_sync_vdso_time_data __arm_sync_vdso_time_data

/* The asm-generic header needs to be included after the definitions above */
#include <asm-generic/vdso/vsyscall.h>
Expand Down
4 changes: 0 additions & 4 deletions arch/arm/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,6 @@ int main(void)
DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER);
DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
BLANK();
#ifdef CONFIG_VDSO
DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store));
#endif
BLANK();
#ifdef CONFIG_ARM_MPU
DEFINE(MPU_RNG_INFO_RNGS, offsetof(struct mpu_rgn_info, rgns));
DEFINE(MPU_RNG_INFO_USED, offsetof(struct mpu_rgn_info, used));
Expand Down
34 changes: 7 additions & 27 deletions arch/arm/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

#include <linux/cache.h>
#include <linux/vdso_datastore.h>
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/kernel.h>
Expand All @@ -33,15 +34,6 @@ extern char vdso_start[], vdso_end[];
/* Total number of pages needed for the data and text portions of the VDSO. */
unsigned int vdso_total_pages __ro_after_init;

static union vdso_data_store vdso_data_store __page_aligned_data;
struct vdso_data *vdso_data = vdso_data_store.data;

static struct page *vdso_data_page __ro_after_init;
static const struct vm_special_mapping vdso_data_mapping = {
.name = "[vvar]",
.pages = &vdso_data_page,
};

static int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
Expand Down Expand Up @@ -192,9 +184,6 @@ static int __init vdso_init(void)
if (vdso_text_pagelist == NULL)
return -ENOMEM;

/* Grab the VDSO data page. */
vdso_data_page = virt_to_page(vdso_data);

/* Grab the VDSO text pages. */
for (i = 0; i < text_pages; i++) {
struct page *page;
Expand All @@ -205,7 +194,7 @@ static int __init vdso_init(void)

vdso_text_mapping.pages = vdso_text_pagelist;

vdso_total_pages = 1; /* for the data/vvar page */
vdso_total_pages = VDSO_NR_PAGES; /* for the data/vvar pages */
vdso_total_pages += text_pages;

cntvct_ok = cntvct_functional();
Expand All @@ -216,16 +205,7 @@ static int __init vdso_init(void)
}
arch_initcall(vdso_init);

static int install_vvar(struct mm_struct *mm, unsigned long addr)
{
struct vm_area_struct *vma;

vma = _install_special_mapping(mm, addr, PAGE_SIZE,
VM_READ | VM_MAYREAD,
&vdso_data_mapping);

return PTR_ERR_OR_ZERO(vma);
}
static_assert(__VDSO_PAGES == VDSO_NR_PAGES);

/* assumes mmap_lock is write-locked */
void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
Expand All @@ -238,12 +218,12 @@ void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
if (vdso_text_pagelist == NULL)
return;

if (install_vvar(mm, addr))
if (IS_ERR(vdso_install_vvar_mapping(mm, addr)))
return;

/* Account for vvar page. */
addr += PAGE_SIZE;
len = (vdso_total_pages - 1) << PAGE_SHIFT;
/* Account for vvar pages. */
addr += VDSO_NR_PAGES * PAGE_SIZE;
len = (vdso_total_pages - VDSO_NR_PAGES) << PAGE_SHIFT;

vma = _install_special_mapping(mm, addr, len,
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/vdso/vdso.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
*/

#include <linux/const.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/vdso.h>
#include <vdso/datapage.h>

OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)

SECTIONS
{
PROVIDE(_vdso_data = . - VDSO_DATA_SIZE);
VDSO_VVAR_SYMS

. = SIZEOF_HEADERS;

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/vdso.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H

#define __VVAR_PAGES 2
#define __VDSO_PAGES 4

#ifndef __ASSEMBLY__

Expand Down
32 changes: 17 additions & 15 deletions arch/arm64/include/asm/vdso/compat_gettimeofday.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
}

static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
const struct vdso_data *vd)
const struct vdso_time_data *vd)
{
u64 res;

Expand All @@ -131,43 +131,45 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
return res;
}

static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
static __always_inline const struct vdso_time_data *__aarch64_get_vdso_u_time_data(void)
{
const struct vdso_data *ret;
const struct vdso_time_data *ret;

/*
* This simply puts &_vdso_data into ret. The reason why we don't use
* `ret = _vdso_data` is that the compiler tends to optimise this in a
* very suboptimal way: instead of keeping &_vdso_data in a register,
* it goes through a relocation almost every time _vdso_data must be
* This simply puts &_vdso_time_data into ret. The reason why we don't use
* `ret = _vdso_time_data` is that the compiler tends to optimise this in a
* very suboptimal way: instead of keeping &_vdso_time_data in a register,
* it goes through a relocation almost every time _vdso_time_data must be
* accessed (even in subfunctions). This is both time and space
* consuming: each relocation uses a word in the code section, and it
* has to be loaded at runtime.
*
* This trick hides the assignment from the compiler. Since it cannot
* track where the pointer comes from, it will only use one relocation
* where __arch_get_vdso_data() is called, and then keep the result in
* a register.
* where __aarch64_get_vdso_u_time_data() is called, and then keep the
* result in a register.
*/
asm volatile("mov %0, %1" : "=r"(ret) : "r"(_vdso_data));
asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_time_data));

return ret;
}
#define __arch_get_vdso_u_time_data __aarch64_get_vdso_u_time_data

#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
const struct vdso_time_data *__aarch64_get_vdso_u_timens_data(void)
{
const struct vdso_data *ret;
const struct vdso_time_data *ret;

/* See __arch_get_vdso_data(). */
asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));
/* See __aarch64_get_vdso_u_time_data(). */
asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_timens_data));

return ret;
}
#define __arch_get_vdso_u_timens_data __aarch64_get_vdso_u_timens_data
#endif

static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
{
return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
}
Expand Down
12 changes: 0 additions & 12 deletions arch/arm64/include/asm/vdso/getrandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,6 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
return ret;
}

static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
/*
* The RNG data is in the real VVAR data page, but if a task belongs to a time namespace
* then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_
* PAGE_OFFSET points to the real VVAR page.
*/
if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * (1UL << CONFIG_PAGE_SHIFT);
return &_vdso_rng_data;
}

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETRANDOM_H */
16 changes: 1 addition & 15 deletions arch/arm64/include/asm/vdso/gettimeofday.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
}

static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
const struct vdso_data *vd)
const struct vdso_time_data *vd)
{
u64 res;

Expand Down Expand Up @@ -99,20 +99,6 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
return res;
}

static __always_inline
const struct vdso_data *__arch_get_vdso_data(void)
{
return _vdso_data;
}

#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
return _timens_data;
}
#endif

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
25 changes: 1 addition & 24 deletions arch/arm64/include/asm/vdso/vsyscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,18 @@
#ifndef __ASM_VDSO_VSYSCALL_H
#define __ASM_VDSO_VSYSCALL_H

#define __VDSO_RND_DATA_OFFSET 480

#ifndef __ASSEMBLY__

#include <vdso/datapage.h>

enum vvar_pages {
VVAR_DATA_PAGE_OFFSET,
VVAR_TIMENS_PAGE_OFFSET,
VVAR_NR_PAGES,
};

#define VDSO_PRECISION_MASK ~(0xFF00ULL<<48)

extern struct vdso_data *vdso_data;

/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline
struct vdso_data *__arm64_get_k_vdso_data(void)
{
return vdso_data;
}
#define __arch_get_k_vdso_data __arm64_get_k_vdso_data

static __always_inline
struct vdso_rng_data *__arm64_get_k_vdso_rnd_data(void)
{
return (void *)vdso_data + __VDSO_RND_DATA_OFFSET;
}
#define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data

static __always_inline
void __arm64_update_vsyscall(struct vdso_data *vdata)
void __arm64_update_vsyscall(struct vdso_time_data *vdata)
{
vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK;
vdata[CS_RAW].mask = VDSO_PRECISION_MASK;
Expand Down
Loading

0 comments on commit 2d685b7

Please sign in to comment.