Commit f40c3300 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by H. Peter Anvin
Browse files

x86, vdso: Move the vvar and hpet mappings next to the 64-bit vDSO



This makes the 64-bit and x32 vdsos use the same mechanism as the
32-bit vdso.  Most of the churn is deleting all the old fixmap code.
Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/8af87023f57f6bb96ec8d17fce3f88018195b49b.1399317206.git.luto@amacapital.net

Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 18d0a6fd
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/kmap_types.h> #include <asm/kmap_types.h>
#else #else
#include <asm/vsyscall.h> #include <uapi/asm/vsyscall.h>
#endif #endif
/* /*
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
extern unsigned long __FIXADDR_TOP; extern unsigned long __FIXADDR_TOP;
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
#else #else
#define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE) #define FIXADDR_TOP (round_up(VSYSCALL_ADDR + PAGE_SIZE, 1<<PMD_SHIFT) - \
PAGE_SIZE)
#endif #endif
...@@ -68,11 +69,7 @@ enum fixed_addresses { ...@@ -68,11 +69,7 @@ enum fixed_addresses {
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
FIX_HOLE, FIX_HOLE,
#else #else
VSYSCALL_LAST_PAGE, VSYSCALL_PAGE = (FIXADDR_TOP - VSYSCALL_ADDR) >> PAGE_SHIFT,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+ ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
VVAR_PAGE,
VSYSCALL_HPET,
#ifdef CONFIG_PARAVIRT_CLOCK #ifdef CONFIG_PARAVIRT_CLOCK
PVCLOCK_FIXMAP_BEGIN, PVCLOCK_FIXMAP_BEGIN,
PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1,
......
...@@ -29,31 +29,13 @@ ...@@ -29,31 +29,13 @@
#else #else
#ifdef BUILD_VDSO32 extern char __vvar_page;
#define DECLARE_VVAR(offset, type, name) \ #define DECLARE_VVAR(offset, type, name) \
extern type vvar_ ## name __attribute__((visibility("hidden"))); extern type vvar_ ## name __attribute__((visibility("hidden")));
#define VVAR(name) (vvar_ ## name) #define VVAR(name) (vvar_ ## name)
#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));
#define VVAR(name) (*vvaraddr_ ## name)
#endif
#define DEFINE_VVAR(type, name) \ #define DEFINE_VVAR(type, name) \
type name \ type name \
__attribute__((section(".vvar_" #name), aligned(16))) __visible __attribute__((section(".vvar_" #name), aligned(16))) __visible
......
...@@ -7,11 +7,6 @@ enum vsyscall_num { ...@@ -7,11 +7,6 @@ enum vsyscall_num {
__NR_vgetcpu, __NR_vgetcpu,
}; };
#define VSYSCALL_START (-10UL << 20) #define VSYSCALL_ADDR (-10UL << 20)
#define VSYSCALL_SIZE 1024
#define VSYSCALL_END (-2UL << 20)
#define VSYSCALL_MAPPED_PAGES 1
#define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
#endif /* _UAPI_ASM_X86_VSYSCALL_H */ #endif /* _UAPI_ASM_X86_VSYSCALL_H */
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/vsyscall.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -74,9 +74,6 @@ static inline void hpet_writel(unsigned int d, unsigned int a) ...@@ -74,9 +74,6 @@ static inline void hpet_writel(unsigned int d, unsigned int a)
static inline void hpet_set_mapping(void) static inline void hpet_set_mapping(void)
{ {
hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); 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) static inline void hpet_clear_mapping(void)
......
...@@ -91,7 +91,7 @@ static int addr_to_vsyscall_nr(unsigned long addr) ...@@ -91,7 +91,7 @@ static int addr_to_vsyscall_nr(unsigned long addr)
{ {
int nr; int nr;
if ((addr & ~0xC00UL) != VSYSCALL_START) if ((addr & ~0xC00UL) != VSYSCALL_ADDR)
return -EINVAL; return -EINVAL;
nr = (addr & 0xC00UL) >> 10; nr = (addr & 0xC00UL) >> 10;
...@@ -330,24 +330,17 @@ void __init map_vsyscall(void) ...@@ -330,24 +330,17 @@ 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);
unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, __set_fixmap(VSYSCALL_PAGE, physaddr_vsyscall,
vsyscall_mode == NATIVE vsyscall_mode == NATIVE
? PAGE_KERNEL_VSYSCALL ? PAGE_KERNEL_VSYSCALL
: PAGE_KERNEL_VVAR); : PAGE_KERNEL_VVAR);
BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) != BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) !=
(unsigned long)VSYSCALL_START); (unsigned long)VSYSCALL_ADDR);
__set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) !=
(unsigned long)VVAR_ADDRESS);
} }
static int __init vsyscall_init(void) static int __init vsyscall_init(void)
{ {
BUG_ON(VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE));
cpu_notifier_register_begin(); cpu_notifier_register_begin();
on_each_cpu(cpu_vsyscall_init, NULL, 1); on_each_cpu(cpu_vsyscall_init, NULL, 1);
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
#include <asm/traps.h> /* dotraplinkage, ... */ #include <asm/traps.h> /* dotraplinkage, ... */
#include <asm/pgalloc.h> /* pgd_*(), ... */ #include <asm/pgalloc.h> /* pgd_*(), ... */
#include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */
#include <asm/fixmap.h> /* VSYSCALL_START */ #include <asm/fixmap.h> /* VSYSCALL_ADDR */
#include <asm/vsyscall.h> /* emulate_vsyscall */
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <asm/trace/exceptions.h> #include <asm/trace/exceptions.h>
...@@ -771,7 +772,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, ...@@ -771,7 +772,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
* emulation. * emulation.
*/ */
if (unlikely((error_code & PF_INSTR) && if (unlikely((error_code & PF_INSTR) &&
((address & ~0xfff) == VSYSCALL_START))) { ((address & ~0xfff) == VSYSCALL_ADDR))) {
if (emulate_vsyscall(regs, address)) if (emulate_vsyscall(regs, address))
return; return;
} }
......
...@@ -1055,8 +1055,8 @@ void __init mem_init(void) ...@@ -1055,8 +1055,8 @@ void __init mem_init(void)
after_bootmem = 1; after_bootmem = 1;
/* Register memory areas for /proc/kcore */ /* Register memory areas for /proc/kcore */
kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, kclist_add(&kcore_vsyscall, (void *)VSYSCALL_ADDR,
VSYSCALL_END - VSYSCALL_START, KCORE_OTHER); PAGE_SIZE, KCORE_OTHER);
mem_init_print_info(NULL); mem_init_print_info(NULL);
} }
...@@ -1186,8 +1186,8 @@ int kern_addr_valid(unsigned long addr) ...@@ -1186,8 +1186,8 @@ int kern_addr_valid(unsigned long addr)
* not need special handling anymore: * not need special handling anymore:
*/ */
static struct vm_area_struct gate_vma = { static struct vm_area_struct gate_vma = {
.vm_start = VSYSCALL_START, .vm_start = VSYSCALL_ADDR,
.vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE), .vm_end = VSYSCALL_ADDR + PAGE_SIZE,
.vm_page_prot = PAGE_READONLY_EXEC, .vm_page_prot = PAGE_READONLY_EXEC,
.vm_flags = VM_READ | VM_EXEC .vm_flags = VM_READ | VM_EXEC
}; };
...@@ -1218,7 +1218,7 @@ int in_gate_area(struct mm_struct *mm, unsigned long addr) ...@@ -1218,7 +1218,7 @@ int in_gate_area(struct mm_struct *mm, unsigned long addr)
*/ */
int in_gate_area_no_mm(unsigned long addr) int in_gate_area_no_mm(unsigned long addr)
{ {
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); return (addr & PAGE_MASK) == VSYSCALL_ADDR;
} }
const char *arch_vma_name(struct vm_area_struct *vma) const char *arch_vma_name(struct vm_area_struct *vma)
......
...@@ -30,9 +30,12 @@ extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); ...@@ -30,9 +30,12 @@ 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 #ifdef CONFIG_HPET_TIMER
static inline u32 read_hpet_counter(const volatile void *addr) extern u8 hpet_page
__attribute__((visibility("hidden")));
static notrace cycle_t vread_hpet(void)
{ {
return *(const volatile u32 *) (addr + HPET_COUNTER); return *(const volatile u32 *)(&hpet_page + HPET_COUNTER);
} }
#endif #endif
...@@ -43,11 +46,6 @@ static inline u32 read_hpet_counter(const volatile void *addr) ...@@ -43,11 +46,6 @@ static inline u32 read_hpet_counter(const volatile void *addr)
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <asm/pvclock.h> #include <asm/pvclock.h>
static notrace cycle_t vread_hpet(void)
{
return read_hpet_counter((const void *)fix_to_virt(VSYSCALL_HPET));
}
notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
{ {
long ret; long ret;
...@@ -137,16 +135,6 @@ static notrace cycle_t vread_pvclock(int *mode) ...@@ -137,16 +135,6 @@ static notrace cycle_t vread_pvclock(int *mode)
#else #else
extern u8 hpet_page
__attribute__((visibility("hidden")));
#ifdef CONFIG_HPET_TIMER
static notrace cycle_t vread_hpet(void)
{
return read_hpet_counter((const void *)(&hpet_page));
}
#endif
notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
{ {
long ret; long ret;
......
...@@ -47,7 +47,6 @@ SECTIONS ...@@ -47,7 +47,6 @@ SECTIONS
.text : { *(.text*) } :text =0x90909090, .text : { *(.text*) } :text =0x90909090,
#ifdef BUILD_VDSO32
/* /*
* The remainder of the vDSO consists of special pages that are * The remainder of the vDSO consists of special pages that are
* shared between the kernel and userspace. It needs to be at the * shared between the kernel and userspace. It needs to be at the
...@@ -69,7 +68,6 @@ SECTIONS ...@@ -69,7 +68,6 @@ SECTIONS
hpet_page = .; hpet_page = .;
. = . + PAGE_SIZE; . = . + PAGE_SIZE;
#endif
. = ALIGN(PAGE_SIZE); . = ALIGN(PAGE_SIZE);
end_mapping = .; end_mapping = .;
......
...@@ -1494,7 +1494,7 @@ static int xen_pgd_alloc(struct mm_struct *mm) ...@@ -1494,7 +1494,7 @@ static int xen_pgd_alloc(struct mm_struct *mm)
page->private = (unsigned long)user_pgd; page->private = (unsigned long)user_pgd;
if (user_pgd != NULL) { if (user_pgd != NULL) {
user_pgd[pgd_index(VSYSCALL_START)] = user_pgd[pgd_index(VSYSCALL_ADDR)] =
__pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE);
ret = 0; ret = 0;
} }
...@@ -2062,8 +2062,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) ...@@ -2062,8 +2062,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
case FIX_KMAP_BEGIN ... FIX_KMAP_END: case FIX_KMAP_BEGIN ... FIX_KMAP_END:
# endif # endif
#else #else
case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: case VSYSCALL_PAGE:
case VVAR_PAGE:
#endif #endif
case FIX_TEXT_POKE0: case FIX_TEXT_POKE0:
case FIX_TEXT_POKE1: case FIX_TEXT_POKE1:
...@@ -2104,8 +2103,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) ...@@ -2104,8 +2103,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/* Replicate changes to map the vsyscall page into the user /* Replicate changes to map the vsyscall page into the user
pagetable vsyscall mapping. */ pagetable vsyscall mapping. */
if ((idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) || if (idx == VSYSCALL_PAGE) {
idx == VVAR_PAGE) {
unsigned long vaddr = __fix_to_virt(idx); unsigned long vaddr = __fix_to_virt(idx);
set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte);
} }
......
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