extern unsigned int vced_count, vcei_count;
 
+/*
+ * A special page (the vdso) is mapped into all processes at the very
+ * top of the virtual memory space.
+ */
+#define SPECIAL_PAGES_SIZE PAGE_SIZE
+
 #ifdef CONFIG_32BIT
 /*
  * User space process size: 2GB. This is hardcoded into a few places,
  * so don't change it unless you know what you are doing.
  */
 #define TASK_SIZE      0x7fff8000UL
-#define STACK_TOP      TASK_SIZE
+#define STACK_TOP      ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
 #define TASK_SIZE32    0x7fff8000UL
 #define TASK_SIZE      0x10000000000UL
 #define STACK_TOP      \
-      (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE)
+       (((test_thread_flag(TIF_32BIT_ADDR) ?                           \
+          TASK_SIZE32 : TASK_SIZE) & PAGE_MASK) - SPECIAL_PAGES_SIZE)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
 
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Cavium Networks
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#include <linux/types.h>
+
+
+#ifdef CONFIG_32BIT
+struct mips_vdso {
+       u32 signal_trampoline[2];
+       u32 rt_signal_trampoline[2];
+};
+#else  /* !CONFIG_32BIT */
+struct mips_vdso {
+       u32 o32_signal_trampoline[2];
+       u32 o32_rt_signal_trampoline[2];
+       u32 rt_signal_trampoline[2];
+       u32 n32_rt_signal_trampoline[2];
+};
+#endif /* CONFIG_32BIT */
+
+#endif /* __ASM_VDSO_H */
 
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009, 2010 Cavium Networks, Inc.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/binfmts.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/unistd.h>
+
+#include <asm/vdso.h>
+#include <asm/uasm.h>
+
+/*
+ * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ */
+#define __NR_O32_sigreturn             4119
+#define __NR_O32_rt_sigreturn          4193
+#define __NR_N32_rt_sigreturn          6211
+
+static struct page *vdso_page;
+
+static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
+{
+       uasm_i_addiu(&tramp, 2, 0, sigreturn);  /* li v0, sigreturn */
+       uasm_i_syscall(&tramp, 0);
+}
+
+static int __init init_vdso(void)
+{
+       struct mips_vdso *vdso;
+
+       vdso_page = alloc_page(GFP_KERNEL);
+       if (!vdso_page)
+               panic("Cannot allocate vdso");
+
+       vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+       if (!vdso)
+               panic("Cannot map vdso");
+       clear_page(vdso);
+
+       install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
+#ifdef CONFIG_32BIT
+       install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
+#else
+       install_trampoline(vdso->n32_rt_signal_trampoline,
+                          __NR_N32_rt_sigreturn);
+       install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
+       install_trampoline(vdso->o32_rt_signal_trampoline,
+                          __NR_O32_rt_sigreturn);
+#endif
+
+       vunmap(vdso);
+
+       pr_notice("init_vdso successfull\n");
+
+       return 0;
+}
+device_initcall(init_vdso);
+
+static unsigned long vdso_addr(unsigned long start)
+{
+       return STACK_TOP;
+}
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+       int ret;
+       unsigned long addr;
+       struct mm_struct *mm = current->mm;
+
+       down_write(&mm->mmap_sem);
+
+       addr = vdso_addr(mm->start_stack);
+
+       addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
+       if (IS_ERR_VALUE(addr)) {
+               ret = addr;
+               goto up_fail;
+       }
+
+       ret = install_special_mapping(mm, addr, PAGE_SIZE,
+                                     VM_READ|VM_EXEC|
+                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+                                     VM_ALWAYSDUMP,
+                                     &vdso_page);
+
+       if (ret)
+               goto up_fail;
+
+       mm->context.vdso = (void *)addr;
+
+up_fail:
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+               return "[vdso]";
+       return NULL;
+}