Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 189776
b: refs/heads/master
c: c52d0d3
h: refs/heads/master
v: v3
  • Loading branch information
David Daney authored and Ralf Baechle committed Apr 12, 2010
1 parent 9566d2d commit eead1ef
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 58b9e2239fa63c7c470acb4a77e9da17e6a6fa4f
refs/heads/master: c52d0d30aef84aa8893b34e5254716c8ab5c4472
4 changes: 4 additions & 0 deletions trunk/arch/mips/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,8 @@ extern const char *__elf_platform;
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif

#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
#endif /* _ASM_ELF_H */
5 changes: 4 additions & 1 deletion trunk/arch/mips/include/asm/mmu.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef __ASM_MMU_H
#define __ASM_MMU_H

typedef unsigned long mm_context_t[NR_CPUS];
typedef struct {
unsigned long asid[NR_CPUS];
void *vdso;
} mm_context_t;

#endif /* __ASM_MMU_H */
2 changes: 1 addition & 1 deletion trunk/arch/mips/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ extern unsigned long smtc_asid_mask;

#endif

#define cpu_context(cpu, mm) ((mm)->context[cpu])
#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)

Expand Down
11 changes: 9 additions & 2 deletions trunk/arch/mips/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,19 @@ extern void (*cpu_wait)(void);

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
Expand All @@ -59,7 +65,8 @@ extern unsigned int vced_count, vcei_count;
#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
Expand Down
29 changes: 29 additions & 0 deletions trunk/arch/mips/include/asm/vdso.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 */
2 changes: 1 addition & 1 deletion trunk/arch/mips/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds

obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o setup.o signal.o syscall.o \
time.o topology.o traps.o unaligned.o watch.o
time.o topology.o traps.o unaligned.o watch.o vdso.o

ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_ftrace.o = -pg
Expand Down
6 changes: 5 additions & 1 deletion trunk/arch/mips/kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
int do_color_align;
unsigned long task_size;

task_size = STACK_TOP;
#ifdef CONFIG_32BIT
task_size = TASK_SIZE;
#else /* Must be CONFIG_64BIT*/
task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE;
#endif

if (len > task_size)
return -ENOMEM;
Expand Down
112 changes: 112 additions & 0 deletions trunk/arch/mips/kernel/vdso.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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;
}

0 comments on commit eead1ef

Please sign in to comment.