First step of consolidating the VDSO data page handling:

The VDSO data page handling is architecture specific for historical
   reasons, but there is no real technical reason to do so.
 
   Aside of that VDSO data has become a dump ground for various mechanisms
   and fail to provide a clear separation of the functionalities.
 
   Clean this up by:
 
     * consolidating the VDSO page data by getting rid of architecture
       specific warts especially in x86 and PowerPC.
 
     * removing the last includes of header files which are pulling in other
       headers outside of the VDSO namespace.
 
     * seperating timekeeping and other VDSO data accordingly.
 
   Further consolidation of the VDSO page handling is done in subsequent
   changes scheduled for the next merge window.
 
   This also lays the ground for expanding the VDSO time getters for
   independent PTP clocks in a generic way without making every architecture
   add support seperately.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmc7kyoTHHRnbHhAbGlu
 dXRyb25peC5kZQAKCRCmGPVMDXSYoVBjD/9awdN2YeCGIM9rlHIktUdNRmRSL2SL
 6av1CPffN5DenONYTXWrDYPkC4yfjUwIs8H57uzFo10yA7RQ/Qfq+O68k5GnuFew
 jvpmmYSZ6TT21AmAaCIhn+kdl9YbEJFvN2AWH85Bl29k9FGB04VzJlQMMjfEZ1a5
 Mhwv+cfYNuPSZmU570jcxW2XgbyTWlLZBByXX/Tuz9bwpmtszba507bvo45x6gIP
 twaWNzrsyJpdXfMrfUnRiChN8jHlDN7I6fgQvpsoRH5FOiVwIFo0Ip2rKbk+ONfD
 W/rcU5oeqRIxRVDHzf2Sv8WPHMCLRv01ZHBcbJOtgvZC3YiKgKYoeEKabu9ZL1BH
 6VmrxjYOBBFQHOYAKPqBuS7BgH5PmtMbDdSZXDfRaAKaCzhCRysdlWW7z48r2R//
 zPufb7J6Tle23AkuZWhFjvlGgSBl4zxnTFn31HYOyQps3TMI4y50Z2DhE/EeU8a6
 DRl8/k1KQVDUZ6udJogS5kOr1J8pFtUPrA2uhR8UyLdx7YKiCzcdO1qWAjtXlVe8
 oNpzinU+H9bQqGe9IyS7kCG9xNaCRZNkln5Q1WfnkTzg5f6ihfaCvIku3l4bgVpw
 3HmcxYiC6RxQB+ozwN7hzCCKT4L9aMhr/457TNOqRkj2Elw3nvJ02L4aI86XAKLE
 jwO9Fkp9qcCxCw==
 =q5eD
 -----END PGP SIGNATURE-----

Merge tag 'timers-vdso-2024-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull vdso data page handling updates from Thomas Gleixner:
 "First steps of consolidating the VDSO data page handling.

  The VDSO data page handling is architecture specific for historical
  reasons, but there is no real technical reason to do so.

  Aside of that VDSO data has become a dump ground for various
  mechanisms and fail to provide a clear separation of the
  functionalities.

  Clean this up by:

   - consolidating the VDSO page data by getting rid of architecture
     specific warts especially in x86 and PowerPC.

   - removing the last includes of header files which are pulling in
     other headers outside of the VDSO namespace.

   - seperating timekeeping and other VDSO data accordingly.

  Further consolidation of the VDSO page handling is done in subsequent
  changes scheduled for the next merge window.

  This also lays the ground for expanding the VDSO time getters for
  independent PTP clocks in a generic way without making every
  architecture add support seperately"

* tag 'timers-vdso-2024-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (42 commits)
  x86/vdso: Add missing brackets in switch case
  vdso: Rename struct arch_vdso_data to arch_vdso_time_data
  powerpc: Split systemcfg struct definitions out from vdso
  powerpc: Split systemcfg data out of vdso data page
  powerpc: Add kconfig option for the systemcfg page
  powerpc/pseries/lparcfg: Use num_possible_cpus() for potential processors
  powerpc/pseries/lparcfg: Fix printing of system_active_processors
  powerpc/procfs: Propagate error of remap_pfn_range()
  powerpc/vdso: Remove offset comment from 32bit vdso_arch_data
  x86/vdso: Split virtual clock pages into dedicated mapping
  x86/vdso: Delete vvar.h
  x86/vdso: Access vdso data without vvar.h
  x86/vdso: Move the rng offset to vsyscall.h
  x86/vdso: Access rng vdso data without vvar.h
  x86/vdso: Access timens vdso data without vvar.h
  x86/vdso: Allocate vvar page from C code
  x86/vdso: Access rng data from kernel without vvar
  x86/vdso: Place vdso_data at beginning of vvar page
  x86/vdso: Use __arch_get_vdso_data() to access vdso data
  x86/mm/mmap: Remove arch_vma_name()
  ...
This commit is contained in:
Linus Torvalds 2024-11-19 16:09:13 -08:00
commit 0352387523
98 changed files with 371 additions and 781 deletions

View File

@ -1529,7 +1529,7 @@ config HAVE_SPARSE_SYSCALL_NR
entries at 4000, 5000 and 6000 locations. This option turns on syscall entries at 4000, 5000 and 6000 locations. This option turns on syscall
related optimizations for a given architecture. related optimizations for a given architecture.
config ARCH_HAS_VDSO_DATA config ARCH_HAS_VDSO_TIME_DATA
bool bool
config HAVE_STATIC_CALL config HAVE_STATIC_CALL

View File

@ -4,11 +4,7 @@
#include <linux/const.h> #include <linux/const.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <vdso/page.h>
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -14,7 +14,7 @@
/* PAGE_SHIFT determines the page size */ /* PAGE_SHIFT determines the page size */
#ifdef __KERNEL__ #ifdef __KERNEL__
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#else #else
/* /*
* Default 8k * Default 8k
@ -24,11 +24,10 @@
* not available * not available
*/ */
#define PAGE_SHIFT 13 #define PAGE_SHIFT 13
#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
#define PAGE_MASK (~(PAGE_SIZE-1))
#endif #endif
#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
#define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */ #define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */
#define PAGE_MASK (~(PAGE_SIZE-1))
#endif /* _UAPI__ASM_ARC_PAGE_H */ #endif /* _UAPI__ASM_ARC_PAGE_H */

View File

@ -7,10 +7,7 @@
#ifndef _ASMARM_PAGE_H #ifndef _ASMARM_PAGE_H
#define _ASMARM_PAGE_H #define _ASMARM_PAGE_H
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -15,8 +15,6 @@
#define VDSO_HAS_CLOCK_GETRES 1 #define VDSO_HAS_CLOCK_GETRES 1
extern struct vdso_data *__get_datapage(void);
static __always_inline int gettimeofday_fallback( static __always_inline int gettimeofday_fallback(
struct __kernel_old_timeval *_tv, struct __kernel_old_timeval *_tv,
struct timezone *_tz) struct timezone *_tz)
@ -139,7 +137,7 @@ static __always_inline u64 __arch_get_hw_counter(int clock_mode,
static __always_inline const struct vdso_data *__arch_get_vdso_data(void) static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{ {
return __get_datapage(); return _vdso_data;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -4,16 +4,12 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
extern struct vdso_data *vdso_data; extern struct vdso_data *vdso_data;
extern bool cntvct_ok; extern bool cntvct_ok;
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline static __always_inline
struct vdso_data *__arm_get_k_vdso_data(void) struct vdso_data *__arm_get_k_vdso_data(void)
{ {

View File

@ -14,7 +14,6 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timekeeper_internal.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/arch_timer.h> #include <asm/arch_timer.h>
#include <asm/barrier.h> #include <asm/barrier.h>

View File

@ -5,7 +5,7 @@ include $(srctree)/lib/vdso/Makefile
hostprogs := vdsomunge hostprogs := vdsomunge
obj-vdso := vgettimeofday.o datapage.o note.o obj-vdso := vgettimeofday.o note.o
# Build rules # Build rules
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds

View File

@ -1,16 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
.align 2
.L_vdso_data_ptr:
.long _start - . - VDSO_DATA_SIZE
ENTRY(__get_datapage)
.fnstart
adr r0, .L_vdso_data_ptr
ldr r1, [r0]
add r0, r0, r1
bx lr
.fnend
ENDPROC(__get_datapage)

View File

@ -11,6 +11,7 @@
*/ */
#include <linux/const.h> #include <linux/const.h>
#include <asm/asm-offsets.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/vdso.h> #include <asm/vdso.h>
@ -19,7 +20,7 @@ OUTPUT_ARCH(arm)
SECTIONS SECTIONS
{ {
PROVIDE(_start = .); PROVIDE(_vdso_data = . - VDSO_DATA_SIZE);
. = SIZEOF_HEADERS; . = SIZEOF_HEADERS;

View File

@ -10,9 +10,6 @@
#include <linux/const.h> #include <linux/const.h>
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#endif /* __ASM_PAGE_DEF_H */ #endif /* __ASM_PAGE_DEF_H */

View File

@ -5,13 +5,6 @@
#ifndef __ASM_VDSO_H #ifndef __ASM_VDSO_H
#define __ASM_VDSO_H #define __ASM_VDSO_H
/*
* Default link address for the vDSO.
* Since we randomise the VDSO mapping, there's little point in trying
* to prelink this.
*/
#define VDSO_LBASE 0x0
#define __VVAR_PAGES 2 #define __VVAR_PAGES 2
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
@ -20,7 +13,7 @@
#define VDSO_SYMBOL(base, name) \ #define VDSO_SYMBOL(base, name) \
({ \ ({ \
(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ (void *)(vdso_offset_##name + (unsigned long)(base)); \
}) })
extern char vdso_start[], vdso_end[]; extern char vdso_start[], vdso_end[];

View File

@ -6,7 +6,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
enum vvar_pages { enum vvar_pages {
@ -37,7 +36,7 @@ struct vdso_rng_data *__arm64_get_k_vdso_rnd_data(void)
#define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data #define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data
static __always_inline static __always_inline
void __arm64_update_vsyscall(struct vdso_data *vdata, struct timekeeper *tk) void __arm64_update_vsyscall(struct vdso_data *vdata)
{ {
vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK; vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK;
vdata[CS_RAW].mask = VDSO_PRECISION_MASK; vdata[CS_RAW].mask = VDSO_PRECISION_MASK;

View File

@ -19,7 +19,6 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time_namespace.h> #include <linux/time_namespace.h>
#include <linux/timekeeper_internal.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <vdso/helpers.h> #include <vdso/helpers.h>
@ -39,8 +38,6 @@ struct vdso_abi_info {
const char *vdso_code_start; const char *vdso_code_start;
const char *vdso_code_end; const char *vdso_code_end;
unsigned long vdso_pages; unsigned long vdso_pages;
/* Data Mapping */
struct vm_special_mapping *dm;
/* Code Mapping */ /* Code Mapping */
struct vm_special_mapping *cm; struct vm_special_mapping *cm;
}; };
@ -113,6 +110,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page); return (struct vdso_data *)(vvar_page);
} }
static const struct vm_special_mapping vvar_map;
/* /*
* The vvar mapping contains data for a specific time namespace, so when a task * 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. * changes namespace we must unmap its vvar data for the old namespace.
@ -129,12 +128,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_lock(mm); mmap_read_lock(mm);
for_each_vma(vmi, vma) { for_each_vma(vmi, vma) {
if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA64].dm)) if (vma_is_special_mapping(vma, &vvar_map))
zap_vma_pages(vma); zap_vma_pages(vma);
#ifdef CONFIG_COMPAT_VDSO
if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA32].dm))
zap_vma_pages(vma);
#endif
} }
mmap_read_unlock(mm); mmap_read_unlock(mm);
@ -176,6 +171,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
return vmf_insert_pfn(vma, vmf->address, pfn); return vmf_insert_pfn(vma, vmf->address, pfn);
} }
static const struct vm_special_mapping vvar_map = {
.name = "[vvar]",
.fault = vvar_fault,
};
static int __setup_additional_pages(enum vdso_abi abi, static int __setup_additional_pages(enum vdso_abi abi,
struct mm_struct *mm, struct mm_struct *mm,
struct linux_binprm *bprm, struct linux_binprm *bprm,
@ -199,7 +199,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES * PAGE_SIZE, ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_PFNMAP, VM_READ|VM_MAYREAD|VM_PFNMAP,
vdso_info[abi].dm); &vvar_map);
if (IS_ERR(ret)) if (IS_ERR(ret))
goto up_fail; goto up_fail;
@ -229,7 +229,6 @@ static int __setup_additional_pages(enum vdso_abi abi,
enum aarch32_map { enum aarch32_map {
AA32_MAP_VECTORS, /* kuser helpers */ AA32_MAP_VECTORS, /* kuser helpers */
AA32_MAP_SIGPAGE, AA32_MAP_SIGPAGE,
AA32_MAP_VVAR,
AA32_MAP_VDSO, AA32_MAP_VDSO,
}; };
@ -254,10 +253,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
.pages = &aarch32_sig_page, .pages = &aarch32_sig_page,
.mremap = aarch32_sigpage_mremap, .mremap = aarch32_sigpage_mremap,
}, },
[AA32_MAP_VVAR] = {
.name = "[vvar]",
.fault = vvar_fault,
},
[AA32_MAP_VDSO] = { [AA32_MAP_VDSO] = {
.name = "[vdso]", .name = "[vdso]",
.mremap = vdso_mremap, .mremap = vdso_mremap,
@ -307,7 +302,6 @@ static int __init __aarch32_alloc_vdso_pages(void)
if (!IS_ENABLED(CONFIG_COMPAT_VDSO)) if (!IS_ENABLED(CONFIG_COMPAT_VDSO))
return 0; return 0;
vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO]; vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
return __vdso_init(VDSO_ABI_AA32); return __vdso_init(VDSO_ABI_AA32);
@ -402,26 +396,14 @@ int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
} }
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
enum aarch64_map { static struct vm_special_mapping aarch64_vdso_map __ro_after_init = {
AA64_MAP_VVAR, .name = "[vdso]",
AA64_MAP_VDSO, .mremap = vdso_mremap,
};
static struct vm_special_mapping aarch64_vdso_maps[] __ro_after_init = {
[AA64_MAP_VVAR] = {
.name = "[vvar]",
.fault = vvar_fault,
},
[AA64_MAP_VDSO] = {
.name = "[vdso]",
.mremap = vdso_mremap,
},
}; };
static int __init vdso_init(void) static int __init vdso_init(void)
{ {
vdso_info[VDSO_ABI_AA64].dm = &aarch64_vdso_maps[AA64_MAP_VVAR]; vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_map;
vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_maps[AA64_MAP_VDSO];
return __vdso_init(VDSO_ABI_AA64); return __vdso_init(VDSO_ABI_AA64);
} }

View File

@ -25,7 +25,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS #ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif #endif
. = VDSO_LBASE + SIZEOF_HEADERS; . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text .hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) } .gnu.hash : { *(.gnu.hash) }

View File

@ -22,7 +22,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS #ifdef CONFIG_TIME_NS
PROVIDE_HIDDEN(_timens_data = _vdso_data + PAGE_SIZE); PROVIDE_HIDDEN(_timens_data = _vdso_data + PAGE_SIZE);
#endif #endif
. = VDSO_LBASE + SIZEOF_HEADERS; . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text .hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) } .gnu.hash : { *(.gnu.hash) }

View File

@ -64,9 +64,6 @@ config CSKY
select GENERIC_IRQ_MULTI_HANDLER select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_32
select GENERIC_GETTIMEOFDAY
select GX6605S_TIMER if CPU_CK610 select GX6605S_TIMER if CPU_CK610
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
@ -80,7 +77,6 @@ config CSKY
select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_KMEMLEAK
select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_GENERIC_VDSO
select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_ERROR_INJECTION

View File

@ -7,12 +7,8 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <linux/const.h> #include <linux/const.h>
/* #include <vdso/page.h>
* PAGE_SHIFT determines the page size: 4KB
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define THREAD_SIZE (PAGE_SIZE * 2) #define THREAD_SIZE (PAGE_SIZE * 2)
#define THREAD_MASK (~(THREAD_SIZE - 1)) #define THREAD_MASK (~(THREAD_SIZE - 1))
#define THREAD_SHIFT (PAGE_SHIFT + 1) #define THREAD_SHIFT (PAGE_SHIFT + 1)

View File

@ -1,9 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_VDSO_CSKY_CLOCKSOURCE_H
#define __ASM_VDSO_CSKY_CLOCKSOURCE_H
#define VDSO_ARCH_CLOCKMODES \
VDSO_CLOCKMODE_ARCHTIMER
#endif /* __ASM_VDSO_CSKY_CLOCKSOURCE_H */

View File

@ -1,114 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_VDSO_CSKY_GETTIMEOFDAY_H
#define __ASM_VDSO_CSKY_GETTIMEOFDAY_H
#ifndef __ASSEMBLY__
#include <asm/barrier.h>
#include <asm/unistd.h>
#include <abi/regdef.h>
#include <uapi/linux/time.h>
#define VDSO_HAS_CLOCK_GETRES 1
static __always_inline
int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
struct timezone *_tz)
{
register struct __kernel_old_timeval *tv asm("a0") = _tv;
register struct timezone *tz asm("a1") = _tz;
register long ret asm("a0");
register long nr asm(syscallid) = __NR_gettimeofday;
asm volatile ("trap 0\n"
: "=r" (ret)
: "r"(tv), "r"(tz), "r"(nr)
: "memory");
return ret;
}
static __always_inline
long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
register clockid_t clkid asm("a0") = _clkid;
register struct __kernel_timespec *ts asm("a1") = _ts;
register long ret asm("a0");
register long nr asm(syscallid) = __NR_clock_gettime64;
asm volatile ("trap 0\n"
: "=r" (ret)
: "r"(clkid), "r"(ts), "r"(nr)
: "memory");
return ret;
}
static __always_inline
long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
{
register clockid_t clkid asm("a0") = _clkid;
register struct old_timespec32 *ts asm("a1") = _ts;
register long ret asm("a0");
register long nr asm(syscallid) = __NR_clock_gettime;
asm volatile ("trap 0\n"
: "=r" (ret)
: "r"(clkid), "r"(ts), "r"(nr)
: "memory");
return ret;
}
static __always_inline
int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
register clockid_t clkid asm("a0") = _clkid;
register struct __kernel_timespec *ts asm("a1") = _ts;
register long ret asm("a0");
register long nr asm(syscallid) = __NR_clock_getres_time64;
asm volatile ("trap 0\n"
: "=r" (ret)
: "r"(clkid), "r"(ts), "r"(nr)
: "memory");
return ret;
}
static __always_inline
int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
{
register clockid_t clkid asm("a0") = _clkid;
register struct old_timespec32 *ts asm("a1") = _ts;
register long ret asm("a0");
register long nr asm(syscallid) = __NR_clock_getres;
asm volatile ("trap 0\n"
: "=r" (ret)
: "r"(clkid), "r"(ts), "r"(nr)
: "memory");
return ret;
}
uint64_t csky_pmu_read_cc(void);
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
const struct vdso_data *vd)
{
#ifdef CONFIG_CSKY_PMU_V1
return csky_pmu_read_cc();
#else
return 0;
#endif
}
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
return _vdso_data;
}
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_VDSO_CSKY_GETTIMEOFDAY_H */

View File

@ -1,12 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_VDSO_CSKY_PROCESSOR_H
#define __ASM_VDSO_CSKY_PROCESSOR_H
#ifndef __ASSEMBLY__
#define cpu_relax() barrier()
#endif /* __ASSEMBLY__ */
#endif /* __ASM_VDSO_CSKY_PROCESSOR_H */

View File

@ -1,22 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_VDSO_CSKY_VSYSCALL_H
#define __ASM_VDSO_CSKY_VSYSCALL_H
#ifndef __ASSEMBLY__
#include <vdso/datapage.h>
extern struct vdso_data *vdso_data;
static __always_inline struct vdso_data *__csky_get_k_vdso_data(void)
{
return vdso_data;
}
#define __arch_get_k_vdso_data __csky_get_k_vdso_data
#include <asm-generic/vdso/vsyscall.h>
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_VDSO_CSKY_VSYSCALL_H */

View File

@ -8,23 +8,19 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/page.h> #include <asm/page.h>
#include <vdso/datapage.h>
extern char vdso_start[], vdso_end[]; extern char vdso_start[], vdso_end[];
static unsigned int vdso_pages; static unsigned int vdso_pages;
static struct page **vdso_pagelist; static struct page **vdso_pagelist;
static union vdso_data_store vdso_data_store __page_aligned_data;
struct vdso_data *vdso_data = vdso_data_store.data;
static int __init vdso_init(void) static int __init vdso_init(void)
{ {
unsigned int i; unsigned int i;
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
vdso_pagelist = vdso_pagelist =
kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL); kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
if (unlikely(vdso_pagelist == NULL)) { if (unlikely(vdso_pagelist == NULL)) {
pr_err("vdso: pagelist allocation failed\n"); pr_err("vdso: pagelist allocation failed\n");
return -ENOMEM; return -ENOMEM;
@ -36,7 +32,6 @@ static int __init vdso_init(void)
pg = virt_to_page(vdso_start + (i << PAGE_SHIFT)); pg = virt_to_page(vdso_start + (i << PAGE_SHIFT));
vdso_pagelist[i] = pg; vdso_pagelist[i] = pg;
} }
vdso_pagelist[i] = virt_to_page(vdso_data);
return 0; return 0;
} }
@ -52,11 +47,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
static struct vm_special_mapping vdso_mapping = { static struct vm_special_mapping vdso_mapping = {
.name = "[vdso]", .name = "[vdso]",
}; };
static struct vm_special_mapping vvar_mapping = {
.name = "[vvar]",
};
vdso_len = (vdso_pages + 1) << PAGE_SHIFT; vdso_len = vdso_pages << PAGE_SHIFT;
mmap_write_lock(mm); mmap_write_lock(mm);
vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0); vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0);
@ -85,27 +77,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
} }
vdso_base += (vdso_pages << PAGE_SHIFT); vdso_base += (vdso_pages << PAGE_SHIFT);
vvar_mapping.pages = &vdso_pagelist[vdso_pages];
vma = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
(VM_READ | VM_MAYREAD), &vvar_mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
mm->context.vdso = NULL;
goto end;
}
ret = 0; ret = 0;
end: end:
mmap_write_unlock(mm); mmap_write_unlock(mm);
return ret; return ret;
} }
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_mm && (vma->vm_start == (long)vma->vm_mm->context.vdso))
return "[vdso]";
if (vma->vm_mm && (vma->vm_start ==
(long)vma->vm_mm->context.vdso + PAGE_SIZE))
return "[vdso_data]";
return NULL;
}

View File

@ -5,7 +5,6 @@ include $(srctree)/lib/vdso/Makefile
# Symbols present in the vdso # Symbols present in the vdso
vdso-syms += rt_sigreturn vdso-syms += rt_sigreturn
vdso-syms += vgettimeofday
# Files to link into the vdso # Files to link into the vdso
obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o

View File

@ -49,10 +49,6 @@ VERSION
LINUX_5.10 { LINUX_5.10 {
global: global:
__vdso_rt_sigreturn; __vdso_rt_sigreturn;
__vdso_clock_gettime;
__vdso_clock_gettime64;
__vdso_gettimeofday;
__vdso_clock_getres;
local: *; local: *;
}; };
} }

View File

@ -1,30 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/time.h>
#include <linux/types.h>
#include <vdso/gettime.h>
extern
int __vdso_clock_gettime(clockid_t clock,
struct old_timespec32 *ts)
{
return __cvdso_clock_gettime32(clock, ts);
}
int __vdso_clock_gettime64(clockid_t clock,
struct __kernel_timespec *ts)
{
return __cvdso_clock_gettime(clock, ts);
}
int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
struct timezone *tz)
{
return __cvdso_gettimeofday(tv, tz);
}
int __vdso_clock_getres(clockid_t clock_id,
struct old_timespec32 *res)
{
return __cvdso_clock_getres_time32(clock_id, res);
}

View File

@ -45,9 +45,7 @@
#define HVM_HUGEPAGE_SIZE 0x5 #define HVM_HUGEPAGE_SIZE 0x5
#endif #endif
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -8,12 +8,7 @@
#include <linux/const.h> #include <linux/const.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
/* #include <vdso/page.h>
* PAGE_SHIFT determines the page size
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) #define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)

View File

@ -30,8 +30,7 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{ {
return (const struct vdso_rng_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * return &_loongarch_data.rng_data;
PAGE_SIZE + offsetof(struct loongarch_vdso_data, rng_data));
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -91,14 +91,14 @@ static inline bool loongarch_vdso_hres_capable(void)
static __always_inline const struct vdso_data *__arch_get_vdso_data(void) static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{ {
return (const struct vdso_data *)get_vdso_data(); return _vdso_data;
} }
#ifdef CONFIG_TIME_NS #ifdef CONFIG_TIME_NS
static __always_inline static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{ {
return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE); return _timens_data;
} }
#endif #endif
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -48,23 +48,7 @@ enum vvar_pages {
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
static inline unsigned long get_vdso_base(void) extern struct loongarch_vdso_data _loongarch_data __attribute__((visibility("hidden")));
{
unsigned long addr;
__asm__(
" la.pcrel %0, _start\n"
: "=r" (addr)
:
:);
return addr;
}
static inline unsigned long get_vdso_data(void)
{
return get_vdso_base() - VVAR_SIZE;
}
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */

View File

@ -4,15 +4,11 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
extern struct vdso_data *vdso_data; extern struct vdso_data *vdso_data;
extern struct vdso_rng_data *vdso_rng_data; extern struct vdso_rng_data *vdso_rng_data;
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline static __always_inline
struct vdso_data *__loongarch_get_k_vdso_data(void) struct vdso_data *__loongarch_get_k_vdso_data(void)
{ {

View File

@ -14,6 +14,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ftrace.h> #include <asm/ftrace.h>
#include <vdso/datapage.h>
static void __used output_ptreg_defines(void) static void __used output_ptreg_defines(void)
{ {
@ -321,3 +322,11 @@ static void __used output_kvm_defines(void)
OFFSET(KVM_GPGD, kvm, arch.pgd); OFFSET(KVM_GPGD, kvm, arch.pgd);
BLANK(); BLANK();
} }
static void __used output_vdso_defines(void)
{
COMMENT("LoongArch vDSO offsets.");
DEFINE(__VVAR_PAGES, VVAR_NR_PAGES);
BLANK();
}

View File

@ -15,7 +15,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time_namespace.h> #include <linux/time_namespace.h>
#include <linux/timekeeper_internal.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/vdso.h> #include <asm/vdso.h>

View File

@ -3,6 +3,8 @@
* Author: Huacai Chen <chenhuacai@loongson.cn> * Author: Huacai Chen <chenhuacai@loongson.cn>
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/ */
#include <asm/page.h>
#include <generated/asm-offsets.h>
OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch") OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch")
@ -10,7 +12,11 @@ OUTPUT_ARCH(loongarch)
SECTIONS SECTIONS
{ {
PROVIDE(_start = .); PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE);
#ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif
PROVIDE(_loongarch_data = _vdso_data + 2 * PAGE_SIZE);
. = SIZEOF_HEADERS; . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text .hash : { *(.hash) } :text

View File

@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void)
static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void) static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
{ {
return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE); return _loongarch_data.pdata;
} }
extern extern

View File

@ -6,10 +6,8 @@
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/page_offset.h> #include <asm/page_offset.h>
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_OFFSET (PAGE_OFFSET_RAW) #define PAGE_OFFSET (PAGE_OFFSET_RAW)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -19,10 +19,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_KERNEL_BASE_ADDR)) #define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_KERNEL_BASE_ADDR))

View File

@ -14,12 +14,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
/* #include <vdso/page.h>
* PAGE_SHIFT determines the page size
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
/* /*
* This is used for calculating the real page sizes * This is used for calculating the real page sizes

View File

@ -4,7 +4,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
extern struct vdso_data *vdso_data; extern struct vdso_data *vdso_data;

View File

@ -14,7 +14,6 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timekeeper_internal.h>
#include <asm/abi.h> #include <asm/abi.h>
#include <asm/mips-cps.h> #include <asm/mips-cps.h>

View File

@ -270,7 +270,7 @@ int main(int argc, char **argv)
/* Write out the stripped VDSO data. */ /* Write out the stripped VDSO data. */
fprintf(out_file, fprintf(out_file,
"static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t", "static unsigned char vdso_image_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
vdso_size); vdso_size);
for (i = 0; i < vdso_size; i++) { for (i = 0; i < vdso_size; i++) {
if (!(i % 10)) if (!(i % 10))
@ -286,7 +286,7 @@ int main(int argc, char **argv)
fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n", fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
(vdso_name[0]) ? "_" : "", vdso_name); (vdso_name[0]) ? "_" : "", vdso_name);
fprintf(out_file, "\t.data = vdso_data,\n"); fprintf(out_file, "\t.data = vdso_image_data,\n");
fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size); fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
fprintf(out_file, "\t.mapping = {\n"); fprintf(out_file, "\t.mapping = {\n");
fprintf(out_file, "\t\t.name = \"[vdso]\",\n"); fprintf(out_file, "\t\t.name = \"[vdso]\",\n");

View File

@ -18,12 +18,7 @@
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/const.h> #include <linux/const.h>
/* #include <vdso/page.h>
* PAGE_SHIFT determines the page size
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
/* /*
* PAGE_OFFSET -- the first address of the first page of memory. * PAGE_OFFSET -- the first address of the first page of memory.

View File

@ -15,16 +15,7 @@
#ifndef __ASM_OPENRISC_PAGE_H #ifndef __ASM_OPENRISC_PAGE_H
#define __ASM_OPENRISC_PAGE_H #define __ASM_OPENRISC_PAGE_H
#include <vdso/page.h>
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#ifdef __ASSEMBLY__
#define PAGE_SIZE (1 << PAGE_SHIFT)
#else
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#endif
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_OFFSET 0xc0000000 #define PAGE_OFFSET 0xc0000000
#define KERNELBASE PAGE_OFFSET #define KERNELBASE PAGE_OFFSET

View File

@ -4,9 +4,7 @@
#include <linux/const.h> #include <linux/const.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA

View File

@ -1302,6 +1302,14 @@ config MODULES_SIZE
endmenu endmenu
config PPC64_PROC_SYSTEMCFG
def_bool y
depends on PPC64 && PROC_FS
help
This option enables the presence of /proc/ppc64/systemcfg through
which the systemcfg page can be accessed.
This interface only exists for backwards-compatibility.
if PPC64 if PPC64
# This value must have zeroes in the bottom 60 bits otherwise lots will break # This value must have zeroes in the bottom 60 bits otherwise lots will break
config PAGE_OFFSET config PAGE_OFFSET

View File

@ -21,8 +21,7 @@
* page size. When using 64K pages however, whether we are really supporting * page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions. * 64K pages in HW or not is irrelevant to those definitions.
*/ */
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifndef CONFIG_HUGETLB_PAGE #ifndef CONFIG_HUGETLB_PAGE
@ -41,13 +40,6 @@ extern unsigned int hpage_shift;
#define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1)
#endif #endif
/*
* Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we
* assign PAGE_MASK to a larger type it gets extended the way we want
* (i.e. with 1s in the high bits)
*/
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
/* /*
* KERNELBASE is the virtual address of the start of the kernel, it's often * KERNELBASE is the virtual address of the start of the kernel, it's often
* the same as PAGE_OFFSET, but _might not be_. * the same as PAGE_OFFSET, but _might not be_.

View File

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _SYSTEMCFG_H
#define _SYSTEMCFG_H
/*
* Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
* Copyright (C) 2005 Benjamin Herrenschmidy <benh@kernel.crashing.org>,
* IBM Corp.
*/
#ifdef CONFIG_PPC64
/*
* If the major version changes we are incompatible.
* Minor version changes are a hint.
*/
#define SYSTEMCFG_MAJOR 1
#define SYSTEMCFG_MINOR 1
#include <linux/types.h>
struct systemcfg {
__u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
struct { /* Systemcfg version numbers */
__u32 major; /* Major number 0x10 */
__u32 minor; /* Minor number 0x14 */
} version;
/* Note about the platform flags: it now only contains the lpar
* bit. The actual platform number is dead and buried
*/
__u32 platform; /* Platform flags 0x18 */
__u32 processor; /* Processor type 0x1C */
__u64 processorCount; /* # of physical processors 0x20 */
__u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
__u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
__u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */
__u64 stamp_xsec; /* (NU) 0x48 */
__u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */
__u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */
__u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */
__u32 dcache_size; /* L1 d-cache size 0x60 */
__u32 dcache_line_size; /* L1 d-cache line size 0x64 */
__u32 icache_size; /* L1 i-cache size 0x68 */
__u32 icache_line_size; /* L1 i-cache line size 0x6C */
};
extern struct systemcfg *systemcfg;
#endif /* CONFIG_PPC64 */
#endif /* _SYSTEMCFG_H */

View File

@ -4,12 +4,8 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline static __always_inline
struct vdso_data *__arch_get_k_vdso_data(void) struct vdso_data *__arch_get_k_vdso_data(void)
{ {

View File

@ -9,29 +9,6 @@
* IBM Corp. * IBM Corp.
*/ */
/*
* Note about this structure:
*
* This structure was historically called systemcfg and exposed to
* userland via /proc/ppc64/systemcfg. Unfortunately, this became an
* ABI issue as some proprietary software started relying on being able
* to mmap() it, thus we have to keep the base layout at least for a
* few kernel versions.
*
* However, since ppc32 doesn't suffer from this backward handicap,
* a simpler version of the data structure is used there with only the
* fields actually used by the vDSO.
*
*/
/*
* If the major version changes we are incompatible.
* Minor version changes are a hint.
*/
#define SYSTEMCFG_MAJOR 1
#define SYSTEMCFG_MINOR 1
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/unistd.h> #include <linux/unistd.h>
@ -40,41 +17,10 @@
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32) #define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
/*
* So here is the ppc64 backward compatible version
*/
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
struct vdso_arch_data { struct vdso_arch_data {
__u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ __u64 tb_ticks_per_sec; /* Timebase tics / sec */
struct { /* Systemcfg version numbers */
__u32 major; /* Major number 0x10 */
__u32 minor; /* Minor number 0x14 */
} version;
/* Note about the platform flags: it now only contains the lpar
* bit. The actual platform number is dead and buried
*/
__u32 platform; /* Platform flags 0x18 */
__u32 processor; /* Processor type 0x1C */
__u64 processorCount; /* # of physical processors 0x20 */
__u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
__u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
__u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */
__u64 stamp_xsec; /* (NU) 0x48 */
__u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */
__u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */
__u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */
__u32 dcache_size; /* L1 d-cache size 0x60 */
__u32 dcache_line_size; /* L1 d-cache line size 0x64 */
__u32 icache_size; /* L1 i-cache size 0x68 */
__u32 icache_line_size; /* L1 i-cache line size 0x6C */
/* those additional ones don't have to be located anywhere
* special as they were not part of the original systemcfg
*/
__u32 dcache_block_size; /* L1 d-cache block size */ __u32 dcache_block_size; /* L1 d-cache block size */
__u32 icache_block_size; /* L1 i-cache block size */ __u32 icache_block_size; /* L1 i-cache block size */
__u32 dcache_log_block_size; /* L1 d-cache log block size */ __u32 dcache_log_block_size; /* L1 d-cache log block size */
@ -88,11 +34,8 @@ struct vdso_arch_data {
#else /* CONFIG_PPC64 */ #else /* CONFIG_PPC64 */
/*
* And here is the simpler 32 bits version
*/
struct vdso_arch_data { struct vdso_arch_data {
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ __u64 tb_ticks_per_sec; /* Timebase tics / sec */
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */ __u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */ __u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
struct vdso_data data[CS_BASES]; struct vdso_data data[CS_BASES];

View File

@ -4,6 +4,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/memblock.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -12,9 +13,10 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/systemcfg.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64_PROC_SYSTEMCFG
static loff_t page_map_seek(struct file *file, loff_t off, int whence) static loff_t page_map_seek(struct file *file, loff_t off, int whence)
{ {
@ -33,10 +35,9 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) if ((vma->vm_end - vma->vm_start) > PAGE_SIZE)
return -EINVAL; return -EINVAL;
remap_pfn_range(vma, vma->vm_start, return remap_pfn_range(vma, vma->vm_start,
__pa(pde_data(file_inode(file))) >> PAGE_SHIFT, __pa(pde_data(file_inode(file))) >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot); PAGE_SIZE, vma->vm_page_prot);
return 0;
} }
static const struct proc_ops page_map_proc_ops = { static const struct proc_ops page_map_proc_ops = {
@ -45,13 +46,35 @@ static const struct proc_ops page_map_proc_ops = {
.proc_mmap = page_map_mmap, .proc_mmap = page_map_mmap,
}; };
static union {
struct systemcfg data;
u8 page[PAGE_SIZE];
} systemcfg_data_store __page_aligned_data;
struct systemcfg *systemcfg = &systemcfg_data_store.data;
static int __init proc_ppc64_init(void) static int __init proc_ppc64_init(void)
{ {
struct proc_dir_entry *pde; struct proc_dir_entry *pde;
strcpy((char *)systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
systemcfg->version.major = SYSTEMCFG_MAJOR;
systemcfg->version.minor = SYSTEMCFG_MINOR;
systemcfg->processor = mfspr(SPRN_PVR);
/*
* Fake the old platform number for pSeries and add
* in LPAR bit if necessary
*/
systemcfg->platform = 0x100;
if (firmware_has_feature(FW_FEATURE_LPAR))
systemcfg->platform |= 1;
systemcfg->physicalMemorySize = memblock_phys_mem_size();
systemcfg->dcache_size = ppc64_caches.l1d.size;
systemcfg->dcache_line_size = ppc64_caches.l1d.line_size;
systemcfg->icache_size = ppc64_caches.l1i.size;
systemcfg->icache_line_size = ppc64_caches.l1i.line_size;
pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL, pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL,
&page_map_proc_ops, vdso_data); &page_map_proc_ops, systemcfg);
if (!pde) if (!pde)
return 1; return 1;
proc_set_size(pde, PAGE_SIZE); proc_set_size(pde, PAGE_SIZE);
@ -60,7 +83,7 @@ static int __init proc_ppc64_init(void)
} }
__initcall(proc_ppc64_init); __initcall(proc_ppc64_init);
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64_PROC_SYSTEMCFG */
/* /*
* Create the ppc64 and ppc64/rtas directories early. This allows us to * Create the ppc64 and ppc64/rtas directories early. This allows us to

View File

@ -67,6 +67,7 @@
#include <asm/cpu_has_feature.h> #include <asm/cpu_has_feature.h>
#include <asm/kasan.h> #include <asm/kasan.h>
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/systemcfg.h>
#include "setup.h" #include "setup.h"
@ -560,7 +561,9 @@ void __init smp_setup_cpu_maps(void)
out: out:
of_node_put(dn); of_node_put(dn);
} }
vdso_data->processorCount = num_present_cpus(); #endif
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
systemcfg->processorCount = num_present_cpus();
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
/* Initialize CPU <=> thread mapping/ /* Initialize CPU <=> thread mapping/

View File

@ -61,6 +61,7 @@
#include <asm/ftrace.h> #include <asm/ftrace.h>
#include <asm/kup.h> #include <asm/kup.h>
#include <asm/fadump.h> #include <asm/fadump.h>
#include <asm/systemcfg.h>
#include <trace/events/ipi.h> #include <trace/events/ipi.h>
@ -1186,8 +1187,8 @@ int generic_cpu_disable(void)
return -EBUSY; return -EBUSY;
set_cpu_online(cpu, false); set_cpu_online(cpu, false);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64_PROC_SYSTEMCFG
vdso_data->processorCount--; systemcfg->processorCount--;
#endif #endif
/* Update affinity of all IRQs previously aimed at this CPU */ /* Update affinity of all IRQs previously aimed at this CPU */
irq_migrate_all_off_this_cpu(); irq_migrate_all_off_this_cpu();
@ -1642,10 +1643,12 @@ void start_secondary(void *unused)
secondary_cpu_time_init(); secondary_cpu_time_init();
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64_PROC_SYSTEMCFG
if (system_state == SYSTEM_RUNNING) if (system_state == SYSTEM_RUNNING)
vdso_data->processorCount++; systemcfg->processorCount++;
#endif
#ifdef CONFIG_PPC64
vdso_getcpu_init(); vdso_getcpu_init();
#endif #endif
set_numa_node(numa_cpu_lookup_table[cpu]); set_numa_node(numa_cpu_lookup_table[cpu]);

View File

@ -71,11 +71,11 @@
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/systemcfg.h>
/* powerpc clocksource/clockevent code */ /* powerpc clocksource/clockevent code */
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/timekeeper_internal.h>
static u64 timebase_read(struct clocksource *); static u64 timebase_read(struct clocksource *);
static struct clocksource clocksource_timebase = { static struct clocksource clocksource_timebase = {
@ -951,6 +951,9 @@ void __init time_init(void)
} }
vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
#endif
/* initialise and enable the large decrementer (if we have one) */ /* initialise and enable the large decrementer (if we have one) */
set_decrementer_max(); set_decrementer_max();

View File

@ -16,7 +16,6 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/memblock.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/time_namespace.h> #include <linux/time_namespace.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
@ -349,25 +348,6 @@ 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
/*
* Fill up the "systemcfg" stuff for backward compatibility
*/
strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
vdso_data->version.major = SYSTEMCFG_MAJOR;
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);
/*
* Fake the old platform number for pSeries and add
* in LPAR bit if necessary
*/
vdso_data->platform = 0x100;
if (firmware_has_feature(FW_FEATURE_LPAR))
vdso_data->platform |= 1;
vdso_data->physicalMemorySize = memblock_phys_mem_size();
vdso_data->dcache_size = ppc64_caches.l1d.size;
vdso_data->dcache_line_size = ppc64_caches.l1d.line_size;
vdso_data->icache_size = ppc64_caches.l1i.size;
vdso_data->icache_line_size = ppc64_caches.l1i.line_size;
vdso_data->dcache_block_size = ppc64_caches.l1d.block_size; vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
vdso_data->icache_block_size = ppc64_caches.l1i.block_size; vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size; vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;

View File

@ -36,6 +36,7 @@
#include <asm/kexec.h> #include <asm/kexec.h>
#include <asm/reg.h> #include <asm/reg.h>
#include <asm/powernv.h> #include <asm/powernv.h>
#include <asm/systemcfg.h>
#include "powernv.h" #include "powernv.h"
@ -136,7 +137,9 @@ static int pnv_smp_cpu_disable(void)
* the generic fixup_irqs. --BenH. * the generic fixup_irqs. --BenH.
*/ */
set_cpu_online(cpu, false); set_cpu_online(cpu, false);
vdso_data->processorCount--; #ifdef CONFIG_PPC64_PROC_SYSTEMCFG
systemcfg->processorCount--;
#endif
if (cpu == boot_cpuid) if (cpu == boot_cpuid)
boot_cpuid = cpumask_any(cpu_online_mask); boot_cpuid = cpumask_any(cpu_online_mask);
if (xive_enabled()) if (xive_enabled())

View File

@ -33,6 +33,7 @@
#include <asm/xive.h> #include <asm/xive.h>
#include <asm/plpar_wrappers.h> #include <asm/plpar_wrappers.h>
#include <asm/topology.h> #include <asm/topology.h>
#include <asm/systemcfg.h>
#include "pseries.h" #include "pseries.h"
@ -83,7 +84,9 @@ static int pseries_cpu_disable(void)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
set_cpu_online(cpu, false); set_cpu_online(cpu, false);
vdso_data->processorCount--; #ifdef CONFIG_PPC64_PROC_SYSTEMCFG
systemcfg->processorCount--;
#endif
/*fix boot_cpuid here*/ /*fix boot_cpuid here*/
if (cpu == boot_cpuid) if (cpu == boot_cpuid)

View File

@ -29,7 +29,6 @@
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/vdso_datapage.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/machdep.h> #include <asm/machdep.h>
@ -530,7 +529,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL);
if (lrdrp == NULL) { if (lrdrp == NULL) {
partition_potential_processors = vdso_data->processorCount; partition_potential_processors = num_possible_cpus();
} else { } else {
partition_potential_processors = be32_to_cpup(lrdrp + 4); partition_potential_processors = be32_to_cpup(lrdrp + 4);
} }
@ -553,7 +552,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
} else { /* non SPLPAR case */ } else { /* non SPLPAR case */
seq_printf(m, "system_active_processors=%d\n", seq_printf(m, "system_active_processors=%d\n",
partition_potential_processors); partition_active_processors);
seq_printf(m, "system_potential_processors=%d\n", seq_printf(m, "system_potential_processors=%d\n",
partition_potential_processors); partition_potential_processors);

View File

@ -51,7 +51,7 @@ config RISCV
select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN select ARCH_HAS_UBSAN
select ARCH_HAS_VDSO_DATA select ARCH_HAS_VDSO_TIME_DATA
select ARCH_KEEP_MEMBLOCK if ACPI select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX

View File

@ -12,9 +12,7 @@
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/const.h> #include <linux/const.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define HPAGE_SHIFT PMD_SHIFT #define HPAGE_SHIFT PMD_SHIFT
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)

View File

@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#ifndef __RISCV_ASM_VDSO_DATA_H #ifndef __RISCV_ASM_VDSO_TIME_DATA_H
#define __RISCV_ASM_VDSO_DATA_H #define __RISCV_ASM_VDSO_TIME_DATA_H
#include <linux/types.h> #include <linux/types.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <asm/hwprobe.h> #include <asm/hwprobe.h>
struct arch_vdso_data { struct arch_vdso_time_data {
/* Stash static answers to the hwprobe queries when all CPUs are selected. */ /* Stash static answers to the hwprobe queries when all CPUs are selected. */
__u64 all_cpu_hwprobe_values[RISCV_HWPROBE_MAX_KEY + 1]; __u64 all_cpu_hwprobe_values[RISCV_HWPROBE_MAX_KEY + 1];
@ -14,4 +14,4 @@ struct arch_vdso_data {
__u8 homogeneous_cpus; __u8 homogeneous_cpus;
}; };
#endif /* __RISCV_ASM_VDSO_DATA_H */ #endif /* __RISCV_ASM_VDSO_TIME_DATA_H */

View File

@ -4,14 +4,10 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
extern struct vdso_data *vdso_data; extern struct vdso_data *vdso_data;
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline struct vdso_data *__riscv_get_k_vdso_data(void) static __always_inline struct vdso_data *__riscv_get_k_vdso_data(void)
{ {
return vdso_data; return vdso_data;

View File

@ -402,7 +402,7 @@ static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs,
static int __init init_hwprobe_vdso_data(void) static int __init init_hwprobe_vdso_data(void)
{ {
struct vdso_data *vd = __arch_get_k_vdso_data(); struct vdso_data *vd = __arch_get_k_vdso_data();
struct arch_vdso_data *avd = &vd->arch_data; struct arch_vdso_time_data *avd = &vd->arch_data;
u64 id_bitsmash = 0; u64 id_bitsmash = 0;
struct riscv_hwprobe pair; struct riscv_hwprobe pair;
int key; int key;

View File

@ -23,11 +23,6 @@ enum vvar_pages {
VVAR_NR_PAGES, VVAR_NR_PAGES,
}; };
enum rv_vdso_map {
RV_VDSO_MAP_VVAR,
RV_VDSO_MAP_VDSO,
};
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
static union vdso_data_store vdso_data_store __page_aligned_data; static union vdso_data_store vdso_data_store __page_aligned_data;
@ -38,8 +33,6 @@ struct __vdso_info {
const char *vdso_code_start; const char *vdso_code_start;
const char *vdso_code_end; const char *vdso_code_end;
unsigned long vdso_pages; unsigned long vdso_pages;
/* Data Mapping */
struct vm_special_mapping *dm;
/* Code Mapping */ /* Code Mapping */
struct vm_special_mapping *cm; struct vm_special_mapping *cm;
}; };
@ -92,6 +85,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page); return (struct vdso_data *)(vvar_page);
} }
static const struct vm_special_mapping rv_vvar_map;
/* /*
* The vvar mapping contains data for a specific time namespace, so when a task * 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. * changes namespace we must unmap its vvar data for the old namespace.
@ -108,12 +103,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_lock(mm); mmap_read_lock(mm);
for_each_vma(vmi, vma) { for_each_vma(vmi, vma) {
if (vma_is_special_mapping(vma, vdso_info.dm)) if (vma_is_special_mapping(vma, &rv_vvar_map))
zap_vma_pages(vma); zap_vma_pages(vma);
#ifdef CONFIG_COMPAT
if (vma_is_special_mapping(vma, compat_vdso_info.dm))
zap_vma_pages(vma);
#endif
} }
mmap_read_unlock(mm); mmap_read_unlock(mm);
@ -155,43 +146,34 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
return vmf_insert_pfn(vma, vmf->address, pfn); return vmf_insert_pfn(vma, vmf->address, pfn);
} }
static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = { static const struct vm_special_mapping rv_vvar_map = {
[RV_VDSO_MAP_VVAR] = { .name = "[vvar]",
.name = "[vvar]", .fault = vvar_fault,
.fault = vvar_fault, };
},
[RV_VDSO_MAP_VDSO] = { static struct vm_special_mapping rv_vdso_map __ro_after_init = {
.name = "[vdso]", .name = "[vdso]",
.mremap = vdso_mremap, .mremap = vdso_mremap,
},
}; };
static struct __vdso_info vdso_info __ro_after_init = { static struct __vdso_info vdso_info __ro_after_init = {
.name = "vdso", .name = "vdso",
.vdso_code_start = vdso_start, .vdso_code_start = vdso_start,
.vdso_code_end = vdso_end, .vdso_code_end = vdso_end,
.dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR], .cm = &rv_vdso_map,
.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
}; };
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = { static struct vm_special_mapping rv_compat_vdso_map __ro_after_init = {
[RV_VDSO_MAP_VVAR] = { .name = "[vdso]",
.name = "[vvar]", .mremap = vdso_mremap,
.fault = vvar_fault,
},
[RV_VDSO_MAP_VDSO] = {
.name = "[vdso]",
.mremap = vdso_mremap,
},
}; };
static struct __vdso_info compat_vdso_info __ro_after_init = { static struct __vdso_info compat_vdso_info __ro_after_init = {
.name = "compat_vdso", .name = "compat_vdso",
.vdso_code_start = compat_vdso_start, .vdso_code_start = compat_vdso_start,
.vdso_code_end = compat_vdso_end, .vdso_code_end = compat_vdso_end,
.dm = &rv_compat_vdso_maps[RV_VDSO_MAP_VVAR], .cm = &rv_compat_vdso_map,
.cm = &rv_compat_vdso_maps[RV_VDSO_MAP_VDSO],
}; };
#endif #endif
@ -227,7 +209,7 @@ static int __setup_additional_pages(struct mm_struct *mm,
} }
ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE, ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE,
(VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info->dm); (VM_READ | VM_MAYREAD | VM_PFNMAP), &rv_vvar_map);
if (IS_ERR(ret)) if (IS_ERR(ret))
goto up_fail; goto up_fail;

View File

@ -17,7 +17,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count,
unsigned int flags) unsigned int flags)
{ {
const struct vdso_data *vd = __arch_get_vdso_data(); const struct vdso_data *vd = __arch_get_vdso_data();
const struct arch_vdso_data *avd = &vd->arch_data; const struct arch_vdso_time_data *avd = &vd->arch_data;
bool all_cpus = !cpusetsize && !cpus; bool all_cpus = !cpusetsize && !cpus;
struct riscv_hwprobe *p = pairs; struct riscv_hwprobe *p = pairs;
struct riscv_hwprobe *end = pairs + pair_count; struct riscv_hwprobe *end = pairs + pair_count;
@ -52,7 +52,7 @@ static int riscv_vdso_get_cpus(struct riscv_hwprobe *pairs, size_t pair_count,
unsigned int flags) unsigned int flags)
{ {
const struct vdso_data *vd = __arch_get_vdso_data(); const struct vdso_data *vd = __arch_get_vdso_data();
const struct arch_vdso_data *avd = &vd->arch_data; const struct arch_vdso_time_data *avd = &vd->arch_data;
struct riscv_hwprobe *p = pairs; struct riscv_hwprobe *p = pairs;
struct riscv_hwprobe *end = pairs + pair_count; struct riscv_hwprobe *end = pairs + pair_count;
unsigned char *c = (unsigned char *)cpus; unsigned char *c = (unsigned char *)cpus;

View File

@ -95,7 +95,7 @@ config S390
select ARCH_HAS_STRICT_MODULE_RWX select ARCH_HAS_STRICT_MODULE_RWX
select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_UBSAN select ARCH_HAS_UBSAN
select ARCH_HAS_VDSO_DATA select ARCH_HAS_VDSO_TIME_DATA
select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_INLINE_READ_LOCK select ARCH_INLINE_READ_LOCK
select ARCH_INLINE_READ_LOCK_BH select ARCH_INLINE_READ_LOCK_BH

View File

@ -12,14 +12,8 @@
#include <asm/types.h> #include <asm/types.h>
#include <asm/asm.h> #include <asm/asm.h>
#define _PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define _PAGE_SIZE (_AC(1, UL) << _PAGE_SHIFT)
#define _PAGE_MASK (~(_PAGE_SIZE - 1))
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT _PAGE_SHIFT
#define PAGE_SIZE _PAGE_SIZE
#define PAGE_MASK _PAGE_MASK
#define PAGE_DEFAULT_ACC _AC(0, UL) #define PAGE_DEFAULT_ACC _AC(0, UL)
/* storage-protection override */ /* storage-protection override */
#define PAGE_SPO_ACC 9 #define PAGE_SPO_ACC 9

View File

@ -338,7 +338,7 @@ static inline int is_module_addr(void *addr)
#define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT) #define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT)
#define _REGION3_INDEX (0x7ffUL << _REGION3_SHIFT) #define _REGION3_INDEX (0x7ffUL << _REGION3_SHIFT)
#define _SEGMENT_INDEX (0x7ffUL << _SEGMENT_SHIFT) #define _SEGMENT_INDEX (0x7ffUL << _SEGMENT_SHIFT)
#define _PAGE_INDEX (0xffUL << _PAGE_SHIFT) #define _PAGE_INDEX (0xffUL << PAGE_SHIFT)
#define _REGION1_SIZE (1UL << _REGION1_SHIFT) #define _REGION1_SIZE (1UL << _REGION1_SHIFT)
#define _REGION2_SIZE (1UL << _REGION2_SHIFT) #define _REGION2_SIZE (1UL << _REGION2_SHIFT)

View File

@ -12,9 +12,6 @@ int vdso_getcpu_init(void);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* Default link address for the vDSO */
#define VDSO_LBASE 0
#define __VVAR_PAGES 2 #define __VVAR_PAGES 2
#define VDSO_VERSION_STRING LINUX_2.6.29 #define VDSO_VERSION_STRING LINUX_2.6.29

View File

@ -1,12 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __S390_ASM_VDSO_DATA_H
#define __S390_ASM_VDSO_DATA_H
#include <linux/types.h>
struct arch_vdso_data {
__s64 tod_steering_delta;
__u64 tod_steering_end;
};
#endif /* __S390_ASM_VDSO_DATA_H */

View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __S390_ASM_VDSO_TIME_DATA_H
#define __S390_ASM_VDSO_TIME_DATA_H
#include <linux/types.h>
struct arch_vdso_time_data {
__s64 tod_steering_delta;
__u64 tod_steering_end;
};
#endif /* __S390_ASM_VDSO_TIME_DATA_H */

View File

@ -7,7 +7,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <asm/vdso.h> #include <asm/vdso.h>
@ -17,10 +16,6 @@ enum vvar_pages {
VVAR_NR_PAGES VVAR_NR_PAGES
}; };
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
static __always_inline struct vdso_data *__s390_get_k_vdso_data(void) static __always_inline struct vdso_data *__s390_get_k_vdso_data(void)
{ {
return vdso_data; return vdso_data;

View File

@ -36,7 +36,6 @@
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/timekeeper_internal.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>

View File

@ -16,7 +16,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS #ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif #endif
. = VDSO_LBASE + SIZEOF_HEADERS; . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text .hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) } .gnu.hash : { *(.gnu.hash) }

View File

@ -18,7 +18,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS #ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif #endif
. = VDSO_LBASE + SIZEOF_HEADERS; . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text .hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) } .gnu.hash : { *(.gnu.hash) }

View File

@ -128,7 +128,7 @@ static void dump_pagetable(unsigned long asce, unsigned long address)
goto out; goto out;
table = __va(entry & _SEGMENT_ENTRY_ORIGIN); table = __va(entry & _SEGMENT_ENTRY_ORIGIN);
} }
table += (address & _PAGE_INDEX) >> _PAGE_SHIFT; table += (address & _PAGE_INDEX) >> PAGE_SHIFT;
if (get_kernel_nofault(entry, table)) if (get_kernel_nofault(entry, table))
goto bad; goto bad;
pr_cont("P:%016lx ", entry); pr_cont("P:%016lx ", entry);

View File

@ -900,7 +900,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
if (*table & _REGION_ENTRY_INVALID) if (*table & _REGION_ENTRY_INVALID)
return NULL; return NULL;
table = __va(*table & _SEGMENT_ENTRY_ORIGIN); table = __va(*table & _SEGMENT_ENTRY_ORIGIN);
table += (gaddr & _PAGE_INDEX) >> _PAGE_SHIFT; table += (gaddr & _PAGE_INDEX) >> PAGE_SHIFT;
} }
return table; return table;
} }
@ -1366,7 +1366,7 @@ static void gmap_unshadow_page(struct gmap *sg, unsigned long raddr)
table = gmap_table_walk(sg, raddr, 0); /* get page table pointer */ table = gmap_table_walk(sg, raddr, 0); /* get page table pointer */
if (!table || *table & _PAGE_INVALID) if (!table || *table & _PAGE_INVALID)
return; return;
gmap_call_notifier(sg, raddr, raddr + _PAGE_SIZE - 1); gmap_call_notifier(sg, raddr, raddr + PAGE_SIZE - 1);
ptep_unshadow_pte(sg->mm, raddr, (pte_t *) table); ptep_unshadow_pte(sg->mm, raddr, (pte_t *) table);
} }
@ -1384,7 +1384,7 @@ static void __gmap_unshadow_pgt(struct gmap *sg, unsigned long raddr,
int i; int i;
BUG_ON(!gmap_is_shadow(sg)); BUG_ON(!gmap_is_shadow(sg));
for (i = 0; i < _PAGE_ENTRIES; i++, raddr += _PAGE_SIZE) for (i = 0; i < _PAGE_ENTRIES; i++, raddr += PAGE_SIZE)
pgt[i] = _PAGE_INVALID; pgt[i] = _PAGE_INVALID;
} }

View File

@ -278,7 +278,7 @@ static inline unsigned long base_##NAME##_addr_end(unsigned long addr, \
return (next - 1) < (end - 1) ? next : end; \ return (next - 1) < (end - 1) ? next : end; \
} }
BASE_ADDR_END_FUNC(page, _PAGE_SIZE) BASE_ADDR_END_FUNC(page, PAGE_SIZE)
BASE_ADDR_END_FUNC(segment, _SEGMENT_SIZE) BASE_ADDR_END_FUNC(segment, _SEGMENT_SIZE)
BASE_ADDR_END_FUNC(region3, _REGION3_SIZE) BASE_ADDR_END_FUNC(region3, _REGION3_SIZE)
BASE_ADDR_END_FUNC(region2, _REGION2_SIZE) BASE_ADDR_END_FUNC(region2, _REGION2_SIZE)
@ -302,7 +302,7 @@ static int base_page_walk(unsigned long *origin, unsigned long addr,
if (!alloc) if (!alloc)
return 0; return 0;
pte = origin; pte = origin;
pte += (addr & _PAGE_INDEX) >> _PAGE_SHIFT; pte += (addr & _PAGE_INDEX) >> PAGE_SHIFT;
do { do {
next = base_page_addr_end(addr, end); next = base_page_addr_end(addr, end);
*pte = base_lra(addr); *pte = base_lra(addr);

View File

@ -8,10 +8,8 @@
#include <linux/const.h> #include <linux/const.h>
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PTE_MASK PAGE_MASK #define PTE_MASK PAGE_MASK
#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)

View File

@ -11,9 +11,7 @@
#include <linux/const.h> #include <linux/const.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -4,9 +4,7 @@
#include <linux/const.h> #include <linux/const.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT #include <vdso/page.h>
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
/* Flushing for D-cache alias handling is only needed if /* Flushing for D-cache alias handling is only needed if
* the page size is smaller than 16K. * the page size is smaller than 16K.

View File

@ -9,10 +9,7 @@
#include <linux/const.h> #include <linux/const.h>
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/vdso/vsyscall.h>
/* /*
* Linker script for vDSO. This is an ELF shared object prelinked to * Linker script for vDSO. This is an ELF shared object prelinked to
@ -16,23 +17,16 @@ SECTIONS
* segment. * segment.
*/ */
vvar_start = . - 4 * PAGE_SIZE; vvar_start = . - __VVAR_PAGES * PAGE_SIZE;
vvar_page = vvar_start; vvar_page = vvar_start;
/* Place all vvars at the offsets in asm/vvar.h. */ vdso_rng_data = vvar_page + __VDSO_RND_DATA_OFFSET;
#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
#include <asm/vvar.h>
#undef EMIT_VVAR
pvclock_page = vvar_start + PAGE_SIZE; timens_page = vvar_start + PAGE_SIZE;
hvclock_page = vvar_start + 2 * PAGE_SIZE;
timens_page = vvar_start + 3 * PAGE_SIZE;
#undef _ASM_X86_VVAR_H vclock_pages = vvar_start + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE;
/* Place all vvars in timens too at the offsets in asm/vvar.h. */ pvclock_page = vclock_pages + VDSO_PAGE_PVCLOCK_OFFSET * PAGE_SIZE;
#define EMIT_VVAR(name, offset) timens_ ## name = timens_page + offset; hvclock_page = vclock_pages + VDSO_PAGE_HVCLOCK_OFFSET * PAGE_SIZE;
#include <asm/vvar.h>
#undef EMIT_VVAR
. = SIZEOF_HEADERS; . = SIZEOF_HEADERS;

View File

@ -20,26 +20,20 @@
#include <asm/vgtod.h> #include <asm/vgtod.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/vvar.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/vdso/vsyscall.h>
#include <clocksource/hyperv_timer.h> #include <clocksource/hyperv_timer.h>
#undef _ASM_X86_VVAR_H
#define EMIT_VVAR(name, offset) \
const size_t name ## _offset = offset;
#include <asm/vvar.h>
struct vdso_data *arch_get_vdso_data(void *vvar_page) struct vdso_data *arch_get_vdso_data(void *vvar_page)
{ {
return (struct vdso_data *)(vvar_page + _vdso_data_offset); return (struct vdso_data *)vvar_page;
} }
#undef EMIT_VVAR
DEFINE_VVAR(struct vdso_data, _vdso_data); static union vdso_data_store vdso_data_store __page_aligned_data;
DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data); struct vdso_data *vdso_data = vdso_data_store.data;
unsigned int vclocks_used __read_mostly; unsigned int vclocks_used __read_mostly;
@ -154,7 +148,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
if (sym_offset == image->sym_vvar_page) { if (sym_offset == image->sym_vvar_page) {
struct page *timens_page = find_timens_vvar_page(vma); struct page *timens_page = find_timens_vvar_page(vma);
pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT; pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT;
/* /*
* If a task belongs to a time namespace then a namespace * If a task belongs to a time namespace then a namespace
@ -182,32 +176,52 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
} }
return vmf_insert_pfn(vma, vmf->address, pfn); return vmf_insert_pfn(vma, vmf->address, pfn);
} else if (sym_offset == image->sym_pvclock_page) {
struct pvclock_vsyscall_time_info *pvti =
pvclock_get_pvti_cpu0_va();
if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)) {
return vmf_insert_pfn_prot(vma, vmf->address,
__pa(pvti) >> PAGE_SHIFT,
pgprot_decrypted(vma->vm_page_prot));
}
} else if (sym_offset == image->sym_hvclock_page) {
pfn = hv_get_tsc_pfn();
if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
return vmf_insert_pfn(vma, vmf->address, pfn);
} else if (sym_offset == image->sym_timens_page) { } else if (sym_offset == image->sym_timens_page) {
struct page *timens_page = find_timens_vvar_page(vma); struct page *timens_page = find_timens_vvar_page(vma);
if (!timens_page) if (!timens_page)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT; pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT;
return vmf_insert_pfn(vma, vmf->address, pfn); return vmf_insert_pfn(vma, vmf->address, pfn);
} }
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
static vm_fault_t vvar_vclock_fault(const struct vm_special_mapping *sm,
struct vm_area_struct *vma, struct vm_fault *vmf)
{
switch (vmf->pgoff) {
#ifdef CONFIG_PARAVIRT_CLOCK
case VDSO_PAGE_PVCLOCK_OFFSET:
{
struct pvclock_vsyscall_time_info *pvti =
pvclock_get_pvti_cpu0_va();
if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))
return vmf_insert_pfn_prot(vma, vmf->address,
__pa(pvti) >> PAGE_SHIFT,
pgprot_decrypted(vma->vm_page_prot));
break;
}
#endif /* CONFIG_PARAVIRT_CLOCK */
#ifdef CONFIG_HYPERV_TIMER
case VDSO_PAGE_HVCLOCK_OFFSET:
{
unsigned long pfn = hv_get_tsc_pfn();
if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
return vmf_insert_pfn(vma, vmf->address, pfn);
break;
}
#endif /* CONFIG_HYPERV_TIMER */
}
return VM_FAULT_SIGBUS;
}
static const struct vm_special_mapping vdso_mapping = { static const struct vm_special_mapping vdso_mapping = {
.name = "[vdso]", .name = "[vdso]",
.fault = vdso_fault, .fault = vdso_fault,
@ -217,6 +231,10 @@ static const struct vm_special_mapping vvar_mapping = {
.name = "[vvar]", .name = "[vvar]",
.fault = vvar_fault, .fault = vvar_fault,
}; };
static const struct vm_special_mapping vvar_vclock_mapping = {
.name = "[vvar_vclock]",
.fault = vvar_vclock_fault,
};
/* /*
* Add vdso and vvar mappings to current process. * Add vdso and vvar mappings to current process.
@ -259,7 +277,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
vma = _install_special_mapping(mm, vma = _install_special_mapping(mm,
addr, addr,
-image->sym_vvar_start, (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
VM_PFNMAP, VM_PFNMAP,
&vvar_mapping); &vvar_mapping);
@ -267,11 +285,26 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
ret = PTR_ERR(vma); ret = PTR_ERR(vma);
do_munmap(mm, text_start, image->size, NULL); do_munmap(mm, text_start, image->size, NULL);
} else { goto up_fail;
current->mm->context.vdso = (void __user *)text_start;
current->mm->context.vdso_image = image;
} }
vma = _install_special_mapping(mm,
addr + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE,
VDSO_NR_VCLOCK_PAGES * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
VM_PFNMAP,
&vvar_vclock_mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
do_munmap(mm, text_start, image->size, NULL);
do_munmap(mm, addr, image->size, NULL);
goto up_fail;
}
current->mm->context.vdso = (void __user *)text_start;
current->mm->context.vdso_image = image;
up_fail: up_fail:
mmap_write_unlock(mm); mmap_write_unlock(mm);
return ret; return ret;
@ -293,7 +326,8 @@ int map_vdso_once(const struct vdso_image *image, unsigned long addr)
*/ */
for_each_vma(vmi, vma) { for_each_vma(vmi, vma) {
if (vma_is_special_mapping(vma, &vdso_mapping) || if (vma_is_special_mapping(vma, &vdso_mapping) ||
vma_is_special_mapping(vma, &vvar_mapping)) { vma_is_special_mapping(vma, &vvar_mapping) ||
vma_is_special_mapping(vma, &vvar_vclock_mapping)) {
mmap_write_unlock(mm); mmap_write_unlock(mm);
return -EEXIST; return -EEXIST;
} }

View File

@ -6,10 +6,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/mem_encrypt.h> #include <linux/mem_encrypt.h>
/* PAGE_SHIFT determines the page size */ #include <vdso/page.h>
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1) #define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)

View File

@ -8,7 +8,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/vvar.h>
/** /**
* getrandom_syscall - Invoke the getrandom() syscall. * getrandom_syscall - Invoke the getrandom() syscall.
@ -28,13 +27,14 @@ static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsig
return ret; return ret;
} }
#define __vdso_rng_data (VVAR(_vdso_rng_data)) extern struct vdso_rng_data vdso_rng_data
__attribute__((visibility("hidden")));
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{ {
if (IS_ENABLED(CONFIG_TIME_NS) && __vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS) if (IS_ENABLED(CONFIG_TIME_NS) && __arch_get_vdso_data()->clock_mode == VDSO_CLOCKMODE_TIMENS)
return (void *)&__vdso_rng_data + ((void *)&__timens_vdso_data - (void *)&__vdso_data); return (void *)&vdso_rng_data + ((void *)&timens_page - (void *)__arch_get_vdso_data());
return &__vdso_rng_data; return &vdso_rng_data;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -14,14 +14,16 @@
#include <uapi/linux/time.h> #include <uapi/linux/time.h>
#include <asm/vgtod.h> #include <asm/vgtod.h>
#include <asm/vvar.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/pvclock.h> #include <asm/pvclock.h>
#include <clocksource/hyperv_timer.h> #include <clocksource/hyperv_timer.h>
#define __vdso_data (VVAR(_vdso_data)) extern struct vdso_data vvar_page
#define __timens_vdso_data (TIMENS(_vdso_data)) __attribute__((visibility("hidden")));
extern struct vdso_data timens_page
__attribute__((visibility("hidden")));
#define VDSO_HAS_TIME 1 #define VDSO_HAS_TIME 1
@ -61,7 +63,7 @@ extern struct ms_hyperv_tsc_page hvclock_page
static __always_inline static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{ {
return __timens_vdso_data; return &timens_page;
} }
#endif #endif
@ -275,7 +277,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode,
static __always_inline const struct vdso_data *__arch_get_vdso_data(void) static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{ {
return __vdso_data; return &vvar_page;
} }
static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd) static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd)

View File

@ -2,12 +2,19 @@
#ifndef __ASM_VDSO_VSYSCALL_H #ifndef __ASM_VDSO_VSYSCALL_H
#define __ASM_VDSO_VSYSCALL_H #define __ASM_VDSO_VSYSCALL_H
#define __VDSO_RND_DATA_OFFSET 640
#define __VVAR_PAGES 4
#define VDSO_NR_VCLOCK_PAGES 2
#define VDSO_PAGE_PVCLOCK_OFFSET 0
#define VDSO_PAGE_HVCLOCK_OFFSET 1
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <asm/vgtod.h> #include <asm/vgtod.h>
#include <asm/vvar.h>
extern struct vdso_data *vdso_data;
/* /*
* Update the vDSO data page to keep in sync with kernel timekeeping. * Update the vDSO data page to keep in sync with kernel timekeeping.
@ -15,14 +22,14 @@
static __always_inline static __always_inline
struct vdso_data *__x86_get_k_vdso_data(void) struct vdso_data *__x86_get_k_vdso_data(void)
{ {
return _vdso_data; return vdso_data;
} }
#define __arch_get_k_vdso_data __x86_get_k_vdso_data #define __arch_get_k_vdso_data __x86_get_k_vdso_data
static __always_inline static __always_inline
struct vdso_rng_data *__x86_get_k_vdso_rng_data(void) struct vdso_rng_data *__x86_get_k_vdso_rng_data(void)
{ {
return &_vdso_rng_data; return (void *)vdso_data + __VDSO_RND_DATA_OFFSET;
} }
#define __arch_get_k_vdso_rng_data __x86_get_k_vdso_rng_data #define __arch_get_k_vdso_rng_data __x86_get_k_vdso_rng_data

View File

@ -1,71 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* vvar.h: Shared vDSO/kernel variable declarations
* Copyright (c) 2011 Andy Lutomirski
*
* A handful of variables are accessible (read-only) from userspace
* code in the vsyscall page and the vdso. They are declared here.
* Some other file must define them with DEFINE_VVAR.
*
* In normal kernel code, they are used like any other variable.
* In user code, they are accessed through the VVAR macro.
*
* These variables live in a page of kernel data that has an extra RO
* mapping for userspace. Each variable needs a unique offset within
* that page; specify that offset with the DECLARE_VVAR macro. (If
* you mess up, the linker will catch it.)
*/
#ifndef _ASM_X86_VVAR_H
#define _ASM_X86_VVAR_H
#ifdef EMIT_VVAR
/*
* EMIT_VVAR() is used by the kernel linker script to put vvars in the
* right place. Also, it's used by kernel code to import offsets values.
*/
#define DECLARE_VVAR(offset, type, name) \
EMIT_VVAR(name, offset)
#define DECLARE_VVAR_SINGLE(offset, type, name) \
EMIT_VVAR(name, offset)
#else
extern char __vvar_page;
#define DECLARE_VVAR(offset, type, name) \
extern type vvar_ ## name[CS_BASES] \
__attribute__((visibility("hidden"))); \
extern type timens_ ## name[CS_BASES] \
__attribute__((visibility("hidden"))); \
#define DECLARE_VVAR_SINGLE(offset, type, name) \
extern type vvar_ ## name \
__attribute__((visibility("hidden"))); \
#define VVAR(name) (vvar_ ## name)
#define TIMENS(name) (timens_ ## name)
#define DEFINE_VVAR(type, name) \
type name[CS_BASES] \
__attribute__((section(".vvar_" #name), aligned(16))) __visible
#define DEFINE_VVAR_SINGLE(type, name) \
type name \
__attribute__((section(".vvar_" #name), aligned(16))) __visible
#endif
/* DECLARE_VVAR(offset, type, name) */
DECLARE_VVAR(128, struct vdso_data, _vdso_data)
#if !defined(_SINGLE_DATA)
#define _SINGLE_DATA
DECLARE_VVAR_SINGLE(640, struct vdso_rng_data, _vdso_rng_data)
#endif
#undef DECLARE_VVAR
#undef DECLARE_VVAR_SINGLE
#endif

View File

@ -193,29 +193,6 @@ SECTIONS
ORC_UNWIND_TABLE ORC_UNWIND_TABLE
. = ALIGN(PAGE_SIZE);
__vvar_page = .;
.vvar : AT(ADDR(.vvar) - LOAD_OFFSET) {
/* work around gold bug 13023 */
__vvar_beginning_hack = .;
/* Place all vvars at the offsets in asm/vvar.h. */
#define EMIT_VVAR(name, offset) \
. = __vvar_beginning_hack + offset; \
*(.vvar_ ## name)
#include <asm/vvar.h>
#undef EMIT_VVAR
/*
* Pad the rest of the page with zeros. Otherwise the loader
* can leave garbage here.
*/
. = __vvar_beginning_hack + PAGE_SIZE;
} :data
. = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
/* Init code and data - will be freed after init */ /* Init code and data - will be freed after init */
. = ALIGN(PAGE_SIZE); . = ALIGN(PAGE_SIZE);
.init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) { .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {

View File

@ -163,11 +163,6 @@ unsigned long get_mmap_base(int is_legacy)
return is_legacy ? mm->mmap_legacy_base : mm->mmap_base; return is_legacy ? mm->mmap_legacy_base : mm->mmap_base;
} }
const char *arch_vma_name(struct vm_area_struct *vma)
{
return NULL;
}
/** /**
* mmap_address_hint_valid - Validate the address hint of mmap * mmap_address_hint_valid - Validate the address hint of mmap
* @addr: Address hint * @addr: Address hint

View File

@ -90,7 +90,6 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
"init_per_cpu__.*|" "init_per_cpu__.*|"
"__end_rodata_hpage_align|" "__end_rodata_hpage_align|"
#endif #endif
"__vvar_page|"
"_end)$" "_end)$"
}; };

View File

@ -18,13 +18,7 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/kmem_layout.h> #include <asm/kmem_layout.h>
/* #include <vdso/page.h>
* PAGE_SHIFT determines the page size
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR

View File

@ -302,7 +302,7 @@ static void gen6_check_faults(struct intel_gt *gt)
{ {
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
enum intel_engine_id id; enum intel_engine_id id;
u32 fault; unsigned long fault;
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
fault = GEN6_RING_FAULT_REG_READ(engine); fault = GEN6_RING_FAULT_REG_READ(engine);
@ -310,8 +310,8 @@ static void gen6_check_faults(struct intel_gt *gt)
gt_dbg(gt, "Unexpected fault\n" gt_dbg(gt, "Unexpected fault\n"
"\tAddr: 0x%08lx\n" "\tAddr: 0x%08lx\n"
"\tAddress space: %s\n" "\tAddress space: %s\n"
"\tSource ID: %d\n" "\tSource ID: %ld\n"
"\tType: %d\n", "\tType: %ld\n",
fault & PAGE_MASK, fault & PAGE_MASK,
fault & RING_FAULT_GTTSEL_MASK ? fault & RING_FAULT_GTTSEL_MASK ?
"GGTT" : "PPGTT", "GGTT" : "PPGTT",

View File

@ -12,8 +12,7 @@ static __always_inline struct vdso_data *__arch_get_k_vdso_data(void)
#endif /* __arch_get_k_vdso_data */ #endif /* __arch_get_k_vdso_data */
#ifndef __arch_update_vsyscall #ifndef __arch_update_vsyscall
static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata, static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata)
struct timekeeper *tk)
{ {
} }
#endif /* __arch_update_vsyscall */ #endif /* __arch_update_vsyscall */

View File

@ -19,10 +19,10 @@
#include <vdso/time32.h> #include <vdso/time32.h>
#include <vdso/time64.h> #include <vdso/time64.h>
#ifdef CONFIG_ARCH_HAS_VDSO_DATA #ifdef CONFIG_ARCH_HAS_VDSO_TIME_DATA
#include <asm/vdso/data.h> #include <asm/vdso/time_data.h>
#else #else
struct arch_vdso_data {}; struct arch_vdso_time_data {};
#endif #endif
#define VDSO_BASES (CLOCK_TAI + 1) #define VDSO_BASES (CLOCK_TAI + 1)
@ -114,7 +114,7 @@ struct vdso_data {
u32 hrtimer_res; u32 hrtimer_res;
u32 __unused; u32 __unused;
struct arch_vdso_data arch_data; struct arch_vdso_time_data arch_data;
}; };
/** /**

31
include/vdso/page.h Normal file
View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __VDSO_PAGE_H
#define __VDSO_PAGE_H
#include <uapi/linux/const.h>
/*
* PAGE_SHIFT determines the page size.
*
* Note: This definition is required because PAGE_SHIFT is used
* in several places throuout the codebase.
*/
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
#define PAGE_SIZE (_AC(1,UL) << CONFIG_PAGE_SHIFT)
#if !defined(CONFIG_64BIT)
/*
* Applies only to 32-bit architectures.
*
* Subtle: (1 << CONFIG_PAGE_SHIFT) is an int, not an unsigned long.
* So if we assign PAGE_MASK to a larger type it gets extended the
* way we want (i.e. with 1s in the high bits) while masking a
* 64-bit value such as phys_addr_t.
*/
#define PAGE_MASK (~((1 << CONFIG_PAGE_SHIFT) - 1))
#else
#define PAGE_MASK (~(PAGE_SIZE - 1))
#endif
#endif /* __VDSO_PAGE_H */

View File

@ -119,7 +119,7 @@ void update_vsyscall(struct timekeeper *tk)
if (clock_mode != VDSO_CLOCKMODE_NONE) if (clock_mode != VDSO_CLOCKMODE_NONE)
update_vdso_data(vdata, tk); update_vdso_data(vdata, tk);
__arch_update_vsyscall(vdata, tk); __arch_update_vsyscall(vdata);
vdso_write_end(vdata); vdso_write_end(vdata);