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