URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [or32/] [kernel/] [entry.S] - Rev 1765
Compare with Previous | Blame | View Log
/*
* linux/arch/or32/kernel/entry.S
*
* or32 version
* author(s): Matjaz Breskvar (phoenix@opencores.org)
*
* changes:
* 18. 11. 2003: Matjaz Breskvar (phoenix@opencores.org)
* initial port to or32 architecture
* 06. 12. 2003: Matjaz Breskvar (phoenix@opencores.org)
* major changes in handling exceptions
* physical addresses used only by code in head.S
* cleand exception handlers and moved them to entry.S
* 10. 11. 2005: Gyorgy Jeney (nog@sdf.lonestar.org)
* 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/config.h>
#include <linux/linkage.h>
#include <linux/sys.h>
#include <asm/processor.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/pgtable.h>
/* some defines to ease or32 assembly programming */
#include "or32_defs.h"
#include "or32_funcs.S"
#define GET_CURRENT(reg,t1) \
LOAD_SYMBOL_2_GPR(reg,_current_set) ;\
tophys (t1,reg) ;\
l.lwz reg,0(t1)
/* =========================================================[ 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, r2, EPCR, ESR a already saved */ ;\
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 ;\
l.sw GPR10(r1),r10 ;\
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, r2, EPCR, ESR a already saved */ ;\
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 ;\
l.sw GPR10(r1),r10 ;\
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)
#ifndef CONFIG_ESR_EXCEPTION_WORKS
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 %x %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)
#ifndef CONFIG_ESR_EXCEPTION_WORKS
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 %x %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)
/* check that userspace didn't try to fool us with
* syscall number greater then __NR_syscall.
*/
l.sfgeui r11,NR_syscalls
l.bnf 10f
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),r11
l.addi r1,r1,0x8
.section .rodata, "a"
42:
.string "\n\rkernel error: SYSCALL_NR out of range (0x%x)\n\r"
.align 4
.previous
/* let's fix it to the last */
l.ori r11,r0,NR_syscalls-1
10:
ENABLE_INTERRUPTS(r9) // enable interrupts, r9 is temp
// Check if syscall needs to be traced
l.lwz r30,TASK_PTRACE(r2)
l.andi r30,r30,PT_TRACESYS
l.sfnei r30,0
l.bf trace_a_syscall
l.nop
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)
// Ok, syscall doesn't need to be traced, call it
l.jalr r30
l.addi r8,r1,0 // regs pointer
l.sw GPR11(r1),r11 // save return value
20:
l.sw RESULT(r1),r11 // save result
99:
l.j _ret_from_sys_call
l.addi r12,r0,0x1 // we came from syscall
/* ---[ 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 ] === */
ENTRY(_ret_from_fork)
l.jal _schedule_tail
l.nop
// Check if PT_TRACESYS is set on the current process
l.lwz r4,TASK_PTRACE(r2)
l.andi r4,r4,PT_TRACESYS
l.sfnei r4,0
l.bf tracesys_exit
l.nop
l.j _ret_from_sys_call
l.nop
ENTRY(_ret_from_sys_call)
DISABLE_INTERRUPTS(r3,r4)
/* kernel -> user transition
* we need to save kernel sp so we can restore it
* at user -> kernel transition
*/
LOAD_SYMBOL_2_GPR(r3,_current_set)
l.lwz r2,0(r3)
l.addi r4,r1,INT_FRAME_SIZE
l.sw (THREAD+THREAD_KSP)(r2),r4
/*
* if (current->need_resched != 0)
* schedule();
*/
reschedule:
l.lwz r3,NEED_RESCHED(r2)
l.sfeqi r3,0
l.bf signal_return
l.nop
l.jal _schedule
l.nop
l.j reschedule
l.nop
/*
* if (current->sigpending != 0)
* do_signal(r3,r4);
*/
signal_return:
/* __PHX__ recheck the right behaviour */
// ENABLE_INTERRUPTS(r3)
DISABLE_INTERRUPTS(r3,r4)
/* r12 is parameter: 1 if we came fro sys_call, else 0 */
l.lwz r5,SIGPENDING(r2)
l.sfeqi r5,0
l.bf _restore_all
l.addi r3,r12,0
l.addi r4,r0,0
l.addi r5,r1,0
l.jal _do_signal
l.nop
l.j _restore_all
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 (THREAD+THREAD_KSP)(r2),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
*/
l.j _ret_from_sys_call
l.nop
/* =================================================[ trace syscall ] === */
trace_a_syscall:
l.jal _syscall_trace
// Save the system call number for strace
l.sw SYSCALLNO(r1),r11
// Restore argument registers
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 r11,SYSCALLNO(r1)
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)
// Do the sys call
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
l.addi r12,r0,0x1 // we came from syscall
tracesys_exit:
l.jal _syscall_trace
l.addi r14,r12,0
l.j _ret_from_sys_call
l.addi r12,r14,0
/* ========================================================[ 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.
*/
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,r2,0 /* Save old 'current' to 'last' return value*/
l.lwz r3,(GPR3-INT_FRAME_SIZE)(r1)
PUSH_PT_REGS_NO_TRANS
l.sw THREAD_KSP(r3),r1 /* Set old stack pointer */
l.lwz r1,THREAD_KSP(r4) /* Load new stack pointer */
l.addi r2,r4,-THREAD /* set current (r2) to new */
RESTORE_ALL_NO_R11
/* =================================================[ syscall table ] === */
.data
.align 4
.global _sys_call_table
_sys_call_table:
.long SYMBOL_NAME(_sys_ni_syscall) /* 0 - old "setup()" system call */
.long SYMBOL_NAME(_sys_exit)
.long SYMBOL_NAME(_sys_fork)
.long SYMBOL_NAME(_sys_read)
.long SYMBOL_NAME(_sys_write)
.long SYMBOL_NAME(_sys_open) /* 5 */
.long SYMBOL_NAME(_sys_close)
.long SYMBOL_NAME(_sys_waitpid)
.long SYMBOL_NAME(_sys_creat)
.long SYMBOL_NAME(_sys_link)
.long SYMBOL_NAME(_sys_unlink) /* 10 */
.long SYMBOL_NAME(_sys_execve)
.long SYMBOL_NAME(_sys_chdir)
.long SYMBOL_NAME(_sys_time)
.long SYMBOL_NAME(_sys_mknod)
.long SYMBOL_NAME(_sys_chmod) /* 15 */
.long SYMBOL_NAME(_sys_lchown)
.long SYMBOL_NAME(_sys_ni_syscall) /* old break syscall holder */
.long SYMBOL_NAME(_sys_stat)
.long SYMBOL_NAME(_sys_lseek)
.long SYMBOL_NAME(_sys_getpid) /* 20 */
.long SYMBOL_NAME(_sys_mount)
.long SYMBOL_NAME(_sys_oldumount)
.long SYMBOL_NAME(_sys_setuid)
.long SYMBOL_NAME(_sys_getuid)
.long SYMBOL_NAME(_sys_stime) /* 25 */
.long SYMBOL_NAME(_sys_ptrace)
.long SYMBOL_NAME(_sys_alarm)
.long SYMBOL_NAME(_sys_fstat)
.long SYMBOL_NAME(_sys_pause)
.long SYMBOL_NAME(_sys_utime) /* 30 */
.long SYMBOL_NAME(_sys_ni_syscall) /* old stty syscall holder */
.long SYMBOL_NAME(_sys_ni_syscall) /* old gtty syscall holder */
.long SYMBOL_NAME(_sys_access)
.long SYMBOL_NAME(_sys_nice)
.long SYMBOL_NAME(_sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
.long SYMBOL_NAME(_sys_sync)
.long SYMBOL_NAME(_sys_kill)
.long SYMBOL_NAME(_sys_rename)
.long SYMBOL_NAME(_sys_mkdir)
.long SYMBOL_NAME(_sys_rmdir) /* 40 */
.long SYMBOL_NAME(_sys_dup)
.long SYMBOL_NAME(_sys_pipe)
.long SYMBOL_NAME(_sys_times)
.long SYMBOL_NAME(_sys_ni_syscall) /* old prof syscall holder */
.long SYMBOL_NAME(_sys_brk) /* 45 */
.long SYMBOL_NAME(_sys_setgid)
.long SYMBOL_NAME(_sys_getgid)
.long SYMBOL_NAME(_sys_signal)
.long SYMBOL_NAME(_sys_geteuid)
.long SYMBOL_NAME(_sys_getegid) /* 50 */
.long SYMBOL_NAME(_sys_acct)
.long SYMBOL_NAME(_sys_umount) /* recycled never used phys() */
.long SYMBOL_NAME(_sys_ni_syscall) /* old lock syscall holder */
.long SYMBOL_NAME(_sys_ioctl)
.long SYMBOL_NAME(_sys_fcntl) /* 55 */
.long SYMBOL_NAME(_sys_ni_syscall) /* old mpx syscall holder */
.long SYMBOL_NAME(_sys_setpgid)
.long SYMBOL_NAME(_sys_ni_syscall) /* old ulimit syscall holder */
.long SYMBOL_NAME(_sys_ni_syscall) /* old _sys_olduname holder */
.long SYMBOL_NAME(_sys_umask) /* 60 */
.long SYMBOL_NAME(_sys_chroot)
.long SYMBOL_NAME(_sys_ustat)
.long SYMBOL_NAME(_sys_dup2)
.long SYMBOL_NAME(_sys_getppid)
.long SYMBOL_NAME(_sys_getpgrp) /* 65 */
.long SYMBOL_NAME(_sys_setsid)
.long SYMBOL_NAME(_sys_sigaction)
.long SYMBOL_NAME(_sys_sgetmask)
.long SYMBOL_NAME(_sys_ssetmask)
.long SYMBOL_NAME(_sys_setreuid) /* 70 */
.long SYMBOL_NAME(_sys_setregid)
.long SYMBOL_NAME(_sys_sigsuspend)
.long SYMBOL_NAME(_sys_sigpending)
.long SYMBOL_NAME(_sys_sethostname)
.long SYMBOL_NAME(_sys_setrlimit) /* 75 */
.long SYMBOL_NAME(_sys_old_getrlimit)
.long SYMBOL_NAME(_sys_getrusage)
.long SYMBOL_NAME(_sys_gettimeofday)
.long SYMBOL_NAME(_sys_settimeofday)
.long SYMBOL_NAME(_sys_getgroups) /* 80 */
.long SYMBOL_NAME(_sys_setgroups)
.long SYMBOL_NAME(_sys_select) /* was old_select */
.long SYMBOL_NAME(_sys_symlink)
.long SYMBOL_NAME(_sys_lstat)
.long SYMBOL_NAME(_sys_readlink) /* 85 */
.long SYMBOL_NAME(_sys_uselib)
.long SYMBOL_NAME(_sys_swapon)
.long SYMBOL_NAME(_sys_reboot)
.long SYMBOL_NAME(_old_readdir)
.long SYMBOL_NAME(_old_mmap) /* 90 */
.long SYMBOL_NAME(_sys_munmap)
.long SYMBOL_NAME(_sys_truncate)
.long SYMBOL_NAME(_sys_ftruncate)
.long SYMBOL_NAME(_sys_fchmod)
.long SYMBOL_NAME(_sys_fchown) /* 95 */
.long SYMBOL_NAME(_sys_getpriority)
.long SYMBOL_NAME(_sys_setpriority)
.long SYMBOL_NAME(_sys_ni_syscall) /* old profil syscall holder */
.long SYMBOL_NAME(_sys_statfs)
.long SYMBOL_NAME(_sys_fstatfs) /* 100 */
.long SYMBOL_NAME(_sys_ni_syscall) /* _sys_ioperm in i386 */
.long SYMBOL_NAME(_sys_socketcall)
.long SYMBOL_NAME(_sys_syslog)
.long SYMBOL_NAME(_sys_setitimer)
.long SYMBOL_NAME(_sys_getitimer) /* 105 */
.long SYMBOL_NAME(_sys_newstat)
.long SYMBOL_NAME(_sys_newlstat)
.long SYMBOL_NAME(_sys_newfstat)
.long SYMBOL_NAME(_sys_ni_syscall) /* old _sys_uname holder */
.long SYMBOL_NAME(_sys_ni_syscall) /* 110 */ /* _sys_iopl in i386 */
.long SYMBOL_NAME(_sys_vhangup)
.long SYMBOL_NAME(_sys_ni_syscall) /* old 'idle' syscall */
.long SYMBOL_NAME(_sys_ni_syscall) /* vm86 in i386 */
.long SYMBOL_NAME(_sys_wait4)
.long SYMBOL_NAME(_sys_swapoff) /* 115 */
.long SYMBOL_NAME(_sys_sysinfo)
.long SYMBOL_NAME(_sys_ipc)
.long SYMBOL_NAME(_sys_fsync)
.long SYMBOL_NAME(_sys_sigreturn)
.long SYMBOL_NAME(_sys_clone) /* 120 */
.long SYMBOL_NAME(_sys_setdomainname)
.long SYMBOL_NAME(_sys_newuname)
.long SYMBOL_NAME(_sys_ni_syscall)
.long SYMBOL_NAME(_sys_adjtimex)
.long SYMBOL_NAME(_sys_mprotect) /* 125 */
.long SYMBOL_NAME(_sys_sigprocmask)
.long SYMBOL_NAME(_sys_create_module)
.long SYMBOL_NAME(_sys_init_module)
.long SYMBOL_NAME(_sys_delete_module)
.long SYMBOL_NAME(_sys_get_kernel_syms) /* 130 */
.long SYMBOL_NAME(_sys_quotactl)
.long SYMBOL_NAME(_sys_getpgid)
.long SYMBOL_NAME(_sys_fchdir)
.long SYMBOL_NAME(_sys_bdflush)
.long SYMBOL_NAME(_sys_sysfs) /* 135 */
.long SYMBOL_NAME(_sys_personality)
.long SYMBOL_NAME(_sys_ni_syscall) /* for afs_syscall */
.long SYMBOL_NAME(_sys_setfsuid)
.long SYMBOL_NAME(_sys_setfsgid)
.long SYMBOL_NAME(_sys_llseek) /* 140 */
.long SYMBOL_NAME(_sys_getdents)
.long SYMBOL_NAME(_sys_select)
.long SYMBOL_NAME(_sys_flock)
.long SYMBOL_NAME(_sys_msync)
.long SYMBOL_NAME(_sys_readv) /* 145 */
.long SYMBOL_NAME(_sys_writev)
.long SYMBOL_NAME(_sys_getsid)
.long SYMBOL_NAME(_sys_fdatasync)
.long SYMBOL_NAME(_sys_sysctl)
.long SYMBOL_NAME(_sys_mlock) /* 150 */
.long SYMBOL_NAME(_sys_munlock)
.long SYMBOL_NAME(_sys_mlockall)
.long SYMBOL_NAME(_sys_munlockall)
.long SYMBOL_NAME(_sys_sched_setparam)
.long SYMBOL_NAME(_sys_sched_getparam) /* 155 */
.long SYMBOL_NAME(_sys_sched_setscheduler)
.long SYMBOL_NAME(_sys_sched_getscheduler)
.long SYMBOL_NAME(_sys_sched_yield)
.long SYMBOL_NAME(_sys_sched_get_priority_max)
.long SYMBOL_NAME(_sys_sched_get_priority_min) /* 160 */
.long SYMBOL_NAME(_sys_sched_rr_get_interval)
.long SYMBOL_NAME(_sys_nanosleep)
.long SYMBOL_NAME(_sys_mremap)
.long SYMBOL_NAME(_sys_setresuid)
.long SYMBOL_NAME(_sys_getresuid) /* 165 */
.long SYMBOL_NAME(_sys_query_module)
.long SYMBOL_NAME(_sys_poll)
.long SYMBOL_NAME(_sys_nfsservctl)
.long SYMBOL_NAME(_sys_setresgid)
.long SYMBOL_NAME(_sys_getresgid) /* 170 */
.long SYMBOL_NAME(_sys_prctl)
.long SYMBOL_NAME(_sys_rt_sigreturn)
.long SYMBOL_NAME(_sys_rt_sigaction)
.long SYMBOL_NAME(_sys_rt_sigprocmask)
.long SYMBOL_NAME(_sys_rt_sigpending) /* 175 */
.long SYMBOL_NAME(_sys_rt_sigtimedwait)
.long SYMBOL_NAME(_sys_rt_sigqueueinfo)
.long SYMBOL_NAME(_sys_rt_sigsuspend)
.long SYMBOL_NAME(_sys_pread)
.long SYMBOL_NAME(_sys_pwrite) /* 180 */
.long SYMBOL_NAME(_sys_chown)
.long SYMBOL_NAME(_sys_getcwd)
.long SYMBOL_NAME(_sys_capget)
.long SYMBOL_NAME(_sys_capset)
.long SYMBOL_NAME(_sys_sigaltstack) /* 185 */
.long SYMBOL_NAME(_sys_sendfile)
.long SYMBOL_NAME(_sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(_sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(_sys_vfork)
.long SYMBOL_NAME(_sys_getrlimit) /* 190 */
.long SYMBOL_NAME(_sys_readahead)
.long SYMBOL_NAME(_sys_mmap2)
.long SYMBOL_NAME(_sys_truncate64)
.long SYMBOL_NAME(_sys_ftruncate64)
.long SYMBOL_NAME(_sys_stat64) /* 195 */
.long SYMBOL_NAME(_sys_lstat64)
.long SYMBOL_NAME(_sys_fstat64)
.long SYMBOL_NAME(_sys_ni_syscall) /* _sys_pciconfig_read */
.long SYMBOL_NAME(_sys_ni_syscall) /* _sys_pciconfig_write */
.long SYMBOL_NAME(_sys_ni_syscall) /* 200 */ /* _sys_pciconfig_iobase */
.long SYMBOL_NAME(_sys_ni_syscall) /* 201 - reserved - MacOnLinux - new */
.long SYMBOL_NAME(_sys_getdents64)
.long SYMBOL_NAME(_sys_pivot_root)
.long SYMBOL_NAME(_sys_fcntl64)
.long SYMBOL_NAME(_sys_madvise) /* 205 */
.long SYMBOL_NAME(_sys_mincore)
.long SYMBOL_NAME(_sys_gettid)
.long SYMBOL_NAME(_sys_tkill)
.long SYMBOL_NAME(_sys_setxattr)
.long SYMBOL_NAME(_sys_lsetxattr) /* 210 */
.long SYMBOL_NAME(_sys_fsetxattr)
.long SYMBOL_NAME(_sys_getxattr)
.long SYMBOL_NAME(_sys_lgetxattr)
.long SYMBOL_NAME(_sys_fgetxattr)
.long SYMBOL_NAME(_sys_listxattr) /* 215 */
.long SYMBOL_NAME(_sys_llistxattr)
.long SYMBOL_NAME(_sys_flistxattr)
.long SYMBOL_NAME(_sys_removexattr)
.long SYMBOL_NAME(_sys_lremovexattr)
.long SYMBOL_NAME(_sys_fremovexattr) /* 220 */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_futex */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_sched_setaffinity */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_sched_getaffinity */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_security */
.long SYMBOL_NAME(_sys_ni_syscall) /* 225 reserved for Tux */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_sendfile64 */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_io_setup */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_io_destroy */
.long SYMBOL_NAME(_sys_ni_syscall) /* reserved for sys_io_getevents */
.long SYMBOL_NAME(_sys_ni_syscall) /* 230 reserved for sys_io_submit */
.long SYMBOL_NAME(_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 SYMBOL_NAME(_sys_ni_syscall)
.endr
/* ============================================================[ EOF ]=== */