OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [or32/] [kernel/] [entry.S] - Rev 7

Compare with Previous | Blame | View Log

/*
 *  linux/arch/or32/kernel/entry.S
 *
 *  or32 version
 *    author(s): Matjaz Breskvar (phoenix@bsemi.com)
 *
 *  changes:
 *  18. 11. 2003: Matjaz Breskvar (phoenix@bsemi.com)
 *    initial port to or32 architecture
 *  06. 12. 2003: Matjaz Breskvar (phoenix@bsemi.com)
 *    major changes in handling exceptions
 *    physical addresses used only by code in head.S
 *    cleand exception handlers and moved them to entry.S
 *  31. 12. 2005: Gyorgy Jeney (nog@bsemi.com)
 *    Added syscall traceing code
 *
 * syscall table entries are based on ppc port, so they will probably 
 * need some more cleaning.
 *
 * Stack layout in 'ret_from_system_call':
 *      ptrace needs to have all regs on the stack.
 *      if the order here is changed, it needs to be
 *      updated in fork.c:copy_process, signal.c:do_signal,
 *      ptrace.c and ptrace.h
 *
 * syscall table entries are based on ppc port, so it will probably need
 * some more cleaning.
 */

#include <linux/linkage.h>
#include <linux/sys.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/or32_asm.h>
#include <asm/spr_defs.h>

#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/unistd.h>
#include <asm/pgtable.h>
#include <asm/asm-offsets.h>
                
/* some defines to ease or32 assembly programming */
#include "or32_funcs.S"
        
#define GET_CURRENT_THREAD_INFO(reg,ksp)                        \
        l.srli  reg,ksp,PAGE_SHIFT                              ;\
        l.slli  reg,reg,PAGE_SHIFT
        
/* =========================================================[ macros ]=== */

#define PUSH_PT_REGS_NO_TRANS                                   \
        l.addi  r1,r1,-(INT_FRAME_SIZE)                         ;\
        l.sw    GPR3(r1),r3                                     ;\
        l.sw    ORIG_GPR3(r1),r3                                ;\
        l.mfspr r3,r0,SPR_EPCR_BASE                             ;\
        l.sw    PC(r1),r3                                       ;\
        l.mfspr r3,r0,SPR_ESR_BASE                              ;\
        l.sw    SR(r1),r3                                       ;\
        l.addi  r3,r1,+(INT_FRAME_SIZE)                         ;\
        l.sw    SP(r1),r3                                       ;\
        l.sw    GPR2(r1),r2                                     ;\
        l.lwz   r3,GPR3(r1)                                     ;\
        l.sw    GPR4(r1),r4                                     ;\
        l.sw    GPR5(r1),r5                                     ;\
        l.sw    GPR6(r1),r6                                     ;\
        l.sw    GPR7(r1),r7                                     ;\
        l.sw    GPR8(r1),r8                                     ;\
        l.sw    GPR9(r1),r9                                     ;\
        l.sw    GPR10(r1),r10                                   ;\
        l.sw    GPR11(r1),r11                                   ;\
        l.sw    GPR12(r1),r12                                   ;\
        l.sw    GPR13(r1),r13                                   ;\
        l.sw    GPR14(r1),r14                                   ;\
        l.sw    GPR15(r1),r15                                   ;\
        l.sw    GPR16(r1),r16                                   ;\
        l.sw    GPR17(r1),r17                                   ;\
        l.sw    GPR18(r1),r18                                   ;\
        l.sw    GPR19(r1),r19                                   ;\
        l.sw    GPR20(r1),r20                                   ;\
        l.sw    GPR21(r1),r21                                   ;\
        l.sw    GPR22(r1),r22                                   ;\
        l.sw    GPR23(r1),r23                                   ;\
        l.sw    GPR24(r1),r24                                   ;\
        l.sw    GPR25(r1),r25                                   ;\
        l.sw    GPR26(r1),r26                                   ;\
        l.sw    GPR27(r1),r27                                   ;\
        l.sw    GPR28(r1),r28                                   ;\
        l.sw    GPR29(r1),r29                                   ;\
        l.sw    GPR30(r1),r30                                   ;\
        l.sw    GPR31(r1),r31                                   ;\
        l.sw    RESULT(r1),r0

        
/*
 * We need to disable interrupts at beginning of RESTORE_ALL
 * since interrupt might come in after we've loaded EPC return address
 * and overwrite EPC with address somewhere in RESTORE_ALL
 * which is of course wrong!
 */
        
#define RESTORE_ALL                                             \
        DISABLE_INTERRUPTS(r3,r4)                               ;\
        l.lwz   r3,PC(r1)                                       ;\
        l.mtspr r0,r3,SPR_EPCR_BASE                             ;\
        l.lwz   r3,SR(r1)                                       ;\
        l.mtspr r0,r3,SPR_ESR_BASE                              ;\
        l.lwz   r2,GPR2(r1)                                     ;\
        l.lwz   r3,GPR3(r1)                                     ;\
        l.lwz   r4,GPR4(r1)                                     ;\
        l.lwz   r5,GPR5(r1)                                     ;\
        l.lwz   r6,GPR6(r1)                                     ;\
        l.lwz   r7,GPR7(r1)                                     ;\
        l.lwz   r8,GPR8(r1)                                     ;\
        l.lwz   r9,GPR9(r1)                                     ;\
        l.lwz   r10,GPR10(r1)                                   ;\
        l.lwz   r11,GPR11(r1)                                   ;\
        l.lwz   r12,GPR12(r1)                                   ;\
        l.lwz   r13,GPR13(r1)                                   ;\
        l.lwz   r14,GPR14(r1)                                   ;\
        l.lwz   r15,GPR15(r1)                                   ;\
        l.lwz   r16,GPR16(r1)                                   ;\
        l.lwz   r17,GPR17(r1)                                   ;\
        l.lwz   r18,GPR18(r1)                                   ;\
        l.lwz   r19,GPR19(r1)                                   ;\
        l.lwz   r20,GPR20(r1)                                   ;\
        l.lwz   r21,GPR21(r1)                                   ;\
        l.lwz   r22,GPR22(r1)                                   ;\
        l.lwz   r23,GPR23(r1)                                   ;\
        l.lwz   r24,GPR24(r1)                                   ;\
        l.lwz   r25,GPR25(r1)                                   ;\
        l.lwz   r26,GPR26(r1)                                   ;\
        l.lwz   r27,GPR27(r1)                                   ;\
        l.lwz   r28,GPR28(r1)                                   ;\
        l.lwz   r29,GPR29(r1)                                   ;\
        l.lwz   r30,GPR30(r1)                                   ;\
        l.lwz   r31,GPR31(r1)                                   ;\
        l.lwz   r1,SP(r1)                                       ;\
        l.rfe

#define RESTORE_ALL_NO_R11                                      \
        DISABLE_INTERRUPTS(r3,r4)                               ;\
        l.lwz   r3,PC(r1)                                       ;\
        l.mtspr r0,r3,SPR_EPCR_BASE                             ;\
        l.lwz   r3,SR(r1)                                       ;\
        l.mtspr r0,r3,SPR_ESR_BASE                              ;\
        l.lwz   r2,GPR2(r1)                                     ;\
        l.lwz   r3,GPR3(r1)                                     ;\
        l.lwz   r4,GPR4(r1)                                     ;\
        l.lwz   r5,GPR5(r1)                                     ;\
        l.lwz   r6,GPR6(r1)                                     ;\
        l.lwz   r7,GPR7(r1)                                     ;\
        l.lwz   r8,GPR8(r1)                                     ;\
        l.lwz   r9,GPR9(r1)                                     ;\
        l.lwz   r10,GPR10(r1)                                   ;\
        l.lwz   r12,GPR12(r1)                                   ;\
        l.lwz   r13,GPR13(r1)                                   ;\
        l.lwz   r14,GPR14(r1)                                   ;\
        l.lwz   r15,GPR15(r1)                                   ;\
        l.lwz   r16,GPR16(r1)                                   ;\
        l.lwz   r17,GPR17(r1)                                   ;\
        l.lwz   r18,GPR18(r1)                                   ;\
        l.lwz   r19,GPR19(r1)                                   ;\
        l.lwz   r20,GPR20(r1)                                   ;\
        l.lwz   r21,GPR21(r1)                                   ;\
        l.lwz   r22,GPR22(r1)                                   ;\
        l.lwz   r23,GPR23(r1)                                   ;\
        l.lwz   r24,GPR24(r1)                                   ;\
        l.lwz   r25,GPR25(r1)                                   ;\
        l.lwz   r26,GPR26(r1)                                   ;\
        l.lwz   r27,GPR27(r1)                                   ;\
        l.lwz   r28,GPR28(r1)                                   ;\
        l.lwz   r29,GPR29(r1)                                   ;\
        l.lwz   r30,GPR30(r1)                                   ;\
        l.lwz   r31,GPR31(r1)                                   ;\
        l.lwz   r1,SP(r1)                                       ;\
        l.rfe

                
#define EXCEPTION_ENTRY(handler)                                \
        .global handler                                         ;\
handler:                                                        ;\
        /* r1, EPCR, ESR a already saved */                     ;\
        l.sw    GPR2(r1),r2                                     ;\
        l.sw    GPR3(r1),r3                                     ;\
        l.sw    ORIG_GPR3(r1),r3                                ;\
        /* r4 already save */                                   ;\
        l.sw    GPR5(r1),r5                                     ;\
        l.sw    GPR6(r1),r6                                     ;\
        l.sw    GPR7(r1),r7                                     ;\
        l.sw    GPR8(r1),r8                                     ;\
        l.sw    GPR9(r1),r9                                     ;\
        /* r10 already saved */                                 ;\
        l.sw    GPR11(r1),r11                                   ;\
        /* r12,r13 already saved */                             ;\
        l.sw    GPR14(r1),r14                                   ;\
        l.sw    GPR15(r1),r15                                   ;\
        l.sw    GPR16(r1),r16                                   ;\
        l.sw    GPR17(r1),r17                                   ;\
        l.sw    GPR18(r1),r18                                   ;\
        l.sw    GPR19(r1),r19                                   ;\
        l.sw    GPR20(r1),r20                                   ;\
        l.sw    GPR21(r1),r21                                   ;\
        l.sw    GPR22(r1),r22                                   ;\
        l.sw    GPR23(r1),r23                                   ;\
        l.sw    GPR24(r1),r24                                   ;\
        l.sw    GPR25(r1),r25                                   ;\
        l.sw    GPR26(r1),r26                                   ;\
        l.sw    GPR27(r1),r27                                   ;\
        l.sw    GPR28(r1),r28                                   ;\
        l.sw    GPR29(r1),r29                                   ;\
        l.sw    GPR30(r1),r30                                   ;\
        /* r31 already save */                                  ;\
        l.sw    RESULT(r1),r0

#define UNHANDLED_EXCEPTION(handler,vector)                     \
        .global handler                                         ;\
handler:                                                        ;\
        /* r1, EPCR, ESR already saved */                       ;\
        l.sw    GPR2(r1),r2                                     ;\
        l.sw    GPR3(r1),r3                                     ;\
        l.sw    ORIG_GPR3(r1),r3                                ;\
        l.sw    GPR5(r1),r5                                     ;\
        l.sw    GPR6(r1),r6                                     ;\
        l.sw    GPR7(r1),r7                                     ;\
        l.sw    GPR8(r1),r8                                     ;\
        l.sw    GPR9(r1),r9                                     ;\
        /* r10 already saved */                                 ;\
        l.sw    GPR11(r1),r11                                   ;\
        /* r12,r13 already saved */                             ;\
        l.sw    GPR14(r1),r14                                   ;\
        l.sw    GPR15(r1),r15                                   ;\
        l.sw    GPR16(r1),r16                                   ;\
        l.sw    GPR17(r1),r17                                   ;\
        l.sw    GPR18(r1),r18                                   ;\
        l.sw    GPR19(r1),r19                                   ;\
        l.sw    GPR20(r1),r20                                   ;\
        l.sw    GPR21(r1),r21                                   ;\
        l.sw    GPR22(r1),r22                                   ;\
        l.sw    GPR23(r1),r23                                   ;\
        l.sw    GPR24(r1),r24                                   ;\
        l.sw    GPR25(r1),r25                                   ;\
        l.sw    GPR26(r1),r26                                   ;\
        l.sw    GPR27(r1),r27                                   ;\
        l.sw    GPR28(r1),r28                                   ;\
        l.sw    GPR29(r1),r29                                   ;\
        l.sw    GPR30(r1),r30                                   ;\
        /* r31 already saved */                                 ;\
        l.sw    RESULT(r1),r0                                   ;\
        l.addi  r3,r1,0                                         ;\
        /* r4 is exception EA */                                ;\
        l.addi  r5,r0,vector                                    ;\
        l.jal   _unhandled_exception                            ;\
        l.nop                                                   ;\
        l.j     _ret_from_exception                             ;\
        l.nop   1
        
/*
 * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR
 *       contain the same values as when exception we're handling
 *       occured. in fact they never do. if you need them use
 *       values saved on stack (for SPR_EPC, SPR_ESR) or content
 *       of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE()
 *       in 'arch/or32/kernel/head.S'
 */
        
/* =====================================================[ exceptions] === */

/* ---[ 0x100: RESET exception ]----------------------------------------- */

EXCEPTION_ENTRY(_tng_kernel_start)
        l.jal   _start
        l.nop
        
/* ---[ 0x200: BUS exception ]------------------------------------------- */
        
UNHANDLED_EXCEPTION(_vector_0x200,0x200)

/* ---[ 0x300: Data Page Fault exception ]------------------------------- */

EXCEPTION_ENTRY(_data_page_fault_handler)
        /* set up parameters for do_page_fault */
        l.addi  r3,r1,0                    // pt_regs
        /* r4 set be EXCEPTION_HANDLE */   // effective address of fault
        l.ori   r5,r0,0x300                // exception vector

        /*
         * __PHX__: TODO
         *
         * all this can be written much simpler. look at
         * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
         */
#ifdef CONFIG_OR32_NO_SPR_SR_DSX
        l.lwz   r6,PC(r3)                  // address of an offending insn
        l.lwz   r6,0(r6)                   // instruction that caused pf

        l.srli  r6,r6,26                   // check opcode for jump insn
        l.sfeqi r6,0                       // l.j
        l.bf    8f
        l.sfeqi r6,1                       // l.jal
        l.bf    8f
        l.sfeqi r6,3                       // l.bnf
        l.bf    8f
        l.sfeqi r6,4                       // l.bf
        l.bf    8f
        l.sfeqi r6,0x11                    // l.jr
        l.bf    8f
        l.sfeqi r6,0x12                    // l.jalr
        l.bf    8f
        
        l.nop

        l.j     9f
        l.nop
8:

        l.lwz   r6,PC(r3)                  // address of an offending insn
        l.addi  r6,r6,4
        l.lwz   r6,0(r6)                   // instruction that caused pf
        l.srli  r6,r6,26                   // get opcode
9:

#else

        l.mfspr r6,r0,SPR_SR               // SR
//      l.lwz   r6,SR(r3)                  // ESR
        l.andi  r6,r6,SPR_SR_DSX           // check for delay slot exception
        l.sfeqi r6,0x1                     // exception happened in delay slot
        l.bnf   7f      
        l.lwz   r6,PC(r3)                  // address of an offending insn
        
        l.addi  r6,r6,4                    // offending insn is in delay slot
7:
        l.lwz   r6,0(r6)                   // instruction that caused pf
        l.srli  r6,r6,26                   // check opcode for write access                     
#endif          

        l.sfgeui r6,0x34                   // check opcode for write access
        l.bnf   1f
        l.sfleui r6,0x37
        l.bnf   1f
        l.ori   r6,r0,0x1                  // write access
        l.j     2f
        l.nop
1:      l.ori   r6,r0,0x0                  // !write access
2:
        
        /* call fault.c handler in or32/mm/fault.c */
        l.jal   _do_page_fault
        l.nop
        l.j     _ret_from_exception
        l.nop
        
/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */

EXCEPTION_ENTRY(_insn_page_fault_handler)       
        /* set up parameters for do_page_fault */
        l.addi  r3,r1,0                    // pt_regs
        /* r4 set be EXCEPTION_HANDLE */   // effective address of fault
        l.ori   r5,r0,0x400                // exception vector
        l.ori   r6,r0,0x0                  // !write access
        
        /* call fault.c handler in or32/mm/fault.c */
        l.jal   _do_page_fault
        l.nop
        l.j     _ret_from_exception
        l.nop

        
/* ---[ 0x500: Timer exception ]----------------------------------------- */

EXCEPTION_ENTRY(_timer_handler)
#ifdef CONFIG_OR32_ESR_EXCEPTION_BUG_CHECK
        
        l.lwz   r4,SR(r1)               // were interrupts enabled ?
        l.andi  r4,r4,SPR_SR_TEE
        l.sfeqi r4,0
        l.bnf   1f                      // tick irq enabled, all ok.
        l.nop

        l.addi  r1,r1,-0x8
        LOAD_SYMBOL_2_GPR(r3,42f)
        l.sw    0x0(r1),r3
        l.jal   _printk
        l.sw    0x4(r1),r4
        l.addi  r1,r1,0x8

        .section .rodata, "a"
42:     
                .string "\n\rESR interrupt bug: in _timer_handler (ESR %x)\n\r"
                .align 4
        .previous

        l.ori   r4,r4,SPR_SR_TEE        // fix the bug
//      l.sw    SR(r1),r4
1:      
#endif
        l.addi r3,r1,0
        LOAD_SYMBOL_2_GPR(r8,_timer_interrupt)
        l.jalr r8
        l.nop
        l.j    _ret_from_intr
        l.nop

/* ---[ 0x600: Aligment exception ]-------------------------------------- */

#if 1
UNHANDLED_EXCEPTION(_vector_0x600,0x600)
#endif
                
#if 0
EXCEPTION_ENTRY(_aligment_handler)
//        l.mfspr r2,r0,SPR_EEAR_BASE     /* Load the efective addres */
        l.addi  r2,r4,0
//        l.mfspr r5,r0,SPR_EPCR_BASE     /* Load the insn address */
        l.lwz   r5,PC(r1)
        
        l.lwz   r3,0(r5)                /* Load insn */
        l.srli  r4,r3,26                /* Shift left to get the insn opcode */

        l.sfeqi r4,0x00                 /* Check if the load/store insn is in delay slot */
        l.bf    jmp
        l.sfeqi r4,0x01
        l.bf    jmp
        l.sfeqi r4,0x03
        l.bf    jmp
        l.sfeqi r4,0x04
        l.bf    jmp
        l.sfeqi r4,0x11
        l.bf    jr
        l.sfeqi r4,0x12
        l.bf    jr
        l.nop
        l.j     1f
        l.addi  r5,r5,4                 /* Increment PC to get return insn address */
        
jmp:
        l.slli  r4,r3,6                 /* Get the signed extended jump length */
        l.srai  r4,r4,4

        l.lwz   r3,4(r5)                /* Load the real load/store insn */

        l.add   r5,r5,r4                /* Calculate jump target address */
        
        l.j     1f
        l.srli  r4,r3,26                /* Shift left to get the insn opcode */

jr:
        l.slli  r4,r3,9                 /* Shift to get the reg nb */
        l.andi  r4,r4,0x7c

        l.lwz   r3,4(r5)                /* Load the real load/store insn */

        l.add   r4,r4,r1                /* Load the jump register value from the stack */
        l.lwz   r5,0(r4)

        l.srli  r4,r3,26                /* Shift left to get the insn opcode */
        
        
1:      
//        l.mtspr r0,r5,SPR_EPCR_BASE
        l.sw    PC(r1),r5
        
        l.sfeqi r4,0x26
        l.bf    lhs
        l.sfeqi r4,0x25
        l.bf    lhz
        l.sfeqi r4,0x22
        l.bf    lws
        l.sfeqi r4,0x21
        l.bf    lwz
        l.sfeqi r4,0x37
        l.bf    sh
        l.sfeqi r4,0x35
        l.bf    sw
        l.nop

1:      l.j     1b                      /* I don't know what to do */
        l.nop

lhs:    l.lbs   r5,0(r2)
        l.slli  r5,r5,8
        l.lbz   r6,1(r2)
        l.or    r5,r5,r6
        l.srli  r4,r3,19
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.j     align_end
        l.sw    0(r4),r5        
        
lhz:    l.lbz   r5,0(r2)
        l.slli  r5,r5,8
        l.lbz   r6,1(r2)
        l.or    r5,r5,r6
        l.srli  r4,r3,19
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.j     align_end
        l.sw    0(r4),r5        
                
lws:    l.lbs   r5,0(r2)
        l.slli  r5,r5,24
        l.lbz   r6,1(r2)
        l.slli  r6,r6,16
        l.or    r5,r5,r6
        l.lbz   r6,2(r2)
        l.slli  r6,r6,8
        l.or    r5,r5,r6
        l.lbz   r6,3(r2)
        l.or    r5,r5,r6
        l.srli  r4,r3,19
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.j     align_end
        l.sw    0(r4),r5        
                
lwz:    l.lbz   r5,0(r2)
        l.slli  r5,r5,24
        l.lbz   r6,1(r2)
        l.slli  r6,r6,16
        l.or    r5,r5,r6
        l.lbz   r6,2(r2)
        l.slli  r6,r6,8
        l.or    r5,r5,r6
        l.lbz   r6,3(r2)
        l.or    r5,r5,r6
        l.srli  r4,r3,19
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.j     align_end
        l.sw    0(r4),r5        
                
sh:
        l.srli  r4,r3,9
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.lwz   r5,0(r4)        
        l.sb    1(r2),r5
        l.srli  r5,r5,8
        l.j     align_end
        l.sb    0(r2),r5

sw:
        l.srli  r4,r3,9
        l.andi  r4,r4,0x7c
        l.add   r4,r4,r1
        l.lwz   r5,0(r4)        
        l.sb    3(r2),r5
        l.srli  r5,r5,8
        l.sb    2(r2),r5
        l.srli  r5,r5,8
        l.sb    1(r2),r5
        l.srli  r5,r5,8
        l.j     align_end
        l.sb    0(r2),r5

align_end:
        l.j    _ret_from_intr
        l.nop   
#endif  

/* ---[ 0x700: Illegal insn exception ]---------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x700,0x700)

/* ---[ 0x800: External interrupt exception ]---------------------------- */

EXCEPTION_ENTRY(_external_irq_handler)
#ifdef CONFIG_OR32_ESR_EXCEPTION_BUG_CHECK
        l.lwz   r4,SR(r1)               // were interrupts enabled ?
        l.andi  r4,r4,SPR_SR_IEE
        l.sfeqi r4,0
        l.bnf   1f                      // ext irq enabled, all ok.
        l.nop

        l.addi  r1,r1,-0x8
        LOAD_SYMBOL_2_GPR(r3,42f)
        l.sw    0x0(r1),r3
        l.jal   _printk
        l.sw    0x4(r1),r4
        l.addi  r1,r1,0x8

        .section .rodata, "a"
42:     
                .string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
                .align 4
        .previous

        l.ori   r4,r4,SPR_SR_IEE        // fix the bug
//      l.sw    SR(r1),r4
1:      
#endif
        l.addi r3,r1,0
        LOAD_SYMBOL_2_GPR(r8,_do_IRQ)
        l.jalr r8
        l.nop
        l.j    _ret_from_intr
        l.nop   
        
/* ---[ 0x900: DTLB miss exception ]------------------------------------- */

                
/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */

                
/* ---[ 0xb00: Range exception ]----------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0xb00,0xb00)

/* ---[ 0xc00: Syscall exception ]--------------------------------------- */

EXCEPTION_ENTRY(_sys_call_handler)
        /* r3 is not tainted by EXCEPTION_HANDLE() */
        
        /* r4 holds the EEAR address of the fault, load the original r4 */
        l.lwz   r4,GPR4(r1)

        l.lwz   r30,TI_FLAGS(r10)
        l.andi  r30,r30,_TIF_SYSCALL_TRACE
        l.sfne  r30,r0
        l.bf    _syscall_trace_entry
        l.nop

        /* check that userspace didn't try to fool us with 
         * syscall number greater then __NR_syscall. 
         */     
        l.sfgeui r11,NR_syscalls
        l.bf    _syscall_badsys
        l.nop
        
        /* WTF: no other arch has this?? */
        ENABLE_INTERRUPTS(r9)           // enable interrupts, r9 is temp

_syscall_call:
        l.movhi r30,hi(_sys_call_table)
        l.ori   r30,r30,lo(_sys_call_table)
        l.slli  r11,r11,2
        l.add   r30,r30,r11
        l.lwz   r30,0(r30)
        
        l.jalr  r30
        l.addi  r8,r1,0                 // regs pointer

        l.sw    GPR11(r1),r11           // save return value
        l.sw    RESULT(r1),r11          // save result

_syscall_exit:
        DISABLE_INTERRUPTS(r3,r4)
        l.lwz   r30,TI_FLAGS(r10)
        l.andi  r3,r30,_TIF_ALLWORK_MASK
        l.sfne  r3,r0
        l.bf    _syscall_exit_work
        l.nop

        l.j     _restore_all
        l.nop

_syscall_trace_entry:
        l.sw    SYSCALLNO(r1),r11
        l.addi  r3,r1,0
        l.addi  r4,r0,0
        l.jal   _do_syscall_trace
        l.nop

        /* Restore arguments */
        l.lwz   r11,SYSCALLNO(r1)
        l.lwz   r3,GPR3(r1)
        l.lwz   r4,GPR4(r1)
        l.lwz   r5,GPR5(r1)
        l.lwz   r6,GPR6(r1)
        l.lwz   r7,GPR7(r1)
        l.sfgeui r11,NR_syscalls
        l.bnf   _syscall_call
        l.nop

        l.addi  r30,r0,-ENOSYS
        l.sw    GPR11(r1),r30
        l.sw    RESULT(r1),r30

        l.j     _syscall_exit
        l.nop

_syscall_badsys:
        /* Just return -ENOSYS */
        l.addi  r30,r0,-ENOSYS
        l.sw    RESULT(r1),r30
        l.sw    GPR11(r1),r30
        l.j     _resume_userspace
        l.nop

_syscall_exit_work:
        /* r30 holds TI_flags */
        l.andi  r3,r30,_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP
        l.sfne  r3,r0
        l.bnf   _work_pending
        l.nop

        ENABLE_INTERRUPTS(r3)

        l.addi  r3,r1,0
        l.addi  r4,r0,1
        l.jal   _do_syscall_trace
        l.nop

        l.j     _resume_userspace
        l.nop


/* ---[ 0xd00: Trap exception ]------------------------------------------ */

UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)

/* ---[ 0xe00: Trap exception ]------------------------------------------ */

UNHANDLED_EXCEPTION(_vector_0xe00,0xe00)

/* ---[ 0xf00: Reserved exception ]-------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0xf00,0xf00)

/* ---[ 0x1000: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1000,0x1000)

/* ---[ 0x1100: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1100,0x1100)

/* ---[ 0x1200: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1200,0x1200)

/* ---[ 0x1300: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1300,0x1300)

/* ---[ 0x1400: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1400,0x1400)

/* ---[ 0x1500: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1500,0x1500)

/* ---[ 0x1600: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1600,0x1600)

/* ---[ 0x1700: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1700,0x1700)

/* ---[ 0x1800: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1800,0x1800)

/* ---[ 0x1900: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1900,0x1900)

/* ---[ 0x1a00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1a00,0x1a00)

/* ---[ 0x1b00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1b00,0x1b00)

/* ---[ 0x1c00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1c00,0x1c00)

/* ---[ 0x1d00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1d00,0x1d00)

/* ---[ 0x1e00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1e00,0x1e00)

/* ---[ 0x1f00: Reserved exception ]------------------------------------- */

UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)

/* ========================================================[ return ] === */

_work_pending:
        /*
         * if (current_thread_info->flags & _TIF_NEED_RESCHED)
         *     schedule();
         */ 
        l.lwz   r3,TI_FLAGS(r10)
        l.andi  r3,r3,_TIF_NEED_RESCHED
        l.sfeqi r3,0
        l.bf    work_notifysig
        l.nop

work_resched:
        l.jal   _schedule
        l.nop
        DISABLE_INTERRUPTS(r3,r4)

        l.lwz   r3,TI_FLAGS(r10)
        l.andi  r30,r3,_TIF_WORK_MASK
        l.sfnei r30,0
        l.bnf   _restore_all
        l.nop
        l.andi  r30,r3,_TIF_NEED_RESCHED
        l.sfnei r30,0
        l.bf    work_resched
        l.nop
        /* 
         * if (current_thread_info->flags & _TIF_SIGPENDING)
         *     do_signal(r3,r4);
         */
work_notifysig:
        l.lwz   r5,TI_FLAGS(r10)
        l.andi  r5,r5,_TIF_SIGPENDING   
        l.sfeqi r5,0
        l.bf    _resume_userspace
        l.addi  r3,r0,1
        l.addi  r4,r0,0
        l.addi  r5,r1,0
        l.jal   _do_signal
        l.nop
        l.j     _resume_userspace
        l.nop


ENTRY(_ret_from_fork)
        l.jal   _schedule_tail
        l.nop

        l.j     _syscall_exit
        l.nop


ENTRY(_restore_all)
        // we need to save KSP here too
        // or else fork's 'eat' stack space
        l.addi  r4,r1,INT_FRAME_SIZE
        l.sw    (TI_KSP)(r10),r4
        RESTORE_ALL
        
ENTRY(_ret_from_intr)
        // i386 version:        
        // GET_CURRENT(%ebx)

ENTRY(_ret_from_exception)
        l.lwz   r4,SR(r1)
        l.andi  r3,r4,SPR_SR_SM
        l.sfeqi r3,0
        l.bnf   _restore_all
        l.nop
        /* 
         * return to usermode
         */
_resume_userspace:
        DISABLE_INTERRUPTS(r3,r4)
        l.lwz   r3,TI_FLAGS(r10)
        l.andi  r3,r3,_TIF_WORK_MASK
        l.sfeqi r3,0
        l.bnf   _work_pending
        l.nop
        l.j     _restore_all
        l.nop

/* ========================================================[ switch ] === */

/*
 * This routine switches between two different tasks.  The process
 * state of one is saved on its kernel stack.  Then the state
 * of the other is restored from its kernel stack.  The memory
 * management hardware is updated to the second process's state.
 * Finally, we can return to the second process, via the 'return'.
 *
 * Note: there are two ways to get to the "going out" portion
 * of this code; either by coming in via the entry (_switch)
 * or via "fork" which must set up an environment equivalent
 * to the "_switch" path.  If you change this (or in particular, the
 * SAVE_REGS macro), you'll have to change the fork code also.
 */


/* __switch MUST never lay on page boundry, cause it runs from
 * effective addresses and beeing interrupted by iTLB miss would kill it. 
 * dTLB miss seams to never accour in the bad place since data accesses
 * are from task structures which are always page aligned.
 *
 * The problem happens in RESTORE_ALL_NO_R11 where we first set the EPCR
 * register, then load the previous register values and only at the end call
 * the l.rfe instruction. If get TLB miss in beetwen the EPCR register gets
 * garbled and we end up calling l.rfe with the wrong EPCR. (same probably
 * holds for ESR)
 *
 * To avoid this problems it is sufficient to align __switch to
 * some nice round number smaller than it's size...
 */
        
        .align 0x400
ENTRY(__switch)
        l.sw    (GPR3-INT_FRAME_SIZE)(r1),r3
        l.mtspr r0,r9,SPR_EPCR_BASE             /* Link register to EPCR */
        l.mfspr r3,r0,SPR_SR                    /* From SR to ESR */
        l.mtspr r0,r3,SPR_ESR_BASE
        l.addi  r11,r10,0                       /* Save old 'current' to 'last' return value*/
        l.lwz   r3,(GPR3-INT_FRAME_SIZE)(r1)
        PUSH_PT_REGS_NO_TRANS
/* DEBUGING HELP */
        l.or    r21,r1,r0
        l.or    r22,r2,r0
        l.or    r23,r3,r0
        l.or    r24,r4,r0
/* END DEBUGGING HELP */
        l.sw    TI_KSP(r3),r1                   /* Save old stack pointer */
        l.lwz   r1,TI_KSP(r4)                   /* Load new stack pointer */
        l.addi  r10,r5,0                        /* set current (r10) to new */
        RESTORE_ALL_NO_R11
                
/* =================================================[ syscall table ] === */
        
        .data
        .align 4
ENTRY(_sys_call_table)
        .long _sys_ni_syscall   /* 0  -  old "setup()" system call */
        .long _sys_exit
        .long _sys_fork
        .long _sys_read
        .long _sys_write
        .long _sys_open         /* 5 */
        .long _sys_close
        .long _sys_waitpid
        .long _sys_creat
        .long _sys_link
        .long _sys_unlink       /* 10 */
        .long _sys_execve
        .long _sys_chdir
        .long _sys_time
        .long _sys_mknod
        .long _sys_chmod        /* 15 */
        .long _sys_lchown
        .long _sys_ni_syscall           /* old break syscall holder */
        .long _sys_stat
        .long _sys_lseek
        .long _sys_getpid       /* 20 */
        .long _sys_mount
        .long _sys_oldumount
        .long _sys_setuid
        .long _sys_getuid
        .long _sys_stime        /* 25 */
        .long _sys_ptrace
        .long _sys_alarm
        .long _sys_fstat
        .long _sys_pause
        .long _sys_utime        /* 30 */
        .long _sys_ni_syscall           /* old stty syscall holder */
        .long _sys_ni_syscall           /* old gtty syscall holder */
        .long _sys_access
        .long _sys_nice
        .long _sys_ni_syscall   /* 35:   old ftime syscall holder */
        .long _sys_sync
        .long _sys_kill
        .long _sys_rename
        .long _sys_mkdir
        .long _sys_rmdir        /* 40 */
        .long _sys_dup
        .long _sys_pipe
        .long _sys_times
        .long _sys_ni_syscall   /* old prof syscall holder */
        .long _sys_brk          /* 45 */
        .long _sys_setgid
        .long _sys_getgid
        .long _sys_signal
        .long _sys_geteuid
        .long _sys_getegid      /* 50 */
        .long _sys_acct
        .long _sys_umount               /* recycled never used phys() */
        .long _sys_ni_syscall           /* old lock syscall holder */
        .long _sys_ioctl
        .long _sys_fcntl        /* 55 */
        .long _sys_ni_syscall           /* old mpx syscall holder */
        .long _sys_setpgid
        .long _sys_ni_syscall           /* old ulimit syscall holder */
        .long _sys_ni_syscall           /* old _sys_olduname holder */
        .long _sys_umask        /* 60 */
        .long _sys_chroot
        .long _sys_ustat
        .long _sys_dup2
        .long _sys_getppid
        .long _sys_getpgrp      /* 65 */
        .long _sys_setsid
        .long _sys_sigaction
        .long _sys_sgetmask
        .long _sys_ssetmask
        .long _sys_setreuid     /* 70 */
        .long _sys_setregid
        .long _sys_sigsuspend
        .long _sys_sigpending
        .long _sys_sethostname
        .long _sys_setrlimit    /* 75 */
        .long _sys_old_getrlimit
        .long _sys_getrusage
        .long _sys_gettimeofday
        .long _sys_settimeofday
        .long _sys_getgroups    /* 80 */
        .long _sys_setgroups
        .long _sys_select               /* was old_select */
        .long _sys_symlink
        .long _sys_lstat
        .long _sys_readlink     /* 85 */
        .long _sys_uselib
        .long _sys_swapon
        .long _sys_reboot
        .long _old_readdir
        .long _old_mmap         /* 90 */
        .long _sys_munmap
        .long _sys_truncate
        .long _sys_ftruncate
        .long _sys_fchmod
        .long _sys_fchown       /* 95 */
        .long _sys_getpriority
        .long _sys_setpriority
        .long _sys_ni_syscall                   /* old profil syscall holder */
        .long _sys_statfs
        .long _sys_fstatfs      /* 100 */
        .long _sys_ni_syscall                   /* _sys_ioperm in i386 */
        .long _sys_socketcall
        .long _sys_syslog
        .long _sys_setitimer
        .long _sys_getitimer    /* 105 */
        .long _sys_newstat
        .long _sys_newlstat
        .long _sys_newfstat
        .long _sys_ni_syscall                   /* old _sys_uname holder */
        .long _sys_ni_syscall   /* 110 */       /* _sys_iopl in i386 */
        .long _sys_vhangup
        .long _sys_ni_syscall   /* old 'idle' syscall */
        .long _sys_ni_syscall                   /* vm86 in i386 */
        .long _sys_wait4
        .long _sys_swapoff      /* 115 */
        .long _sys_sysinfo
        .long _sys_ipc
        .long _sys_fsync
        .long _sys_sigreturn
        .long _sys_clone        /* 120 */
        .long _sys_setdomainname
        .long _sys_newuname
        .long _sys_ni_syscall
        .long _sys_adjtimex
        .long _sys_mprotect     /* 125 */
        .long _sys_sigprocmask
        .long _sys_ni_syscall   /* old "create_module" */
        .long _sys_init_module
        .long _sys_delete_module
        .long _sys_ni_syscall   /* 130: old "get_kernel_syms" */
        .long _sys_quotactl
        .long _sys_getpgid
        .long _sys_fchdir
        .long _sys_bdflush
        .long _sys_sysfs        /* 135 */
        .long _sys_personality
        .long _sys_ni_syscall   /* reserved for afs_syscall */
        .long _sys_setfsuid
        .long _sys_setfsgid
        .long _sys_llseek       /* 140 */
        .long _sys_getdents
        .long _sys_select
        .long _sys_flock
        .long _sys_msync
        .long _sys_readv        /* 145 */
        .long _sys_writev
        .long _sys_getsid
        .long _sys_fdatasync
        .long _sys_sysctl
        .long _sys_mlock        /* 150 */
        .long _sys_munlock
        .long _sys_mlockall
        .long _sys_munlockall
        .long _sys_sched_setparam
        .long _sys_sched_getparam       /* 155 */
        .long _sys_sched_setscheduler
        .long _sys_sched_getscheduler
        .long _sys_sched_yield
        .long _sys_sched_get_priority_max
        .long _sys_sched_get_priority_min       /* 160 */
        .long _sys_sched_rr_get_interval
        .long _sys_nanosleep
        .long _sys_mremap
        .long _sys_setresuid
        .long _sys_getresuid    /* 165 */
        .long _sys_ni_syscall           /* old sys_query_module */
        .long _sys_poll
        .long _sys_nfsservctl
        .long _sys_setresgid
        .long _sys_getresgid    /* 170 */
        .long _sys_prctl
        .long _sys_rt_sigreturn
        .long _sys_rt_sigaction
        .long _sys_rt_sigprocmask       
        .long _sys_rt_sigpending        /* 175 */
        .long _sys_rt_sigtimedwait
        .long _sys_rt_sigqueueinfo
        .long _sys_rt_sigsuspend
        .long _sys_pread64
        .long _sys_pwrite64     /* 180 */
        .long _sys_chown
        .long _sys_getcwd
        .long _sys_capget
        .long _sys_capset
        .long _sys_sigaltstack  /* 185 */
        .long _sys_sendfile
        .long _sys_ni_syscall   /* streams1 */
        .long _sys_ni_syscall   /* streams2 */
        .long _sys_vfork
        .long _sys_getrlimit    /* 190 */
        .long _sys_readahead
        .long _sys_mmap2
        .long _sys_truncate64
        .long _sys_ftruncate64
        .long _sys_stat64       /* 195 */
        .long _sys_lstat64
        .long _sys_fstat64
        .long _sys_ni_syscall   /*      _sys_pciconfig_read */
        .long _sys_ni_syscall   /*      _sys_pciconfig_write */
        .long _sys_ni_syscall   /* 200  _sys_pciconfig_iobase */
        .long _sys_ni_syscall   /* 201  - reserved - MacOnLinux */
        .long _sys_getdents64
        .long _sys_pivot_root
        .long _sys_fcntl64
        .long _sys_madvise      /* 205 */
        .long _sys_mincore
        .long _sys_gettid
        .long _sys_tkill
        .long _sys_setxattr
        .long _sys_lsetxattr    /* 210 */
        .long _sys_fsetxattr
        .long _sys_getxattr
        .long _sys_lgetxattr
        .long _sys_fgetxattr
        .long _sys_listxattr    /* 215 */
        .long _sys_llistxattr
        .long _sys_flistxattr
        .long _sys_removexattr
        .long _sys_lremovexattr
        .long _sys_fremovexattr /* 220  */
        .long _sys_ni_syscall   /*      reserved for sys_futex */
        .long _sys_ni_syscall   /*      reserved for sys_sched_setaffinity */
        .long _sys_ni_syscall   /*      reserved for sys_sched_getaffinity */
        .long _sys_ni_syscall   /*      reserved for sys_security */
        .long _sys_ni_syscall   /* 225  reserved for Tux */
        .long _sys_ni_syscall   /*      reserved for sys_sendfile64 */
        .long _sys_ni_syscall   /*      reserved for sys_io_setup */
        .long _sys_ni_syscall   /*      reserved for sys_io_destroy */
        .long _sys_ni_syscall   /*      reserved for sys_io_getevents */
        .long _sys_ni_syscall   /* 230  reserved for sys_io_submit */
        .long _sys_ni_syscall   /*      reserved for sys_io_cancel */

        /*
         * NOTE!! This doesn't have to be exact - we just have
         * to make sure we have _enough_ of the "sys_ni_syscall"
         * entries. Don't panic if you notice that this hasn't
         * been shrunk every time we add a new system call.
         */

        .rept NR_syscalls-(.-_sys_call_table)/4
                .long _sys_ni_syscall
        .endr

/* ============================================================[ EOF ]=== */

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.