Commit 1ed95e52 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar

x86/vdso: Remove direct HPET access through the vDSO

Allowing user code to map the HPET is problematic.  HPET
implementations are notoriously buggy, and there are probably many
machines on which even MMIO reads from bogus HPET addresses are
problematic.

We have a report that the Dell Precision M2800 with:

  ACPI: HPET 0x00000000C8FE6238 000038 (v01 DELL   CBX3  01072009 AMI. 00000005)

is either so slow when accessing the HPET or actually hangs in some
regard, causing soft lockups to be reported if users do unexpected
things to the HPET.

The vclock HPET code has also always been a questionable speedup.
Accessing an HPET is exceedingly slow (on the order of several
microseconds), so the added overhead in requiring a syscall to read
the HPET is a small fraction of the total code of accessing it.

To avoid future problems, let's just delete the code entirely.

In the long run, this could actually be a speedup.  Waiman Long as a
patch to optimize the case where multiple CPUs contend for the HPET,
but that won't help unless all the accesses are mediated by the
kernel.
Reported-by: default avatarRasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarBorislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Waiman Long <Waiman.Long@hpe.com>
Cc: Waiman Long <waiman.long@hpe.com>
Link: http://lkml.kernel.org/r/d2f90bba98db9905041cff294646d290d378f67a.1460074438.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 42c748bb
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <uapi/linux/time.h> #include <uapi/linux/time.h>
#include <asm/vgtod.h> #include <asm/vgtod.h>
#include <asm/hpet.h>
#include <asm/vvar.h> #include <asm/vvar.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/msr.h> #include <asm/msr.h>
...@@ -28,16 +27,6 @@ extern int __vdso_clock_gettime(clockid_t clock, struct timespec *ts); ...@@ -28,16 +27,6 @@ extern int __vdso_clock_gettime(clockid_t clock, struct timespec *ts);
extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz);
extern time_t __vdso_time(time_t *t); extern time_t __vdso_time(time_t *t);
#ifdef CONFIG_HPET_TIMER
extern u8 hpet_page
__attribute__((visibility("hidden")));
static notrace cycle_t vread_hpet(void)
{
return *(const volatile u32 *)(&hpet_page + HPET_COUNTER);
}
#endif
#ifdef CONFIG_PARAVIRT_CLOCK #ifdef CONFIG_PARAVIRT_CLOCK
extern u8 pvclock_page extern u8 pvclock_page
__attribute__((visibility("hidden"))); __attribute__((visibility("hidden")));
...@@ -195,10 +184,6 @@ notrace static inline u64 vgetsns(int *mode) ...@@ -195,10 +184,6 @@ notrace static inline u64 vgetsns(int *mode)
if (gtod->vclock_mode == VCLOCK_TSC) if (gtod->vclock_mode == VCLOCK_TSC)
cycles = vread_tsc(); cycles = vread_tsc();
#ifdef CONFIG_HPET_TIMER
else if (gtod->vclock_mode == VCLOCK_HPET)
cycles = vread_hpet();
#endif
#ifdef CONFIG_PARAVIRT_CLOCK #ifdef CONFIG_PARAVIRT_CLOCK
else if (gtod->vclock_mode == VCLOCK_PVCLOCK) else if (gtod->vclock_mode == VCLOCK_PVCLOCK)
cycles = vread_pvclock(mode); cycles = vread_pvclock(mode);
......
...@@ -25,7 +25,7 @@ SECTIONS ...@@ -25,7 +25,7 @@ SECTIONS
* segment. * segment.
*/ */
vvar_start = . - 3 * PAGE_SIZE; vvar_start = . - 2 * PAGE_SIZE;
vvar_page = vvar_start; vvar_page = vvar_start;
/* Place all vvars at the offsets in asm/vvar.h. */ /* Place all vvars at the offsets in asm/vvar.h. */
...@@ -35,8 +35,7 @@ SECTIONS ...@@ -35,8 +35,7 @@ SECTIONS
#undef __VVAR_KERNEL_LDS #undef __VVAR_KERNEL_LDS
#undef EMIT_VVAR #undef EMIT_VVAR
hpet_page = vvar_start + PAGE_SIZE; pvclock_page = vvar_start + PAGE_SIZE;
pvclock_page = vvar_start + 2 * PAGE_SIZE;
. = SIZEOF_HEADERS; . = SIZEOF_HEADERS;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/vvar.h> #include <asm/vvar.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/hpet.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
...@@ -129,16 +128,6 @@ static int vvar_fault(const struct vm_special_mapping *sm, ...@@ -129,16 +128,6 @@ static int vvar_fault(const struct vm_special_mapping *sm,
if (sym_offset == image->sym_vvar_page) { if (sym_offset == image->sym_vvar_page) {
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
__pa_symbol(&__vvar_page) >> PAGE_SHIFT); __pa_symbol(&__vvar_page) >> PAGE_SHIFT);
} else if (sym_offset == image->sym_hpet_page) {
#ifdef CONFIG_HPET_TIMER
if (hpet_address && vclock_was_used(VCLOCK_HPET)) {
ret = vm_insert_pfn_prot(
vma,
(unsigned long)vmf->virtual_address,
hpet_address >> PAGE_SHIFT,
pgprot_noncached(PAGE_READONLY));
}
#endif
} else if (sym_offset == image->sym_pvclock_page) { } else if (sym_offset == image->sym_pvclock_page) {
struct pvclock_vsyscall_time_info *pvti = struct pvclock_vsyscall_time_info *pvti =
pvclock_pvti_cpu0_va(); pvclock_pvti_cpu0_va();
......
...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
#ifndef _ASM_X86_CLOCKSOURCE_H #ifndef _ASM_X86_CLOCKSOURCE_H
#define _ASM_X86_CLOCKSOURCE_H #define _ASM_X86_CLOCKSOURCE_H
#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_PVCLOCK 2 /* vDSO should use vread_pvclock. */
#define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */ #define VCLOCK_MAX 2
#define VCLOCK_MAX 3
struct arch_clocksource_data { struct arch_clocksource_data {
int vclock_mode; int vclock_mode;
......
...@@ -773,7 +773,6 @@ static struct clocksource clocksource_hpet = { ...@@ -773,7 +773,6 @@ 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,
.archdata = { .vclock_mode = VCLOCK_HPET },
}; };
static int hpet_clocksource_register(void) static int hpet_clocksource_register(void)
......
...@@ -809,8 +809,7 @@ TRACE_EVENT(kvm_write_tsc_offset, ...@@ -809,8 +809,7 @@ TRACE_EVENT(kvm_write_tsc_offset,
#define host_clocks \ #define host_clocks \
{VCLOCK_NONE, "none"}, \ {VCLOCK_NONE, "none"}, \
{VCLOCK_TSC, "tsc"}, \ {VCLOCK_TSC, "tsc"} \
{VCLOCK_HPET, "hpet"} \
TRACE_EVENT(kvm_update_master_clock, TRACE_EVENT(kvm_update_master_clock,
TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched), TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment