diff options
author | Roland McGrath <roland@redhat.com> | 2007-02-08 14:20:42 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-09 09:25:47 -0800 |
commit | 7d91d531900bfa1165d445390b3b13a8013f98f7 (patch) | |
tree | ede8518a1cc86191b344462d12e19fb37cb3ccbf | |
parent | fa5dc22f8586cc3742413dd05f5cd9e039dfab9e (diff) |
[PATCH] i386 vDSO: use install_special_mapping
This patch uses install_special_mapping for the i386 vDSO setup, consolidating
duplicated code.
Signed-off-by: Roland McGrath <roland@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/i386/kernel/sysenter.c | 53 |
1 files changed, 11 insertions, 42 deletions
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index 5da744204d1..bc882a2b1db 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -70,11 +70,12 @@ void enable_sep_cpu(void) */ extern const char vsyscall_int80_start, vsyscall_int80_end; extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; -static void *syscall_page; +static struct page *syscall_pages[1]; int __init sysenter_setup(void) { - syscall_page = (void *)get_zeroed_page(GFP_ATOMIC); + void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC); + syscall_pages[0] = virt_to_page(syscall_page); #ifdef CONFIG_COMPAT_VDSO __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY); @@ -96,31 +97,12 @@ int __init sysenter_setup(void) } #ifndef CONFIG_COMPAT_VDSO -static struct page *syscall_nopage(struct vm_area_struct *vma, - unsigned long adr, int *type) -{ - struct page *p = virt_to_page(adr - vma->vm_start + syscall_page); - get_page(p); - return p; -} - -/* Prevent VMA merging */ -static void syscall_vma_close(struct vm_area_struct *vma) -{ -} - -static struct vm_operations_struct syscall_vm_ops = { - .close = syscall_vma_close, - .nopage = syscall_nopage, -}; - /* Defined in vsyscall-sysenter.S */ extern void SYSENTER_RETURN; /* Setup a VMA at program startup for the vsyscall page */ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) { - struct vm_area_struct *vma; struct mm_struct *mm = current->mm; unsigned long addr; int ret; @@ -132,38 +114,25 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) goto up_fail; } - vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); - if (!vma) { - ret = -ENOMEM; - goto up_fail; - } - - vma->vm_start = addr; - vma->vm_end = addr + PAGE_SIZE; - /* MAYWRITE to allow gdb to COW and set breakpoints */ - vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; /* + * MAYWRITE to allow gdb to COW and set breakpoints + * * Make sure the vDSO gets into every core dump. * Dumping its contents makes post-mortem fully interpretable later * without matching up the same kernel and hardware config to see * what PC values meant. */ - vma->vm_flags |= VM_ALWAYSDUMP; - vma->vm_flags |= mm->def_flags; - vma->vm_page_prot = protection_map[vma->vm_flags & 7]; - vma->vm_ops = &syscall_vm_ops; - vma->vm_mm = mm; - - ret = insert_vm_struct(mm, vma); - if (unlikely(ret)) { - kmem_cache_free(vm_area_cachep, vma); + ret = install_special_mapping(mm, addr, PAGE_SIZE, + VM_READ|VM_EXEC| + VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| + VM_ALWAYSDUMP, + syscall_pages); + if (ret) goto up_fail; - } current->mm->context.vdso = (void *)addr; current_thread_info()->sysenter_return = (void *)VDSO_SYM(&SYSENTER_RETURN); - mm->total_vm++; up_fail: up_write(&mm->mmap_sem); return ret; |