RESEND [PATCH 3/6] arm64: Refactor vDSO init/setup

2018-10-01 Thread Mark Salyzyn
From: Kevin Brodsky 

Move the logic for setting up mappings and pages for the vDSO into
static functions. This makes the vDSO setup code more consistent with
the compat side and will allow to reuse it for the future compat vDSO.

Signed-off-by: Kevin Brodsky 
Signed-off-by: Mark Salyzyn 
Tested-by: Mark Salyzyn 
Cc: James Morse 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Andy Lutomirski 
Cc: Dmitry Safonov 
Cc: John Stultz 
Cc: Mark Rutland 
Cc: Laura Abbott 
Cc: Kees Cook 
Cc: Ard Biesheuvel 
Cc: Andy Gross 
Cc: Andrew Pinski 
Cc: Thomas Gleixner 
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: Jeremy Linton 
Cc: android-ker...@android.com
---
 arch/arm64/kernel/vdso.c | 118 +++
 1 file changed, 70 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 76a94bed4bd5..8529e85a521f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -39,8 +39,11 @@
 #include 
 #include 
 
-extern char vdso_start[], vdso_end[];
-static unsigned long vdso_pages __ro_after_init;
+struct vdso_mappings {
+   unsigned long num_code_pages;
+   struct vm_special_mapping data_mapping;
+   struct vm_special_mapping code_mapping;
+};
 
 /*
  * The vDSO data page.
@@ -164,95 +167,114 @@ static int vdso_mremap(const struct vm_special_mapping 
*sm,
return 0;
 }
 
-static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
-   {
-   .name   = "[vvar]",
-   },
-   {
-   .name   = "[vdso]",
-   .mremap = vdso_mremap,
-   },
-};
-
-static int __init vdso_init(void)
+static int __init vdso_mappings_init(const char *name,
+const char *code_start,
+const char *code_end,
+struct vdso_mappings *mappings)
 {
-   int i;
+   unsigned long i, vdso_page;
struct page **vdso_pagelist;
unsigned long pfn;
 
-   if (memcmp(vdso_start, "\177ELF", 4)) {
-   pr_err("vDSO is not a valid ELF object!\n");
+   if (memcmp(code_start, "\177ELF", 4)) {
+   pr_err("%s is not a valid ELF object!\n", name);
return -EINVAL;
}
 
-   vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
-   pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-   vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
-
-   /* Allocate the vDSO pagelist, plus a page for the data. */
-   vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
-   GFP_KERNEL);
+   vdso_pages = (code_end - code_start) >> PAGE_SHIFT;
+   pr_info("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+   name, vdso_pages + 1, vdso_pages, code_start, 1L,
+   vdso_data);
+
+   /*
+* Allocate space for storing pointers to the vDSO code pages + the
+* data page. The pointers must have the same lifetime as the mappings,
+* which are static, so there is no need to keep track of the pointer
+* array to free it.
+*/
+   vdso_pagelist = kmalloc_array(vdso_pages + 1, sizeof(struct page *),
+ GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
 
/* Grab the vDSO data page. */
vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
 
-
/* Grab the vDSO code pages. */
-   pfn = sym_to_pfn(vdso_start);
+   pfn = sym_to_pfn(code_start);
 
for (i = 0; i < vdso_pages; i++)
vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
 
-   vdso_spec[0].pages = _pagelist[0];
-   vdso_spec[1].pages = _pagelist[1];
+   /* Populate the special mapping structures */
+   mappings->data_mapping = (struct vm_special_mapping) {
+   .name   = "[vvar]",
+   .pages  = _pagelist[0],
+   };
+
+   mappings->code_mapping = (struct vm_special_mapping) {
+   .name   = "[vdso]",
+   .pages  = _pagelist[1],
+   };
 
+   mappings->num_code_pages = vdso_pages;
return 0;
 }
+
+static struct vdso_mappings vdso_mappings __ro_after_init;
+
+static int __init vdso_init(void)
+{
+   extern char vdso_start[], vdso_end[];
+
+   return vdso_mappings_init("vdso", vdso_start, vdso_end,
+ _mappings);
+}
 arch_initcall(vdso_init);
 
-int arch_setup_additional_pages(struct linux_binprm *bprm,
-   int uses_interp)
+static int vdso_setup(struct mm_struct *mm,
+ const struct vdso_mappings *mappings)
 {
-   struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
 
-   vdso_text_len = vdso_pages << PAGE_SHIFT;
+   vdso_text_len = mappings->num_code_pages << 

RESEND [PATCH 3/6] arm64: Refactor vDSO init/setup

2018-10-01 Thread Mark Salyzyn
From: Kevin Brodsky 

Move the logic for setting up mappings and pages for the vDSO into
static functions. This makes the vDSO setup code more consistent with
the compat side and will allow to reuse it for the future compat vDSO.

Signed-off-by: Kevin Brodsky 
Signed-off-by: Mark Salyzyn 
Tested-by: Mark Salyzyn 
Cc: James Morse 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Andy Lutomirski 
Cc: Dmitry Safonov 
Cc: John Stultz 
Cc: Mark Rutland 
Cc: Laura Abbott 
Cc: Kees Cook 
Cc: Ard Biesheuvel 
Cc: Andy Gross 
Cc: Andrew Pinski 
Cc: Thomas Gleixner 
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: Jeremy Linton 
Cc: android-ker...@android.com
---
 arch/arm64/kernel/vdso.c | 118 +++
 1 file changed, 70 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 76a94bed4bd5..8529e85a521f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -39,8 +39,11 @@
 #include 
 #include 
 
-extern char vdso_start[], vdso_end[];
-static unsigned long vdso_pages __ro_after_init;
+struct vdso_mappings {
+   unsigned long num_code_pages;
+   struct vm_special_mapping data_mapping;
+   struct vm_special_mapping code_mapping;
+};
 
 /*
  * The vDSO data page.
@@ -164,95 +167,114 @@ static int vdso_mremap(const struct vm_special_mapping 
*sm,
return 0;
 }
 
-static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
-   {
-   .name   = "[vvar]",
-   },
-   {
-   .name   = "[vdso]",
-   .mremap = vdso_mremap,
-   },
-};
-
-static int __init vdso_init(void)
+static int __init vdso_mappings_init(const char *name,
+const char *code_start,
+const char *code_end,
+struct vdso_mappings *mappings)
 {
-   int i;
+   unsigned long i, vdso_page;
struct page **vdso_pagelist;
unsigned long pfn;
 
-   if (memcmp(vdso_start, "\177ELF", 4)) {
-   pr_err("vDSO is not a valid ELF object!\n");
+   if (memcmp(code_start, "\177ELF", 4)) {
+   pr_err("%s is not a valid ELF object!\n", name);
return -EINVAL;
}
 
-   vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
-   pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-   vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
-
-   /* Allocate the vDSO pagelist, plus a page for the data. */
-   vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
-   GFP_KERNEL);
+   vdso_pages = (code_end - code_start) >> PAGE_SHIFT;
+   pr_info("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+   name, vdso_pages + 1, vdso_pages, code_start, 1L,
+   vdso_data);
+
+   /*
+* Allocate space for storing pointers to the vDSO code pages + the
+* data page. The pointers must have the same lifetime as the mappings,
+* which are static, so there is no need to keep track of the pointer
+* array to free it.
+*/
+   vdso_pagelist = kmalloc_array(vdso_pages + 1, sizeof(struct page *),
+ GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
 
/* Grab the vDSO data page. */
vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
 
-
/* Grab the vDSO code pages. */
-   pfn = sym_to_pfn(vdso_start);
+   pfn = sym_to_pfn(code_start);
 
for (i = 0; i < vdso_pages; i++)
vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
 
-   vdso_spec[0].pages = _pagelist[0];
-   vdso_spec[1].pages = _pagelist[1];
+   /* Populate the special mapping structures */
+   mappings->data_mapping = (struct vm_special_mapping) {
+   .name   = "[vvar]",
+   .pages  = _pagelist[0],
+   };
+
+   mappings->code_mapping = (struct vm_special_mapping) {
+   .name   = "[vdso]",
+   .pages  = _pagelist[1],
+   };
 
+   mappings->num_code_pages = vdso_pages;
return 0;
 }
+
+static struct vdso_mappings vdso_mappings __ro_after_init;
+
+static int __init vdso_init(void)
+{
+   extern char vdso_start[], vdso_end[];
+
+   return vdso_mappings_init("vdso", vdso_start, vdso_end,
+ _mappings);
+}
 arch_initcall(vdso_init);
 
-int arch_setup_additional_pages(struct linux_binprm *bprm,
-   int uses_interp)
+static int vdso_setup(struct mm_struct *mm,
+ const struct vdso_mappings *mappings)
 {
-   struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
 
-   vdso_text_len = vdso_pages << PAGE_SHIFT;
+   vdso_text_len = mappings->num_code_pages << 

RESEND [PATCH 3/6] arm64: Refactor vDSO init/setup

2018-06-18 Thread Mark Salyzyn
From: Kevin Brodsky 

Move the logic for setting up mappings and pages for the vDSO into
static functions. This makes the vDSO setup code more consistent with
the compat side and will allow to reuse it for the future compat vDSO.

Signed-off-by: Kevin Brodsky 
Signed-off-by: Mark Salyzyn 
Cc: James Morse 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Andy Lutomirski 
Cc: Dmitry Safonov 
Cc: John Stultz 
Cc: Mark Rutland 
Cc: Laura Abbott 
Cc: Kees Cook 
Cc: Ard Biesheuvel 
Cc: Andy Gross 
Cc: Andrew Pinski 
Cc: Thomas Gleixner 
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: Jeremy Linton 
---
 arch/arm64/kernel/vdso.c | 118 +++
 1 file changed, 70 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 76a94bed4bd5..8529e85a521f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -39,8 +39,11 @@
 #include 
 #include 
 
-extern char vdso_start[], vdso_end[];
-static unsigned long vdso_pages __ro_after_init;
+struct vdso_mappings {
+   unsigned long num_code_pages;
+   struct vm_special_mapping data_mapping;
+   struct vm_special_mapping code_mapping;
+};
 
 /*
  * The vDSO data page.
@@ -164,95 +167,114 @@ static int vdso_mremap(const struct vm_special_mapping 
*sm,
return 0;
 }
 
-static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
-   {
-   .name   = "[vvar]",
-   },
-   {
-   .name   = "[vdso]",
-   .mremap = vdso_mremap,
-   },
-};
-
-static int __init vdso_init(void)
+static int __init vdso_mappings_init(const char *name,
+const char *code_start,
+const char *code_end,
+struct vdso_mappings *mappings)
 {
-   int i;
+   unsigned long i, vdso_page;
struct page **vdso_pagelist;
unsigned long pfn;
 
-   if (memcmp(vdso_start, "\177ELF", 4)) {
-   pr_err("vDSO is not a valid ELF object!\n");
+   if (memcmp(code_start, "\177ELF", 4)) {
+   pr_err("%s is not a valid ELF object!\n", name);
return -EINVAL;
}
 
-   vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
-   pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-   vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
-
-   /* Allocate the vDSO pagelist, plus a page for the data. */
-   vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
-   GFP_KERNEL);
+   vdso_pages = (code_end - code_start) >> PAGE_SHIFT;
+   pr_info("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+   name, vdso_pages + 1, vdso_pages, code_start, 1L,
+   vdso_data);
+
+   /*
+* Allocate space for storing pointers to the vDSO code pages + the
+* data page. The pointers must have the same lifetime as the mappings,
+* which are static, so there is no need to keep track of the pointer
+* array to free it.
+*/
+   vdso_pagelist = kmalloc_array(vdso_pages + 1, sizeof(struct page *),
+ GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
 
/* Grab the vDSO data page. */
vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
 
-
/* Grab the vDSO code pages. */
-   pfn = sym_to_pfn(vdso_start);
+   pfn = sym_to_pfn(code_start);
 
for (i = 0; i < vdso_pages; i++)
vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
 
-   vdso_spec[0].pages = _pagelist[0];
-   vdso_spec[1].pages = _pagelist[1];
+   /* Populate the special mapping structures */
+   mappings->data_mapping = (struct vm_special_mapping) {
+   .name   = "[vvar]",
+   .pages  = _pagelist[0],
+   };
+
+   mappings->code_mapping = (struct vm_special_mapping) {
+   .name   = "[vdso]",
+   .pages  = _pagelist[1],
+   };
 
+   mappings->num_code_pages = vdso_pages;
return 0;
 }
+
+static struct vdso_mappings vdso_mappings __ro_after_init;
+
+static int __init vdso_init(void)
+{
+   extern char vdso_start[], vdso_end[];
+
+   return vdso_mappings_init("vdso", vdso_start, vdso_end,
+ _mappings);
+}
 arch_initcall(vdso_init);
 
-int arch_setup_additional_pages(struct linux_binprm *bprm,
-   int uses_interp)
+static int vdso_setup(struct mm_struct *mm,
+ const struct vdso_mappings *mappings)
 {
-   struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
 
-   vdso_text_len = vdso_pages << PAGE_SHIFT;
+   vdso_text_len = mappings->num_code_pages << PAGE_SHIFT;
/* Be sure to map the data page */

RESEND [PATCH 3/6] arm64: Refactor vDSO init/setup

2018-06-18 Thread Mark Salyzyn
From: Kevin Brodsky 

Move the logic for setting up mappings and pages for the vDSO into
static functions. This makes the vDSO setup code more consistent with
the compat side and will allow to reuse it for the future compat vDSO.

Signed-off-by: Kevin Brodsky 
Signed-off-by: Mark Salyzyn 
Cc: James Morse 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Andy Lutomirski 
Cc: Dmitry Safonov 
Cc: John Stultz 
Cc: Mark Rutland 
Cc: Laura Abbott 
Cc: Kees Cook 
Cc: Ard Biesheuvel 
Cc: Andy Gross 
Cc: Andrew Pinski 
Cc: Thomas Gleixner 
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: Jeremy Linton 
---
 arch/arm64/kernel/vdso.c | 118 +++
 1 file changed, 70 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 76a94bed4bd5..8529e85a521f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -39,8 +39,11 @@
 #include 
 #include 
 
-extern char vdso_start[], vdso_end[];
-static unsigned long vdso_pages __ro_after_init;
+struct vdso_mappings {
+   unsigned long num_code_pages;
+   struct vm_special_mapping data_mapping;
+   struct vm_special_mapping code_mapping;
+};
 
 /*
  * The vDSO data page.
@@ -164,95 +167,114 @@ static int vdso_mremap(const struct vm_special_mapping 
*sm,
return 0;
 }
 
-static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
-   {
-   .name   = "[vvar]",
-   },
-   {
-   .name   = "[vdso]",
-   .mremap = vdso_mremap,
-   },
-};
-
-static int __init vdso_init(void)
+static int __init vdso_mappings_init(const char *name,
+const char *code_start,
+const char *code_end,
+struct vdso_mappings *mappings)
 {
-   int i;
+   unsigned long i, vdso_page;
struct page **vdso_pagelist;
unsigned long pfn;
 
-   if (memcmp(vdso_start, "\177ELF", 4)) {
-   pr_err("vDSO is not a valid ELF object!\n");
+   if (memcmp(code_start, "\177ELF", 4)) {
+   pr_err("%s is not a valid ELF object!\n", name);
return -EINVAL;
}
 
-   vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
-   pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-   vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
-
-   /* Allocate the vDSO pagelist, plus a page for the data. */
-   vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
-   GFP_KERNEL);
+   vdso_pages = (code_end - code_start) >> PAGE_SHIFT;
+   pr_info("%s: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+   name, vdso_pages + 1, vdso_pages, code_start, 1L,
+   vdso_data);
+
+   /*
+* Allocate space for storing pointers to the vDSO code pages + the
+* data page. The pointers must have the same lifetime as the mappings,
+* which are static, so there is no need to keep track of the pointer
+* array to free it.
+*/
+   vdso_pagelist = kmalloc_array(vdso_pages + 1, sizeof(struct page *),
+ GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
 
/* Grab the vDSO data page. */
vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
 
-
/* Grab the vDSO code pages. */
-   pfn = sym_to_pfn(vdso_start);
+   pfn = sym_to_pfn(code_start);
 
for (i = 0; i < vdso_pages; i++)
vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
 
-   vdso_spec[0].pages = _pagelist[0];
-   vdso_spec[1].pages = _pagelist[1];
+   /* Populate the special mapping structures */
+   mappings->data_mapping = (struct vm_special_mapping) {
+   .name   = "[vvar]",
+   .pages  = _pagelist[0],
+   };
+
+   mappings->code_mapping = (struct vm_special_mapping) {
+   .name   = "[vdso]",
+   .pages  = _pagelist[1],
+   };
 
+   mappings->num_code_pages = vdso_pages;
return 0;
 }
+
+static struct vdso_mappings vdso_mappings __ro_after_init;
+
+static int __init vdso_init(void)
+{
+   extern char vdso_start[], vdso_end[];
+
+   return vdso_mappings_init("vdso", vdso_start, vdso_end,
+ _mappings);
+}
 arch_initcall(vdso_init);
 
-int arch_setup_additional_pages(struct linux_binprm *bprm,
-   int uses_interp)
+static int vdso_setup(struct mm_struct *mm,
+ const struct vdso_mappings *mappings)
 {
-   struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
 
-   vdso_text_len = vdso_pages << PAGE_SHIFT;
+   vdso_text_len = mappings->num_code_pages << PAGE_SHIFT;
/* Be sure to map the data page */