[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [microblaze-uclinux] Interrupts disabled in RETURN macro
Hi Alejandro,
Can you please post a diff? Much easier to scan quickly than the whole
file :)
Thanks,
John
Alejandro Lucero wrote:
> Hi John,
>
> I'm looking at the RETURN macro (entry.S) and I'd like to ask you why
> interrupts are disabled immediately. I think it's possible to delay it just
> until before POP_STATE since is here when the problematic r14 register is
> modified. In the current way scheduling is called without interrupts, the same
> with do_signal.
>
> Delaying disabling interrupts would improve interrupts latency since less code
> would be executed with interrupts disabled.
>
> I have tested this approach and it works even with high interrupts frequency.
> Perhaps I'm forgetting something and in this way some race condition can
> happen and it's hard to reproduce in my tests.
>
> With the ret_from_trap happens the same problem. BIPSET is used before RETURN
> so a lot of code is executed without interrupts when it could do it with
> them. To improve latencies the BIPSET could be delayed just until before
> POP_STATE and this BIPSET could be used by interrupts return too, instead of
> ENTRY_CLI. Some updates to IRQ RETURN, now rtbd instead of rtid, and adding
> interrupts enabled when saving PSW in SAVE_SYS_REGS_FOR_IRQ.
>
> The entry.S modified is attached.
>
> Can you (or someone else) see what I'm forgetting?
>
>
>
> ------------------------------------------------------------------------
>
> /*
> * arch/microblaze/kernel/entry.S -- Low-level system-call handling, trap handlers,
> * and context-switching
> *
> * Copyright (C) 2003 John Williams <jwilliams@xxxxxxxxxxxxxx>
> * Copyright (C) 2001,2002 NEC Corporation
> * Copyright (C) 2001,2002 Miles Bader <miles@xxxxxxx>
> *
> * 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.
> *
> * Written by Miles Bader <miles@xxxxxxx>
> * Heavily modified by John Williams for Microblaze
> */
>
> #include <linux/sys.h>
>
> #include <asm/entry.h>
> #include <asm/clinkage.h>
> #include <asm/current.h>
> #include <asm/processor.h>
> #include <asm/irq.h>
> #include <linux/config.h>
> #include <asm/exceptions.h>
>
> #include "microblaze_defs.h"
>
>
> /* Make a slightly more convenient alias for C_SYMBOL_NAME. */
> #define CSYM C_SYMBOL_NAME
>
> /* The offset of the struct pt_regs in a `state save frame' on the stack. */
> #define PTO STATE_SAVE_PT_OFFSET
>
> /* Standard way of enabling and disabling interrupts in entry.S */
> #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
> #define ENTRY_CLI(scratch_reg) \
> msrclr scratch_reg, 0x2; \
> nop;
>
> #define ENTRY_EI(scratch_reg) \
> msrset scratch_reg, 0x2; \
> nop;
>
> #else
>
> #define ENTRY_CLI(scratch_reg) \
> mfs scratch_reg, rmsr; \
> andi scratch_reg, scratch_reg, ~2; \
> mts rmsr, scratch_reg; \
> nop;
>
> #define ENTRY_EI(scratch_reg) \
> mfs scratch_reg, rmsr; \
> ori scratch_reg, scratch_reg, 2; \
> mts rmsr, scratch_reg; \
> nop;
> #endif
>
> /* Various ways of setting and clearing BIP in flags reg. This is mucky, but
> necessary */
> //#ifdef CONFIG_MICROBLAZE_BIPDIRECT
> #if 1
> /* using microblaze version that allows msr ops to write to BIP */
> #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
> #define BIPCLR(scratch_reg) \
> msrclr scratch_reg, 0x8; \
> nop;
>
> #define BIPSET(scratch_reg) \
> msrset scratch_reg, 0x8; \
> nop;
> #else
> #define BIPCLR(scratch_reg) \
> mfs scratch_reg, rmsr; \
> andi scratch_reg, scratch_reg, ~0x8; \
> mts rmsr, scratch_reg; \
> nop;
>
> #define BIPSET(scratch_reg) \
> mfs scratch_reg, rmsr; \
> ori scratch_reg, scratch_reg, 0x8; \
> mts rmsr, scratch_reg; \
> nop;
> #endif
> #else
> /* Older microblaze version that prevents direct access to BIP bit
> We hack around it using the rtbd and brki instructions */
> #define BIPCLR(scratch_reg) \
> rtbd r0, 1f; \
> nop; \
> 1:
>
> #define BIPSET(scratch_reg) \
> brki r0, 1f; \
> 1:
> #endif
>
> /* Standard macros to save and restore regs in the pt_regs struct pointed
> to by the stack pointer (r1) */
> #define SAVE_REG(reg_num) \
> swi macrology_paste(r,reg_num), r1, PTO+PT_GPR(reg_num);
>
> #define RESTORE_REG(reg_num) \
> lwi macrology_paste(r,reg_num), r1, PTO+PT_GPR(reg_num);
>
> /* Save argument registers to the struct pt_regs pointed to by EP. */
> #define SAVE_ARG_REGS \
> SAVE_REG(5); \
> SAVE_REG(6); \
> SAVE_REG(7); \
> SAVE_REG(8); \
> SAVE_REG(9); \
> SAVE_REG(10);
>
> /* Restore argument registers from the struct pt_regs pointed to by EP. */
> #define RESTORE_ARG_REGS \
> RESTORE_REG(5); \
> RESTORE_REG(6); \
> RESTORE_REG(7); \
> RESTORE_REG(8); \
> RESTORE_REG(9); \
> RESTORE_REG(10);
>
> /* Save value return registers to the struct pt_regs pointed to by EP. */
> #define SAVE_RVAL_REGS \
> SAVE_REG(3); \
> SAVE_REG(4);
>
> /* Restore value return registers from the struct pt_regs pointed to by EP. */
> #define RESTORE_RVAL_REGS \
> RESTORE_REG(3); \
> RESTORE_REG(4);
>
> #define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS
>
> #define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL \
> SAVE_REG(11); \
> SAVE_REG(12);
>
> #define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS
>
> #define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL \
> RESTORE_REG(11); \
> RESTORE_REG(12);
>
> /* Save `call clobbered' registers to the struct pt_regs pointed to by EP. */
> #define SAVE_CALL_CLOBBERED_REGS \
> SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
> SAVE_RVAL_REGS; \
> SAVE_ARG_REGS; \
> SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;
> /* Restore `call clobbered' registers from the struct pt_regs pointed to
> by EP. */
> #define RESTORE_CALL_CLOBBERED_REGS \
> RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
> RESTORE_RVAL_REGS; \
> RESTORE_ARG_REGS; \
> RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;
>
> /* Save `call clobbered' registers except for the return-value registers
> to the struct pt_regs pointed to by EP. */
> #define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \
> SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
> SAVE_ARG_REGS; \
> SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;
> /* Restore `call clobbered' registers except for the return-value registers
> from the struct pt_regs pointed to by EP. */
> #define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \
> RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
> RESTORE_ARG_REGS; \
> RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;
>
> #define ZERO_REG(reg_num) \
> add r ## reg_num, r0, r0;
>
> /* Zero `call clobbered' registers except for the return-value registers. */
> #define ZERO_CALL_CLOBBERED_REGS_NO_RVAL \
> ZERO_REG(11); ZERO_REG(12);
>
> /* Save `call saved' registers to the struct pt_regs pointed to by EP. */
> #define SAVE_CALL_SAVED_REGS \
> SAVE_REG(19); \
> SAVE_REG(20); \
> SAVE_REG(21); \
> SAVE_REG(22); \
> SAVE_REG(23); \
> SAVE_REG(24); \
> SAVE_REG(25); \
> SAVE_REG(26); \
> SAVE_REG(27); \
> SAVE_REG(28); \
> SAVE_REG(29); \
> SAVE_REG(30); \
> SAVE_REG(31);
>
> /* Restore `call saved' registers from the struct pt_regs pointed to by EP. */
> #define RESTORE_CALL_SAVED_REGS \
> RESTORE_REG(19); \
> RESTORE_REG(20); \
> RESTORE_REG(21); \
> RESTORE_REG(22); \
> RESTORE_REG(23); \
> RESTORE_REG(24); \
> RESTORE_REG(25); \
> RESTORE_REG(26); \
> RESTORE_REG(27); \
> RESTORE_REG(28); \
> RESTORE_REG(29); \
> RESTORE_REG(30); \
> RESTORE_REG(31);
>
>
> /* Save link register into state save frame */
> #define SAVE_LINK(linkreg) \
> swi linkreg, r1, PTO+PT_PC; /* PC, before IRQ/trap /*
>
> /* Restore saved PC into desired return link register */
> #define RESTORE_LINK(linkreg) \
> lwi linkreg, r1, PTO+PT_PC; /* PC, before IRQ/trap /*
>
> /* Save a special reg into saved state frame */
> #define SAVE_SPECIAL(reg,OFFS) \
> mfs r11, r ## reg; \
> swi r11, r1, PTO+PT_ ## OFFS;
>
> /* Restore a special reg from saved state frame */
> #define RESTORE_SPECIAL(reg,OFFS) \
> lwi r11, r1, PTO+PT_ ## OFFS; \
> mts r ## reg , r11;
>
> /* Save processor status word into saved state frame */
> #define SAVE_PSW \
> SAVE_SPECIAL(msr,PSW)
>
> /* Restore processor status word from saved state frame */
> #define RESTORE_PSW \
> RESTORE_SPECIAL(msr,PSW)
>
> /* Save system registers to the struct pt_regs pointed to by REG.
> r11 is clobbered. */
> #define SAVE_SYS_REGS_FOR_IRQ \
> SAVE_REG(17); \
> SAVE_LINK(r14); \
> mfs r11, rmsr; \
> ori r11, r11, 0xa; /* Needed for RTLinux */ \
> swi r11, r1, PTO+PT_PSW;
>
> /* Restore system registers from the struct pt_regs pointed to by EP.
> clobber r14 to restore status register, it gets fixed immediately */
> #define RESTORE_SYS_REGS_FOR_IRQ \
> RESTORE_REG(17); \
> RESTORE_PSW; \
> RESTORE_LINK(r14);
>
> /* Save system registers to the struct pt_regs pointed to by REG.
> r11 is clobbered. */
> #define SAVE_SYS_REGS_FOR_TRAP \
> SAVE_REG(17); \
> SAVE_LINK(r14); \
> mfs r11, rmsr; \
> ori r11, r11, 0xa; /* Needed for RTLinux */ \
> swi r11, r1, PTO+PT_PSW;
>
>
> /* Restore system registers from the struct pt_regs pointed to by EP.
> clobber r11 to restore status register */
> #define RESTORE_SYS_REGS_FOR_TRAP \
> RESTORE_REG(17); \
> RESTORE_PSW; \
> RESTORE_LINK(r14);
>
> /* Save system registers to the struct pt_regs pointed to by REG.
> r11 is clobbered. */
> #define SAVE_SYS_REGS_FOR_DBTRAP \
> SAVE_REG(17); \
> SAVE_LINK(r14); \
> SAVE_PSW;
>
> /* Restore system registers from the struct pt_regs pointed to by EP.
> clobber r11 to restore status register */
> #define RESTORE_SYS_REGS_FOR_DBTRAP \
> RESTORE_REG(17); \
> RESTORE_PSW; \
> RESTORE_LINK(r14);
>
> /* Save system registers to the struct pt_regs pointed to by REG. This is a
> NMI-specific version, because NMIs save the PC/PSW in a different place
> than other interrupt requests. r11 is clobbered. */
> #define SAVE_SYS_REGS_FOR_NMI \
> SAVE_LINK(r16); \
> SAVE_PSW;
>
> /* Restore system registers from the struct pt_regs pointed to by EP. This is
> a NMI-specific version, because NMIs save the PC/PSW in a different place
> than other interrupt requests. r11 is clobbered (it is used as a scratch
> register because the POP_STATE macro restores it, and this macro is usually
> used inside POP_STATE). */
> #define RESTORE_SYS_REGS_FOR_NMI \
> RESTORE_PSW; \
> RESTORE_LINK(r16);
>
> /* Push register state, except for the stack pointer, on the stack in the form
> of a struct pt_regs, in preparation for a system call. This macro makes
> sure that `special' registers, system registers; TYPE identifies the set of
> extra registers to be saved as well. EP is clobbered.
> Uses add(i)k to prevent corrupting carry flags prior to them being saved */
> #ifdef CONFIG_REGISTER_TASK_PTR
> #define PUSH_STATE(type) \
> addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ \
> SAVE_REG(2); /* Save SDA */ \
> SAVE_REG(13); /* Save SDA2 */ \
> SAVE_REG(15); /* Save LP */ \
> SAVE_REG(18); /* Save asm scratch reg */ \
> SAVE_REG(CURRENT_TASK_REGNUM); /* Save current task reg */ \
> type ## _STATE_SAVER;
> #else
> #define PUSH_STATE(type) \
> addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ \
> SAVE_REG(2); /* Save SDA */ \
> SAVE_REG(13); /* Save SDA2 */ \
> SAVE_REG(15); /* Save LP */ \
> SAVE_REG(18); /* Save asm scratch reg */ \
> type ## _STATE_SAVER;
> #endif
>
> /* Pop a register state, except for the stack pointer, from the struct pt_regs
> on the stack. */
> #ifdef CONFIG_REGISTER_TASK_PTR
> #define POP_STATE(type) \
> type ## _STATE_RESTORER; \
> RESTORE_REG(2); /* Restore SDA */ \
> RESTORE_REG(13); /* Restore SDA2 */ \
> RESTORE_REG(15); /* Restore LP */ \
> RESTORE_REG(18); /* Restore asm scratch reg */ \
> RESTORE_REG(CURRENT_TASK_REGNUM); /* Restore cur task reg */ \
> addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
> #else
> #define POP_STATE(type) \
> type ## _STATE_RESTORER; \
> RESTORE_REG(2); /* Restore SDA */ \
> RESTORE_REG(13); /* Restore SDA2 */ \
> RESTORE_REG(15); /* Restore LP */ \
> RESTORE_REG(18); /* Restore asm scratch reg */ \
> addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
> #endif
>
>
> /* Switch to the kernel stack if necessary, and push register state on
> the stack in the form of a struct pt_regs. Also load the current
> task pointer if switching from user mode. The stack-pointer (r3)
> should have already been saved to the memory location SP_SAVE_LOC
> (the reason for this is that the interrupt vectors may be beyond a
> 22-bit signed offset jump from the actual interrupt handler, and this
> allows them to save the stack-pointer and use that register to do an
> indirect jump). This macro makes sure that `special' registers,
> system registers, and the stack pointer are saved; TYPE identifies
> the set of extra registers to be saved as well. SYSCALL_NUM is the
> register in which the system-call number this state is for is stored
> (r0 if this isn't a system call). Interrupts should already be
> disabled when calling this. */
> #define SAVE_STATE(type, syscall_num, sp_save_loc) \
> swi r11, r0, R11_SAVE; /* Save r11 */ \
> lwi r11, r0, KM; /* See if already in kernel mode. */ \
> beqi r11, 1f; /* Jump ahead if coming from user */ \
> lwi r11, r0, R11_SAVE; /* restore r11 */ \
> /* Kernel-mode state save. */ \
> lwi r1, r0, sp_save_loc; /* Reload kernel stack-pointer. */ \
> swi r1, r1, (PT_GPR(GPR_SP)-PT_SIZE); /* Save original SP. */ \
> PUSH_STATE(type); \
> addi r11, r0, 1; /* Was in kernel-mode. */ \
> swi r11, r1, PTO+PT_KERNEL_MODE; \
> brid 2f; \
> nop; /* Fill delay slot */ \
> 1: /* User-mode state save. */ \
> lwi r11, r0, R11_SAVE; /* restore r11 */ \
> lwi r1, r0, KSP; /* Switch to kernel stack. */ \
> PUSH_STATE(type); \
> swi r0, r1, PTO+PT_KERNEL_MODE; /* Was in user-mode. */ \
> lwi r11, r0, sp_save_loc; \
> swi r11, r1, PTO+PT_GPR(GPR_SP); /* Store user SP. */ \
> addi r11, r0, 1; \
> swi r11, r0, KM; /* Now we're in kernel-mode. */ \
> GET_CURRENT_TASK(CURRENT_TASK); /* Update the current task pointer.*/ \
> 2: /* Save away the syscall number. */ \
> swi syscall_num, r1, PTO+PT_SYSCALL
>
>
> /* Save register state not normally saved by PUSH_STATE for TYPE. */
> #define SAVE_EXTRA_STATE(type) \
> type ## _EXTRA_STATE_SAVER;
>
> /* Restore register state not normally restored by POP_STATE for TYPE. */
> #define RESTORE_EXTRA_STATE(type) \
> type ## _EXTRA_STATE_RESTORER;
>
> /* Save any call-clobbered registers not normally saved by PUSH_STATE
> for TYPE. */
> #define SAVE_EXTRA_STATE_FOR_FUNCALL(type) \
> type ## _FUNCALL_EXTRA_STATE_SAVER;
>
> /* Restore any call-clobbered registers not normally restored by POP_STATE for
> TYPE. */
> #define RESTORE_EXTRA_STATE_FOR_FUNCALL(type) \
> type ## _FUNCALL_EXTRA_STATE_RESTORER;
>
>
> /* These are extra_state_saver/restorer values for a user trap. Note that we
> save the argument registers so that restarted syscalls will function
> properly (otherwise it wouldn't be necessary), and we must _not_ restore
> the return-value registers (so that traps can return a value!), but there
> are various options for what happens to other call-clobbered registers,
> selected by preprocessor conditionals. */
>
> #if TRAPS_PRESERVE_CALL_CLOBBERED_REGS
>
> /* Traps save/restore all call-clobbered registers (except for rval regs). */
> #define TRAP_STATE_SAVER \
> SAVE_CALL_CLOBBERED_REGS_NO_RVAL; \
> SAVE_SYS_REGS_FOR_TRAP
>
> #define TRAP_STATE_RESTORER \
> RESTORE_CALL_CLOBBERED_REGS_NO_RVAL; \
> RESTORE_SYS_REGS_FOR_TRAP
>
> #else /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
>
> /* Traps don't save call-clobbered registers (but do still save arg regs). */
> #define TRAP_STATE_SAVER \
> SAVE_ARG_REGS; \
> SAVE_SYS_REGS_FOR_TRAP
>
> #if TRAPS_ZERO_CALL_CLOBBERED_REGS
>
> /* Traps zero call-clobbered registers (except for arg/rval regs) before
> returning from a system call, to avoid any internal values from leaking out
> of the kernel. */
> #define TRAP_STATE_RESTORER \
> ZERO_CALL_CLOBBERED_REGS_NO_ARGS_NO_RVAL; \
> RESTORE_ARG_REGS; \
> RESTORE_SYS_REGS_FOR_TRAP
>
> #else /* !TRAPS_ZERO_CALL_CLOBBERED_REGS */
>
> /* When traps return, they just leave call-clobbered registers (except for arg
> regs) with whatever value they have from the kernel. */
> #define TRAP_STATE_RESTORER \
> RESTORE_ARG_REGS; \
> RESTORE_SYS_REGS_FOR_TRAP
>
> #endif /* TRAPS_ZERO_CALL_CLOBBERED_REGS */
> #endif /* TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
>
> /* Save registers not normally saved by traps. */
> #define TRAP_EXTRA_STATE_SAVER \
> SAVE_RVAL_REGS; \
> SAVE_CALL_SAVED_REGS
> #define TRAP_EXTRA_STATE_RESTORER \
> RESTORE_RVAL_REGS; \
> RESTORE_CALL_SAVED_REGS
> #define TRAP_FUNCALL_EXTRA_STATE_SAVER \
> SAVE_RVAL_REGS
> #define TRAP_FUNCALL_EXTRA_STATE_RESTORER \
> RESTORE_RVAL_REGS
>
> /* Save registers not normally saved by traps. */
> /* DBTRAP saves everything on entry, so nothing "extra" to save */
> #define DBTRAP_EXTRA_STATE_SAVER
> #define DBTRAP_EXTRA_STATE_RESTORER
>
> #define DBTRAP_FUNCALL_EXTRA_STATE_SAVER
> #define DBTRAP_FUNCALL_EXTRA_STATE_RESTORER
>
> /* The PTRACE syscall expects the entire PT_REGS struct to be correct, so no
> optimisations allows - we must save all registers immediately upon entry */
> #define DBTRAP_STATE_SAVER \
> SAVE_CALL_SAVED_REGS; \
> SAVE_CALL_CLOBBERED_REGS; \
> SAVE_SYS_REGS_FOR_DBTRAP
>
> #define DBTRAP_STATE_RESTORER \
> RESTORE_CALL_SAVED_REGS; \
> RESTORE_SYS_REGS_FOR_DBTRAP; \
> RESTORE_CALL_CLOBBERED_REGS
>
>
> /* Register saving/restoring for maskable interrupts. */
> #define IRQ_STATE_SAVER \
> SAVE_CALL_CLOBBERED_REGS; \
> SAVE_SYS_REGS_FOR_IRQ
>
> #define IRQ_STATE_RESTORER \
> RESTORE_SYS_REGS_FOR_IRQ \
> RESTORE_CALL_CLOBBERED_REGS;
>
> #define IRQ_EXTRA_STATE_SAVER \
> SAVE_CALL_SAVED_REGS
>
> #define IRQ_EXTRA_STATE_RESTORER \
> RESTORE_CALL_SAVED_REGS
>
> #define IRQ_FUNCALL_EXTRA_STATE_SAVER /* nothing */
>
> #define IRQ_FUNCALL_EXTRA_STATE_RESTORER /* nothing */
>
> /* Register saving/restoring for non-maskable interrupts. */
> #define NMI_STATE_SAVER \
> SAVE_CALL_CLOBBERED_REGS; \
> SAVE_SYS_REGS_FOR_NMI
>
> #define NMI_STATE_RESTORER \
> RESTORE_CALL_CLOBBERED_REGS; \
> RESTORE_SYS_REGS_FOR_NMI
>
> #define NMI_EXTRA_STATE_SAVER \
> SAVE_CALL_SAVED_REGS
>
> #define NMI_EXTRA_STATE_RESTORER \
> RESTORE_CALL_SAVED_REGS
>
> #define NMI_FUNCALL_EXTRA_STATE_SAVER /* nothing */
>
> #define NMI_FUNCALL_EXTRA_STATE_RESTORER /* nothing */
>
> /* Register saving/restoring for a context switch. We don't need to save too
> many registers, because context-switching looks like a function call (via
> the function `switch_thread'), so callers will save any call-clobbered
> registers themselves. The stack pointer and return value are handled by
> switch_thread itself. */
> #define SWITCH_STATE_SAVER \
> SAVE_CALL_SAVED_REGS \
> SAVE_PSW
>
> #define SWITCH_STATE_RESTORER \
> RESTORE_CALL_SAVED_REGS \
> RESTORE_PSW
>
> /* Instructions to return from an IRQ */
> #define IRQ_RETURN_INST \
> rtbd r14, 0; /* Follow interrupt link pointer back to */ \
> /* next insn after interrupt occured */ \
> nop; /* Delay slot */
>
> /* Instructions to return from a trap */
> /* Note we use rtbd to clear BIP bit on way out */
> /* Return offset is 4, to execute instruction after syscall brki insn*/
> #define TRAP_RETURN_INST \
> rtbd r14, 4; /* r14 used as trap link register */ \
> nop;
>
> /* Instructions to return from a debug trap */
> /* Note we use rtbd to clear BIP bit on exit */
> /* Return offset is zero, to ensure trapped instruction is re-executed */
> #define DBTRAP_RETURN_INST \
> rtbd r14, 0; /* r14 used as trap link register */ \
> nop;
>
> /* Code fragment to return from NMI */
> #define NMI_RETURN_INST \
> rtbd r16, 8; /* r16 is NMI (brk) link register */ \
> nop;
>
> /* Restore register state from the struct pt_regs on the stack, switch back
> to the user stack if necessary, and return from the trap/interrupt.
> EXTRA_STATE_RESTORER is a sequence of assembly language statements to
> restore anything not restored by this macro. Only registers not saved by
> the C compiler are restored (that is, R1(sp), R2(gp), R15(lp), and
> anything restored by EXTRA_STATE_RESTORER). */
> #define RETURN(type) \
> lwi r11, r1, PTO+PT_KERNEL_MODE; \
> bnei r11, 2f; /* See if returning to kernel mode, */\
> /* ... if so, skip resched &c. */ \
> \
> /* We're returning to user mode, so check for various conditions that \
> trigger rescheduling. */ \
> /* Get current task ptr into r11 */ \
> RETRIEVE_CURRENT_TASK(r11); \
> lwi r11, r11, TASK_NEED_RESCHED; \
> bnei r11, 3f; /* Call the scheduler */ \
> \
> /* XXX Is PT_DTRACE handling needed here? */ \
> /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here. */ \
> \
> /* Maybe handle a signal */ \
> 5: RETRIEVE_CURRENT_TASK(r11); \
> lwi r11, r11, TASK_SIGPENDING; \
> bnei r11, 4f; /* Signals to handle, handle them */ \
> \
> RETRIEVE_CURRENT_TASK(r11); \
> lwi r11, r11, TASK_PTRACE; \
> bnei r11, 4f; /* Signals to handle, handle them */ \
> \
> /* Finally, return to user state. */ \
> 1: BIPSET(r11); \
> swi r0, r0, KM; /* Now officially in user state. */ \
> POP_STATE(type); \
> swi r1, r0, KSP; /* Save the kernel stack pointer. */ \
> lwi r1, r1, PT_GPR(GPR_SP)-PT_SIZE; \
> /* Restore user stack pointer. */ \
> bri 6f; \
> \
> /* Return to kernel state. */ \
> 2: BIPSET(r11); \
> POP_STATE(type); \
> 6: \
> type ## _return: /* Make global symbol for debugging */ \
> type ## _RETURN_INST \
> \
> /* Call the scheduler before returning from a syscall/trap. */ \
> 3: SAVE_EXTRA_STATE_FOR_FUNCALL(type); /* Prepare for funcall. */ \
> bralid r15, CSYM(schedule); /* Call scheduler */ \
> nop; /* delay slot */ \
> RESTORE_EXTRA_STATE_FOR_FUNCALL(type); \
> brid 5b; /* Back to continue return processing */ \
> nop; \
> \
> /* Handle a signal return; Pending signals should be in r18. */ \
> 4: /* Not all registers are saved by the normal trap/interrupt entry \
> points (for instance, call-saved registers (because the normal \
> C-compiler calling sequence in the kernel makes sure they're \
> preserved), and call-clobbered registers in the case of \
> traps), but signal handlers may want to examine or change the \
> complete register state. Here we save anything not saved by \
> the normal entry sequence, so that it may be safely restored \
> (in a possibly modified form) after do_signal returns. */ \
> SAVE_EXTRA_STATE(type) /* Save state not saved by entry. */ \
> la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ \
> add r6, r0, r0; /* Arg 2: sigset_t *oldset */ \
> bralid r15, CSYM(do_signal); /* Handle any signals */ \
> nop; \
> RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \
> brid 1b; \
> nop;
>
>
> /* Jump to the appropriate function for the system call number in r12
> (r12 is not preserved), or return an error if r12 is not valid. The
> LP register should point to the location where the called function
> should return. [note that MAKE_SYS_CALL uses label 1] */
> #define MAKE_SYS_CALL \
> /* See if the system call number is valid. */ \
> addi r11, r12, -NR_syscalls; \
> bgei r11,1f; \
> /* Figure out which function to use for this system call. */ \
> /* Note Microblaze barrel shift is optional, so don't rely on it */ \
> add r12, r12, r12; /* convert num -> ptr */ \
> add r12, r12, r12; \
> lwi r12, r12, CSYM(sys_call_table); /* Get function pointer */ \
> /* Make the system call. */ \
> bra r12; \
> /* The syscall number is invalid, return an error. */ \
> 1: addi r3, r0, -ENOSYS; \
> rtsd r15,8; /* looks like a normal subroutine return */
>
>
> // Ugly kludge to get around some Xilinx mb-gcc wierdness
> .data
> .globl CSYM(_shift_temp_loc)
> CSYM(_shift_temp_loc):
> .long 0
>
> .text
>
> /*
> * User trap.
> *
> * System calls are handled here.
> *
> * Syscall protocol:
> * Syscall number in r12, args in r5-r10
> * Return value in r3
> *
> * Trap entered via brki instruction, so BIP bit is set, and interrupts
> * are masked. This is nice, means we don't have to CLI before state save
> */
> G_ENTRY(trap):
> swi r1, r0, ENTRY_SP; // save stack (emulate v850)
> SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
> BIPCLR(r11); // Clear BIP
> // BIP now cleared, interrupts enabled
> la r15, r0, ret_from_trap-8// where the trap should return
> // need -8 to adjust for rtsd r15, 8
> MAKE_SYS_CALL // Jump to the syscall function.
> END(trap)
>
> /* This is just like ret_from_trap, but first restores extra registers
> saved by some wrappers. */
> L_ENTRY(restore_extra_regs_and_ret_from_trap):
> RESTORE_EXTRA_STATE(TRAP)
> // fall through
> END(restore_extra_regs_and_ret_from_trap)
>
> /* Entry point used to return from a syscall/trap. */
> /* We re-enable BIP bit before state restore */
> L_ENTRY(ret_from_trap):
> RETURN(TRAP)
> END(ret_from_trap)
>
> /* This the initial entry point for a new child thread, with an appropriate
> stack in place that makes it look the the child is in the middle of an
> syscall. This function is actually `returned to' from switch_thread
> (copy_thread makes ret_from_fork the return address in each new thread's
> saved context). */
> C_ENTRY(ret_from_fork):
> bralid r15, CSYM(schedule_tail); // ...which is schedule_tail's arg
> add r3, r5, r0; // switch_thread returns the prev task.
> // ( in the delay slot )
> add r3, r0, r0; // Child's fork call should return 0.
> brid ret_from_trap // Do normal trap return.
> nop;
> C_END(ret_from_fork)
>
>
> #if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS
> // Make sure r13 and r14 are preserved, in case we have to restart a
> // system call because of a signal (ep has already been set by caller).
> //st.w r13, PTO+PT_GPR(13)[sp]
> //st.w r14, PTO+PT_GPR(13)[sp]
> la r15, r0, ret_from_long_syscall-8
> #endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
>
> MAKE_SYS_CALL // Jump to the syscall function.
> END(syscall_long)
>
> #if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS
> /* Entry point used to return from a long syscall. Only needed to restore
> r13/r14 if the general trap mechanism doesnt' do so. */
> L_ENTRY(ret_from_long_syscall):
> //ld.w PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
> //ld.w PTO+PT_GPR(13)[sp], r14
> brid ret_from_trap; // The rest is the same as other traps
> nop;
> END(ret_from_long_syscall)
> #endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
>
>
> /* These syscalls need access to the struct pt_regs on the stack, so we
> implement them in assembly (they're basically all wrappers anyway). */
>
> L_ENTRY(sys_fork_wrapper):
> #ifdef NO_MM
> // fork almost works, enough to trick you into looking elsewhere :-(
> addi r3, r0, -EINVAL
> rtsd r15, 8;
> #else
> // Save state not saved by entry. This is actually slight overkill;
> // it's actually only necessary to save any state restored by
> // switch_thread that's not saved by the trap entry.
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> addi r5, r0, SIGCHLD // Arg 0: flags
> lwi r6, r1, PTO+PT_GPR(GPR_SP) // Arg 1: child SP (use parent's)
> la r7, r1, PTO; // Arg 2: parent context
> add r9. r0, r0; // Arg 3: (unused)
> brid CSYM(do_fork) // Do real work (tail-call).
> nop;
> #endif
> END(sys_fork_wrapper)
>
> L_ENTRY(sys_vfork_wrapper):
> // Save state not saved by entry. This is actually slight overkill;
> // it's actually only necessary to save any state restored by
> // switch_thread that's not saved by the trap entry.
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> addi r5, r0, CLONE_VFORK | CLONE_VM | SIGCHLD // Arg 0: flags
> lwi r6, r1, PTO+PT_GPR(GPR_SP) // Arg 1: child SP (use parent's)
> la r7, r1, PTO; // Arg 2: parent context
> add r8, r0, r0; // Arg 3: (unused)
> brid CSYM(do_fork) // Do real work (tail-call).
> nop
> END(sys_vfork_wrapper)
>
> L_ENTRY(sys_clone_wrapper):
> // Save state not saved by entry. This is actually slight overkill;
> // it's actually only necessary to save any state restored by
> // switch_thread that's not saved by the trap entry.
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> bnei r6, 1f; // See if child SP arg (arg 1) is 0.
> lwi r6, r1, PTO+PT_GPR(GPR_SP); // If so, use paret's stack ptr
> 1: la r7, r1, PTO; // Arg 2: parent context
> add r8, r0, r0; // Arg 3: (unused)
> brid CSYM(do_fork) // Do real work (tail-call).
> nop;
> END(sys_clone_wrapper)
>
> L_ENTRY(sys_execve_wrapper):
> la r8, r1, PTO; // add user context as 4th arg
> brid CSYM(sys_execve); // Do real work (tail-call).
> nop;
> END(sys_execve_wrapper)
>
> L_ENTRY(sys_sigsuspend_wrapper):
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> la r6, r1, PTO; // add user context as 2nd arg
> bralid r15, CSYM(sys_sigsuspend); // Do real work.
> nop;
> brid restore_extra_regs_and_ret_from_trap;
> nop;
> END(sys_sigsuspend_wrapper)
>
> L_ENTRY(sys_rt_sigsuspend_wrapper):
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> la r7, r1, PTO; // add user context as 3rd arg
> brlid r15, CSYM(sys_rt_sigsuspend); // Do real work.
> nop;
> brid restore_extra_regs_and_ret_from_trap;
> nop;
> END(sys_rt_sigsuspend_wrapper)
>
> L_ENTRY(sys_sigreturn_wrapper):
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> la r5, r1, PTO; // add user context as 1st arg
> brlid r15, CSYM(sys_sigreturn); // Do real work.
> nop;
> brid restore_extra_regs_and_ret_from_trap;
> nop;
> END(sys_sigreturn_wrapper)
>
> L_ENTRY(sys_rt_sigreturn_wrapper):
> SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
> la r5, r1, PTO; // add user context as 1st arg
> brlid r15, CSYM(sys_rt_sigreturn) // Do real work.
> nop;
> brid restore_extra_regs_and_ret_from_trap;
> nop;
> END(sys_rt_sigreturn_wrapper)
>
>
> /*
> * Hardware maskable interrupts.
> *
> * The stack-pointer (r1) should have already been saved to the memory
> * location ENTRY_SP.
> * Currently this is just because the v850 code does it. This should
> * be removed at some point to streamline things
> */
> G_ENTRY(irq):
> swi r1, r0, ENTRY_SP; // save stack (emulate v850)
> swi r11, r0, 0x554;
> swi r12, r0, 0x558;
> lwi r11, r0, 0x41200018; // first param irq number
> bgti r11, 4f;
> lwi r11, r0, 0x41c00008;
> lwi r12, r0, 0x41c00004;
> rsub r11, r12, r11;
> swi r11, r0, 0x570;
> lwi r12, r0, 0x574;
> rsub r11, r11, r12;
> bgti r11, 4f;
> lwi r11, r0, 0x570;
> swi r11, r0, 0x574;
> 4:
> lwi r12, r0, 0x558;
> lwi r11, r0, 0x554;
>
> SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
>
> add r5, r0, r0; // Clear first param
> la r6, r1, PTO; // User regs are arg2
>
> // It's up to the high level handler to query the
> // interrupt controller and get the IRQ number etc
>
> // Call the high-level interrupt handling code.
> bralid r15, CSYM(handle_irq);
> nop;
>
> // fall through
>
> /* Entry point used to return from an interrupt (also used by exception
> handle
> s, below). */
> ret_from_irq:
> RETURN(IRQ)
> END(irq)
>
>
> /*
> * Hardware non-maskable interrupts.
> *
> * The stack-pointer (r1) should have already been saved to the memory
> * location ENTRY_SP (the reason for this is that the interrupt vectors may be
> * beyond a 22-bit signed offset jump from the actual interrupt handler, and
> * this allows them to save the stack-pointer and use that register to do an
> * indirect jump).
> */
> G_ENTRY(nmi):
> swi r1, r0, NMI_ENTRY_SP; /* Save state (emulate v850) */
> SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers. */
>
> add r5, r0, r0;
> la r6, r1, PTO; /* User regs are arg2. */
>
> /* Non-maskable interrupts always lie right after maskable interrupts.
> Call the generic IRQ handler, with two arguments, the IRQ number,
> and a pointer to the user registers, to handle the specifics.
> (we subtract one because the first NMI has code 1). */
> bralid r15, CSYM(handle_irq);
> nop;
>
> RETURN(NMI)
> END(nmi0)
>
>
> /*
> * Illegal instruction trap.
> *
> * The stack-pointer (r3) should have already been saved to the memory
> * location ENTRY_SP (the reason for this is that the interrupt vectors may be
> * beyond a 22-bit signed offset jump from the actual interrupt handler, and
> * this allows them to save the stack-pointer and use that register to do an
> * indirect jump).
> */
> G_ENTRY(illegal_instruction):
> swi r1, r0, ENTRY_SP; // Save stack (emulate v850)
> SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
> ENTRY_EI(r11);
> addi r5, r0, SIGILL; // Arg 0: signal number
> RETRIEVE_CURRENT_TASK(r6); // Arg 1: task
> la r15, r0, ret_from_irq-8 // where the handler should return
> brid CSYM(force_sig);
> nop;
>
> END(illegal_instruction)
>
>
> /*
> * `Debug' trap
> * We enter dbtrap in "BIP" (breakpoint) mode.
> * So we exit the breakpoint mode with an 'rtbd' and proceed with the
> * original dbtrap.
> * however, wait to save state first
> */
> G_ENTRY(dbtrap):
> /* BIP bit is set on entry, no interrupts can occur */
> swi r1, r0, ENTRY_SP; // Save stack (emulate v850)
> SAVE_STATE (DBTRAP, r0, ENTRY_SP) // Save registers.
> BIPCLR(r11);
> /* BIP bit now clear, interrupts can occur */
> // Should insert code to detect illegal traps etc
>
> addi r5, r0, SIGTRAP; // send the trap signal
> RETRIEVE_CURRENT_TASK(r6); // to the current task
> brlid r15, CSYM(send_sig);
> add r7, r0, r0; // 3rd param zero (delay slot)
>
> BIPSET(r11); /* Set BIP again, ready for state restore */
> RETURN(DBTRAP);
>
> END(dbtrap)
>
> G_ENTRY(reset_trap):
>
> /* BIP bit is set on entry, no interrupts can occur */
> swi r1, r0, ENTRY_SP; // Save stack (emulate v850)
> SAVE_STATE (DBTRAP, r0, ENTRY_SP) // Save registers.
> BIPCLR(r11);
>
> // For now, call into kernel for debugging
> brlid r15, CSYM(debug_trap);
> la r5, r1, PTO
> // And loop forever! */
> foo: brid foo
> nop
> END(reset_trap)
>
> /*
> * Trap with no handler
> */
> L_ENTRY(bad_trap_wrapper):
> add r5, r0, r19; // Arg 0: trap number
> la r6, r1, PTO; // Arg 1: user regs
> brid CSYM(bad_trap); // tail call handler
> nop;
>
> END(bad_trap_wrapper)
>
> /*
> * This is where we switch between two threads. The arguments are:
> * r5 -- pointer to the struct thread for the `current' process
> * r6 -- pointer to the struct thread for the `new' process.
> * when this function returns, it will return to the new thread.
> */
> C_ENTRY(switch_thread):
>
> // Return the previous task
> // Do this before push_state, so that return value is on stack
> // Update the current task pointer
> //GET_CURRENT_TASK(CURRENT_TASK)
> RETRIEVE_CURRENT_TASK(r3);
>
> // First, push the current processor state on the stack
> PUSH_STATE(SWITCH)
>
> // Now save the location of the kernel stack pointer for this thread;
> // since we've pushed all other state on the stack, this is enough to
> // restore it all later.
> swi r1, r5, THREAD_KSP;
> // Now restore the stack pointer from the new process
> lwi r1, r6, THREAD_KSP;
> // ... and restore all state from that
> POP_STATE(SWITCH)
> // Update the current task pointer
> GET_CURRENT_TASK(CURRENT_TASK)
> // Now return into the new thread
> rtsd r15,8;
> nop;
> C_END(switch_thread)
>
> .section .rodata
>
> .align 4
> .globl CSYM(sys_call_table)
> CSYM(sys_call_table):
> .long CSYM(sys_ni_syscall) // 0 - old "setup()" system call
> .long CSYM(sys_exit)
> .long sys_fork_wrapper
> .long CSYM(sys_read)
> .long CSYM(sys_write)
> .long CSYM(sys_open) // 5
> .long CSYM(sys_close)
> .long CSYM(sys_waitpid)
> .long CSYM(sys_creat)
> .long CSYM(sys_link)
> .long CSYM(sys_unlink) // 10
> .long sys_execve_wrapper
> .long CSYM(sys_chdir)
> .long CSYM(sys_time)
> .long CSYM(sys_mknod)
> .long CSYM(sys_chmod) // 15
> .long CSYM(sys_chown16)
> .long CSYM(sys_ni_syscall) // was: break
> .long CSYM(sys_ni_syscall) // was: oldstat (aka stat)
> .long CSYM(sys_lseek)
> .long CSYM(sys_getpid) // 20
> .long CSYM(sys_mount)
> .long CSYM(sys_oldumount)
> .long CSYM(sys_setuid16)
> .long CSYM(sys_getuid16)
> .long CSYM(sys_stime) // 25
> .long CSYM(sys_ptrace)
> .long CSYM(sys_alarm)
> .long CSYM(sys_ni_syscall) // was: oldfstat (aka fstat)
> .long CSYM(sys_pause)
> .long CSYM(sys_utime) // 30
> .long CSYM(sys_ni_syscall) // was: stty
> .long CSYM(sys_ni_syscall) // was: gtty
> .long CSYM(sys_access)
> .long CSYM(sys_nice)
> .long CSYM(sys_ni_syscall) // 35, was: ftime
> .long CSYM(sys_sync)
> .long CSYM(sys_kill)
> .long CSYM(sys_rename)
> .long CSYM(sys_mkdir)
> .long CSYM(sys_rmdir) // 40
> .long CSYM(sys_dup)
> .long CSYM(sys_pipe)
> .long CSYM(sys_times)
> .long CSYM(sys_ni_syscall) // was: prof
> .long CSYM(sys_brk) // 45
> .long CSYM(sys_setgid16)
> .long CSYM(sys_getgid16)
> .long CSYM(sys_signal)
> .long CSYM(sys_geteuid16)
> .long CSYM(sys_getegid16) // 50
> .long CSYM(sys_acct)
> .long CSYM(sys_umount) // recycled never used phys()
> .long CSYM(sys_ni_syscall) // was: lock
> .long CSYM(sys_ioctl)
> .long CSYM(sys_fcntl) // 55
> .long CSYM(sys_ni_syscall) // was: mpx
> .long CSYM(sys_setpgid)
> .long CSYM(sys_ni_syscall) // was: ulimit
> .long CSYM(sys_ni_syscall)
> .long CSYM(sys_umask) // 60
> .long CSYM(sys_chroot)
> .long CSYM(sys_ustat)
> .long CSYM(sys_dup2)
> .long CSYM(sys_getppid)
> .long CSYM(sys_getpgrp) // 65
> .long CSYM(sys_setsid)
> .long CSYM(sys_sigaction)
> .long CSYM(sys_sgetmask)
> .long CSYM(sys_ssetmask)
> .long CSYM(sys_setreuid16) // 70
> .long CSYM(sys_setregid16)
> .long sys_sigsuspend_wrapper
> .long CSYM(sys_sigpending)
> .long CSYM(sys_sethostname)
> .long CSYM(sys_setrlimit) // 75
> .long CSYM(sys_old_getrlimit)
> .long CSYM(sys_getrusage)
> .long CSYM(sys_gettimeofday)
> .long CSYM(sys_settimeofday)
> .long CSYM(sys_getgroups16) // 80
> .long CSYM(sys_setgroups16)
> .long CSYM(sys_ni_syscall) // was: old_select
> .long CSYM(sys_symlink)
> .long CSYM(sys_ni_syscall) // was: oldlstat (aka lstat)
> .long CSYM(sys_readlink) // 85
> .long CSYM(sys_uselib)
> .long CSYM(sys_swapon)
> .long CSYM(sys_reboot)
> .long CSYM(old_readdir)
> .long CSYM(sys_mmap) // 90
> .long CSYM(sys_munmap)
> .long CSYM(sys_truncate)
> .long CSYM(sys_ftruncate)
> .long CSYM(sys_fchmod)
> .long CSYM(sys_fchown16) // 95
> .long CSYM(sys_getpriority)
> .long CSYM(sys_setpriority)
> .long CSYM(sys_ni_syscall) // was: profil
> .long CSYM(sys_statfs)
> .long CSYM(sys_fstatfs) // 100
> .long CSYM(sys_ni_syscall) // i386: ioperm
> .long CSYM(sys_socketcall)
> .long CSYM(sys_syslog)
> .long CSYM(sys_setitimer)
> .long CSYM(sys_getitimer) // 105
> .long CSYM(sys_newstat)
> .long CSYM(sys_newlstat)
> .long CSYM(sys_newfstat)
> .long CSYM(sys_ni_syscall) // was: olduname (aka uname)
> .long CSYM(sys_ni_syscall) // 110, i386: iopl
> .long CSYM(sys_vhangup)
> .long CSYM(sys_ni_syscall) // was: idle
> .long CSYM(sys_ni_syscall) // i386: vm86old
> .long CSYM(sys_wait4)
> .long CSYM(sys_swapoff) // 115
> .long CSYM(sys_sysinfo)
> .long CSYM(sys_ipc)
> .long CSYM(sys_fsync)
> .long sys_sigreturn_wrapper
> .long sys_clone_wrapper // 120
> .long CSYM(sys_setdomainname)
> .long CSYM(sys_newuname)
> .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush
> .long CSYM(sys_adjtimex)
> .long CSYM(sys_mprotect) // 125
> .long CSYM(sys_sigprocmask)
> .long CSYM(sys_create_module)
> .long CSYM(sys_init_module)
> .long CSYM(sys_delete_module)
> .long CSYM(sys_get_kernel_syms) // 130
> .long CSYM(sys_quotactl)
> .long CSYM(sys_getpgid)
> .long CSYM(sys_fchdir)
> .long CSYM(sys_bdflush)
> .long CSYM(sys_sysfs) // 135
> .long CSYM(sys_personality)
> .long CSYM(sys_ni_syscall) // for afs_syscall
> .long CSYM(sys_setfsuid16)
> .long CSYM(sys_setfsgid16)
> .long CSYM(sys_llseek) // 140
> .long CSYM(sys_getdents)
> .long CSYM(sys_select)
> .long CSYM(sys_flock)
> .long CSYM(sys_msync)
> .long CSYM(sys_readv) // 145
> .long CSYM(sys_writev)
> .long CSYM(sys_getsid)
> .long CSYM(sys_fdatasync)
> .long CSYM(sys_sysctl)
> .long CSYM(sys_mlock) // 150
> .long CSYM(sys_munlock)
> .long CSYM(sys_mlockall)
> .long CSYM(sys_munlockall)
> .long CSYM(sys_sched_setparam)
> .long CSYM(sys_sched_getparam) // 155
> .long CSYM(sys_sched_setscheduler)
> .long CSYM(sys_sched_getscheduler)
> .long CSYM(sys_sched_yield)
> .long CSYM(sys_sched_get_priority_max)
> .long CSYM(sys_sched_get_priority_min) // 160
> .long CSYM(sys_sched_rr_get_interval)
> .long CSYM(sys_nanosleep)
> .long CSYM(sys_mremap)
> .long CSYM(sys_setresuid16)
> .long CSYM(sys_getresuid16) // 165
> .long CSYM(sys_ni_syscall) // for vm86
> .long CSYM(sys_query_module)
> .long CSYM(sys_poll)
> .long CSYM(sys_nfsservctl)
> .long CSYM(sys_setresgid16) // 170
> .long CSYM(sys_getresgid16)
> .long CSYM(sys_prctl)
> .long sys_rt_sigreturn_wrapper
> .long CSYM(sys_rt_sigaction)
> .long CSYM(sys_rt_sigprocmask) // 175
> .long CSYM(sys_rt_sigpending)
> .long CSYM(sys_rt_sigtimedwait)
> .long CSYM(sys_rt_sigqueueinfo)
> .long sys_rt_sigsuspend_wrapper
> .long CSYM(sys_pread) // 180
> .long CSYM(sys_pwrite)
> .long CSYM(sys_lchown16);
> .long CSYM(sys_getcwd)
> .long CSYM(sys_capget)
> .long CSYM(sys_capset) // 185
> .long CSYM(sys_sigaltstack)
> .long CSYM(sys_sendfile)
> .long CSYM(sys_ni_syscall) // streams1
> .long CSYM(sys_ni_syscall) // streams2
> .long sys_vfork_wrapper // 190
> .long CSYM(sys_getrlimit)
> .long CSYM(sys_mmap2)
> .long CSYM(sys_truncate64)
> .long CSYM(sys_ftruncate64)
> .long CSYM(sys_stat64) // 195
> .long CSYM(sys_lstat64)
> .long CSYM(sys_fstat64)
> .long CSYM(sys_chown)
> .long CSYM(sys_getuid)
> .long CSYM(sys_getgid) // 200
> .long CSYM(sys_geteuid)
> .long CSYM(sys_getegid)
> .long CSYM(sys_setreuid)
> .long CSYM(sys_setregid)
> .long CSYM(sys_getgroups) // 205
> .long CSYM(sys_setgroups)
> .long CSYM(sys_fchown)
> .long CSYM(sys_setresuid)
> .long CSYM(sys_getresuid)
> .long CSYM(sys_setresgid) // 210
> .long CSYM(sys_getresgid)
> .long CSYM(sys_lchown)
> .long CSYM(sys_setuid)
> .long CSYM(sys_setgid)
> .long CSYM(sys_setfsuid) // 215
> .long CSYM(sys_setfsgid)
> .long CSYM(sys_pivot_root)
> .long CSYM(sys_mincore) // just returns ENOSYS without MMU
> .long CSYM(sys_madvise) // just returns ENOSYS without MMU
> .long CSYM(sys_getdents64) // 220
> .long CSYM(sys_fcntl64)
> .long CSYM(sys_ni_syscall) // Reserved for TUX
> .long CSYM(sys_ni_syscall) // Reserved for `security'
> .long CSYM(sys_gettid)
> .long CSYM(sys_ni_syscall) // 225, sys_readahead on i386
>
> .space (NR_syscalls-225)*4
___________________________
microblaze-uclinux mailing list
microblaze-uclinux@xxxxxxxxxxxxxx
Project Home Page : http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux
Mailing List Archive : http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/