summaryrefslogtreecommitdiff
path: root/arch/um/sys-x86/vdso/vma.c
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2011-08-18 20:03:19 +0100
committerRichard Weinberger <richard@nod.at>2011-11-02 14:14:51 +0100
commit6582b7f7743da6ce3e3714e9e8b18e0e073d4acd (patch)
tree649346d2333865ccd4bb4d560ceb50c39139c5c2 /arch/um/sys-x86/vdso/vma.c
parent858ba94499b4f48e9eb0be7cf0092f1ea9460fef (diff)
downloadlwn-6582b7f7743da6ce3e3714e9e8b18e0e073d4acd.tar.gz
lwn-6582b7f7743da6ce3e3714e9e8b18e0e073d4acd.zip
um: merge arch/um/sys-{i386,x86_64}
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/sys-x86/vdso/vma.c')
-rw-r--r--arch/um/sys-x86/vdso/vma.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/arch/um/sys-x86/vdso/vma.c b/arch/um/sys-x86/vdso/vma.c
new file mode 100644
index 000000000000..9495c8d0ce37
--- /dev/null
+++ b/arch/um/sys-x86/vdso/vma.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+ struct page *um_vdso;
+
+ BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+ um_vdso_addr = task_size - PAGE_SIZE;
+
+ vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
+ if (!vdsop)
+ goto oom;
+
+ um_vdso = alloc_page(GFP_KERNEL);
+ if (!um_vdso) {
+ kfree(vdsop);
+
+ goto oom;
+ }
+
+ copy_page(page_address(um_vdso), vdso_start);
+ *vdsop = um_vdso;
+
+ return 0;
+
+oom:
+ printk(KERN_ERR "Cannot allocate vdso\n");
+ vdso_enabled = 0;
+
+ return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ int err;
+ struct mm_struct *mm = current->mm;
+
+ if (!vdso_enabled)
+ return 0;
+
+ down_write(&mm->mmap_sem);
+
+ err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+ VM_READ|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+ VM_ALWAYSDUMP,
+ vdsop);
+
+ up_write(&mm->mmap_sem);
+
+ return err;
+}