mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
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 CLOCKSOURCE_WATCHDOG
|
||||
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_TIME_VSYSCALL if X86_64
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select KTIME_SCALAR if X86_32
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
|
@ -3,8 +3,6 @@
|
||||
#ifndef _ASM_X86_CLOCKSOURCE_H
|
||||
#define _ASM_X86_CLOCKSOURCE_H
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
#define VCLOCK_NONE 0 /* No vDSO clock available. */
|
||||
#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */
|
||||
#define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */
|
||||
@ -14,6 +12,4 @@ struct arch_clocksource_data {
|
||||
int vclock_mode;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
#endif /* _ASM_X86_CLOCKSOURCE_H */
|
||||
|
@ -16,9 +16,6 @@
|
||||
* 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)
|
||||
|
||||
/* The kernel linker script defines its own magic to put vvars in the
|
||||
@ -29,6 +26,15 @@
|
||||
|
||||
#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) \
|
||||
static type const * const vvaraddr_ ## name = \
|
||||
(void *)(VVAR_ADDRESS + (offset));
|
||||
|
@ -26,7 +26,7 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o
|
||||
obj-y += probe_roms.o
|
||||
obj-$(CONFIG_X86_32) += i386_ksyms_32.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_emu_64.o
|
||||
obj-$(CONFIG_SYSFS) += ksysfs.o
|
||||
|
@ -752,9 +752,7 @@ static struct clocksource clocksource_hpet = {
|
||||
.mask = HPET_MASK,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.resume = hpet_resume_counter,
|
||||
#ifdef CONFIG_X86_64
|
||||
.archdata = { .vclock_mode = VCLOCK_HPET },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int hpet_clocksource_register(void)
|
||||
|
@ -985,9 +985,7 @@ static struct clocksource clocksource_tsc = {
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
|
||||
CLOCK_SOURCE_MUST_VERIFY,
|
||||
#ifdef CONFIG_X86_64
|
||||
.archdata = { .vclock_mode = VCLOCK_TSC },
|
||||
#endif
|
||||
};
|
||||
|
||||
void mark_tsc_unstable(char *reason)
|
||||
|
@ -147,7 +147,6 @@ SECTIONS
|
||||
_edata = .;
|
||||
} :data
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__vvar_page = .;
|
||||
@ -169,8 +168,6 @@ SECTIONS
|
||||
|
||||
. = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
/* Init code and data - will be freed after init */
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
|
||||
|
@ -47,14 +47,12 @@
|
||||
#include <asm/segment.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/topology.h>
|
||||
#include <asm/vgtod.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "vsyscall_trace.h"
|
||||
|
||||
DEFINE_VVAR(int, vgetcpu_mode);
|
||||
DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
|
||||
|
||||
static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
|
||||
|
||||
@ -77,48 +75,6 @@ static int __init vsyscall_setup(char *str)
|
||||
}
|
||||
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,
|
||||
const char *message)
|
||||
{
|
||||
@ -374,7 +330,6 @@ void __init map_vsyscall(void)
|
||||
{
|
||||
extern char __vsyscall_page;
|
||||
unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
|
||||
extern char __vvar_page;
|
||||
unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
|
||||
|
||||
__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|"
|
||||
"init_per_cpu__.*|"
|
||||
"__end_rodata_hpage_align|"
|
||||
"__vvar_page|"
|
||||
#endif
|
||||
"__vvar_page|"
|
||||
"_end)$"
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user