Re: [PATCH 1/4] Make vsyscall_gtod_data handling x86 generic

Andy Lutomirski
2014-02-01T23:40:23Z

On Sat, Feb 1, 2014 at 7:32 AM, <stefani@seibold.net> wrote:
> From: Stefani Seibold <stefani@seibold.net>
>
> 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.
>
> Signed-off-by: Stefani Seibold <stefani@seibold.net>

Acked-by: Andy Lutomirski <luto@amacapital.net>

...with the caveat that it would be even better if you moved vgetcpu
over and called this thing vvar.c instead of vsyscall_gtod.c.

> ---
> arch/x86/Kconfig | 4 +--
> arch/x86/include/asm/clocksource.h | 4 ---
> arch/x86/include/asm/fixmap.h | 2 ++
> arch/x86/include/asm/vvar.h | 4 +++
> arch/x86/kernel/Makefile | 3 +-
> arch/x86/kernel/hpet.c | 4 ---
> arch/x86/kernel/setup.c | 2 --
> arch/x86/kernel/tsc.c | 2 --
> arch/x86/kernel/vmlinux.lds.S | 3 --
> arch/x86/kernel/vsyscall_32.c | 24 +++++++++++++++
> arch/x86/kernel/vsyscall_64.c | 44 ----------------------------
> arch/x86/kernel/vsyscall_gtod.c | 60 ++++++++++++++++++++++++++++++++++++++
> 12 files changed, 94 insertions(+), 62 deletions(-)
> create mode 100644 arch/x86/kernel/vsyscall_32.c
> create mode 100644 arch/x86/kernel/vsyscall_gtod.c
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 940e50e..b556f00 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -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
> diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h
> index 16a57f4..eda81dc 100644
> --- a/arch/x86/include/asm/clocksource.h
> +++ b/arch/x86/include/asm/clocksource.h
> @@ -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 */
> diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
> index 7252cd3..504c04a 100644
> --- a/arch/x86/include/asm/fixmap.h
> +++ b/arch/x86/include/asm/fixmap.h
> @@ -74,6 +74,8 @@ extern unsigned long __FIXADDR_TOP;
> enum fixed_addresses {
> #ifdef CONFIG_X86_32
> FIX_HOLE,
> + VSYSCALL_HPET,
> + VVAR_PAGE,
> FIX_VDSO,
> #else
> VSYSCALL_LAST_PAGE,
> diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h
> index d76ac40..c442782 100644
> --- a/arch/x86/include/asm/vvar.h
> +++ b/arch/x86/include/asm/vvar.h
> @@ -17,7 +17,11 @@
> */
>
> /* Base address of vvars. This is not ABI. */
> +#ifdef CONFIG_X86_64
> #define VVAR_ADDRESS (-10*1024*1024 - 4096)
> +#else
> +#define VVAR_ADDRESS 0xffffd000
> +#endif
>
> #if defined(__VVAR_KERNEL_LDS)
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index cb648c8..3282eda 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -26,7 +26,8 @@ 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_32) += vsyscall_32.o
> obj-$(CONFIG_X86_64) += vsyscall_64.o
> obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
> obj-$(CONFIG_SYSFS) += ksysfs.o
> diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
> index da85a8e..54263f0 100644
> --- a/arch/x86/kernel/hpet.c
> +++ b/arch/x86/kernel/hpet.c
> @@ -74,9 +74,7 @@ static inline void hpet_writel(unsigned int d, unsigned int a)
> static inline void hpet_set_mapping(void)
> {
> hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
> -#ifdef CONFIG_X86_64
> __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VVAR_NOCACHE);
> -#endif
> }
>
> static inline void hpet_clear_mapping(void)
> @@ -752,9 +750,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)
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 06853e6..56ff330 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -1182,9 +1182,7 @@ void __init setup_arch(char **cmdline_p)
>
> tboot_probe();
>
> -#ifdef CONFIG_X86_64
> map_vsyscall();
> -#endif
>
> generic_apic_probe();
>
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 19e5adb..f49d1a2 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -988,9 +988,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)
> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> index da6b35a..1d4897b 100644
> --- a/arch/x86/kernel/vmlinux.lds.S
> +++ b/arch/x86/kernel/vmlinux.lds.S
> @@ -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) {
> diff --git a/arch/x86/kernel/vsyscall_32.c b/arch/x86/kernel/vsyscall_32.c
> new file mode 100644
> index 0000000..f541dfa
> --- /dev/null
> +++ b/arch/x86/kernel/vsyscall_32.c
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
> + * Copyright 2003 Andi Kleen, SuSE Labs.
> + *
> + * Modified for x86 32 bit arch 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 <asm/vsyscall.h>
> +#include <asm/pgtable.h>
> +#include <asm/fixmap.h>
> +
> +void __init map_vsyscall(void)
> +{
> + extern char __vvar_page;
> + unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
> +
> + __set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
> +}
> +
> diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
> index 1f96f93..50622ed 100644
> --- a/arch/x86/kernel/vsyscall_64.c
> +++ b/arch/x86/kernel/vsyscall_64.c
> @@ -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)
> {
> diff --git a/arch/x86/kernel/vsyscall_gtod.c b/arch/x86/kernel/vsyscall_gtod.c
> new file mode 100644
> index 0000000..91862a4
> --- /dev/null
> +++ b/arch/x86/kernel/vsyscall_gtod.c
> @@ -0,0 +1,60 @@
> +/*
> + * 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);
> +}
> +
> --
> 1.8.5.3
>

--
Andy Lutomirski
AMA Capital Management, LLC