powerpc/vdso: Switch to generic storage implementation
The generic storage implementation provides the same features as the custom one. However it can be shared between architectures, making maintenance easier. Co-developed-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-14-13a4669dfc8c@linutronix.de
This commit is contained in:
committed by
Thomas Gleixner
parent
69896119dc
commit
223970df2b
@@ -159,6 +159,7 @@ config PPC
|
|||||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
select ARCH_HAS_UACCESS_FLUSHCACHE
|
select ARCH_HAS_UACCESS_FLUSHCACHE
|
||||||
select ARCH_HAS_UBSAN
|
select ARCH_HAS_UBSAN
|
||||||
|
select ARCH_HAS_VDSO_ARCH_DATA
|
||||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||||
select ARCH_HAVE_EXTRA_ELF_NOTES if SPU_BASE
|
select ARCH_HAVE_EXTRA_ELF_NOTES if SPU_BASE
|
||||||
select ARCH_KEEP_MEMBLOCK
|
select ARCH_KEEP_MEMBLOCK
|
||||||
@@ -209,6 +210,7 @@ config PPC
|
|||||||
select GENERIC_PTDUMP
|
select GENERIC_PTDUMP
|
||||||
select GENERIC_SMP_IDLE_THREAD
|
select GENERIC_SMP_IDLE_THREAD
|
||||||
select GENERIC_TIME_VSYSCALL
|
select GENERIC_TIME_VSYSCALL
|
||||||
|
select GENERIC_VDSO_DATA_STORE
|
||||||
select GENERIC_VDSO_TIME_NS
|
select GENERIC_VDSO_TIME_NS
|
||||||
select HAS_IOPORT if PCI
|
select HAS_IOPORT if PCI
|
||||||
select HAVE_ARCH_AUDITSYSCALL
|
select HAVE_ARCH_AUDITSYSCALL
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#define _ASM_POWERPC_VDSO_H
|
#define _ASM_POWERPC_VDSO_H
|
||||||
|
|
||||||
#define VDSO_VERSION_STRING LINUX_2.6.15
|
#define VDSO_VERSION_STRING LINUX_2.6.15
|
||||||
|
#define __VDSO_PAGES 4
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
|
||||||
|
* Copyright (C) 2005 Benjamin Herrenschmidy <benh@kernel.crashing.org>,
|
||||||
|
* IBM Corp.
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_POWERPC_VDSO_ARCH_DATA_H
|
||||||
|
#define _ASM_POWERPC_VDSO_ARCH_DATA_H
|
||||||
|
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
|
|
||||||
|
struct vdso_arch_data {
|
||||||
|
__u64 tb_ticks_per_sec; /* Timebase tics / sec */
|
||||||
|
__u32 dcache_block_size; /* L1 d-cache block size */
|
||||||
|
__u32 icache_block_size; /* L1 i-cache block size */
|
||||||
|
__u32 dcache_log_block_size; /* L1 d-cache log block size */
|
||||||
|
__u32 icache_log_block_size; /* L1 i-cache log block size */
|
||||||
|
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||||
|
__u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat syscalls */
|
||||||
|
};
|
||||||
|
|
||||||
|
#else /* CONFIG_PPC64 */
|
||||||
|
|
||||||
|
struct vdso_arch_data {
|
||||||
|
__u64 tb_ticks_per_sec; /* Timebase tics / sec */
|
||||||
|
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||||
|
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
|
#endif /* _ASM_POWERPC_VDSO_ARCH_DATA_H */
|
||||||
@@ -43,20 +43,21 @@ static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsig
|
|||||||
(unsigned long)len, (unsigned long)flags);
|
(unsigned long)len, (unsigned long)flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline struct vdso_rng_data *__arch_get_vdso_rng_data(void)
|
static __always_inline const struct vdso_rng_data *__arch_get_vdso_u_rng_data(void)
|
||||||
{
|
{
|
||||||
struct vdso_arch_data *data;
|
struct vdso_rng_data *data;
|
||||||
|
|
||||||
asm (
|
asm (
|
||||||
" bcl 20, 31, .+4 ;"
|
" bcl 20, 31, .+4 ;"
|
||||||
"0: mflr %0 ;"
|
"0: mflr %0 ;"
|
||||||
" addis %0, %0, (_vdso_datapage - 0b)@ha ;"
|
" addis %0, %0, (vdso_u_rng_data - 0b)@ha ;"
|
||||||
" addi %0, %0, (_vdso_datapage - 0b)@l ;"
|
" addi %0, %0, (vdso_u_rng_data - 0b)@l ;"
|
||||||
: "=r" (data) : : "lr"
|
: "=r" (data) : : "lr"
|
||||||
);
|
);
|
||||||
|
|
||||||
return &data->rng_data;
|
return data;
|
||||||
}
|
}
|
||||||
|
#define __arch_get_vdso_u_rng_data __arch_get_vdso_u_rng_data
|
||||||
|
|
||||||
ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state,
|
ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state,
|
||||||
size_t opaque_len);
|
size_t opaque_len);
|
||||||
|
|||||||
@@ -94,22 +94,12 @@ int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
|
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return get_tb();
|
return get_tb();
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct vdso_data *__arch_get_vdso_data(void);
|
static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
|
||||||
|
|
||||||
#ifdef CONFIG_TIME_NS
|
|
||||||
static __always_inline
|
|
||||||
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
|
|
||||||
{
|
|
||||||
return (void *)vd + (1U << CONFIG_PAGE_SHIFT);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -135,21 +125,22 @@ static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
|
|||||||
|
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
|
int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
|
int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
#else
|
#else
|
||||||
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
|
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
|
int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
|
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
#endif
|
#endif
|
||||||
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
|
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
|
__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
|
||||||
const struct vdso_data *vd);
|
const struct vdso_time_data *vd);
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */
|
#endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */
|
||||||
|
|||||||
@@ -6,19 +6,6 @@
|
|||||||
|
|
||||||
#include <asm/vdso_datapage.h>
|
#include <asm/vdso_datapage.h>
|
||||||
|
|
||||||
static __always_inline
|
|
||||||
struct vdso_data *__arch_get_k_vdso_data(void)
|
|
||||||
{
|
|
||||||
return vdso_data->data;
|
|
||||||
}
|
|
||||||
#define __arch_get_k_vdso_data __arch_get_k_vdso_data
|
|
||||||
|
|
||||||
static __always_inline
|
|
||||||
struct vdso_rng_data *__arch_get_k_vdso_rng_data(void)
|
|
||||||
{
|
|
||||||
return &vdso_data->rng_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The asm-generic header needs to be included after the definitions above */
|
/* The asm-generic header needs to be included after the definitions above */
|
||||||
#include <asm-generic/vdso/vsyscall.h>
|
#include <asm-generic/vdso/vsyscall.h>
|
||||||
|
|
||||||
|
|||||||
@@ -11,56 +11,18 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/unistd.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <vdso/datapage.h>
|
#include <vdso/datapage.h>
|
||||||
|
|
||||||
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
|
|
||||||
struct vdso_arch_data {
|
|
||||||
__u64 tb_ticks_per_sec; /* Timebase tics / sec */
|
|
||||||
__u32 dcache_block_size; /* L1 d-cache block size */
|
|
||||||
__u32 icache_block_size; /* L1 i-cache block size */
|
|
||||||
__u32 dcache_log_block_size; /* L1 d-cache log block size */
|
|
||||||
__u32 icache_log_block_size; /* L1 i-cache log block size */
|
|
||||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
|
||||||
__u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat syscalls */
|
|
||||||
|
|
||||||
struct vdso_rng_data rng_data;
|
|
||||||
|
|
||||||
struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
|
|
||||||
};
|
|
||||||
|
|
||||||
#else /* CONFIG_PPC64 */
|
|
||||||
|
|
||||||
struct vdso_arch_data {
|
|
||||||
__u64 tb_ticks_per_sec; /* Timebase tics / sec */
|
|
||||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
|
||||||
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
|
||||||
struct vdso_rng_data rng_data;
|
|
||||||
|
|
||||||
struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CONFIG_PPC64 */
|
|
||||||
|
|
||||||
extern struct vdso_arch_data *vdso_data;
|
|
||||||
|
|
||||||
#else /* __ASSEMBLY__ */
|
#else /* __ASSEMBLY__ */
|
||||||
|
|
||||||
.macro get_datapage ptr offset=0
|
.macro get_datapage ptr symbol
|
||||||
bcl 20, 31, .+4
|
bcl 20, 31, .+4
|
||||||
999:
|
999:
|
||||||
mflr \ptr
|
mflr \ptr
|
||||||
addis \ptr, \ptr, (_vdso_datapage - 999b + \offset)@ha
|
addis \ptr, \ptr, (\symbol - 999b)@ha
|
||||||
addi \ptr, \ptr, (_vdso_datapage - 999b + \offset)@l
|
addi \ptr, \ptr, (\symbol - 999b)@l
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#include <asm/asm-offsets.h>
|
|
||||||
#include <asm/page.h>
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|||||||
@@ -334,7 +334,6 @@ int main(void)
|
|||||||
#endif /* ! CONFIG_PPC64 */
|
#endif /* ! CONFIG_PPC64 */
|
||||||
|
|
||||||
/* datapage offsets for use by vdso */
|
/* datapage offsets for use by vdso */
|
||||||
OFFSET(VDSO_DATA_OFFSET, vdso_arch_data, data);
|
|
||||||
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec);
|
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec);
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size);
|
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size);
|
||||||
|
|||||||
@@ -950,7 +950,7 @@ void __init time_init(void)
|
|||||||
sys_tz.tz_dsttime = 0;
|
sys_tz.tz_dsttime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
|
vdso_k_arch_data->tb_ticks_per_sec = tb_ticks_per_sec;
|
||||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||||
systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
|
systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+11
-104
@@ -17,7 +17,7 @@
|
|||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/time_namespace.h>
|
#include <linux/vdso_datastore.h>
|
||||||
#include <vdso/datapage.h>
|
#include <vdso/datapage.h>
|
||||||
|
|
||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
@@ -32,6 +32,8 @@
|
|||||||
#include <asm/vdso_datapage.h>
|
#include <asm/vdso_datapage.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
|
static_assert(__VDSO_PAGES == VDSO_NR_PAGES);
|
||||||
|
|
||||||
/* The alignment of the vDSO */
|
/* The alignment of the vDSO */
|
||||||
#define VDSO_ALIGNMENT (1 << 16)
|
#define VDSO_ALIGNMENT (1 << 16)
|
||||||
|
|
||||||
@@ -40,24 +42,6 @@ extern char vdso64_start, vdso64_end;
|
|||||||
|
|
||||||
long sys_ni_syscall(void);
|
long sys_ni_syscall(void);
|
||||||
|
|
||||||
/*
|
|
||||||
* The vdso data page (aka. systemcfg for old ppc64 fans) is here.
|
|
||||||
* Once the early boot kernel code no longer needs to muck around
|
|
||||||
* with it, it will become dynamically allocated
|
|
||||||
*/
|
|
||||||
static union {
|
|
||||||
struct vdso_arch_data data;
|
|
||||||
u8 page[2 * PAGE_SIZE];
|
|
||||||
} vdso_data_store __page_aligned_data;
|
|
||||||
struct vdso_arch_data *vdso_data = &vdso_data_store.data;
|
|
||||||
|
|
||||||
enum vvar_pages {
|
|
||||||
VVAR_BASE_PAGE_OFFSET,
|
|
||||||
VVAR_TIME_PAGE_OFFSET,
|
|
||||||
VVAR_TIMENS_PAGE_OFFSET,
|
|
||||||
VVAR_NR_PAGES,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma,
|
static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma,
|
||||||
unsigned long text_size)
|
unsigned long text_size)
|
||||||
{
|
{
|
||||||
@@ -96,14 +80,6 @@ static void vdso_close(const struct vm_special_mapping *sm, struct vm_area_struc
|
|||||||
mm->context.vdso = NULL;
|
mm->context.vdso = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
|
||||||
struct vm_area_struct *vma, struct vm_fault *vmf);
|
|
||||||
|
|
||||||
static struct vm_special_mapping vvar_spec __ro_after_init = {
|
|
||||||
.name = "[vvar]",
|
|
||||||
.fault = vvar_fault,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct vm_special_mapping vdso32_spec __ro_after_init = {
|
static struct vm_special_mapping vdso32_spec __ro_after_init = {
|
||||||
.name = "[vdso]",
|
.name = "[vdso]",
|
||||||
.mremap = vdso32_mremap,
|
.mremap = vdso32_mremap,
|
||||||
@@ -116,73 +92,6 @@ static struct vm_special_mapping vdso64_spec __ro_after_init = {
|
|||||||
.close = vdso_close,
|
.close = vdso_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_TIME_NS
|
|
||||||
struct vdso_data *arch_get_vdso_data(void *vvar_page)
|
|
||||||
{
|
|
||||||
return vvar_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The vvar mapping contains data for a specific time namespace, so when a task
|
|
||||||
* changes namespace we must unmap its vvar data for the old namespace.
|
|
||||||
* Subsequent faults will map in data for the new namespace.
|
|
||||||
*
|
|
||||||
* For more details see timens_setup_vdso_data().
|
|
||||||
*/
|
|
||||||
int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
|
||||||
{
|
|
||||||
struct mm_struct *mm = task->mm;
|
|
||||||
VMA_ITERATOR(vmi, mm, 0);
|
|
||||||
struct vm_area_struct *vma;
|
|
||||||
|
|
||||||
mmap_read_lock(mm);
|
|
||||||
for_each_vma(vmi, vma) {
|
|
||||||
if (vma_is_special_mapping(vma, &vvar_spec))
|
|
||||||
zap_vma_pages(vma);
|
|
||||||
}
|
|
||||||
mmap_read_unlock(mm);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
switch (vmf->pgoff) {
|
|
||||||
case VVAR_BASE_PAGE_OFFSET:
|
|
||||||
pfn = virt_to_pfn(vdso_data);
|
|
||||||
break;
|
|
||||||
case VVAR_TIME_PAGE_OFFSET:
|
|
||||||
if (timens_page)
|
|
||||||
pfn = page_to_pfn(timens_page);
|
|
||||||
else
|
|
||||||
pfn = virt_to_pfn(vdso_data->data);
|
|
||||||
break;
|
|
||||||
#ifdef CONFIG_TIME_NS
|
|
||||||
case VVAR_TIMENS_PAGE_OFFSET:
|
|
||||||
/*
|
|
||||||
* If a task belongs to a time namespace then a namespace
|
|
||||||
* specific VVAR is mapped with the VVAR_DATA_PAGE_OFFSET and
|
|
||||||
* the real VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET
|
|
||||||
* offset.
|
|
||||||
* See also the comment near timens_setup_vdso_data().
|
|
||||||
*/
|
|
||||||
if (!timens_page)
|
|
||||||
return VM_FAULT_SIGBUS;
|
|
||||||
pfn = virt_to_pfn(vdso_data->data);
|
|
||||||
break;
|
|
||||||
#endif /* CONFIG_TIME_NS */
|
|
||||||
default:
|
|
||||||
return VM_FAULT_SIGBUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vmf_insert_pfn(vma, vmf->address, pfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called from binfmt_elf, we create the special vma for the
|
* This is called from binfmt_elf, we create the special vma for the
|
||||||
* vDSO and insert it into the mm struct tree
|
* vDSO and insert it into the mm struct tree
|
||||||
@@ -191,7 +100,7 @@ static int __arch_setup_additional_pages(struct linux_binprm *bprm, int uses_int
|
|||||||
{
|
{
|
||||||
unsigned long vdso_size, vdso_base, mappings_size;
|
unsigned long vdso_size, vdso_base, mappings_size;
|
||||||
struct vm_special_mapping *vdso_spec;
|
struct vm_special_mapping *vdso_spec;
|
||||||
unsigned long vvar_size = VVAR_NR_PAGES * PAGE_SIZE;
|
unsigned long vvar_size = VDSO_NR_PAGES * PAGE_SIZE;
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
|
|
||||||
@@ -217,9 +126,7 @@ static int __arch_setup_additional_pages(struct linux_binprm *bprm, int uses_int
|
|||||||
/* Add required alignment. */
|
/* Add required alignment. */
|
||||||
vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
|
vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
|
||||||
|
|
||||||
vma = _install_special_mapping(mm, vdso_base, vvar_size,
|
vma = vdso_install_vvar_mapping(mm, vdso_base);
|
||||||
VM_READ | VM_MAYREAD | VM_IO |
|
|
||||||
VM_DONTDUMP | VM_PFNMAP, &vvar_spec);
|
|
||||||
if (IS_ERR(vma))
|
if (IS_ERR(vma))
|
||||||
return PTR_ERR(vma);
|
return PTR_ERR(vma);
|
||||||
|
|
||||||
@@ -299,10 +206,10 @@ static void __init vdso_setup_syscall_map(void)
|
|||||||
|
|
||||||
for (i = 0; i < NR_syscalls; i++) {
|
for (i = 0; i < NR_syscalls; i++) {
|
||||||
if (sys_call_table[i] != (void *)&sys_ni_syscall)
|
if (sys_call_table[i] != (void *)&sys_ni_syscall)
|
||||||
vdso_data->syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
|
vdso_k_arch_data->syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
|
||||||
if (IS_ENABLED(CONFIG_COMPAT) &&
|
if (IS_ENABLED(CONFIG_COMPAT) &&
|
||||||
compat_sys_call_table[i] != (void *)&sys_ni_syscall)
|
compat_sys_call_table[i] != (void *)&sys_ni_syscall)
|
||||||
vdso_data->compat_syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
|
vdso_k_arch_data->compat_syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,10 +259,10 @@ static struct page ** __init vdso_setup_pages(void *start, void *end)
|
|||||||
static int __init vdso_init(void)
|
static int __init vdso_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
|
vdso_k_arch_data->dcache_block_size = ppc64_caches.l1d.block_size;
|
||||||
vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
|
vdso_k_arch_data->icache_block_size = ppc64_caches.l1i.block_size;
|
||||||
vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
|
vdso_k_arch_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
|
||||||
vdso_data->icache_log_block_size = ppc64_caches.l1i.log_block_size;
|
vdso_k_arch_data->icache_log_block_size = ppc64_caches.l1i.log_block_size;
|
||||||
#endif /* CONFIG_PPC64 */
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
vdso_setup_syscall_map();
|
vdso_setup_syscall_map();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
|
|||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
get_datapage r10
|
get_datapage r10 vdso_u_arch_data
|
||||||
mtlr r12
|
mtlr r12
|
||||||
.cfi_restore lr
|
.cfi_restore lr
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
|
|||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
mr. r4,r3
|
mr. r4,r3
|
||||||
get_datapage r3
|
get_datapage r3 vdso_u_arch_data
|
||||||
mtlr r12
|
mtlr r12
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
addi r3,r3,CFG_SYSCALL_MAP64
|
addi r3,r3,CFG_SYSCALL_MAP64
|
||||||
@@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
|
|||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
get_datapage r3
|
get_datapage r3 vdso_u_arch_data
|
||||||
#ifndef __powerpc64__
|
#ifndef __powerpc64__
|
||||||
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
|
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
||||||
#endif
|
#endif
|
||||||
.ifeq \call_time
|
.ifeq \call_time
|
||||||
get_datapage r5 VDSO_DATA_OFFSET
|
get_datapage r5 vdso_u_time_data
|
||||||
.else
|
.else
|
||||||
get_datapage r4 VDSO_DATA_OFFSET
|
get_datapage r4 vdso_u_time_data
|
||||||
.endif
|
.endif
|
||||||
bl CFUNC(DOTSYM(\funct))
|
bl CFUNC(DOTSYM(\funct))
|
||||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <asm/vdso.h>
|
#include <asm/vdso.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm-generic/vmlinux.lds.h>
|
#include <asm-generic/vmlinux.lds.h>
|
||||||
|
#include <vdso/datapage.h>
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
OUTPUT_FORMAT("elf32-powerpcle", "elf32-powerpcle", "elf32-powerpcle")
|
OUTPUT_FORMAT("elf32-powerpcle", "elf32-powerpcle", "elf32-powerpcle")
|
||||||
@@ -16,7 +17,8 @@ OUTPUT_ARCH(powerpc:common)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
|
VDSO_VVAR_SYMS
|
||||||
|
|
||||||
. = SIZEOF_HEADERS;
|
. = SIZEOF_HEADERS;
|
||||||
|
|
||||||
.hash : { *(.hash) } :text
|
.hash : { *(.hash) } :text
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <asm/vdso.h>
|
#include <asm/vdso.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm-generic/vmlinux.lds.h>
|
#include <asm-generic/vmlinux.lds.h>
|
||||||
|
#include <vdso/datapage.h>
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
OUTPUT_FORMAT("elf64-powerpcle", "elf64-powerpcle", "elf64-powerpcle")
|
OUTPUT_FORMAT("elf64-powerpcle", "elf64-powerpcle", "elf64-powerpcle")
|
||||||
@@ -16,7 +17,8 @@ OUTPUT_ARCH(powerpc:common64)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
|
VDSO_VVAR_SYMS
|
||||||
|
|
||||||
. = SIZEOF_HEADERS;
|
. = SIZEOF_HEADERS;
|
||||||
|
|
||||||
.hash : { *(.hash) } :text
|
.hash : { *(.hash) } :text
|
||||||
|
|||||||
@@ -7,43 +7,43 @@
|
|||||||
|
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
|
int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_clock_gettime_data(vd, clock, ts);
|
return __cvdso_clock_gettime_data(vd, clock, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
|
int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_clock_getres_data(vd, clock_id, res);
|
return __cvdso_clock_getres_data(vd, clock_id, res);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
|
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_clock_gettime32_data(vd, clock, ts);
|
return __cvdso_clock_gettime32_data(vd, clock, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
|
int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_clock_gettime_data(vd, clock, ts);
|
return __cvdso_clock_gettime_data(vd, clock, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
|
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_clock_getres_time32_data(vd, clock_id, res);
|
return __cvdso_clock_getres_time32_data(vd, clock_id, res);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
|
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
|
||||||
const struct vdso_data *vd)
|
const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_gettimeofday_data(vd, tv, tz);
|
return __cvdso_gettimeofday_data(vd, tv, tz);
|
||||||
}
|
}
|
||||||
|
|
||||||
__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, const struct vdso_data *vd)
|
__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, const struct vdso_time_data *vd)
|
||||||
{
|
{
|
||||||
return __cvdso_time_data(vd, time);
|
return __cvdso_time_data(vd, time);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user