mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 04:04:26 +08:00
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:
commit
0352387523
@ -1529,7 +1529,7 @@ config HAVE_SPARSE_SYSCALL_NR
|
||||
entries at 4000, 5000 and 6000 locations. This option turns on syscall
|
||||
related optimizations for a given architecture.
|
||||
|
||||
config ARCH_HAS_VDSO_DATA
|
||||
config ARCH_HAS_VDSO_TIME_DATA
|
||||
bool
|
||||
|
||||
config HAVE_STATIC_CALL
|
||||
|
@ -4,11 +4,7 @@
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <asm/pal.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
/* PAGE_SHIFT determines the page size */
|
||||
#ifdef __KERNEL__
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#include <vdso/page.h>
|
||||
#else
|
||||
/*
|
||||
* Default 8k
|
||||
@ -24,11 +24,10 @@
|
||||
* not available
|
||||
*/
|
||||
#define PAGE_SHIFT 13
|
||||
#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#endif
|
||||
|
||||
#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
|
||||
#define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */
|
||||
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
#endif /* _UAPI__ASM_ARC_PAGE_H */
|
||||
|
@ -7,10 +7,7 @@
|
||||
#ifndef _ASMARM_PAGE_H
|
||||
#define _ASMARM_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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -15,8 +15,6 @@
|
||||
|
||||
#define VDSO_HAS_CLOCK_GETRES 1
|
||||
|
||||
extern struct vdso_data *__get_datapage(void);
|
||||
|
||||
static __always_inline int gettimeofday_fallback(
|
||||
struct __kernel_old_timeval *_tv,
|
||||
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)
|
||||
{
|
||||
return __get_datapage();
|
||||
return _vdso_data;
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
@ -4,16 +4,12 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
extern struct vdso_data *vdso_data;
|
||||
extern bool cntvct_ok;
|
||||
|
||||
/*
|
||||
* Update the vDSO data page to keep in sync with kernel timekeeping.
|
||||
*/
|
||||
static __always_inline
|
||||
struct vdso_data *__arm_get_k_vdso_data(void)
|
||||
{
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/arch_timer.h>
|
||||
#include <asm/barrier.h>
|
||||
|
@ -5,7 +5,7 @@ include $(srctree)/lib/vdso/Makefile
|
||||
|
||||
hostprogs := vdsomunge
|
||||
|
||||
obj-vdso := vgettimeofday.o datapage.o note.o
|
||||
obj-vdso := vgettimeofday.o note.o
|
||||
|
||||
# Build rules
|
||||
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
|
||||
|
@ -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)
|
@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
@ -19,7 +20,7 @@ OUTPUT_ARCH(arm)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(_start = .);
|
||||
PROVIDE(_vdso_data = . - VDSO_DATA_SIZE);
|
||||
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
|
@ -10,9 +10,6 @@
|
||||
|
||||
#include <linux/const.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#endif /* __ASM_PAGE_DEF_H */
|
||||
|
@ -5,13 +5,6 @@
|
||||
#ifndef __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
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
@ -20,7 +13,7 @@
|
||||
|
||||
#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[];
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
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
|
||||
|
||||
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_RAW].mask = VDSO_PRECISION_MASK;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time_namespace.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <vdso/datapage.h>
|
||||
#include <vdso/helpers.h>
|
||||
@ -39,8 +38,6 @@ struct vdso_abi_info {
|
||||
const char *vdso_code_start;
|
||||
const char *vdso_code_end;
|
||||
unsigned long vdso_pages;
|
||||
/* Data Mapping */
|
||||
struct vm_special_mapping *dm;
|
||||
/* Code Mapping */
|
||||
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);
|
||||
}
|
||||
|
||||
static const struct vm_special_mapping vvar_map;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -129,12 +128,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
mmap_read_lock(mm);
|
||||
|
||||
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);
|
||||
#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);
|
||||
@ -176,6 +171,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||
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,
|
||||
struct mm_struct *mm,
|
||||
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,
|
||||
VM_READ|VM_MAYREAD|VM_PFNMAP,
|
||||
vdso_info[abi].dm);
|
||||
&vvar_map);
|
||||
if (IS_ERR(ret))
|
||||
goto up_fail;
|
||||
|
||||
@ -229,7 +229,6 @@ up_fail:
|
||||
enum aarch32_map {
|
||||
AA32_MAP_VECTORS, /* kuser helpers */
|
||||
AA32_MAP_SIGPAGE,
|
||||
AA32_MAP_VVAR,
|
||||
AA32_MAP_VDSO,
|
||||
};
|
||||
|
||||
@ -254,10 +253,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
|
||||
.pages = &aarch32_sig_page,
|
||||
.mremap = aarch32_sigpage_mremap,
|
||||
},
|
||||
[AA32_MAP_VVAR] = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
[AA32_MAP_VDSO] = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
@ -307,7 +302,6 @@ static int __init __aarch32_alloc_vdso_pages(void)
|
||||
if (!IS_ENABLED(CONFIG_COMPAT_VDSO))
|
||||
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];
|
||||
|
||||
return __vdso_init(VDSO_ABI_AA32);
|
||||
@ -402,26 +396,14 @@ out:
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
enum aarch64_map {
|
||||
AA64_MAP_VVAR,
|
||||
AA64_MAP_VDSO,
|
||||
};
|
||||
|
||||
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 struct vm_special_mapping aarch64_vdso_map __ro_after_init = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
};
|
||||
|
||||
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_maps[AA64_MAP_VDSO];
|
||||
vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_map;
|
||||
|
||||
return __vdso_init(VDSO_ABI_AA64);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ SECTIONS
|
||||
#ifdef CONFIG_TIME_NS
|
||||
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
|
||||
#endif
|
||||
. = VDSO_LBASE + SIZEOF_HEADERS;
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
|
@ -22,7 +22,7 @@ SECTIONS
|
||||
#ifdef CONFIG_TIME_NS
|
||||
PROVIDE_HIDDEN(_timens_data = _vdso_data + PAGE_SIZE);
|
||||
#endif
|
||||
. = VDSO_LBASE + SIZEOF_HEADERS;
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
|
@ -64,9 +64,6 @@ config CSKY
|
||||
select GENERIC_IRQ_MULTI_HANDLER
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_VDSO_32
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GX6605S_TIMER if CPU_CK610
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
@ -80,7 +77,6 @@ config CSKY
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
|
@ -7,12 +7,8 @@
|
||||
#include <asm/cache.h>
|
||||
#include <linux/const.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define THREAD_SIZE (PAGE_SIZE * 2)
|
||||
#define THREAD_MASK (~(THREAD_SIZE - 1))
|
||||
#define THREAD_SHIFT (PAGE_SHIFT + 1)
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -8,23 +8,19 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
extern char vdso_start[], vdso_end[];
|
||||
|
||||
static unsigned int vdso_pages;
|
||||
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)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
|
||||
vdso_pagelist =
|
||||
kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL);
|
||||
kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
|
||||
if (unlikely(vdso_pagelist == NULL)) {
|
||||
pr_err("vdso: pagelist allocation failed\n");
|
||||
return -ENOMEM;
|
||||
@ -36,7 +32,6 @@ static int __init vdso_init(void)
|
||||
pg = virt_to_page(vdso_start + (i << PAGE_SHIFT));
|
||||
vdso_pagelist[i] = pg;
|
||||
}
|
||||
vdso_pagelist[i] = virt_to_page(vdso_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -52,11 +47,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
static struct vm_special_mapping vdso_mapping = {
|
||||
.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);
|
||||
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);
|
||||
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;
|
||||
end:
|
||||
mmap_write_unlock(mm);
|
||||
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;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ include $(srctree)/lib/vdso/Makefile
|
||||
|
||||
# Symbols present in the vdso
|
||||
vdso-syms += rt_sigreturn
|
||||
vdso-syms += vgettimeofday
|
||||
|
||||
# Files to link into the vdso
|
||||
obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
|
||||
|
@ -49,10 +49,6 @@ VERSION
|
||||
LINUX_5.10 {
|
||||
global:
|
||||
__vdso_rt_sigreturn;
|
||||
__vdso_clock_gettime;
|
||||
__vdso_clock_gettime64;
|
||||
__vdso_gettimeofday;
|
||||
__vdso_clock_getres;
|
||||
local: *;
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -45,9 +45,7 @@
|
||||
#define HVM_HUGEPAGE_SIZE 0x5
|
||||
#endif
|
||||
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifndef __ASSEMBLY__
|
||||
|
@ -8,12 +8,7 @@
|
||||
#include <linux/const.h>
|
||||
#include <asm/addrspace.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
|
||||
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
|
||||
|
@ -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)
|
||||
{
|
||||
return (const struct vdso_rng_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START *
|
||||
PAGE_SIZE + offsetof(struct loongarch_vdso_data, rng_data));
|
||||
return &_loongarch_data.rng_data;
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
@ -91,14 +91,14 @@ static inline bool loongarch_vdso_hres_capable(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
|
||||
static __always_inline
|
||||
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 /* !__ASSEMBLY__ */
|
||||
|
@ -48,23 +48,7 @@ enum vvar_pages {
|
||||
|
||||
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
|
||||
|
||||
static inline unsigned long get_vdso_base(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
extern struct loongarch_vdso_data _loongarch_data __attribute__((visibility("hidden")));
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
@ -4,15 +4,11 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
extern struct vdso_data *vdso_data;
|
||||
extern struct vdso_rng_data *vdso_rng_data;
|
||||
|
||||
/*
|
||||
* Update the vDSO data page to keep in sync with kernel timekeeping.
|
||||
*/
|
||||
static __always_inline
|
||||
struct vdso_data *__loongarch_get_k_vdso_data(void)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
static void __used output_ptreg_defines(void)
|
||||
{
|
||||
@ -321,3 +322,11 @@ static void __used output_kvm_defines(void)
|
||||
OFFSET(KVM_GPGD, kvm, arch.pgd);
|
||||
BLANK();
|
||||
}
|
||||
|
||||
static void __used output_vdso_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch vDSO offsets.");
|
||||
|
||||
DEFINE(__VVAR_PAGES, VVAR_NR_PAGES);
|
||||
BLANK();
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time_namespace.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/vdso.h>
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* 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")
|
||||
|
||||
@ -10,7 +12,11 @@ OUTPUT_ARCH(loongarch)
|
||||
|
||||
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;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
|
@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(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
|
||||
|
@ -6,10 +6,8 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page_offset.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define PAGE_OFFSET (PAGE_OFFSET_RAW)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
@ -19,10 +19,7 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* PAGE_SHIFT determines the page size */
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_KERNEL_BASE_ADDR))
|
||||
|
||||
|
@ -14,12 +14,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/mipsregs.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
/*
|
||||
* This is used for calculating the real page sizes
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
extern struct vdso_data *vdso_data;
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <asm/abi.h>
|
||||
#include <asm/mips-cps.h>
|
||||
|
@ -270,7 +270,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Write out the stripped VDSO data. */
|
||||
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);
|
||||
for (i = 0; i < vdso_size; i++) {
|
||||
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",
|
||||
(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.mapping = {\n");
|
||||
fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
|
||||
|
@ -18,12 +18,7 @@
|
||||
#include <linux/pfn.h>
|
||||
#include <linux/const.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
/*
|
||||
* PAGE_OFFSET -- the first address of the first page of memory.
|
||||
|
@ -15,16 +15,7 @@
|
||||
#ifndef __ASM_OPENRISC_PAGE_H
|
||||
#define __ASM_OPENRISC_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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define PAGE_OFFSET 0xc0000000
|
||||
#define KERNELBASE PAGE_OFFSET
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
||||
|
||||
|
@ -1302,6 +1302,14 @@ config MODULES_SIZE
|
||||
|
||||
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
|
||||
# This value must have zeroes in the bottom 60 bits otherwise lots will break
|
||||
config PAGE_OFFSET
|
||||
|
@ -21,8 +21,7 @@
|
||||
* page size. When using 64K pages however, whether we are really supporting
|
||||
* 64K pages in HW or not is irrelevant to those definitions.
|
||||
*/
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef CONFIG_HUGETLB_PAGE
|
||||
@ -41,13 +40,6 @@ extern unsigned int hpage_shift;
|
||||
#define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1)
|
||||
#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
|
||||
* the same as PAGE_OFFSET, but _might not be_.
|
||||
|
52
arch/powerpc/include/asm/systemcfg.h
Normal file
52
arch/powerpc/include/asm/systemcfg.h
Normal 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 */
|
@ -4,12 +4,8 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
|
||||
/*
|
||||
* Update the vDSO data page to keep in sync with kernel timekeeping.
|
||||
*/
|
||||
static __always_inline
|
||||
struct vdso_data *__arch_get_k_vdso_data(void)
|
||||
{
|
||||
|
@ -9,29 +9,6 @@
|
||||
* 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__
|
||||
|
||||
#include <linux/unistd.h>
|
||||
@ -40,41 +17,10 @@
|
||||
|
||||
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
|
||||
|
||||
/*
|
||||
* So here is the ppc64 backward compatible version
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
struct vdso_arch_data {
|
||||
__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 */
|
||||
|
||||
/* those additional ones don't have to be located anywhere
|
||||
* special as they were not part of the original systemcfg
|
||||
*/
|
||||
__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 */
|
||||
@ -88,11 +34,8 @@ struct vdso_arch_data {
|
||||
|
||||
#else /* CONFIG_PPC64 */
|
||||
|
||||
/*
|
||||
* And here is the simpler 32 bits version
|
||||
*/
|
||||
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 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
||||
struct vdso_data data[CS_BASES];
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -12,9 +13,10 @@
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/systemcfg.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)
|
||||
{
|
||||
@ -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)
|
||||
return -EINVAL;
|
||||
|
||||
remap_pfn_range(vma, vma->vm_start,
|
||||
__pa(pde_data(file_inode(file))) >> PAGE_SHIFT,
|
||||
PAGE_SIZE, vma->vm_page_prot);
|
||||
return 0;
|
||||
return remap_pfn_range(vma, vma->vm_start,
|
||||
__pa(pde_data(file_inode(file))) >> PAGE_SHIFT,
|
||||
PAGE_SIZE, vma->vm_page_prot);
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
&page_map_proc_ops, vdso_data);
|
||||
&page_map_proc_ops, systemcfg);
|
||||
if (!pde)
|
||||
return 1;
|
||||
proc_set_size(pde, PAGE_SIZE);
|
||||
@ -60,7 +83,7 @@ static int __init proc_ppc64_init(void)
|
||||
}
|
||||
__initcall(proc_ppc64_init);
|
||||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
#endif /* CONFIG_PPC64_PROC_SYSTEMCFG */
|
||||
|
||||
/*
|
||||
* Create the ppc64 and ppc64/rtas directories early. This allows us to
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include <asm/cpu_has_feature.h>
|
||||
#include <asm/kasan.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
@ -560,7 +561,9 @@ void __init smp_setup_cpu_maps(void)
|
||||
out:
|
||||
of_node_put(dn);
|
||||
}
|
||||
vdso_data->processorCount = num_present_cpus();
|
||||
#endif
|
||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||
systemcfg->processorCount = num_present_cpus();
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/* Initialize CPU <=> thread mapping/
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/kup.h>
|
||||
#include <asm/fadump.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
||||
#include <trace/events/ipi.h>
|
||||
|
||||
@ -1186,8 +1187,8 @@ int generic_cpu_disable(void)
|
||||
return -EBUSY;
|
||||
|
||||
set_cpu_online(cpu, false);
|
||||
#ifdef CONFIG_PPC64
|
||||
vdso_data->processorCount--;
|
||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||
systemcfg->processorCount--;
|
||||
#endif
|
||||
/* Update affinity of all IRQs previously aimed at this CPU */
|
||||
irq_migrate_all_off_this_cpu();
|
||||
@ -1642,10 +1643,12 @@ void start_secondary(void *unused)
|
||||
|
||||
secondary_cpu_time_init();
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||
if (system_state == SYSTEM_RUNNING)
|
||||
vdso_data->processorCount++;
|
||||
systemcfg->processorCount++;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
vdso_getcpu_init();
|
||||
#endif
|
||||
set_numa_node(numa_cpu_lookup_table[cpu]);
|
||||
|
@ -71,11 +71,11 @@
|
||||
#include <asm/vdso_datapage.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
||||
/* powerpc clocksource/clockevent code */
|
||||
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
static u64 timebase_read(struct clocksource *);
|
||||
static struct clocksource clocksource_timebase = {
|
||||
@ -951,6 +951,9 @@ void __init time_init(void)
|
||||
}
|
||||
|
||||
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) */
|
||||
set_decrementer_max();
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/user.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/time_namespace.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)
|
||||
{
|
||||
#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->icache_block_size = ppc64_caches.l1i.block_size;
|
||||
vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/powernv.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
||||
#include "powernv.h"
|
||||
|
||||
@ -136,7 +137,9 @@ static int pnv_smp_cpu_disable(void)
|
||||
* the generic fixup_irqs. --BenH.
|
||||
*/
|
||||
set_cpu_online(cpu, false);
|
||||
vdso_data->processorCount--;
|
||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||
systemcfg->processorCount--;
|
||||
#endif
|
||||
if (cpu == boot_cpuid)
|
||||
boot_cpuid = cpumask_any(cpu_online_mask);
|
||||
if (xive_enabled())
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <asm/xive.h>
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#include <asm/topology.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
||||
#include "pseries.h"
|
||||
|
||||
@ -83,7 +84,9 @@ static int pseries_cpu_disable(void)
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
set_cpu_online(cpu, false);
|
||||
vdso_data->processorCount--;
|
||||
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
|
||||
systemcfg->processorCount--;
|
||||
#endif
|
||||
|
||||
/*fix boot_cpuid here*/
|
||||
if (cpu == boot_cpuid)
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/mmu.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);
|
||||
|
||||
if (lrdrp == NULL) {
|
||||
partition_potential_processors = vdso_data->processorCount;
|
||||
partition_potential_processors = num_possible_cpus();
|
||||
} else {
|
||||
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 */
|
||||
|
||||
seq_printf(m, "system_active_processors=%d\n",
|
||||
partition_potential_processors);
|
||||
partition_active_processors);
|
||||
|
||||
seq_printf(m, "system_potential_processors=%d\n",
|
||||
partition_potential_processors);
|
||||
|
@ -51,7 +51,7 @@ config RISCV
|
||||
select ARCH_HAS_SYSCALL_WRAPPER
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UBSAN
|
||||
select ARCH_HAS_VDSO_DATA
|
||||
select ARCH_HAS_VDSO_TIME_DATA
|
||||
select ARCH_KEEP_MEMBLOCK if ACPI
|
||||
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
|
||||
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
|
||||
|
@ -12,9 +12,7 @@
|
||||
#include <linux/pfn.h>
|
||||
#include <linux/const.h>
|
||||
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define HPAGE_SHIFT PMD_SHIFT
|
||||
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
|
||||
|
@ -1,12 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __RISCV_ASM_VDSO_DATA_H
|
||||
#define __RISCV_ASM_VDSO_DATA_H
|
||||
#ifndef __RISCV_ASM_VDSO_TIME_DATA_H
|
||||
#define __RISCV_ASM_VDSO_TIME_DATA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <vdso/datapage.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. */
|
||||
__u64 all_cpu_hwprobe_values[RISCV_HWPROBE_MAX_KEY + 1];
|
||||
|
||||
@ -14,4 +14,4 @@ struct arch_vdso_data {
|
||||
__u8 homogeneous_cpus;
|
||||
};
|
||||
|
||||
#endif /* __RISCV_ASM_VDSO_DATA_H */
|
||||
#endif /* __RISCV_ASM_VDSO_TIME_DATA_H */
|
@ -4,14 +4,10 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
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)
|
||||
{
|
||||
return vdso_data;
|
||||
|
@ -402,7 +402,7 @@ static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs,
|
||||
static int __init init_hwprobe_vdso_data(void)
|
||||
{
|
||||
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;
|
||||
struct riscv_hwprobe pair;
|
||||
int key;
|
||||
|
@ -23,11 +23,6 @@ enum vvar_pages {
|
||||
VVAR_NR_PAGES,
|
||||
};
|
||||
|
||||
enum rv_vdso_map {
|
||||
RV_VDSO_MAP_VVAR,
|
||||
RV_VDSO_MAP_VDSO,
|
||||
};
|
||||
|
||||
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
|
||||
|
||||
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_end;
|
||||
unsigned long vdso_pages;
|
||||
/* Data Mapping */
|
||||
struct vm_special_mapping *dm;
|
||||
/* Code Mapping */
|
||||
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);
|
||||
}
|
||||
|
||||
static const struct vm_special_mapping rv_vvar_map;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -108,12 +103,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
mmap_read_lock(mm);
|
||||
|
||||
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);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (vma_is_special_mapping(vma, compat_vdso_info.dm))
|
||||
zap_vma_pages(vma);
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
|
||||
[RV_VDSO_MAP_VVAR] = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
[RV_VDSO_MAP_VDSO] = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
},
|
||||
static const struct vm_special_mapping rv_vvar_map = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
};
|
||||
|
||||
static struct vm_special_mapping rv_vdso_map __ro_after_init = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
};
|
||||
|
||||
static struct __vdso_info vdso_info __ro_after_init = {
|
||||
.name = "vdso",
|
||||
.vdso_code_start = vdso_start,
|
||||
.vdso_code_end = vdso_end,
|
||||
.dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR],
|
||||
.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
|
||||
.cm = &rv_vdso_map,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = {
|
||||
[RV_VDSO_MAP_VVAR] = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
[RV_VDSO_MAP_VDSO] = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
},
|
||||
static struct vm_special_mapping rv_compat_vdso_map __ro_after_init = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
};
|
||||
|
||||
static struct __vdso_info compat_vdso_info __ro_after_init = {
|
||||
.name = "compat_vdso",
|
||||
.vdso_code_start = compat_vdso_start,
|
||||
.vdso_code_end = compat_vdso_end,
|
||||
.dm = &rv_compat_vdso_maps[RV_VDSO_MAP_VVAR],
|
||||
.cm = &rv_compat_vdso_maps[RV_VDSO_MAP_VDSO],
|
||||
.cm = &rv_compat_vdso_map,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -227,7 +209,7 @@ static int __setup_additional_pages(struct mm_struct *mm,
|
||||
}
|
||||
|
||||
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))
|
||||
goto up_fail;
|
||||
|
||||
|
@ -17,7 +17,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count,
|
||||
unsigned int flags)
|
||||
{
|
||||
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;
|
||||
struct riscv_hwprobe *p = pairs;
|
||||
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)
|
||||
{
|
||||
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 *end = pairs + pair_count;
|
||||
unsigned char *c = (unsigned char *)cpus;
|
||||
|
@ -95,7 +95,7 @@ config S390
|
||||
select ARCH_HAS_STRICT_MODULE_RWX
|
||||
select ARCH_HAS_SYSCALL_WRAPPER
|
||||
select ARCH_HAS_UBSAN
|
||||
select ARCH_HAS_VDSO_DATA
|
||||
select ARCH_HAS_VDSO_TIME_DATA
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select ARCH_INLINE_READ_LOCK
|
||||
select ARCH_INLINE_READ_LOCK_BH
|
||||
|
@ -12,14 +12,8 @@
|
||||
#include <asm/types.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define _PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define _PAGE_SIZE (_AC(1, UL) << _PAGE_SHIFT)
|
||||
#define _PAGE_MASK (~(_PAGE_SIZE - 1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
/* 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)
|
||||
/* storage-protection override */
|
||||
#define PAGE_SPO_ACC 9
|
||||
|
@ -338,7 +338,7 @@ static inline int is_module_addr(void *addr)
|
||||
#define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT)
|
||||
#define _REGION3_INDEX (0x7ffUL << _REGION3_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 _REGION2_SIZE (1UL << _REGION2_SHIFT)
|
||||
|
@ -12,9 +12,6 @@ int vdso_getcpu_init(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/* Default link address for the vDSO */
|
||||
#define VDSO_LBASE 0
|
||||
|
||||
#define __VVAR_PAGES 2
|
||||
|
||||
#define VDSO_VERSION_STRING LINUX_2.6.29
|
||||
|
@ -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 */
|
12
arch/s390/include/asm/vdso/time_data.h
Normal file
12
arch/s390/include/asm/vdso/time_data.h
Normal 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 */
|
@ -7,7 +7,6 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
@ -17,10 +16,6 @@ enum vvar_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)
|
||||
{
|
||||
return vdso_data;
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <linux/profile.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
@ -16,7 +16,7 @@ SECTIONS
|
||||
#ifdef CONFIG_TIME_NS
|
||||
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
|
||||
#endif
|
||||
. = VDSO_LBASE + SIZEOF_HEADERS;
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
|
@ -18,7 +18,7 @@ SECTIONS
|
||||
#ifdef CONFIG_TIME_NS
|
||||
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
|
||||
#endif
|
||||
. = VDSO_LBASE + SIZEOF_HEADERS;
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
|
@ -128,7 +128,7 @@ static void dump_pagetable(unsigned long asce, unsigned long address)
|
||||
goto out;
|
||||
table = __va(entry & _SEGMENT_ENTRY_ORIGIN);
|
||||
}
|
||||
table += (address & _PAGE_INDEX) >> _PAGE_SHIFT;
|
||||
table += (address & _PAGE_INDEX) >> PAGE_SHIFT;
|
||||
if (get_kernel_nofault(entry, table))
|
||||
goto bad;
|
||||
pr_cont("P:%016lx ", entry);
|
||||
|
@ -900,7 +900,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
|
||||
if (*table & _REGION_ENTRY_INVALID)
|
||||
return NULL;
|
||||
table = __va(*table & _SEGMENT_ENTRY_ORIGIN);
|
||||
table += (gaddr & _PAGE_INDEX) >> _PAGE_SHIFT;
|
||||
table += (gaddr & _PAGE_INDEX) >> PAGE_SHIFT;
|
||||
}
|
||||
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 */
|
||||
if (!table || *table & _PAGE_INVALID)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1384,7 +1384,7 @@ static void __gmap_unshadow_pgt(struct gmap *sg, unsigned long raddr,
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ static inline unsigned long base_##NAME##_addr_end(unsigned long addr, \
|
||||
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(region3, _REGION3_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)
|
||||
return 0;
|
||||
pte = origin;
|
||||
pte += (addr & _PAGE_INDEX) >> _PAGE_SHIFT;
|
||||
pte += (addr & _PAGE_INDEX) >> PAGE_SHIFT;
|
||||
do {
|
||||
next = base_page_addr_end(addr, end);
|
||||
*pte = base_lra(addr);
|
||||
|
@ -8,10 +8,8 @@
|
||||
|
||||
#include <linux/const.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define PTE_MASK PAGE_MASK
|
||||
|
||||
#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
|
||||
|
@ -11,9 +11,7 @@
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
#define PAGE_SHIFT CONFIG_PAGE_SHIFT
|
||||
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#include <vdso/page.h>
|
||||
|
||||
/* Flushing for D-cache alias handling is only needed if
|
||||
* the page size is smaller than 16K.
|
||||
|
@ -9,10 +9,7 @@
|
||||
|
||||
#include <linux/const.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <asm/vdso.h>
|
||||
#include <asm/vdso/vsyscall.h>
|
||||
|
||||
/*
|
||||
* Linker script for vDSO. This is an ELF shared object prelinked to
|
||||
@ -16,23 +17,16 @@ SECTIONS
|
||||
* segment.
|
||||
*/
|
||||
|
||||
vvar_start = . - 4 * PAGE_SIZE;
|
||||
vvar_start = . - __VVAR_PAGES * PAGE_SIZE;
|
||||
vvar_page = vvar_start;
|
||||
|
||||
/* Place all vvars at the offsets in asm/vvar.h. */
|
||||
#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
|
||||
#include <asm/vvar.h>
|
||||
#undef EMIT_VVAR
|
||||
vdso_rng_data = vvar_page + __VDSO_RND_DATA_OFFSET;
|
||||
|
||||
pvclock_page = vvar_start + PAGE_SIZE;
|
||||
hvclock_page = vvar_start + 2 * PAGE_SIZE;
|
||||
timens_page = vvar_start + 3 * PAGE_SIZE;
|
||||
timens_page = vvar_start + PAGE_SIZE;
|
||||
|
||||
#undef _ASM_X86_VVAR_H
|
||||
/* Place all vvars in timens too at the offsets in asm/vvar.h. */
|
||||
#define EMIT_VVAR(name, offset) timens_ ## name = timens_page + offset;
|
||||
#include <asm/vvar.h>
|
||||
#undef EMIT_VVAR
|
||||
vclock_pages = vvar_start + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE;
|
||||
pvclock_page = vclock_pages + VDSO_PAGE_PVCLOCK_OFFSET * PAGE_SIZE;
|
||||
hvclock_page = vclock_pages + VDSO_PAGE_HVCLOCK_OFFSET * PAGE_SIZE;
|
||||
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
|
@ -20,26 +20,20 @@
|
||||
#include <asm/vgtod.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/vdso.h>
|
||||
#include <asm/vvar.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/vdso/vsyscall.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)
|
||||
{
|
||||
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);
|
||||
DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data);
|
||||
static union vdso_data_store vdso_data_store __page_aligned_data;
|
||||
struct vdso_data *vdso_data = vdso_data_store.data;
|
||||
|
||||
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) {
|
||||
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
|
||||
@ -182,32 +176,52 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||
}
|
||||
|
||||
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) {
|
||||
struct page *timens_page = find_timens_vvar_page(vma);
|
||||
|
||||
if (!timens_page)
|
||||
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 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 = {
|
||||
.name = "[vdso]",
|
||||
.fault = vdso_fault,
|
||||
@ -217,6 +231,10 @@ static const struct vm_special_mapping vvar_mapping = {
|
||||
.name = "[vvar]",
|
||||
.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.
|
||||
@ -259,7 +277,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
|
||||
|
||||
vma = _install_special_mapping(mm,
|
||||
addr,
|
||||
-image->sym_vvar_start,
|
||||
(__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE,
|
||||
VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
|
||||
VM_PFNMAP,
|
||||
&vvar_mapping);
|
||||
@ -267,11 +285,26 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
do_munmap(mm, text_start, image->size, NULL);
|
||||
} else {
|
||||
current->mm->context.vdso = (void __user *)text_start;
|
||||
current->mm->context.vdso_image = image;
|
||||
goto up_fail;
|
||||
}
|
||||
|
||||
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:
|
||||
mmap_write_unlock(mm);
|
||||
return ret;
|
||||
@ -293,7 +326,8 @@ int map_vdso_once(const struct vdso_image *image, unsigned long addr)
|
||||
*/
|
||||
for_each_vma(vmi, vma) {
|
||||
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);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -6,10 +6,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/mem_encrypt.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/vvar.h>
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_TIME_NS) && __vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
|
||||
return (void *)&__vdso_rng_data + ((void *)&__timens_vdso_data - (void *)&__vdso_data);
|
||||
return &__vdso_rng_data;
|
||||
if (IS_ENABLED(CONFIG_TIME_NS) && __arch_get_vdso_data()->clock_mode == VDSO_CLOCKMODE_TIMENS)
|
||||
return (void *)&vdso_rng_data + ((void *)&timens_page - (void *)__arch_get_vdso_data());
|
||||
return &vdso_rng_data;
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
@ -14,14 +14,16 @@
|
||||
|
||||
#include <uapi/linux/time.h>
|
||||
#include <asm/vgtod.h>
|
||||
#include <asm/vvar.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/pvclock.h>
|
||||
#include <clocksource/hyperv_timer.h>
|
||||
|
||||
#define __vdso_data (VVAR(_vdso_data))
|
||||
#define __timens_vdso_data (TIMENS(_vdso_data))
|
||||
extern struct vdso_data vvar_page
|
||||
__attribute__((visibility("hidden")));
|
||||
|
||||
extern struct vdso_data timens_page
|
||||
__attribute__((visibility("hidden")));
|
||||
|
||||
#define VDSO_HAS_TIME 1
|
||||
|
||||
@ -61,7 +63,7 @@ extern struct ms_hyperv_tsc_page hvclock_page
|
||||
static __always_inline
|
||||
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
|
||||
{
|
||||
return __timens_vdso_data;
|
||||
return &timens_page;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
return __vdso_data;
|
||||
return &vvar_page;
|
||||
}
|
||||
|
||||
static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd)
|
||||
|
@ -2,12 +2,19 @@
|
||||
#ifndef __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__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <vdso/datapage.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.
|
||||
@ -15,14 +22,14 @@
|
||||
static __always_inline
|
||||
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
|
||||
|
||||
static __always_inline
|
||||
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
|
||||
|
||||
|
@ -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
|
@ -193,29 +193,6 @@ SECTIONS
|
||||
|
||||
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 */
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
|
||||
|
@ -163,11 +163,6 @@ unsigned long get_mmap_base(int is_legacy)
|
||||
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
|
||||
* @addr: Address hint
|
||||
|
@ -90,7 +90,6 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
|
||||
"init_per_cpu__.*|"
|
||||
"__end_rodata_hpage_align|"
|
||||
#endif
|
||||
"__vvar_page|"
|
||||
"_end)$"
|
||||
};
|
||||
|
||||
|
@ -18,13 +18,7 @@
|
||||
#include <asm/cache.h>
|
||||
#include <asm/kmem_layout.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))
|
||||
#include <vdso/page.h>
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
|
||||
|
@ -302,7 +302,7 @@ static void gen6_check_faults(struct intel_gt *gt)
|
||||
{
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
u32 fault;
|
||||
unsigned long fault;
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
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"
|
||||
"\tAddr: 0x%08lx\n"
|
||||
"\tAddress space: %s\n"
|
||||
"\tSource ID: %d\n"
|
||||
"\tType: %d\n",
|
||||
"\tSource ID: %ld\n"
|
||||
"\tType: %ld\n",
|
||||
fault & PAGE_MASK,
|
||||
fault & RING_FAULT_GTTSEL_MASK ?
|
||||
"GGTT" : "PPGTT",
|
||||
|
@ -12,8 +12,7 @@ static __always_inline struct vdso_data *__arch_get_k_vdso_data(void)
|
||||
#endif /* __arch_get_k_vdso_data */
|
||||
|
||||
#ifndef __arch_update_vsyscall
|
||||
static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata,
|
||||
struct timekeeper *tk)
|
||||
static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata)
|
||||
{
|
||||
}
|
||||
#endif /* __arch_update_vsyscall */
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include <vdso/time32.h>
|
||||
#include <vdso/time64.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_VDSO_DATA
|
||||
#include <asm/vdso/data.h>
|
||||
#ifdef CONFIG_ARCH_HAS_VDSO_TIME_DATA
|
||||
#include <asm/vdso/time_data.h>
|
||||
#else
|
||||
struct arch_vdso_data {};
|
||||
struct arch_vdso_time_data {};
|
||||
#endif
|
||||
|
||||
#define VDSO_BASES (CLOCK_TAI + 1)
|
||||
@ -114,7 +114,7 @@ struct vdso_data {
|
||||
u32 hrtimer_res;
|
||||
u32 __unused;
|
||||
|
||||
struct arch_vdso_data arch_data;
|
||||
struct arch_vdso_time_data arch_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
31
include/vdso/page.h
Normal file
31
include/vdso/page.h
Normal 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 */
|
@ -119,7 +119,7 @@ void update_vsyscall(struct timekeeper *tk)
|
||||
if (clock_mode != VDSO_CLOCKMODE_NONE)
|
||||
update_vdso_data(vdata, tk);
|
||||
|
||||
__arch_update_vsyscall(vdata, tk);
|
||||
__arch_update_vsyscall(vdata);
|
||||
|
||||
vdso_write_end(vdata);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user