2013-01-18 15:12:18 +05:30
/ *
* Low L e v e l I n t e r r u p t s / T r a p s / E x c e p t i o n s ( n o n - T L B ) H a n d l i n g f o r A R C
*
* Copyright ( C ) 2 0 0 4 , 2 0 0 7 - 2 0 1 0 , 2 0 1 1 - 2 0 1 2 S y n o p s y s , I n c . ( w w w . s y n o p s y s . c o m )
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
*
* vineetg : Nov 2 0 1 0 :
* - Vector t a b l e j u m p s ( @8 bytes) converted into branches (@4 bytes)
* - To m a i n t a i n t h e s l o t s i z e o f 8 b y t e s / v e c t o r , a d d e d n o p , w h i c h i s
* not e x e c u t e d a t r u n t i m e .
*
* vineetg : Nov 2 0 0 9 ( E v e r y t h i n g n e e d e d f o r T I F _ R E S T O R E _ S I G M A S K )
* - do_ s i g n a l ( ) i n v o k e d u p o n T I F _ R E S T O R E _ S I G M A S K a s w e l l
* - Wrappers f o r s y s _ { ,r t _ } s i g s u s p e n d ( ) n o l o n g e r n e e d e d a s t h e y d o n ' t
* need p t r e g s a n y m o r e
*
* Vineetg : Oct 2 0 0 9
* - In a r a r e s c e n a r i o , P r o c e s s g e t s a P r i v - V e x c e p t i o n a n d g e t s s c h e d u l e d
* out. S i n c e w e d o n ' t d o F A K E R T I E f o r P r i v - V , C P U e x c p e t i o n s t a t e r e m a i n s
* active ( A E b i t e n a b l e d ) . T h i s c a u s e s a d o u b l e f a u l t f o r a s u b s e q v a l i d
* exception. T h u s F A K E R T I E n e e d e d i n l o w l e v e l P r i v - V i o l a t i o n h a n d l e r .
* Instr E r r o r c o u l d a l s o c a u s e s i m i l a r s c e n a r i o , s o s a m e t h e r e a s w e l l .
*
* Vineetg : Aug 2 8 t h 2 0 0 8 : B u g #94984
* - Zero O v e r h e a d L o o p C o n t e x t s h d b e c l e a r e d w h e n e n t e r i n g I R Q / E X c p / T r a p
* Normally C P U d o e s t h i s a u t o m a t i c a l l y , h o w e v e r w h e n d o i n g F A K E r t i e ,
* we n e e d t o e x p l i c i t l y d o t h i s . T h e p r o b l e m i n m a c r o s
* FAKE_ R E T _ F R O M _ E X C P N a n d F A K E _ R E T _ F R O M _ E X C P N _ L O C K _ I R Q w a s t h a t t h i s b i t
* was b e i n g " C L E A R E D " r a t h e r t h e n " S E T " . S i n c e i t i s L o o p I N H I B I T B i t ,
* setting i t a n d n o t c l e a r i n g i t c l e a r s Z O L c o n t e x t
*
* Vineetg : Dec 2 2 , 2 0 0 7
* Minor S u r g e r y o f L o w L e v e l I S R t o m a k e i t S M P s a f e
* - MMU_ S C R A T C H 0 R e g u s e d f o r f r e e i n g u p r9 i n L e v e l 1 I S R
* - _ current_ t a s k i s m a d e a n a r r a y o f N R _ C P U S
* - Access o f _ c u r r e n t _ t a s k w r a p p e d i n s i d e a m a c r o s o t h a t i f h a r d w a r e
* team a g r e e s f o r a d e d i c a t e d r e g , n o o t h e r c o d e i s t o u c h e d
*
* Amit B h o r , R a h u l T r i v e d i , K a n i k a N e m a , S a m e e r D h a v a l e : C o d i t o T e c h 2 0 0 4
* /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Function A B I
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Arguments r0 - r7
* Caller S a v e d R e g i s t e r s r0 - r12
* Callee S a v e d R e g i s t e r s r13 - r25
* Global P o i n t e r ( g p ) r26
* Frame P o i n t e r ( f p ) r27
* Stack P o i n t e r ( s p ) r28
* Interrupt l i n k r e g i s t e r ( i l i n k 1 ) r29
* Interrupt l i n k r e g i s t e r ( i l i n k 2 ) r30
* Branch l i n k r e g i s t e r ( b l i n k ) r31
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* /
.cpu A7
;############################ Vector Table #################################
.macro VECTOR lbl
# if 1 / * J u s t i n c a s e , b u i l d b r e a k s * /
j \ l b l
# else
b \ l b l
nop
# endif
.endm
.section .vector , " ax" ,@progbits
.align 4
/ * Each e n t r y i n t h e v e c t o r t a b l e m u s t o c c u p y 2 w o r d s . S i n c e i t i s a j u m p
* across s e c t i o n s ( . v e c t o r t o . t e x t ) w e a r e g a u r a n t e e d t h a t ' j s o m e w h e r e '
* will u s e t h e ' j l i m m ' f o r m o f t h e i n t r s u c t i o n a s l o n g a s s o m e w h e r e i s i n
* a s e c t i o n o t h e r t h a n . v e c t o r .
* /
; ********* Critical System Events **********************
VECTOR r e s _ s e r v i c e ; 0x0, Restart Vector (0x0)
VECTOR m e m _ s e r v i c e ; 0x8, Mem exception (0x1)
VECTOR i n s t r _ s e r v i c e ; 0x10, Instrn Error (0x2)
; ******************** Device ISRs **********************
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1
.rept 25
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1 ; Other devices
.endr
/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
; ******************** Exceptions **********************
VECTOR E V _ M a c h i n e C h e c k ; 0x100, Fatal Machine check (0x20)
VECTOR E V _ T L B M i s s I ; 0x108, Intruction TLB miss (0x21)
VECTOR E V _ T L B M i s s D ; 0x110, Data TLB miss (0x22)
VECTOR E V _ T L B P r o t V ; 0x118, Protection Violation (0x23)
; or Misaligned Access
VECTOR E V _ P r i v i l e g e V ; 0x120, Privilege Violation (0x24)
VECTOR E V _ T r a p ; 0x128, Trap exception (0x25)
VECTOR E V _ E x t e n s i o n ; 0x130, Extn Intruction Excp (0x26)
.rept 24
VECTOR r e s e r v e d ; Reserved Exceptions
.endr
# include < l i n u x / l i n k a g e . h > / * A R C _ { E X T R Y ,E X I T } * /
# include < a s m / e n t r y . h > / * S A V E _ A L L _ { I N T 1 ,I N T 2 ,T R A P . . . } * /
# include < a s m / e r r n o . h >
# include < a s m / a r c r e g s . h >
# include < a s m / i r q f l a g s . h >
;##################### Scratch Mem for IRQ stack switching #############
.section .data ; NOT .global
.align 32
.type int1 _ s a v e d _ r e g , @object
.size int1 _ s a v e d _ r e g , 4
int1_saved_reg :
.zero 4
; ---------------------------------------------
.section .text , " ax" ,@progbits
res_service : ; processor restart
flag 0 x1 ; not implemented
nop
nop
reserved : ; processor restart
rtie ; jump to processor initializations
;##################### Interrupt Handling ##############################
; ---------------------------------------------
; Level 1 ISR
; ---------------------------------------------
ARC_ E N T R Y h a n d l e _ i n t e r r u p t _ l e v e l 1
/* free up r9 as scratchpad */
st r9 , [ @int1_saved_reg]
;Which mode (user/kernel) was the system in when intr occured
lr r9 , [ s t a t u s32 _ l 1 ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ I N T 1
lr r0 , [ i c a u s e 1 ]
and r0 , r0 , 0 x1 f
bl. d @arch_do_IRQ
mov r1 , s p
mov r8 ,0 x1
sr r8 , [ A U X _ I R Q _ L V 1 2 ] ; clear bit in Sticky Status Reg
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T h a n d l e _ i n t e r r u p t _ l e v e l 1
;################### Non TLB Exception Handling #############################
; ---------------------------------------------
; Instruction Error Exception Handler
; ---------------------------------------------
ARC_ E N T R Y i n s t r _ s e r v i c e
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
lr r0 , [ e c r ]
lr r1 , [ e f a ]
mov r2 , s p
FAKE_ R E T _ F R O M _ E X C P N r9
bl d o _ i n s t e r r o r _ o r _ k p r o b e
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T i n s t r _ s e r v i c e
; ---------------------------------------------
; Memory Error Exception Handler
; ---------------------------------------------
ARC_ E N T R Y m e m _ s e r v i c e
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
lr r0 , [ e c r ]
lr r1 , [ e f a ]
mov r2 , s p
bl d o _ m e m o r y _ e r r o r
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T m e m _ s e r v i c e
; ---------------------------------------------
; Machine Check Exception Handler
; ---------------------------------------------
ARC_ E N T R Y E V _ M a c h i n e C h e c k
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
lr r0 , [ e c r ]
lr r1 , [ e f a ]
mov r2 , s p
brne r0 , 0 x20 0 1 0 0 , 1 f
bl d o _ t l b _ o v e r l a p _ f a u l t
b r e t _ f r o m _ e x c e p t i o n
1 :
; DEAD END: can't do much, display Regs and HALT
SAVE_ C A L L E E _ S A V E D _ U S E R
GET_ C U R R _ T A S K _ F I E L D _ P T R T A S K _ T H R E A D , r10
st s p , [ r10 , T H R E A D _ C A L L E E _ R E G ]
j d o _ m a c h i n e _ c h e c k _ f a u l t
ARC_ E X I T E V _ M a c h i n e C h e c k
; ---------------------------------------------
; Protection Violation Exception Handler
; ---------------------------------------------
ARC_ E N T R Y E V _ T L B P r o t V
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
;Which mode (user/kernel) was the system in when Exception occured
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
;---------(3) Save some more regs-----------------
; vineetg: Mar 6th: Random Seg Fault issue #1
; ecr and efa were not saved in case an Intr sneaks in
; after fake rtie
;
lr r3 , [ e c r ]
lr r4 , [ e f a ]
; --------(4) Return from CPU Exception Mode ---------
; Fake a rtie, but rtie to next label
; That way, subsequently, do_page_fault ( ) executes in pure kernel
; mode with further Exceptions enabled
FAKE_ R E T _ F R O M _ E X C P N r9
;------ (5) Type of Protection Violation? ----------
;
; ProtV Hardware Exception is triggered for Access Faults of 2 types
; -Access Violaton (WRITE to READ ONLY Page) - for linux COW
; -Unaligned Access (READ/WRITE on odd boundary)
;
cmp r3 , 0 x23 0 4 0 0 ; Misaligned data access ?
beq 4 f
;========= (6a) Access Violation Processing ========
cmp r3 , 0 x23 0 1 0 0
mov r1 , 0 x0 ; if LD exception ? write = 0
mov. n e r1 , 0 x1 ; else write = 1
mov r2 , r4 ; faulting address
mov r0 , s p ; pt_regs
bl d o _ p a g e _ f a u l t
b r e t _ f r o m _ e x c e p t i o n
;========== (6b) Non aligned access ============
4 :
mov r0 , r3 ; cause code
mov r1 , r4 ; faulting address
mov r2 , s p ; pt_regs
bl d o _ m i s a l i g n e d _ a c c e s s
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T E V _ T L B P r o t V
; ---------------------------------------------
; Privilege Violation Exception Handler
; ---------------------------------------------
ARC_ E N T R Y E V _ P r i v i l e g e V
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
lr r0 , [ e c r ]
lr r1 , [ e f a ]
mov r2 , s p
FAKE_ R E T _ F R O M _ E X C P N r9
bl d o _ p r i v i l e g e _ f a u l t
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T E V _ P r i v i l e g e V
; ---------------------------------------------
; Extension Instruction Exception Handler
; ---------------------------------------------
ARC_ E N T R Y E V _ E x t e n s i o n
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ S Y S
lr r0 , [ e c r ]
lr r1 , [ e f a ]
mov r2 , s p
bl d o _ e x t e n s i o n _ f a u l t
b r e t _ f r o m _ e x c e p t i o n
ARC_ E X I T E V _ E x t e n s i o n
;################### Break Point TRAP ##########################
; ======= (5b) Trap is due to Break-Point =========
trap_with_param :
;make sure orig_r8 is a positive value
st N R _ s y s c a l l s + 2 , [ s p , P T _ o r i g _ r8 ]
mov r0 , r12
lr r1 , [ e f a ]
mov r2 , s p
; Now that we have read EFA, its safe to do "fake" rtie
; and get out of CPU exception mode
FAKE_ R E T _ F R O M _ E X C P N r11
; Save callee regs in case gdb wants to have a look
; SP will grow up by size of CALLEE Reg-File
; NOTE: clobbers r12
SAVE_ C A L L E E _ S A V E D _ U S E R
; save location of saved Callee Regs @ thread_struct->pc
GET_ C U R R _ T A S K _ F I E L D _ P T R T A S K _ T H R E A D , r10
st s p , [ r10 , T H R E A D _ C A L L E E _ R E G ]
; Call the trap handler
bl d o _ n o n _ s w i _ t r a p
; unwind stack to discard Callee saved Regs
DISCARD_ C A L L E E _ S A V E D _ U S E R
b r e t _ f r o m _ e x c e p t i o n
;##################### Trap Handling ##############################
;
; EV_Trap caused by TRAP_S and TRAP0 instructions.
;------------------------------------------------------------------
; (1) System Calls
; :parameters in r0-r7.
; :r8 has the system call number
; (2) Break Points
;------------------------------------------------------------------
ARC_ E N T R Y E V _ T r a p
; Need at least 1 reg to code the early exception prolog
EXCPN_ P R O L O G _ F R E E U P _ R E G r9
;Which mode (user/kernel) was the system in when intr occured
lr r9 , [ e r s t a t u s ]
SWITCH_ T O _ K E R N E L _ S T K
SAVE_ A L L _ T R A P
;------- (4) What caused the Trap --------------
lr r12 , [ e c r ]
and. f 0 , r12 , E C R _ P A R A M _ M A S K
bnz t r a p _ w i t h _ p a r a m
; ======= (5a) Trap is due to System Call ========
; Before doing anything, return from CPU Exception Mode
FAKE_ R E T _ F R O M _ E X C P N r11
;============ This is normal System Call case ==========
; Sys-call num shd not exceed the total system calls avail
cmp r8 , N R _ s y s c a l l s
mov. h i r0 , - E N O S Y S
bhi r e t _ f r o m _ s y s t e m _ c a l l
; Offset into the syscall_table and call handler
ld. a s r9 ,[ s y s _ c a l l _ t a b l e , r8 ]
jl [ r9 ] ; Entry into Sys Call Handler
; fall through to ret_from_system_call
ARC_ E X I T E V _ T r a p
ARC_ E N T R Y r e t _ f r o m _ s y s t e m _ c a l l
st r0 , [ s p , P T _ r0 ] ; sys call return value in pt_regs
; fall through yet again to ret_from_exception
;############# Return from Intr/Excp/Trap (Linux Specifics) ##############
;
; If ret to user mode do we need to handle signals, schedule() et al.
ARC_ E N T R Y r e t _ f r o m _ e x c e p t i o n
; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32
ld r8 , [ s p , P T _ s t a t u s32 ] ; returning to User/Kernel Mode
# ifdef C O N F I G _ P R E E M P T
bbit0 r8 , S T A T U S _ U _ B I T , r e s u m e _ k e r n e l _ m o d e
# else
bbit0 r8 , S T A T U S _ U _ B I T , r e s t o r e _ r e g s
# endif
; Before returning to User mode check-for-and-complete any pending work
; such as rescheduling/signal-delivery etc.
resume_user_mode_begin :
; Disable IRQs to ensures that chk for pending work itself is atomic
; (and we don't end up missing a NEED_RESCHED/SIGPENDING due to an
; interim IRQ).
IRQ_ D I S A B L E r10
; Fast Path return to user mode if no pending work
GET_ C U R R _ T H R _ I N F O _ F L A G S r9
and. f 0 , r9 , _ T I F _ W O R K _ M A S K
bz r e s t o r e _ r e g s
; --- (Slow Path #1) task preemption ---
bbit0 r9 , T I F _ N E E D _ R E S C H E D , . L c h k _ p e n d _ s i g n a l s
mov b l i n k , r e s u m e _ u s e r _ m o d e _ b e g i n ; tail-call to U mode ret chks
b @schedule ; BTST+Bnz causes relo error in link
.Lchk_pend_signals :
IRQ_ E N A B L E r10
; --- (Slow Path #2) pending signal ---
mov r0 , s p ; pt_regs for arg to do_signal()/do_notify_resume()
bbit0 r9 , T I F _ S I G P E N D I N G , . L c h k _ n o t i f y _ r e s u m e
; save CALLEE Regs.
; (i) If this signal causes coredump - full regfile needed
; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus
; tracer might call PEEKUSR(CALLEE reg)
;
; NOTE: SP will grow up by size of CALLEE Reg-File
SAVE_ C A L L E E _ S A V E D _ U S E R ; clobbers r12
; save location of saved Callee Regs @ thread_struct->callee
GET_ C U R R _ T A S K _ F I E L D _ P T R T A S K _ T H R E A D , r10
st s p , [ r10 , T H R E A D _ C A L L E E _ R E G ]
bl @do_signal
; unwind SP for cheap discard of Callee saved Regs
DISCARD_ C A L L E E _ S A V E D _ U S E R
b r e s u m e _ u s e r _ m o d e _ b e g i n ; loop back to start of U mode ret
; --- (Slow Path #3) notify_resume ---
.Lchk_notify_resume :
btst r9 , T I F _ N O T I F Y _ R E S U M E
blnz @do_notify_resume
b r e s u m e _ u s e r _ m o d e _ b e g i n ; unconditionally back to U mode ret chks
; for single exit point from this block
# ifdef C O N F I G _ P R E E M P T
resume_kernel_mode :
; Can't preempt if preemption disabled
GET_ C U R R _ T H R _ I N F O _ F R O M _ S P r10
ld r8 , [ r10 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T ]
brne r8 , 0 , r e s t o r e _ r e g s
; check if this task's NEED_RESCHED flag set
ld r9 , [ r10 , T H R E A D _ I N F O _ F L A G S ]
bbit0 r9 , T I F _ N E E D _ R E S C H E D , r e s t o r e _ r e g s
IRQ_ D I S A B L E r9
; Invoke PREEMPTION
bl p r e e m p t _ s c h e d u l e _ i r q
; preempt_schedule_irq() always returns with IRQ disabled
# endif
; fall through
;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
;
; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
; IRQ shd definitely not happen between now and rtie
restore_ r e g s :
; Disable Interrupts while restoring reg-file back
; XXX can this be optimised out
IRQ_ D I S A B L E _ S A V E r9 , r10 ;@r10 has prisitine (pre-disable) copy
; Restore REG File. In case multiple Events outstanding,
; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
; Note that we use realtime STATUS32 (not pt_regs->status32) to
; decide that.
; if Returning from Exception
bbit0 r10 , S T A T U S _ A E _ B I T , n o t _ e x c e p t i o n
RESTORE_ A L L _ S Y S
rtie
; Not Exception so maybe Interrupts (Level 1 or 2)
not_exception :
bbit0 r10 , S T A T U S _ A 1 _ B I T , n o t _ l e v e l 1 _ i n t e r r u p t
;return from level 1
RESTORE_ A L L _ I N T 1
debug_marker_l1 :
rtie
not_level1_interrupt :
;this case is for syscalls or Exceptions (with fake rtie)
RESTORE_ A L L _ S Y S
debug_marker_syscall :
rtie
ARC_ E X I T r e t _ f r o m _ e x c e p t i o n
ARC_ E N T R Y r e t _ f r o m _ f o r k
; when the forked child comes here from the __switch_to function
; r0 has the last task pointer.
; put last task in scheduler queue
2013-01-18 15:12:18 +05:30
bl @schedule_tail
; If kernel thread, jump to it's entry-point
ld r9 , [ s p , P T _ s t a t u s32 ]
brne r9 , 0 , 1 f
jl. d [ r14 ]
mov r0 , r13 ; arg to payload
1 :
; special case of kernel_thread entry point returning back due to
; kernel_execve() - pretend return from syscall to ret to userland
b r e t _ f r o m _ e x c e p t i o n
2013-01-18 15:12:18 +05:30
ARC_ E X I T r e t _ f r o m _ f o r k
2013-01-18 15:12:18 +05:30
;################### Special Sys Call Wrappers ##########################
; TBD: call do_fork directly from here
ARC_ E N T R Y s y s _ f o r k _ w r a p p e r
SAVE_ C A L L E E _ S A V E D _ U S E R
bl @sys_fork
DISCARD_ C A L L E E _ S A V E D _ U S E R
b r e t _ f r o m _ s y s t e m _ c a l l
ARC_ E X I T s y s _ f o r k _ w r a p p e r
ARC_ E N T R Y s y s _ v f o r k _ w r a p p e r
SAVE_ C A L L E E _ S A V E D _ U S E R
bl @sys_vfork
DISCARD_ C A L L E E _ S A V E D _ U S E R
b r e t _ f r o m _ s y s t e m _ c a l l
ARC_ E X I T s y s _ v f o r k _ w r a p p e r
ARC_ E N T R Y s y s _ c l o n e _ w r a p p e r
SAVE_ C A L L E E _ S A V E D _ U S E R
bl @sys_clone
DISCARD_ C A L L E E _ S A V E D _ U S E R
b r e t _ f r o m _ s y s t e m _ c a l l
ARC_ E X I T s y s _ c l o n e _ w r a p p e r