Monday, May 05, 2008

blackfin system call

 /* Adam:

uclibc: syscall()
---> excpt 0;

HW: EVT3 --> trap()
jump _ex_table()->_ex_syscall;
--> raise 15;

HW: EVT15 --> evt_system_call()
call (real system call)
*/

uClibc/libc/sysdeps/linux/bfin/syscall.c:
------------------------------------------
long syscall(long sysnum, long a, long b, long c, long d, long e, long f)
{
int _r0 = 0;

__asm__ __volatile__ (
"R5 = %7;"
"R4 = %6;"
"R3 = %5;"
"R2 = %4;"
"R1 = %3;"
"R0 = %2;"
"P0 = %1;"
"excpt 0;"
"%0 = R0;"
: "=r" (_r0)
: "rm" (sysnum),
"rm" (a),
"rm" (b),
"rm" (c),
"rm" (d),
"rm" (e),
"rm" (f)
: "memory","CC","R0","R1","R2","R3","R4","R5","P0");

if (_r0 >= (unsigned long) -4095) {
(*__errno_location()) = (-_r0);
_r0 = (unsigned long) -1;
}

return (long)_r0;
}

/* Adam:
excpt 0;

The Force Exception instruction forces an exception with code uimm4.
When the EXCPT instruction is issued, the sequencer vectors to the excep-
tion handler that the user provides.

start_kernel()
---> trap_init()

setup_arch()
--> init_exception_vectors()
*/


mach-common/ints-priority.c:
-----------------------------
void __init init_exception_vectors(void)
{
SSYNC();

/* cannot program in software:
* evt0 - emulation (jtag)
* evt1 - reset
*/
bfin_write_EVT2(evt_nmi);
bfin_write_EVT3(trap);
bfin_write_EVT5(evt_ivhw);
bfin_write_EVT6(evt_timer);
bfin_write_EVT7(evt_evt7);
bfin_write_EVT8(evt_evt8);
bfin_write_EVT9(evt_evt9);
bfin_write_EVT10(evt_evt10);
bfin_write_EVT11(evt_evt11);
bfin_write_EVT12(evt_evt12);
bfin_write_EVT13(evt_evt13);
bfin_write_EVT14(evt14_softirq);
bfin_write_EVT15(evt_system_call);
CSYNC();
}

arch/blackfin/kernel/traps.c:
-----------------------------

/* Initiate the event table handler */
void __init trap_init(void)
{
CSYNC();
bfin_write_EVT3(trap);
CSYNC();
}

/* Adam:
EVT3: The 4th entry of event table is for exception.

"excpt 0;" will finally jump here:
*/
arch/blackfin/mach-common/entry.S:
------------------------------------

ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
/* Since the kernel stack can be anywhere, it's not guaranteed to be
* covered by a CPLB. Switch to an exception stack; use RETN as a
* scratch register (for want of a better option).
*/
EX_SCRATCH_REG = sp;
sp.l = _exception_stack_top;
sp.h = _exception_stack_top;
/* Try to deal with syscalls quickly. */
[--sp] = ASTAT;
[--sp] = (R7:6,P5:4);
r7 = SEQSTAT; /* reason code is in bit 5:0 */
r6.l = lo(SEQSTAT_EXCAUSE);
r6.h = hi(SEQSTAT_EXCAUSE);
r7 = r7 & r6;
p5.h = _ex_table;
p5.l = _ex_table;
p4 = r7;
p5 = p5 + (p4 << p4 =" [p5];" r7 =" -ENOSYS;" astat =" [sp++];" sp =" EX_SCRATCH_REG;" fp =" 0;" l =" lo(IPEND);" h =" hi(IPEND);" r0 =" [p2];" r0 =" rets;" r7 =" sp;" l =" lo(ALIGN_PAGE_MASK);" h =" hi(ALIGN_PAGE_MASK);" r7 =" r7" p2 =" r7;" p2 =" [p2];" r7 =" __NR_syscall;" r6 =" p0;" cc =" r6" r7 =" sp;" l =" lo(ALIGN_PAGE_MASK);" h =" hi(ALIGN_PAGE_MASK);" r7 =" r7" p2 =" r7;" r7 =" [p2+TI_FLAGS];" cc =" BITTST(r7,TIF_SYSCALL_TRACE);" p4 =" p0;" l =" _sys_call_table;" h =" _sys_call_table;" p5 =" p5" r0 =" [sp" r1 =" [sp" r2 =" [sp" p5 =" [p5];" r7 =" sp;" l =" lo(ALIGN_PAGE_MASK);" h =" hi(ALIGN_PAGE_MASK);" r7 =" r7">flags */
p5 = r7;
.Lresume_userspace_1:
/* Disable interrupts. */
[--sp] = reti;
reti = [sp++];

r7 = [p5 + TI_FLAGS];
r4.l = lo(_TIF_WORK_MASK);
r4.h = hi(_TIF_WORK_MASK);
r7 = r7 & r4;

.Lsyscall_resched:
cc = BITTST(r7, TIF_NEED_RESCHED);
if !cc jump .Lsyscall_sigpending;

/* Reenable interrupts. */
[--sp] = reti;
r0 = [sp++];

SP += -12;
call _schedule;
SP += 12;

jump .Lresume_userspace_1;

.Lsyscall_sigpending:
cc = BITTST(r7, TIF_RESTORE_SIGMASK);
if cc jump .Lsyscall_do_signals;
cc = BITTST(r7, TIF_SIGPENDING);
if !cc jump .Lsyscall_really_exit;
.Lsyscall_do_signals:
/* Reenable interrupts. */
[--sp] = reti;
r0 = [sp++];

r0 = sp;
SP += -12;
call _do_signal;
SP += 12;

.Lsyscall_really_exit:
r5 = [sp + PT_RESERVED];
rets = r5;
rts;
ENDPROC(_system_call)

Blog Archive