[PATCH v2 4/6] x86: Move the 32-bit vdso special pages after the text

2014-04-24 Thread Andy Lutomirski
This unifies the vdso mapping code and teaches it how to map special
pages at addresses corresponding to symbols in the vdso image.  The
new code is used for all vdso variants, but so far only the 32-bit
variants use the new vvar page position.

Signed-off-by: Andy Lutomirski 
---
 arch/x86/include/asm/elf.h  |   8 +--
 arch/x86/include/asm/vdso.h |   4 ++
 arch/x86/include/asm/vdso32.h   |  11 
 arch/x86/vdso/vdso-layout.lds.S |  42 -
 arch/x86/vdso/vdso2c.c  |  14 +
 arch/x86/vdso/vdso2c.h  |  17 ++
 arch/x86/vdso/vdso32-setup.c| 114 +--
 arch/x86/vdso/vma.c | 128 +---
 8 files changed, 172 insertions(+), 166 deletions(-)
 delete mode 100644 arch/x86/include/asm/vdso32.h

diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 65b21bc..1a055c8 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -333,11 +333,9 @@ struct linux_binprm;
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
   int uses_interp);
-extern int x32_setup_additional_pages(struct linux_binprm *bprm,
- int uses_interp);
-
-extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
-#define compat_arch_setup_additional_pages syscall32_setup_pages
+extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+#define compat_arch_setup_additional_pages compat_arch_setup_additional_pages
 
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 389fe2c..d0a2c90 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -14,6 +14,10 @@ struct vdso_image {
 
unsigned long alt, alt_len;
 
+   unsigned long sym_end_mapping;  /* Total size of the mapping */
+
+   unsigned long sym_vvar_page;
+   unsigned long sym_hpet_page;
unsigned long sym_VDSO32_NOTE_MASK;
unsigned long sym___kernel_sigreturn;
unsigned long sym___kernel_rt_sigreturn;
diff --git a/arch/x86/include/asm/vdso32.h b/arch/x86/include/asm/vdso32.h
deleted file mode 100644
index 7efb701..000
--- a/arch/x86/include/asm/vdso32.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_X86_VDSO32_H
-#define _ASM_X86_VDSO32_H
-
-#define VDSO_BASE_PAGE 0
-#define VDSO_VVAR_PAGE 1
-#define VDSO_HPET_PAGE 2
-#define VDSO_PAGES 3
-#define VDSO_PREV_PAGES2
-#define VDSO_OFFSET(x) ((x) * PAGE_SIZE)
-
-#endif
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 9df017a..e177c08 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -1,3 +1,5 @@
+#include 
+
 /*
  * Linker script for vDSO.  This is an ELF shared object prelinked to
  * its virtual address, and with only one read-only segment.
@@ -6,20 +8,6 @@
 
 SECTIONS
 {
-#ifdef BUILD_VDSO32
-#include 
-
-   hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
-
-   vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
-
-   /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset;
-#define __VVAR_KERNEL_LDS
-#include 
-#undef __VVAR_KERNEL_LDS
-#undef EMIT_VVAR
-#endif
. = SIZEOF_HEADERS;
 
.hash   : { *(.hash) }  :text
@@ -59,11 +47,33 @@ SECTIONS
 
.text   : { *(.text*) } :text   =0x90909090,
 
+#ifdef BUILD_VDSO32
/*
-* The comma above works around a bug in gold:
-* https://sourceware.org/bugzilla/show_bug.cgi?id=16804
+* The remainder of the vDSO consists of special pages that are
+* shared between the kernel and userspace.  It needs to be at the
+* end so that it doesn't overlap the mapping of the actual
+* vDSO image.
 */
 
+   . = ALIGN(PAGE_SIZE);
+   vvar_page = .;
+
+   /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
+#define __VVAR_KERNEL_LDS
+#include 
+#undef __VVAR_KERNEL_LDS
+#undef EMIT_VVAR
+
+   . = vvar_page + PAGE_SIZE;
+
+   hpet_page = .;
+   . = . + PAGE_SIZE;
+#endif
+
+   . = ALIGN(PAGE_SIZE);
+   end_mapping = .;
+
/DISCARD/ : {
*(.discard)
*(.discard.*)
diff --git a/arch/x86/vdso/vdso2c.c b/arch/x86/vdso/vdso2c.c
index 976e8e4..81edd1e 100644
--- a/arch/x86/vdso/vdso2c.c
+++ b/arch/x86/vdso/vdso2c.c
@@ -15,7 +15,21 @@
 #include 
 
 /* Symbols that we need in vdso2c. */
+enum {
+   sym_vvar_page,
+   sym_hpet_page,
+   sym_end_mapping,
+};
+
+const int special_pages[] = {
+   sym_vvar_page,
+   sym_hpet_page,
+};
+
 char const 

[PATCH v2 4/6] x86: Move the 32-bit vdso special pages after the text

2014-04-24 Thread Andy Lutomirski
This unifies the vdso mapping code and teaches it how to map special
pages at addresses corresponding to symbols in the vdso image.  The
new code is used for all vdso variants, but so far only the 32-bit
variants use the new vvar page position.

Signed-off-by: Andy Lutomirski l...@amacapital.net
---
 arch/x86/include/asm/elf.h  |   8 +--
 arch/x86/include/asm/vdso.h |   4 ++
 arch/x86/include/asm/vdso32.h   |  11 
 arch/x86/vdso/vdso-layout.lds.S |  42 -
 arch/x86/vdso/vdso2c.c  |  14 +
 arch/x86/vdso/vdso2c.h  |  17 ++
 arch/x86/vdso/vdso32-setup.c| 114 +--
 arch/x86/vdso/vma.c | 128 +---
 8 files changed, 172 insertions(+), 166 deletions(-)
 delete mode 100644 arch/x86/include/asm/vdso32.h

diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 65b21bc..1a055c8 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -333,11 +333,9 @@ struct linux_binprm;
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
   int uses_interp);
-extern int x32_setup_additional_pages(struct linux_binprm *bprm,
- int uses_interp);
-
-extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
-#define compat_arch_setup_additional_pages syscall32_setup_pages
+extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+#define compat_arch_setup_additional_pages compat_arch_setup_additional_pages
 
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 389fe2c..d0a2c90 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -14,6 +14,10 @@ struct vdso_image {
 
unsigned long alt, alt_len;
 
+   unsigned long sym_end_mapping;  /* Total size of the mapping */
+
+   unsigned long sym_vvar_page;
+   unsigned long sym_hpet_page;
unsigned long sym_VDSO32_NOTE_MASK;
unsigned long sym___kernel_sigreturn;
unsigned long sym___kernel_rt_sigreturn;
diff --git a/arch/x86/include/asm/vdso32.h b/arch/x86/include/asm/vdso32.h
deleted file mode 100644
index 7efb701..000
--- a/arch/x86/include/asm/vdso32.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_X86_VDSO32_H
-#define _ASM_X86_VDSO32_H
-
-#define VDSO_BASE_PAGE 0
-#define VDSO_VVAR_PAGE 1
-#define VDSO_HPET_PAGE 2
-#define VDSO_PAGES 3
-#define VDSO_PREV_PAGES2
-#define VDSO_OFFSET(x) ((x) * PAGE_SIZE)
-
-#endif
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 9df017a..e177c08 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -1,3 +1,5 @@
+#include asm/vdso.h
+
 /*
  * Linker script for vDSO.  This is an ELF shared object prelinked to
  * its virtual address, and with only one read-only segment.
@@ -6,20 +8,6 @@
 
 SECTIONS
 {
-#ifdef BUILD_VDSO32
-#include asm/vdso32.h
-
-   hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
-
-   vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
-
-   /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset;
-#define __VVAR_KERNEL_LDS
-#include asm/vvar.h
-#undef __VVAR_KERNEL_LDS
-#undef EMIT_VVAR
-#endif
. = SIZEOF_HEADERS;
 
.hash   : { *(.hash) }  :text
@@ -59,11 +47,33 @@ SECTIONS
 
.text   : { *(.text*) } :text   =0x90909090,
 
+#ifdef BUILD_VDSO32
/*
-* The comma above works around a bug in gold:
-* https://sourceware.org/bugzilla/show_bug.cgi?id=16804
+* The remainder of the vDSO consists of special pages that are
+* shared between the kernel and userspace.  It needs to be at the
+* end so that it doesn't overlap the mapping of the actual
+* vDSO image.
 */
 
+   . = ALIGN(PAGE_SIZE);
+   vvar_page = .;
+
+   /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
+#define __VVAR_KERNEL_LDS
+#include asm/vvar.h
+#undef __VVAR_KERNEL_LDS
+#undef EMIT_VVAR
+
+   . = vvar_page + PAGE_SIZE;
+
+   hpet_page = .;
+   . = . + PAGE_SIZE;
+#endif
+
+   . = ALIGN(PAGE_SIZE);
+   end_mapping = .;
+
/DISCARD/ : {
*(.discard)
*(.discard.*)
diff --git a/arch/x86/vdso/vdso2c.c b/arch/x86/vdso/vdso2c.c
index 976e8e4..81edd1e 100644
--- a/arch/x86/vdso/vdso2c.c
+++ b/arch/x86/vdso/vdso2c.c
@@ -15,7 +15,21 @@
 #include linux/types.h
 
 /* Symbols that we need in vdso2c. */
+enum {
+   sym_vvar_page,
+   sym_hpet_page,
+   sym_end_mapping,
+};
+
+const int