diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-05-05 15:19:36 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-05-05 16:19:01 -0400 |
commit | f40c330091c7aa9956ab66f97a3abc8a68b67240 (patch) | |
tree | b0c03dce9bf67eb15c98980a7323ca35122d10df | |
parent | 18d0a6fd227177fd243993179c90e454d0638b06 (diff) |
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>
-rw-r--r-- | arch/x86/include/asm/fixmap.h | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/vvar.h | 20 | ||||
-rw-r--r-- | arch/x86/include/uapi/asm/vsyscall.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/hpet.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/vsyscall_64.c | 15 | ||||
-rw-r--r-- | arch/x86/mm/fault.c | 5 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 10 | ||||
-rw-r--r-- | arch/x86/vdso/vclock_gettime.c | 22 | ||||
-rw-r--r-- | arch/x86/vdso/vdso-layout.lds.S | 2 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 8 |
11 files changed, 27 insertions, 77 deletions
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 43f482a0db37..b0910f97a3ea 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/threads.h> | 24 | #include <linux/threads.h> |
25 | #include <asm/kmap_types.h> | 25 | #include <asm/kmap_types.h> |
26 | #else | 26 | #else |
27 | #include <asm/vsyscall.h> | 27 | #include <uapi/asm/vsyscall.h> |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | /* | 30 | /* |
@@ -41,7 +41,8 @@ | |||
41 | extern unsigned long __FIXADDR_TOP; | 41 | extern unsigned long __FIXADDR_TOP; |
42 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) | 42 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) |
43 | #else | 43 | #else |
44 | #define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE) | 44 | #define FIXADDR_TOP (round_up(VSYSCALL_ADDR + PAGE_SIZE, 1<<PMD_SHIFT) - \ |
45 | PAGE_SIZE) | ||
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | 48 | ||
@@ -68,11 +69,7 @@ enum fixed_addresses { | |||
68 | #ifdef CONFIG_X86_32 | 69 | #ifdef CONFIG_X86_32 |
69 | FIX_HOLE, | 70 | FIX_HOLE, |
70 | #else | 71 | #else |
71 | VSYSCALL_LAST_PAGE, | 72 | VSYSCALL_PAGE = (FIXADDR_TOP - VSYSCALL_ADDR) >> PAGE_SHIFT, |
72 | VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE | ||
73 | + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, | ||
74 | VVAR_PAGE, | ||
75 | VSYSCALL_HPET, | ||
76 | #ifdef CONFIG_PARAVIRT_CLOCK | 73 | #ifdef CONFIG_PARAVIRT_CLOCK |
77 | PVCLOCK_FIXMAP_BEGIN, | 74 | PVCLOCK_FIXMAP_BEGIN, |
78 | PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, | 75 | PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, |
diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h index 081d909bc495..5d2b9ad2c6d2 100644 --- a/arch/x86/include/asm/vvar.h +++ b/arch/x86/include/asm/vvar.h | |||
@@ -29,31 +29,13 @@ | |||
29 | 29 | ||
30 | #else | 30 | #else |
31 | 31 | ||
32 | #ifdef BUILD_VDSO32 | 32 | extern char __vvar_page; |
33 | 33 | ||
34 | #define DECLARE_VVAR(offset, type, name) \ | 34 | #define DECLARE_VVAR(offset, type, name) \ |
35 | extern type vvar_ ## name __attribute__((visibility("hidden"))); | 35 | extern type vvar_ ## name __attribute__((visibility("hidden"))); |
36 | 36 | ||
37 | #define VVAR(name) (vvar_ ## name) | 37 | #define VVAR(name) (vvar_ ## name) |
38 | 38 | ||
39 | #else | ||
40 | |||
41 | extern char __vvar_page; | ||
42 | |||
43 | /* Base address of vvars. This is not ABI. */ | ||
44 | #ifdef CONFIG_X86_64 | ||
45 | #define VVAR_ADDRESS (-10*1024*1024 - 4096) | ||
46 | #else | ||
47 | #define VVAR_ADDRESS (&__vvar_page) | ||
48 | #endif | ||
49 | |||
50 | #define DECLARE_VVAR(offset, type, name) \ | ||
51 | static type const * const vvaraddr_ ## name = \ | ||
52 | (void *)(VVAR_ADDRESS + (offset)); | ||
53 | |||
54 | #define VVAR(name) (*vvaraddr_ ## name) | ||
55 | #endif | ||
56 | |||
57 | #define DEFINE_VVAR(type, name) \ | 39 | #define DEFINE_VVAR(type, name) \ |
58 | type name \ | 40 | type name \ |
59 | __attribute__((section(".vvar_" #name), aligned(16))) __visible | 41 | __attribute__((section(".vvar_" #name), aligned(16))) __visible |
diff --git a/arch/x86/include/uapi/asm/vsyscall.h b/arch/x86/include/uapi/asm/vsyscall.h index 85dc1b3825ab..b97dd6e263d2 100644 --- a/arch/x86/include/uapi/asm/vsyscall.h +++ b/arch/x86/include/uapi/asm/vsyscall.h | |||
@@ -7,11 +7,6 @@ enum vsyscall_num { | |||
7 | __NR_vgetcpu, | 7 | __NR_vgetcpu, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | #define VSYSCALL_START (-10UL << 20) | 10 | #define VSYSCALL_ADDR (-10UL << 20) |
11 | #define VSYSCALL_SIZE 1024 | ||
12 | #define VSYSCALL_END (-2UL << 20) | ||
13 | #define VSYSCALL_MAPPED_PAGES 1 | ||
14 | #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr)) | ||
15 | |||
16 | 11 | ||
17 | #endif /* _UAPI_ASM_X86_VSYSCALL_H */ | 12 | #endif /* _UAPI_ASM_X86_VSYSCALL_H */ |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7c65b4666c24..2cbbf88d8f2c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
21 | #include <asm/debugreg.h> | 21 | #include <asm/debugreg.h> |
22 | #include <asm/sections.h> | 22 | #include <asm/sections.h> |
23 | #include <asm/vsyscall.h> | ||
23 | #include <linux/topology.h> | 24 | #include <linux/topology.h> |
24 | #include <linux/cpumask.h> | 25 | #include <linux/cpumask.h> |
25 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 8d80ae011603..bbc15a0362d2 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -74,9 +74,6 @@ static inline void hpet_writel(unsigned int d, unsigned int a) | |||
74 | static inline void hpet_set_mapping(void) | 74 | static inline void hpet_set_mapping(void) |
75 | { | 75 | { |
76 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | 76 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); |
77 | #ifdef CONFIG_X86_64 | ||
78 | __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VVAR_NOCACHE); | ||
79 | #endif | ||
80 | } | 77 | } |
81 | 78 | ||
82 | static inline void hpet_clear_mapping(void) | 79 | static inline void hpet_clear_mapping(void) |
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 8b3b3eb3cead..ea5b5709aa76 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c | |||
@@ -91,7 +91,7 @@ static int addr_to_vsyscall_nr(unsigned long addr) | |||
91 | { | 91 | { |
92 | int nr; | 92 | int nr; |
93 | 93 | ||
94 | if ((addr & ~0xC00UL) != VSYSCALL_START) | 94 | if ((addr & ~0xC00UL) != VSYSCALL_ADDR) |
95 | return -EINVAL; | 95 | return -EINVAL; |
96 | 96 | ||
97 | nr = (addr & 0xC00UL) >> 10; | 97 | nr = (addr & 0xC00UL) >> 10; |
@@ -330,24 +330,17 @@ void __init map_vsyscall(void) | |||
330 | { | 330 | { |
331 | extern char __vsyscall_page; | 331 | extern char __vsyscall_page; |
332 | unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page); | 332 | unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page); |
333 | unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page); | ||
334 | 333 | ||
335 | __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, | 334 | __set_fixmap(VSYSCALL_PAGE, physaddr_vsyscall, |
336 | vsyscall_mode == NATIVE | 335 | vsyscall_mode == NATIVE |
337 | ? PAGE_KERNEL_VSYSCALL | 336 | ? PAGE_KERNEL_VSYSCALL |
338 | : PAGE_KERNEL_VVAR); | 337 | : PAGE_KERNEL_VVAR); |
339 | BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) != | 338 | BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) != |
340 | (unsigned long)VSYSCALL_START); | 339 | (unsigned long)VSYSCALL_ADDR); |
341 | |||
342 | __set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR); | ||
343 | BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != | ||
344 | (unsigned long)VVAR_ADDRESS); | ||
345 | } | 340 | } |
346 | 341 | ||
347 | static int __init vsyscall_init(void) | 342 | static int __init vsyscall_init(void) |
348 | { | 343 | { |
349 | BUG_ON(VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)); | ||
350 | |||
351 | cpu_notifier_register_begin(); | 344 | cpu_notifier_register_begin(); |
352 | 345 | ||
353 | on_each_cpu(cpu_vsyscall_init, NULL, 1); | 346 | on_each_cpu(cpu_vsyscall_init, NULL, 1); |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 8e5722992677..858b47b5221b 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -18,7 +18,8 @@ | |||
18 | #include <asm/traps.h> /* dotraplinkage, ... */ | 18 | #include <asm/traps.h> /* dotraplinkage, ... */ |
19 | #include <asm/pgalloc.h> /* pgd_*(), ... */ | 19 | #include <asm/pgalloc.h> /* pgd_*(), ... */ |
20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ | 20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ |
21 | #include <asm/fixmap.h> /* VSYSCALL_START */ | 21 | #include <asm/fixmap.h> /* VSYSCALL_ADDR */ |
22 | #include <asm/vsyscall.h> /* emulate_vsyscall */ | ||
22 | 23 | ||
23 | #define CREATE_TRACE_POINTS | 24 | #define CREATE_TRACE_POINTS |
24 | #include <asm/trace/exceptions.h> | 25 | #include <asm/trace/exceptions.h> |
@@ -771,7 +772,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | |||
771 | * emulation. | 772 | * emulation. |
772 | */ | 773 | */ |
773 | if (unlikely((error_code & PF_INSTR) && | 774 | if (unlikely((error_code & PF_INSTR) && |
774 | ((address & ~0xfff) == VSYSCALL_START))) { | 775 | ((address & ~0xfff) == VSYSCALL_ADDR))) { |
775 | if (emulate_vsyscall(regs, address)) | 776 | if (emulate_vsyscall(regs, address)) |
776 | return; | 777 | return; |
777 | } | 778 | } |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 563849600d3e..6f881842116c 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -1055,8 +1055,8 @@ void __init mem_init(void) | |||
1055 | after_bootmem = 1; | 1055 | after_bootmem = 1; |
1056 | 1056 | ||
1057 | /* Register memory areas for /proc/kcore */ | 1057 | /* Register memory areas for /proc/kcore */ |
1058 | kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, | 1058 | kclist_add(&kcore_vsyscall, (void *)VSYSCALL_ADDR, |
1059 | VSYSCALL_END - VSYSCALL_START, KCORE_OTHER); | 1059 | PAGE_SIZE, KCORE_OTHER); |
1060 | 1060 | ||
1061 | mem_init_print_info(NULL); | 1061 | mem_init_print_info(NULL); |
1062 | } | 1062 | } |
@@ -1186,8 +1186,8 @@ int kern_addr_valid(unsigned long addr) | |||
1186 | * not need special handling anymore: | 1186 | * not need special handling anymore: |
1187 | */ | 1187 | */ |
1188 | static struct vm_area_struct gate_vma = { | 1188 | static struct vm_area_struct gate_vma = { |
1189 | .vm_start = VSYSCALL_START, | 1189 | .vm_start = VSYSCALL_ADDR, |
1190 | .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE), | 1190 | .vm_end = VSYSCALL_ADDR + PAGE_SIZE, |
1191 | .vm_page_prot = PAGE_READONLY_EXEC, | 1191 | .vm_page_prot = PAGE_READONLY_EXEC, |
1192 | .vm_flags = VM_READ | VM_EXEC | 1192 | .vm_flags = VM_READ | VM_EXEC |
1193 | }; | 1193 | }; |
@@ -1218,7 +1218,7 @@ int in_gate_area(struct mm_struct *mm, unsigned long addr) | |||
1218 | */ | 1218 | */ |
1219 | int in_gate_area_no_mm(unsigned long addr) | 1219 | int in_gate_area_no_mm(unsigned long addr) |
1220 | { | 1220 | { |
1221 | return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); | 1221 | return (addr & PAGE_MASK) == VSYSCALL_ADDR; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | const char *arch_vma_name(struct vm_area_struct *vma) | 1224 | const char *arch_vma_name(struct vm_area_struct *vma) |
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 091554c20bc9..b2e4f493e5b0 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c | |||
@@ -30,9 +30,12 @@ extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); | |||
30 | extern time_t __vdso_time(time_t *t); | 30 | extern time_t __vdso_time(time_t *t); |
31 | 31 | ||
32 | #ifdef CONFIG_HPET_TIMER | 32 | #ifdef CONFIG_HPET_TIMER |
33 | static inline u32 read_hpet_counter(const volatile void *addr) | 33 | extern u8 hpet_page |
34 | __attribute__((visibility("hidden"))); | ||
35 | |||
36 | static notrace cycle_t vread_hpet(void) | ||
34 | { | 37 | { |
35 | return *(const volatile u32 *) (addr + HPET_COUNTER); | 38 | return *(const volatile u32 *)(&hpet_page + HPET_COUNTER); |
36 | } | 39 | } |
37 | #endif | 40 | #endif |
38 | 41 | ||
@@ -43,11 +46,6 @@ static inline u32 read_hpet_counter(const volatile void *addr) | |||
43 | #include <asm/fixmap.h> | 46 | #include <asm/fixmap.h> |
44 | #include <asm/pvclock.h> | 47 | #include <asm/pvclock.h> |
45 | 48 | ||
46 | static notrace cycle_t vread_hpet(void) | ||
47 | { | ||
48 | return read_hpet_counter((const void *)fix_to_virt(VSYSCALL_HPET)); | ||
49 | } | ||
50 | |||
51 | notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) | 49 | notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) |
52 | { | 50 | { |
53 | long ret; | 51 | long ret; |
@@ -137,16 +135,6 @@ static notrace cycle_t vread_pvclock(int *mode) | |||
137 | 135 | ||
138 | #else | 136 | #else |
139 | 137 | ||
140 | extern u8 hpet_page | ||
141 | __attribute__((visibility("hidden"))); | ||
142 | |||
143 | #ifdef CONFIG_HPET_TIMER | ||
144 | static notrace cycle_t vread_hpet(void) | ||
145 | { | ||
146 | return read_hpet_counter((const void *)(&hpet_page)); | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) | 138 | notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) |
151 | { | 139 | { |
152 | long ret; | 140 | long ret; |
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S index e177c08bb4bc..2ec72f651ebf 100644 --- a/arch/x86/vdso/vdso-layout.lds.S +++ b/arch/x86/vdso/vdso-layout.lds.S | |||
@@ -47,7 +47,6 @@ SECTIONS | |||
47 | 47 | ||
48 | .text : { *(.text*) } :text =0x90909090, | 48 | .text : { *(.text*) } :text =0x90909090, |
49 | 49 | ||
50 | #ifdef BUILD_VDSO32 | ||
51 | /* | 50 | /* |
52 | * The remainder of the vDSO consists of special pages that are | 51 | * The remainder of the vDSO consists of special pages that are |
53 | * shared between the kernel and userspace. It needs to be at the | 52 | * shared between the kernel and userspace. It needs to be at the |
@@ -69,7 +68,6 @@ SECTIONS | |||
69 | 68 | ||
70 | hpet_page = .; | 69 | hpet_page = .; |
71 | . = . + PAGE_SIZE; | 70 | . = . + PAGE_SIZE; |
72 | #endif | ||
73 | 71 | ||
74 | . = ALIGN(PAGE_SIZE); | 72 | . = ALIGN(PAGE_SIZE); |
75 | end_mapping = .; | 73 | end_mapping = .; |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 86e02eabb640..3060568248d3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -1494,7 +1494,7 @@ static int xen_pgd_alloc(struct mm_struct *mm) | |||
1494 | page->private = (unsigned long)user_pgd; | 1494 | page->private = (unsigned long)user_pgd; |
1495 | 1495 | ||
1496 | if (user_pgd != NULL) { | 1496 | if (user_pgd != NULL) { |
1497 | user_pgd[pgd_index(VSYSCALL_START)] = | 1497 | user_pgd[pgd_index(VSYSCALL_ADDR)] = |
1498 | __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); | 1498 | __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); |
1499 | ret = 0; | 1499 | ret = 0; |
1500 | } | 1500 | } |
@@ -2062,8 +2062,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) | |||
2062 | case FIX_KMAP_BEGIN ... FIX_KMAP_END: | 2062 | case FIX_KMAP_BEGIN ... FIX_KMAP_END: |
2063 | # endif | 2063 | # endif |
2064 | #else | 2064 | #else |
2065 | case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: | 2065 | case VSYSCALL_PAGE: |
2066 | case VVAR_PAGE: | ||
2067 | #endif | 2066 | #endif |
2068 | case FIX_TEXT_POKE0: | 2067 | case FIX_TEXT_POKE0: |
2069 | case FIX_TEXT_POKE1: | 2068 | case FIX_TEXT_POKE1: |
@@ -2104,8 +2103,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) | |||
2104 | #ifdef CONFIG_X86_64 | 2103 | #ifdef CONFIG_X86_64 |
2105 | /* Replicate changes to map the vsyscall page into the user | 2104 | /* Replicate changes to map the vsyscall page into the user |
2106 | pagetable vsyscall mapping. */ | 2105 | pagetable vsyscall mapping. */ |
2107 | if ((idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) || | 2106 | if (idx == VSYSCALL_PAGE) { |
2108 | idx == VVAR_PAGE) { | ||
2109 | unsigned long vaddr = __fix_to_virt(idx); | 2107 | unsigned long vaddr = __fix_to_virt(idx); |
2110 | set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); | 2108 | set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); |
2111 | } | 2109 | } |