Merge tag 'sound-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[firefly-linux-kernel-4.4.55.git] / arch / tile / mm / elf.c
index 743c951c61b061b516e1bb3ea06b397e42700d91..23f044e8a7ab0e1f06c425655f1f8ecf11f9996e 100644 (file)
@@ -21,7 +21,8 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
-#include <arch/sim_def.h>
+#include <asm/vdso.h>
+#include <arch/sim.h>
 
 /* Notify a running simulator, if any, that an exec just occurred. */
 static void sim_notify_exec(const char *binary_name)
@@ -38,21 +39,55 @@ static void sim_notify_exec(const char *binary_name)
 
 static int notify_exec(struct mm_struct *mm)
 {
-       int retval = 0;  /* failure */
-
-       if (mm->exe_file) {
-               char *buf = (char *) __get_free_page(GFP_KERNEL);
-               if (buf) {
-                       char *path = d_path(&mm->exe_file->f_path,
-                                           buf, PAGE_SIZE);
-                       if (!IS_ERR(path)) {
-                               sim_notify_exec(path);
-                               retval = 1;
-                       }
-                       free_page((unsigned long)buf);
+       char *buf, *path;
+       struct vm_area_struct *vma;
+
+       if (!sim_is_simulator())
+               return 1;
+
+       if (mm->exe_file == NULL)
+               return 0;
+
+       for (vma = current->mm->mmap; ; vma = vma->vm_next) {
+               if (vma == NULL)
+                       return 0;
+               if (vma->vm_file == mm->exe_file)
+                       break;
+       }
+
+       buf = (char *) __get_free_page(GFP_KERNEL);
+       if (buf == NULL)
+               return 0;
+
+       path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE);
+       if (IS_ERR(path)) {
+               free_page((unsigned long)buf);
+               return 0;
+       }
+
+       /*
+        * Notify simulator of an ET_DYN object so we know the load address.
+        * The somewhat cryptic overuse of SIM_CONTROL_DLOPEN allows us
+        * to be backward-compatible with older simulator releases.
+        */
+       if (vma->vm_start == (ELF_ET_DYN_BASE & PAGE_MASK)) {
+               char buf[64];
+               int i;
+
+               snprintf(buf, sizeof(buf), "0x%lx:@", vma->vm_start);
+               for (i = 0; ; ++i) {
+                       char c = buf[i];
+                       __insn_mtspr(SPR_SIM_CONTROL,
+                                    (SIM_CONTROL_DLOPEN
+                                     | (c << _SIM_CONTROL_OPERATOR_BITS)));
+                       if (c == '\0')
+                               break;
                }
        }
-       return retval;
+
+       sim_notify_exec(path);
+       free_page((unsigned long)buf);
+       return 1;
 }
 
 /* Notify a running simulator, if any, that we loaded an interpreter. */
@@ -68,37 +103,10 @@ static void sim_notify_interp(unsigned long load_addr)
 }
 
 
-/* Kernel address of page used to map read-only kernel data into userspace. */
-static void *vdso_page;
-
-/* One-entry array used for install_special_mapping. */
-static struct page *vdso_pages[1];
-
-static int __init vdso_setup(void)
-{
-       vdso_page = (void *)get_zeroed_page(GFP_ATOMIC);
-       memcpy(vdso_page, __rt_sigreturn, __rt_sigreturn_end - __rt_sigreturn);
-       vdso_pages[0] = virt_to_page(vdso_page);
-       return 0;
-}
-device_initcall(vdso_setup);
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-       if (vma->vm_private_data == vdso_pages)
-               return "[vdso]";
-#ifndef __tilegx__
-       if (vma->vm_start == MEM_USER_INTRPT)
-               return "[intrpt]";
-#endif
-       return NULL;
-}
-
 int arch_setup_additional_pages(struct linux_binprm *bprm,
                                int executable_stack)
 {
        struct mm_struct *mm = current->mm;
-       unsigned long vdso_base;
        int retval = 0;
 
        down_write(&mm->mmap_sem);
@@ -111,14 +119,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
        if (!notify_exec(mm))
                sim_notify_exec(bprm->filename);
 
-       /*
-        * MAYWRITE to allow gdb to COW and set breakpoints
-        */
-       vdso_base = VDSO_BASE;
-       retval = install_special_mapping(mm, vdso_base, PAGE_SIZE,
-                                        VM_READ|VM_EXEC|
-                                        VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-                                        vdso_pages);
+       retval = setup_vdso_pages();
 
 #ifndef __tilegx__
        /*