David VomLehn wrote:
On Tue, Apr 21, 2009 at 02:33:24PM -0700, David Daney wrote:
This is a preliminary patch to add a vdso to all user processes.
...
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
new file mode 100644
index 0000000..a1f38a6
...
+static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
+{
+ tramp[0] = 0x24020000 + sigreturn; /* li v0, sigreturn */
+ tramp[1] = 0x0000000c; /* syscall */
+}
We can do away with magic constants by building on asm/inst.h:
static void __init install_trampoline(union mips_instruction *tramp,
short sigreturn)
{
static struct i_format li_sigreturn = { /* li, v0, sigreturn */
.opcode = addiu_op,
.rs = 0, /* zero */
.rt = 2, /* v0 */
};
static struct r_format syscall = { /* syscall */
.opcode = spec_op,
.func = syscall_op
};
tramp[0].i_format = li_sigreturn;
tramp[0].i_format.simmediate = sigreturn;
tramp[1].r_format = syscall;
}
Admittedly, this isn't really a proper use of the r_format structure. The
right way is to add another structure to asm/inst.h and use that:
Perhaps using the uasm would be even better.
[...]
+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:
It seems that this is an unexpected condition that probably indicates
a failure of the expected state of the process at this point. Perhaps
a pr_err() or pr_warning() would be appropriate?
+ up_write(&mm->mmap_sem);
+ return ret;
+}
Really it should always succeed. Something is seriously wrong if you
cannot map that page and we should probably panic().
David Daney