x86, vdso: Make vsyscall_gtod_data handling x86 generic
This patch move the vsyscall_gtod_data handling out of vsyscall_64.c into an additonal file vsyscall_gtod.c to make the functionality available for x86 32 bit kernel. It also adds a new vsyscall_32.c which setup the VVAR page. Reviewed-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Stefani Seibold <stefani@seibold.net> Link: http://lkml.kernel.org/r/1395094933-14252-2-git-send-email-stefani@seibold.net Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
1f2cbcf648
commit
d2312e3379
@ -107,9 +107,9 @@ config X86
|
|||||||
select HAVE_ARCH_SOFT_DIRTY
|
select HAVE_ARCH_SOFT_DIRTY
|
||||||
select CLOCKSOURCE_WATCHDOG
|
select CLOCKSOURCE_WATCHDOG
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select ARCH_CLOCKSOURCE_DATA if X86_64
|
select ARCH_CLOCKSOURCE_DATA
|
||||||
select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
|
select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
|
||||||
select GENERIC_TIME_VSYSCALL if X86_64
|
select GENERIC_TIME_VSYSCALL
|
||||||
select KTIME_SCALAR if X86_32
|
select KTIME_SCALAR if X86_32
|
||||||
select GENERIC_STRNCPY_FROM_USER
|
select GENERIC_STRNCPY_FROM_USER
|
||||||
select GENERIC_STRNLEN_USER
|
select GENERIC_STRNLEN_USER
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#ifndef _ASM_X86_CLOCKSOURCE_H
|
#ifndef _ASM_X86_CLOCKSOURCE_H
|
||||||
#define _ASM_X86_CLOCKSOURCE_H
|
#define _ASM_X86_CLOCKSOURCE_H
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
|
|
||||||
#define VCLOCK_NONE 0 /* No vDSO clock available. */
|
#define VCLOCK_NONE 0 /* No vDSO clock available. */
|
||||||
#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */
|
#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */
|
||||||
#define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */
|
#define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */
|
||||||
@ -14,6 +12,4 @@ struct arch_clocksource_data {
|
|||||||
int vclock_mode;
|
int vclock_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_X86_64 */
|
|
||||||
|
|
||||||
#endif /* _ASM_X86_CLOCKSOURCE_H */
|
#endif /* _ASM_X86_CLOCKSOURCE_H */
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
* you mess up, the linker will catch it.)
|
* you mess up, the linker will catch it.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Base address of vvars. This is not ABI. */
|
|
||||||
#define VVAR_ADDRESS (-10*1024*1024 - 4096)
|
|
||||||
|
|
||||||
#if defined(__VVAR_KERNEL_LDS)
|
#if defined(__VVAR_KERNEL_LDS)
|
||||||
|
|
||||||
/* The kernel linker script defines its own magic to put vvars in the
|
/* The kernel linker script defines its own magic to put vvars in the
|
||||||
@ -29,6 +26,15 @@
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
extern char __vvar_page;
|
||||||
|
|
||||||
|
/* Base address of vvars. This is not ABI. */
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
#define VVAR_ADDRESS (-10*1024*1024 - 4096)
|
||||||
|
#else
|
||||||
|
#define VVAR_ADDRESS (&__vvar_page)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DECLARE_VVAR(offset, type, name) \
|
#define DECLARE_VVAR(offset, type, name) \
|
||||||
static type const * const vvaraddr_ ## name = \
|
static type const * const vvaraddr_ ## name = \
|
||||||
(void *)(VVAR_ADDRESS + (offset));
|
(void *)(VVAR_ADDRESS + (offset));
|
||||||
|
@ -26,7 +26,7 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o
|
|||||||
obj-y += probe_roms.o
|
obj-y += probe_roms.o
|
||||||
obj-$(CONFIG_X86_32) += i386_ksyms_32.o
|
obj-$(CONFIG_X86_32) += i386_ksyms_32.o
|
||||||
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
|
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
|
||||||
obj-y += syscall_$(BITS).o
|
obj-y += syscall_$(BITS).o vsyscall_gtod.o
|
||||||
obj-$(CONFIG_X86_64) += vsyscall_64.o
|
obj-$(CONFIG_X86_64) += vsyscall_64.o
|
||||||
obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
|
obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
|
||||||
obj-$(CONFIG_SYSFS) += ksysfs.o
|
obj-$(CONFIG_SYSFS) += ksysfs.o
|
||||||
|
@ -752,9 +752,7 @@ static struct clocksource clocksource_hpet = {
|
|||||||
.mask = HPET_MASK,
|
.mask = HPET_MASK,
|
||||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||||
.resume = hpet_resume_counter,
|
.resume = hpet_resume_counter,
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
.archdata = { .vclock_mode = VCLOCK_HPET },
|
.archdata = { .vclock_mode = VCLOCK_HPET },
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hpet_clocksource_register(void)
|
static int hpet_clocksource_register(void)
|
||||||
|
@ -985,9 +985,7 @@ static struct clocksource clocksource_tsc = {
|
|||||||
.mask = CLOCKSOURCE_MASK(64),
|
.mask = CLOCKSOURCE_MASK(64),
|
||||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
|
||||||
CLOCK_SOURCE_MUST_VERIFY,
|
CLOCK_SOURCE_MUST_VERIFY,
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
.archdata = { .vclock_mode = VCLOCK_TSC },
|
.archdata = { .vclock_mode = VCLOCK_TSC },
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void mark_tsc_unstable(char *reason)
|
void mark_tsc_unstable(char *reason)
|
||||||
|
@ -147,7 +147,6 @@ SECTIONS
|
|||||||
_edata = .;
|
_edata = .;
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
. = ALIGN(PAGE_SIZE);
|
||||||
__vvar_page = .;
|
__vvar_page = .;
|
||||||
@ -169,8 +168,6 @@ SECTIONS
|
|||||||
|
|
||||||
. = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
|
. = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
|
||||||
|
|
||||||
#endif /* CONFIG_X86_64 */
|
|
||||||
|
|
||||||
/* 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) {
|
||||||
|
@ -47,14 +47,12 @@
|
|||||||
#include <asm/segment.h>
|
#include <asm/segment.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/topology.h>
|
#include <asm/topology.h>
|
||||||
#include <asm/vgtod.h>
|
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "vsyscall_trace.h"
|
#include "vsyscall_trace.h"
|
||||||
|
|
||||||
DEFINE_VVAR(int, vgetcpu_mode);
|
DEFINE_VVAR(int, vgetcpu_mode);
|
||||||
DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
|
|
||||||
|
|
||||||
static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
|
static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
|
||||||
|
|
||||||
@ -77,48 +75,6 @@ static int __init vsyscall_setup(char *str)
|
|||||||
}
|
}
|
||||||
early_param("vsyscall", vsyscall_setup);
|
early_param("vsyscall", vsyscall_setup);
|
||||||
|
|
||||||
void update_vsyscall_tz(void)
|
|
||||||
{
|
|
||||||
vsyscall_gtod_data.sys_tz = sys_tz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_vsyscall(struct timekeeper *tk)
|
|
||||||
{
|
|
||||||
struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
|
|
||||||
|
|
||||||
write_seqcount_begin(&vdata->seq);
|
|
||||||
|
|
||||||
/* copy vsyscall data */
|
|
||||||
vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
|
|
||||||
vdata->clock.cycle_last = tk->clock->cycle_last;
|
|
||||||
vdata->clock.mask = tk->clock->mask;
|
|
||||||
vdata->clock.mult = tk->mult;
|
|
||||||
vdata->clock.shift = tk->shift;
|
|
||||||
|
|
||||||
vdata->wall_time_sec = tk->xtime_sec;
|
|
||||||
vdata->wall_time_snsec = tk->xtime_nsec;
|
|
||||||
|
|
||||||
vdata->monotonic_time_sec = tk->xtime_sec
|
|
||||||
+ tk->wall_to_monotonic.tv_sec;
|
|
||||||
vdata->monotonic_time_snsec = tk->xtime_nsec
|
|
||||||
+ (tk->wall_to_monotonic.tv_nsec
|
|
||||||
<< tk->shift);
|
|
||||||
while (vdata->monotonic_time_snsec >=
|
|
||||||
(((u64)NSEC_PER_SEC) << tk->shift)) {
|
|
||||||
vdata->monotonic_time_snsec -=
|
|
||||||
((u64)NSEC_PER_SEC) << tk->shift;
|
|
||||||
vdata->monotonic_time_sec++;
|
|
||||||
}
|
|
||||||
|
|
||||||
vdata->wall_time_coarse.tv_sec = tk->xtime_sec;
|
|
||||||
vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
|
|
||||||
|
|
||||||
vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse,
|
|
||||||
tk->wall_to_monotonic);
|
|
||||||
|
|
||||||
write_seqcount_end(&vdata->seq);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
|
static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
|
||||||
const char *message)
|
const char *message)
|
||||||
{
|
{
|
||||||
@ -374,7 +330,6 @@ void __init map_vsyscall(void)
|
|||||||
{
|
{
|
||||||
extern char __vsyscall_page;
|
extern char __vsyscall_page;
|
||||||
unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
|
unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
|
||||||
extern char __vvar_page;
|
|
||||||
unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
|
unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
|
||||||
|
|
||||||
__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall,
|
__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall,
|
||||||
|
59
arch/x86/kernel/vsyscall_gtod.c
Normal file
59
arch/x86/kernel/vsyscall_gtod.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
|
||||||
|
* Copyright 2003 Andi Kleen, SuSE Labs.
|
||||||
|
*
|
||||||
|
* Modified for x86 32 bit architecture by
|
||||||
|
* Stefani Seibold <stefani@seibold.net>
|
||||||
|
*
|
||||||
|
* Thanks to hpa@transmeta.com for some useful hint.
|
||||||
|
* Special thanks to Ingo Molnar for his early experience with
|
||||||
|
* a different vsyscall implementation for Linux/IA32 and for the name.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/timekeeper_internal.h>
|
||||||
|
#include <asm/vgtod.h>
|
||||||
|
|
||||||
|
DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
|
||||||
|
|
||||||
|
void update_vsyscall_tz(void)
|
||||||
|
{
|
||||||
|
vsyscall_gtod_data.sys_tz = sys_tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_vsyscall(struct timekeeper *tk)
|
||||||
|
{
|
||||||
|
struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
|
||||||
|
|
||||||
|
write_seqcount_begin(&vdata->seq);
|
||||||
|
|
||||||
|
/* copy vsyscall data */
|
||||||
|
vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
|
||||||
|
vdata->clock.cycle_last = tk->clock->cycle_last;
|
||||||
|
vdata->clock.mask = tk->clock->mask;
|
||||||
|
vdata->clock.mult = tk->mult;
|
||||||
|
vdata->clock.shift = tk->shift;
|
||||||
|
|
||||||
|
vdata->wall_time_sec = tk->xtime_sec;
|
||||||
|
vdata->wall_time_snsec = tk->xtime_nsec;
|
||||||
|
|
||||||
|
vdata->monotonic_time_sec = tk->xtime_sec
|
||||||
|
+ tk->wall_to_monotonic.tv_sec;
|
||||||
|
vdata->monotonic_time_snsec = tk->xtime_nsec
|
||||||
|
+ (tk->wall_to_monotonic.tv_nsec
|
||||||
|
<< tk->shift);
|
||||||
|
while (vdata->monotonic_time_snsec >=
|
||||||
|
(((u64)NSEC_PER_SEC) << tk->shift)) {
|
||||||
|
vdata->monotonic_time_snsec -=
|
||||||
|
((u64)NSEC_PER_SEC) << tk->shift;
|
||||||
|
vdata->monotonic_time_sec++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdata->wall_time_coarse.tv_sec = tk->xtime_sec;
|
||||||
|
vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
|
||||||
|
|
||||||
|
vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse,
|
||||||
|
tk->wall_to_monotonic);
|
||||||
|
|
||||||
|
write_seqcount_end(&vdata->seq);
|
||||||
|
}
|
@ -69,8 +69,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
|
|||||||
"__per_cpu_load|"
|
"__per_cpu_load|"
|
||||||
"init_per_cpu__.*|"
|
"init_per_cpu__.*|"
|
||||||
"__end_rodata_hpage_align|"
|
"__end_rodata_hpage_align|"
|
||||||
"__vvar_page|"
|
|
||||||
#endif
|
#endif
|
||||||
|
"__vvar_page|"
|
||||||
"_end)$"
|
"_end)$"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user