Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 43944
b: refs/heads/master
c: fc4fb2a
h: refs/heads/master
v: v3
  • Loading branch information
Chris Zankel authored and Linus Torvalds committed Dec 10, 2006
1 parent 61c193f commit 3b3d721
Show file tree
Hide file tree
Showing 15 changed files with 1,054 additions and 968 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: 173d6681380aa1d60dfc35ed7178bd7811ba2784
refs/heads/master: fc4fb2adf944d45a7f3d4d38df991c79ffdb6a43
5 changes: 5 additions & 0 deletions trunk/arch/xtensa/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ int main(void)
DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
BLANK();
DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);

/* constants */
DEFINE(_CLONE_VM, CLONE_VM);
DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);

return 0;
}

Expand Down
228 changes: 150 additions & 78 deletions trunk/arch/xtensa/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -1004,13 +1004,10 @@ ENTRY(fast_syscall_kernel)

rsr a0, DEPC # get syscall-nr
_beqz a0, fast_syscall_spill_registers

addi a0, a0, -__NR_sysxtensa
_beqz a0, fast_syscall_sysxtensa
_beqi a0, __NR_xtensa, fast_syscall_xtensa

j kernel_exception


ENTRY(fast_syscall_user)

/* Skip syscall. */
Expand All @@ -1024,9 +1021,7 @@ ENTRY(fast_syscall_user)

rsr a0, DEPC # get syscall-nr
_beqz a0, fast_syscall_spill_registers

addi a0, a0, -__NR_sysxtensa
_beqz a0, fast_syscall_sysxtensa
_beqi a0, __NR_xtensa, fast_syscall_xtensa

j user_exception

Expand All @@ -1047,18 +1042,19 @@ ENTRY(fast_syscall_unrecoverable)
/*
* sysxtensa syscall handler
*
* int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
* int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
* int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
* int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
* a2 a6 a3 a4 a5
* int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused);
* int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused);
* int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
* int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
* a2 a6 a3 a4 a5
*
* Entry condition:
*
* a0: trashed, original value saved on stack (PT_AREG0)
* a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
* a1: a1
* a2: new stack pointer, original in DEPC
* a3: dispatch table
* a2: new stack pointer, original in a0 and DEPC
* a3: dispatch table, original in excsave_1
* a4..a15: unchanged
* depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3
*
Expand Down Expand Up @@ -1091,59 +1087,62 @@ ENTRY(fast_syscall_unrecoverable)
#define CATCH \
67:

ENTRY(fast_syscall_sysxtensa)

_beqz a6, 1f
_blti a6, SYSXTENSA_COUNT, 2f
ENTRY(fast_syscall_xtensa)

1: j user_exception

2: xsr a3, EXCSAVE_1 # restore a3, excsave1
s32i a7, a2, PT_AREG7
xsr a3, EXCSAVE_1 # restore a3, excsave1

s32i a7, a2, PT_AREG7 # we need an additional register
movi a7, 4 # sizeof(unsigned int)
access_ok a0, a3, a7, a2, .Leac
access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp

_beqi a6, SYSXTENSA_ATOMIC_SET, .Lset
_beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
_beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd
addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1
_bgeui a6, SYS_XTENSA_COUNT - 1, .Lill
_bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp

/* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
/* Fall through for ATOMIC_CMP_SWP. */

.Lswp: /* Atomic compare and swap */

TRY l32i a7, a3, 0 # read old value
bne a7, a4, 1f # same as old value? jump
s32i a5, a3, 0 # different, modify value
movi a7, 1 # and return 1
j .Lret

1: movi a7, 0 # same values: return 0
j .Lret

.Ladd: /* Atomic add */
.Lexg: /* Atomic (exchange) add */
TRY l32i a0, a3, 0 # read old value
bne a0, a4, 1f # same as old value? jump
TRY s32i a5, a3, 0 # different, modify value
l32i a7, a2, PT_AREG7 # restore a7
l32i a0, a2, PT_AREG0 # restore a0
movi a2, 1 # and return 1
addi a6, a6, 1 # restore a6 (really necessary?)
rfe

TRY l32i a7, a3, 0
add a4, a4, a7
s32i a4, a3, 0
j .Lret
1: l32i a7, a2, PT_AREG7 # restore a7
l32i a0, a2, PT_AREG0 # restore a0
movi a2, 0 # return 0 (note that we cannot set
addi a6, a6, 1 # restore a6 (really necessary?)
rfe

.Lset: /* Atomic set */
.Lnswp: /* Atomic set, add, and exg_add. */

TRY l32i a7, a3, 0 # read old value as return value
s32i a4, a3, 0 # write new value
TRY l32i a7, a3, 0 # orig
add a0, a4, a7 # + arg
moveqz a0, a4, a6 # set
TRY s32i a0, a3, 0 # write new value

.Lret: mov a0, a2
mov a0, a2
mov a2, a7
l32i a7, a0, PT_AREG7
l32i a3, a0, PT_AREG3
l32i a0, a0, PT_AREG0
l32i a7, a0, PT_AREG7 # restore a7
l32i a0, a0, PT_AREG0 # restore a0
addi a6, a6, 1 # restore a6 (really necessary?)
rfe

CATCH
.Leac: movi a7, -EFAULT
j .Lret
.Leac: l32i a7, a2, PT_AREG7 # restore a7
l32i a0, a2, PT_AREG0 # restore a0
movi a2, -EFAULT
rfe

.Lill: l32i a7, a2, PT_AREG0 # restore a7
l32i a0, a2, PT_AREG0 # restore a0
movi a2, -EINVAL
rfe




Expand Down Expand Up @@ -1906,6 +1905,103 @@ ENTRY(fast_coprocessor)

#endif /* XCHAL_EXTRA_SA_SIZE */

/*
* System Calls.
*
* void system_call (struct pt_regs* regs, int exccause)
* a2 a3
*/

ENTRY(system_call)
entry a1, 32

/* regs->syscall = regs->areg[2] */

l32i a3, a2, PT_AREG2
mov a6, a2
movi a4, do_syscall_trace_enter
s32i a3, a2, PT_SYSCALL
callx4 a4

/* syscall = sys_call_table[syscall_nr] */

movi a4, sys_call_table;
movi a5, __NR_syscall_count
movi a6, -ENOSYS
bgeu a3, a5, 1f

addx4 a4, a3, a4
l32i a4, a4, 0
movi a5, sys_ni_syscall;
beq a4, a5, 1f

/* Load args: arg0 - arg5 are passed via regs. */

l32i a6, a2, PT_AREG6
l32i a7, a2, PT_AREG3
l32i a8, a2, PT_AREG4
l32i a9, a2, PT_AREG5
l32i a10, a2, PT_AREG8
l32i a11, a2, PT_AREG9

/* Pass one additional argument to the syscall: pt_regs (on stack) */
s32i a2, a1, 0

callx4 a4

1: /* regs->areg[2] = return_value */

s32i a6, a2, PT_AREG2
movi a4, do_syscall_trace_leave
mov a6, a2
callx4 a4
retw


/*
* Create a kernel thread
*
* int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
* a2 a2 a3 a4
*/

ENTRY(kernel_thread)
entry a1, 16

mov a5, a2 # preserve fn over syscall
mov a7, a3 # preserve args over syscall

movi a3, _CLONE_VM | _CLONE_UNTRACED
movi a2, __NR_clone
or a6, a4, a3 # arg0: flags
mov a3, a1 # arg1: sp
syscall

beq a3, a1, 1f # branch if parent
mov a6, a7 # args
callx4 a5 # fn(args)

movi a2, __NR_exit
syscall # return value of fn(args) still in a6

1: retw

/*
* Do a system call from kernel instead of calling sys_execve, so we end up
* with proper pt_regs.
*
* int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
* a2 a2 a3 a4
*/

ENTRY(kernel_execve)
entry a1, 16
mov a6, a2 # arg0 is in a6
movi a2, __NR_execve
syscall

retw

/*
* Task switch.
*
Expand Down Expand Up @@ -1964,33 +2060,9 @@ ENTRY(ret_from_fork)
movi a4, schedule_tail
callx4 a4

movi a4, do_syscall_trace
movi a4, do_syscall_trace_leave
mov a6, a1
callx4 a4

j common_exception_return



/*
* Table of syscalls
*/

.data
.align 4
.global sys_call_table
sys_call_table:

#define SYSCALL(call, narg) .word call
#include "syscalls.h"

/*
* Number of arguments of each syscall
*/

.global sys_narg_table
sys_narg_table:

#undef SYSCALL
#define SYSCALL(call, narg) .byte narg
#include "syscalls.h"

71 changes: 41 additions & 30 deletions trunk/arch/xtensa/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,36 +160,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
}


/*
* Create a kernel thread
*/

int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
long retval;
__asm__ __volatile__
("mov a5, %4\n\t" /* preserve fn in a5 */
"mov a6, %3\n\t" /* preserve and setup arg in a6 */
"movi a2, %1\n\t" /* load __NR_clone for syscall*/
"mov a3, sp\n\t" /* sp check and sys_clone */
"mov a4, %5\n\t" /* load flags for syscall */
"syscall\n\t"
"beq a3, sp, 1f\n\t" /* branch if parent */
"callx4 a5\n\t" /* call fn */
"movi a2, %2\n\t" /* load __NR_exit for syscall */
"mov a3, a6\n\t" /* load fn return value */
"syscall\n"
"1:\n\t"
"mov %0, a2\n\t" /* parent returns zero */
:"=r" (retval)
:"i" (__NR_clone), "i" (__NR_exit),
"r" (arg), "r" (fn),
"r" (flags | CLONE_VM)
: "a2", "a3", "a4", "a5", "a6" );
return retval;
}


/*
* These bracket the sleeping functions..
*/
Expand Down Expand Up @@ -452,3 +422,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
{
return dump_task_fpu(regs, current, r);
}

asmlinkage
long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void *child_tls,
void __user *child_tid, long a5,
struct pt_regs *regs)
{
if (!newsp)
newsp = regs->areg[1];
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
}

/*
* * xtensa_execve() executes a new program.
* */

asmlinkage
long xtensa_execve(char __user *name, char __user * __user *argv,
char __user * __user *envp,
long a3, long a4, long a5,
struct pt_regs *regs)
{
long error;
char * filename;

filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
// FIXME: release coprocessor??
error = do_execve(filename, argv, envp, regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
task_unlock(current);
}
putname(filename);
out:
return error;
}

Loading

0 comments on commit 3b3d721

Please sign in to comment.