root/arch/hexagon/kernel/vdso.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vdso_init
  2. arch_setup_additional_pages
  3. arch_vma_name

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * vDSO implementation for Hexagon
   4  *
   5  * Copyright (c) 2011, The Linux Foundation. All rights reserved.
   6  */
   7 
   8 #include <linux/err.h>
   9 #include <linux/mm.h>
  10 #include <linux/vmalloc.h>
  11 #include <linux/binfmts.h>
  12 
  13 #include <asm/vdso.h>
  14 
  15 static struct page *vdso_page;
  16 
  17 /* Create a vDSO page holding the signal trampoline.
  18  * We want this for a non-executable stack.
  19  */
  20 static int __init vdso_init(void)
  21 {
  22         struct hexagon_vdso *vdso;
  23 
  24         vdso_page = alloc_page(GFP_KERNEL);
  25         if (!vdso_page)
  26                 panic("Cannot allocate vdso");
  27 
  28         vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
  29         if (!vdso)
  30                 panic("Cannot map vdso");
  31         clear_page(vdso);
  32 
  33         /* Install the signal trampoline; currently looks like this:
  34          *      r6 = #__NR_rt_sigreturn;
  35          *      trap0(#1);
  36          */
  37         vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
  38         vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
  39 
  40         vunmap(vdso);
  41 
  42         return 0;
  43 }
  44 arch_initcall(vdso_init);
  45 
  46 /*
  47  * Called from binfmt_elf.  Create a VMA for the vDSO page.
  48  */
  49 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
  50 {
  51         int ret;
  52         unsigned long vdso_base;
  53         struct mm_struct *mm = current->mm;
  54 
  55         if (down_write_killable(&mm->mmap_sem))
  56                 return -EINTR;
  57 
  58         /* Try to get it loaded right near ld.so/glibc. */
  59         vdso_base = STACK_TOP;
  60 
  61         vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
  62         if (IS_ERR_VALUE(vdso_base)) {
  63                 ret = vdso_base;
  64                 goto up_fail;
  65         }
  66 
  67         /* MAYWRITE to allow gdb to COW and set breakpoints. */
  68         ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
  69                                       VM_READ|VM_EXEC|
  70                                       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
  71                                       &vdso_page);
  72 
  73         if (ret)
  74                 goto up_fail;
  75 
  76         mm->context.vdso = (void *)vdso_base;
  77 
  78 up_fail:
  79         up_write(&mm->mmap_sem);
  80         return ret;
  81 }
  82 
  83 const char *arch_vma_name(struct vm_area_struct *vma)
  84 {
  85         if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
  86                 return "[vdso]";
  87         return NULL;
  88 }

/* [<][>][^][v][top][bottom][index][help] */