2019-06-04 11:11:33 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2015-02-21 12:39:32 +03:00
/ *
* 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 o m p a c t I S A
*
* Copyright ( C ) 2 0 1 4 - 1 5 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 )
* 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 )
*
* vineetg : May 2 0 1 1
* - Userspace u n a l i g n e d a c c e s s e m u l a t i o n
*
* vineetg : Feb 2 0 1 1 ( p t r a c e l o w l e v e l c o d e f i x e s )
* - traced s y s c a l l r e t u r n c o d e ( r0 ) w a s n o t s a v e d i n t o p t _ r e g s f o r r e s t o r i n g
* into u s e r r e g - f i l e w h e n t r a d e d t a s k r e t s t o u s e r s p a c e .
* - syscalls n e e d i n g a r c h - w r a p p e r s ( m a i n l y f o r p a s s i n g s p a s p t _ r e g s )
* were n o t i n v o k i n g p o s t - s y s c a l l t r a c e h o o k ( j u m p i n g d i r e c t l y i n t o
* ret_ f r o m _ s y s t e m _ c a l l )
*
* 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
2017-05-28 09:52:01 +03:00
* - 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
2015-02-21 12:39:32 +03:00
* 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
2017-05-28 09:52:01 +03:00
* 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 e p t i o n s t a t e r e m a i n s
2015-02-21 12:39:32 +03:00
* 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 : March 2 0 0 9 ( S u p p o r t i n g 2 l e v e l s o f I n t e r r u p t s )
*
* 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 : May 1 6 t h , 2 0 0 8
* - r2 5 n o w c o n t a i n s t h e C u r r e n t T a s k w h e n i n k e r n e l
*
* 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
* /
# include < l i n u x / e r r n o . h >
2017-05-28 09:52:01 +03:00
# include < l i n u x / l i n k a g e . h > / * { E N T R Y ,E X I T } * /
2015-02-21 12:39:32 +03:00
# include < a s m / e n t r y . h >
# include < a s m / i r q f l a g s . h >
.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
2017-05-28 09:52:01 +03:00
* 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 u a 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 s t r 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
2015-02-21 12:39:32 +03:00
* 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 **********************
2015-10-09 08:56:12 +03:00
VECTOR r e s _ s e r v i c e ; 0x0, Reset Vector (0x0)
2015-02-21 12:39:32 +03:00
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 **********************
2016-05-30 16:51:22 +03:00
# ifdef C O N F I G _ A R C _ C O M P A C T _ I R Q _ L E V E L S
2015-02-21 12:39:32 +03:00
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 2
# else
VECTOR h a n d l e _ i n t e r r u p t _ l e v e l 1
# endif
2016-05-30 16:51:22 +03:00
.rept 28
2015-02-21 12:39:32 +03:00
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)
2017-05-28 09:52:01 +03:00
VECTOR E V _ T L B M i s s I ; 0x108, Instruction TLB miss (0x21)
2015-02-21 12:39:32 +03:00
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)
2017-05-28 09:52:01 +03:00
VECTOR E V _ E x t e n s i o n ; 0x130, Extn Instruction Excp (0x26)
2015-02-21 12:39:32 +03:00
.rept 24
VECTOR r e s e r v e d ; Reserved Exceptions
.endr
;##################### Scratch Mem for IRQ stack switching #############
ARCFP_ D A T A i n t 1 _ s a v e d _ r e g
.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
/* Each Interrupt level needs its own scratch */
ARCFP_ D A T A i n t 2 _ s a v e d _ r e g
.type int2 _ s a v e d _ r e g , @object
.size int2 _ s a v e d _ r e g , 4
int2_saved_reg :
.zero 4
; ---------------------------------------------
.section .text , " ax" ,@progbits
2015-10-09 08:56:12 +03:00
reserved :
flag 1 ; Unexpected event, halt
2015-02-21 12:39:32 +03:00
;##################### Interrupt Handling ##############################
# ifdef C O N F I G _ A R C _ C O M P A C T _ I R Q _ L E V E L S
; ---------------------------------------------
; Level 2 ISR: Can interrupt a Level 1 ISR
; ---------------------------------------------
ENTRY( h a n d l e _ i n t e r r u p t _ l e v e l 2 )
INTERRUPT_ P R O L O G U E 2
;------------------------------------------------------
; if L2 IRQ interrupted a L1 ISR, disable preemption
2015-09-06 16:41:12 +03:00
;
; This is to avoid a potential L1-L2-L1 scenario
; -L1 IRQ taken
; -L2 interrupts L1 (before L1 ISR could run)
; -preemption off IRQ, user task in syscall picked to run
; -RTIE to userspace
; Returns from L2 context fine
; But both L1 and L2 re-enabled, so another L1 can be taken
; while prev L1 is still unserviced
;
2015-02-21 12:39:32 +03:00
;------------------------------------------------------
2015-09-06 16:41:12 +03:00
; L2 interrupting L1 implies both L2 and L1 active
; However both A2 and A1 are NOT set in STATUS32, thus
; need to check STATUS32_L2 to determine if L1 was active
2015-02-21 12:39:32 +03:00
ld r9 , [ s p , P T _ s t a t u s32 ] ; get statu32_l2 (saved in pt_regs)
bbit0 r9 , S T A T U S _ A 1 _ B I T , 1 f ; L1 not active when L2 IRQ, so normal
; bump thread_info->preempt_count (Disable preemption)
GET_ C U R R _ T H R _ I N F O _ F R O M _ S P r10
ld r9 , [ r10 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T ]
add r9 , r9 , 1
st r9 , [ r10 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T ]
1 :
;------------------------------------------------------
; setup params for Linux common ISR and invoke it
;------------------------------------------------------
lr r0 , [ i c a u s e 2 ]
and r0 , r0 , 0 x1 f
bl. d @arch_do_IRQ
mov r1 , s p
mov r8 ,0 x2
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
END( h a n d l e _ i n t e r r u p t _ l e v e l 2 )
# endif
2015-10-30 22:52:51 +03:00
; ---------------------------------------------
; User Mode Memory Bus Error Interrupt Handler
2017-05-28 09:52:01 +03:00
; (Kernel mode memory errors handled via separate exception vectors)
2015-10-30 22:52:51 +03:00
; ---------------------------------------------
ENTRY( m e m _ s e r v i c e )
INTERRUPT_ P R O L O G U E 2
mov r0 , i l i n k 2
mov r1 , s p
; User process needs to be killed with SIGBUS, but first need to get
; out of the L2 interrupt context (drop to pure kernel mode) and jump
; off to "C" code where SIGBUS in enqueued
lr r3 , [ s t a t u s32 ]
bclr r3 , r3 , S T A T U S _ A 2 _ B I T
or r3 , r3 , ( S T A T U S _ E 1 _ M A S K | S T A T U S _ E 2 _ M A S K )
sr r3 , [ s t a t u s32 _ l 2 ]
mov i l i n k 2 , 1 f
rtie
1 :
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
END( m e m _ s e r v i c e )
2015-02-21 12:39:32 +03:00
; ---------------------------------------------
; Level 1 ISR
; ---------------------------------------------
ENTRY( h a n d l e _ i n t e r r u p t _ l e v e l 1 )
INTERRUPT_ P R O L O G U E 1
lr r0 , [ i c a u s e 1 ]
and r0 , r0 , 0 x1 f
# ifdef C O N F I G _ T R A C E _ I R Q F L A G S
; icause1 needs to be read early, before calling tracing, which
; can clobber scratch regs, hence use of stack to stash it
push r0
TRACE_ A S M _ I R Q _ D I S A B L E
pop r0
# endif
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
END( 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 #############################
; ---------------------------------------------
; Protection Violation Exception Handler
; ---------------------------------------------
ENTRY( E V _ T L B P r o t V )
EXCEPTION_ P R O L O G U E
2019-05-16 02:08:10 +03:00
mov r2 , r10 ; ECR set into r10 already
2015-02-21 12:39:32 +03:00
lr r0 , [ e f a ] ; Faulting Data address (not part of pt_regs saved above)
; Exception auto-disables further Intr/exceptions.
; Re-enable them by pretending to return from exception
; (so rest of handler executes in pure K mode)
FAKE_ R E T _ F R O M _ E X C P N
mov r1 , s p ; Handle to pt_regs
;------ (5) Type of Protection Violation? ----------
;
; ProtV Hardware Exception is triggered for Access Faults of 2 types
2017-05-28 09:52:01 +03:00
; -Access Violation : 00_23_(00|01|02|03)_00
2015-02-21 12:39:32 +03:00
; x r w r+w
; -Unaligned Access : 00_23_04_00
;
bbit1 r2 , E C R _ C _ B I T _ P R O T V _ M I S A L I G _ D A T A , 4 f
;========= (6a) Access Violation Processing ========
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 :
SAVE_ C A L L E E _ S A V E D _ U S E R
mov r2 , s p ; callee_regs
bl d o _ m i s a l i g n e d _ a c c e s s
; TBD: optimize - do this only if a callee reg was involved
; either a dst of emulated LD/ST or src with address-writeback
RESTORE_ 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
END( E V _ T L B P r o t V )
; Wrapper for Linux page fault handler called from EV_TLBMiss*
; Very similar to ProtV handler case (6a) above, but avoids the extra checks
; for Misaligned access
;
ENTRY( c a l l _ d o _ p a g e _ f a u l t )
EXCEPTION_ P R O L O G U E
lr r0 , [ e f a ] ; Faulting Data address
mov r1 , s p
FAKE_ R E T _ F R O M _ E X C P N
mov b l i n k , r e t _ f r o m _ e x c e p t i o n
b d o _ p a g e _ f a u l t
END( c a l l _ d o _ p a g e _ f a u l t )
;############# Common Handlers for ARCompact and ARCv2 ##############
# include " e n t r y . S "
;############# 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
; All 2 entry points to here already disable interrupts
.Lrestore_regs :
2017-05-28 09:52:01 +03:00
# Interrupts a r e a c t u a l l y d i s a b l e d f r o m t h i s p o i n t o n , b u t w i l l g e t
2016-03-23 12:26:52 +03:00
# reenabled a f t e r w e r e t u r n f r o m i n t e r r u p t / e x c e p t i o n .
# But i r q t r a c e r n e e d s t o b e t o l d n o w . . .
2015-02-21 12:39:32 +03:00
TRACE_ A S M _ I R Q _ E N A B L E
lr r10 , [ s t a t u s32 ]
; Restore REG File. In case multiple Events outstanding,
2017-05-28 09:52:01 +03:00
; use the same priority as rtie: EXCPN, L2 IRQ, L1 IRQ, None
2015-02-21 12:39:32 +03:00
; Note that we use realtime STATUS32 (not pt_regs->status32) to
; decide that.
2015-10-08 15:22:27 +03:00
and. f 0 , r10 , ( S T A T U S _ A 1 _ M A S K | S T A T U S _ A 2 _ M A S K )
bz . L e x c e p _ o r _ p u r e _ K _ r e t
2015-02-21 12:39:32 +03:00
2015-10-08 15:22:27 +03:00
; Returning from Interrupts (Level 1 or 2)
2015-02-21 12:39:32 +03:00
# ifdef C O N F I G _ A R C _ C O M P A C T _ I R Q _ L E V E L S
; Level 2 interrupt return Path - from hardware standpoint
bbit0 r10 , S T A T U S _ A 2 _ B I T , n o t _ l e v e l 2 _ i n t e r r u p t
;------------------------------------------------------------------
; However the context returning might not have taken L2 intr itself
; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
; Special considerations needed for the context which took L2 intr
ld r9 , [ s p , P T _ e v e n t ] ; Ensure this is L2 intr context
brne r9 , e v e n t _ I R Q 2 , 1 4 9 f
;------------------------------------------------------------------
; if L2 IRQ interrupted an L1 ISR, we'd disabled preemption earlier
; so that sched doesn't move to new task, causing L1 to be delayed
; undeterministically. Now that we've achieved that, let's reset
; things to what they were, before returning from L2 context
;----------------------------------------------------------------
ld r9 , [ s p , P T _ s t a t u s32 ] ; get statu32_l2 (saved in pt_regs)
bbit0 r9 , S T A T U S _ A 1 _ B I T , 1 4 9 f ; L1 not active when L2 IRQ, so normal
; decrement thread_info->preempt_count (re-enable preemption)
GET_ C U R R _ T H R _ I N F O _ F R O M _ S P r10
ld r9 , [ r10 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T ]
; paranoid check, given A1 was active when A2 happened, preempt count
; must not be 0 because we would have incremented it.
; If this does happen we simply HALT as it means a BUG !!!
cmp r9 , 0
bnz 2 f
flag 1
2 :
sub r9 , r9 , 1
st r9 , [ r10 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T ]
149 :
2015-10-08 15:22:27 +03:00
INTERRUPT_ E P I L O G U E 2 ; return from level 2 interrupt
2015-02-21 12:39:32 +03:00
debug_marker_l2 :
rtie
not_level2_interrupt :
# endif
2015-10-08 15:22:27 +03:00
INTERRUPT_ E P I L O G U E 1 ; return from level 1 interrupt
2015-02-21 12:39:32 +03:00
debug_marker_l1 :
rtie
2015-10-08 15:22:27 +03:00
.Lexcep_or_pure_K_ret :
2015-02-21 12:39:32 +03:00
2015-03-27 18:29:34 +03:00
;this case is for syscalls or Exceptions or pure kernel mode
2015-02-21 12:39:32 +03:00
EXCEPTION_ E P I L O G U E
debug_marker_syscall :
rtie
2015-03-10 16:43:07 +03:00
END( r e t _ f r o m _ e x c e p t i o n )