Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andy Lutomirski and committed by
H. Peter Anvin
f40c3300 18d0a6fd

+27 -77
+4 -7
arch/x86/include/asm/fixmap.h
··· 24 24 #include <linux/threads.h> 25 25 #include <asm/kmap_types.h> 26 26 #else 27 - #include <asm/vsyscall.h> 27 + #include <uapi/asm/vsyscall.h> 28 28 #endif 29 29 30 30 /* ··· 41 41 extern unsigned long __FIXADDR_TOP; 42 42 #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) 43 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 46 #endif 46 47 47 48 ··· 69 68 #ifdef CONFIG_X86_32 70 69 FIX_HOLE, 71 70 #else 72 - VSYSCALL_LAST_PAGE, 73 - VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE 74 - + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, 75 - VVAR_PAGE, 76 - VSYSCALL_HPET, 71 + VSYSCALL_PAGE = (FIXADDR_TOP - VSYSCALL_ADDR) >> PAGE_SHIFT, 77 72 #ifdef CONFIG_PARAVIRT_CLOCK 78 73 PVCLOCK_FIXMAP_BEGIN, 79 74 PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1,
+1 -19
arch/x86/include/asm/vvar.h
··· 29 29 30 30 #else 31 31 32 - #ifdef BUILD_VDSO32 32 + extern char __vvar_page; 33 33 34 34 #define DECLARE_VVAR(offset, type, name) \ 35 35 extern type vvar_ ## name __attribute__((visibility("hidden"))); 36 36 37 37 #define VVAR(name) (vvar_ ## name) 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 38 57 39 #define DEFINE_VVAR(type, name) \ 58 40 type name \
+1 -6
arch/x86/include/uapi/asm/vsyscall.h
··· 7 7 __NR_vgetcpu, 8 8 }; 9 9 10 - #define VSYSCALL_START (-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 - 10 + #define VSYSCALL_ADDR (-10UL << 20) 16 11 17 12 #endif /* _UAPI_ASM_X86_VSYSCALL_H */
+1
arch/x86/kernel/cpu/common.c
··· 20 20 #include <asm/processor.h> 21 21 #include <asm/debugreg.h> 22 22 #include <asm/sections.h> 23 + #include <asm/vsyscall.h> 23 24 #include <linux/topology.h> 24 25 #include <linux/cpumask.h> 25 26 #include <asm/pgtable.h>
-3
arch/x86/kernel/hpet.c
··· 74 74 static inline void hpet_set_mapping(void) 75 75 { 76 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 79 static inline void hpet_clear_mapping(void)
+4 -11
arch/x86/kernel/vsyscall_64.c
··· 91 91 { 92 92 int nr; 93 93 94 - if ((addr & ~0xC00UL) != VSYSCALL_START) 94 + if ((addr & ~0xC00UL) != VSYSCALL_ADDR) 95 95 return -EINVAL; 96 96 97 97 nr = (addr & 0xC00UL) >> 10; ··· 330 330 { 331 331 extern char __vsyscall_page; 332 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 335 vsyscall_mode == NATIVE 337 336 ? PAGE_KERNEL_VSYSCALL 338 337 : PAGE_KERNEL_VVAR); 339 - BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) != 340 - (unsigned long)VSYSCALL_START); 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); 338 + BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) != 339 + (unsigned long)VSYSCALL_ADDR); 345 340 } 346 341 347 342 static int __init vsyscall_init(void) 348 343 { 349 - BUG_ON(VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)); 350 - 351 344 cpu_notifier_register_begin(); 352 345 353 346 on_each_cpu(cpu_vsyscall_init, NULL, 1);
+3 -2
arch/x86/mm/fault.c
··· 18 18 #include <asm/traps.h> /* dotraplinkage, ... */ 19 19 #include <asm/pgalloc.h> /* pgd_*(), ... */ 20 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 24 #define CREATE_TRACE_POINTS 24 25 #include <asm/trace/exceptions.h> ··· 772 771 * emulation. 773 772 */ 774 773 if (unlikely((error_code & PF_INSTR) && 775 - ((address & ~0xfff) == VSYSCALL_START))) { 774 + ((address & ~0xfff) == VSYSCALL_ADDR))) { 776 775 if (emulate_vsyscall(regs, address)) 777 776 return; 778 777 }
+5 -5
arch/x86/mm/init_64.c
··· 1055 1055 after_bootmem = 1; 1056 1056 1057 1057 /* Register memory areas for /proc/kcore */ 1058 - kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 1059 - VSYSCALL_END - VSYSCALL_START, KCORE_OTHER); 1058 + kclist_add(&kcore_vsyscall, (void *)VSYSCALL_ADDR, 1059 + PAGE_SIZE, KCORE_OTHER); 1060 1060 1061 1061 mem_init_print_info(NULL); 1062 1062 } ··· 1186 1186 * not need special handling anymore: 1187 1187 */ 1188 1188 static struct vm_area_struct gate_vma = { 1189 - .vm_start = VSYSCALL_START, 1190 - .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE), 1189 + .vm_start = VSYSCALL_ADDR, 1190 + .vm_end = VSYSCALL_ADDR + PAGE_SIZE, 1191 1191 .vm_page_prot = PAGE_READONLY_EXEC, 1192 1192 .vm_flags = VM_READ | VM_EXEC 1193 1193 }; ··· 1218 1218 */ 1219 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 1224 const char *arch_vma_name(struct vm_area_struct *vma)
+5 -17
arch/x86/vdso/vclock_gettime.c
··· 30 30 extern time_t __vdso_time(time_t *t); 31 31 32 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 40 #endif 38 41 ··· 45 42 #include <asm/vsyscall.h> 46 43 #include <asm/fixmap.h> 47 44 #include <asm/pvclock.h> 48 - 49 - static notrace cycle_t vread_hpet(void) 50 - { 51 - return read_hpet_counter((const void *)fix_to_virt(VSYSCALL_HPET)); 52 - } 53 45 54 46 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) 55 47 { ··· 134 136 #endif 135 137 136 138 #else 137 - 138 - extern u8 hpet_page 139 - __attribute__((visibility("hidden"))); 140 - 141 - #ifdef CONFIG_HPET_TIMER 142 - static notrace cycle_t vread_hpet(void) 143 - { 144 - return read_hpet_counter((const void *)(&hpet_page)); 145 - } 146 - #endif 147 139 148 140 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) 149 141 {
-2
arch/x86/vdso/vdso-layout.lds.S
··· 47 47 48 48 .text : { *(.text*) } :text =0x90909090, 49 49 50 - #ifdef BUILD_VDSO32 51 50 /* 52 51 * The remainder of the vDSO consists of special pages that are 53 52 * shared between the kernel and userspace. It needs to be at the ··· 68 69 69 70 hpet_page = .; 70 71 . = . + PAGE_SIZE; 71 - #endif 72 72 73 73 . = ALIGN(PAGE_SIZE); 74 74 end_mapping = .;
+3 -5
arch/x86/xen/mmu.c
··· 1494 1494 page->private = (unsigned long)user_pgd; 1495 1495 1496 1496 if (user_pgd != NULL) { 1497 - user_pgd[pgd_index(VSYSCALL_START)] = 1497 + user_pgd[pgd_index(VSYSCALL_ADDR)] = 1498 1498 __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); 1499 1499 ret = 0; 1500 1500 } ··· 2062 2062 case FIX_KMAP_BEGIN ... FIX_KMAP_END: 2063 2063 # endif 2064 2064 #else 2065 - case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: 2066 - case VVAR_PAGE: 2065 + case VSYSCALL_PAGE: 2067 2066 #endif 2068 2067 case FIX_TEXT_POKE0: 2069 2068 case FIX_TEXT_POKE1: ··· 2103 2104 #ifdef CONFIG_X86_64 2104 2105 /* Replicate changes to map the vsyscall page into the user 2105 2106 pagetable vsyscall mapping. */ 2106 - if ((idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) || 2107 - idx == VVAR_PAGE) { 2107 + if (idx == VSYSCALL_PAGE) { 2108 2108 unsigned long vaddr = __fix_to_virt(idx); 2109 2109 set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); 2110 2110 }