[C/R ARM][PATCH 1/3] ARM: Rudimentary syscall interfaces
From: Matt Helsley <hidden>
Date: 2010-03-25 01:17:58
Also in:
lkml
On Wed, Mar 24, 2010 at 06:11:32PM -0700, Matt Helsley wrote:
On Wed, Mar 24, 2010 at 08:36:39PM +0100, Christoffer Dall wrote:
<snip>
quoted
Re-using the assembly code or factoring it out so that it can be used from multiple places doesn't seem very pleasing to me, as the assembly code is in the critical path and written specifically for the context of a process entering the kernel. Please correct me if I'm wrong. I imagine simply a function in C, more or less re-implementing the logic that's already in entry-common.S, might do the trick. I wouldn't worry much about the performance in this case as it will not be used often. The following _untested_ snippet illustrates my idea: --- arch/arm/include/asm/syscall.h | 93 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 92 insertions(+), 1 deletions(-)diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 3b3248f..a7f2615 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h@@ -10,10 +10,101 @@ #ifndef _ASM_ARM_SYSCALLS_H #define _ASM_ARM_SYSCALLS_H +static inline int get_swi_instruction(struct task_struct *task, + struct pt_regs *regs, + unsigned long *instr) +{ + struct page *page = NULL; + unsigned long instr_addr; + unsigned long *ptr; + int ret; + + instr_addr = regs->ARM_pc - 4; + + down_read(&task->mm->mmap_sem); + ret = get_user_pages(task, task->mm, instr_addr, + 1, 0, 0, &page, NULL); + up_read(&task->mm->mmap_sem); + + if (ret < 0) + return ret; + + ptr = (unsigned long *)kmap_atomic(page, KM_USER1); + memcpy(instr, + ptr + (instr_addr >> PAGE_SHIFT),^shouldn't this be: instr_addr & PAGE_MASK
Oops, made my own mistake. I think the address of the kmap'd instruction would be: ptr + (instr_addr & ~PAGE_MASK) Cheers, -Matt Helsley