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: Andy Lutomirski <luto@amacapital.net> Link: http://lkml.kernel.org/r/8af87023f57f6bb96ec8d17fce3f88018195b49b.1399317206.git.luto@amacapital.net Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
18d0a6fd22
commit
f40c330091
11 changed files with 27 additions and 77 deletions
|
@ -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 @@
|
||||||
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 {
|
||||||
#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 @@
|
||||||
|
|
||||||
#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 {
|
||||||
__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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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 @@
|
||||||
#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,
|
||||||
* 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)
|
||||||
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)
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
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)
|
||||||
#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)
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
.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
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
#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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue