2009-05-26 16:30:21 +02:00
/ *
* Low- l e v e l s y s t e m - c a l l h a n d l i n g , t r a p h a n d l e r s a n d c o n t e x t - s w i t c h i n g
*
* Copyright ( C ) 2 0 0 8 - 2 0 0 9 M i c h a l S i m e k < m o n s t r @monstr.eu>
* Copyright ( C ) 2 0 0 8 - 2 0 0 9 P e t a L o g i x
* Copyright ( C ) 2 0 0 3 J o h n W i l l i a m s < j w i l l i a m s @itee.uq.edu.au>
* Copyright ( C ) 2 0 0 1 ,2 0 0 2 N E C C o r p o r a t i o n
* Copyright ( C ) 2 0 0 1 ,2 0 0 2 M i l e s B a d e r < m i l e s @gnu.org>
*
* This f i l e i s s u b j e c t t o t h e t e r m s a n d c o n d i t i o n s o f t h e G N U G e n e r a l
* Public L i c e n s e . S e e t h e f i l e C O P Y I N G i n t h e m a i n d i r e c t o r y o f t h i s
* archive f o r m o r e d e t a i l s .
*
* Written b y M i l e s B a d e r < m i l e s @gnu.org>
* Heavily m o d i f i e d b y J o h n W i l l i a m s f o r M i c r o b l a z e
* /
# include < l i n u x / s y s . h >
# include < l i n u x / l i n k a g e . h >
# include < a s m / e n t r y . h >
# include < a s m / c u r r e n t . h >
# include < a s m / p r o c e s s o r . h >
# include < a s m / e x c e p t i o n s . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / p a g e . h >
# include < a s m / u n i s t d . h >
# include < l i n u x / e r r n o . h >
# include < a s m / s i g n a l . h >
2009-12-07 08:21:34 +01:00
# undef D E B U G
2011-01-31 15:04:43 +01:00
# ifdef D E B U G
/* Create space for syscalls counting. */
.section .data
.global syscall_debug_table
.align 4
syscall_debug_table :
.space ( _ _ NR_ s y s c a l l s * 4 )
# endif / * D E B U G * /
2009-05-26 16:30:21 +02:00
# define C _ E N T R Y ( n a m e ) . g l o b l n a m e ; .align 4; name
/ *
* Various w a y s o f s e t t i n g a n d c l e a r i n g B I P i n f l a g s r e g .
* This i s m u c k y , b u t n e c e s s a r y u s i n g m i c r o b l a z e v e r s i o n t h a t
* allows m s r o p s t o w r i t e t o B I P
* /
# if C O N F I G _ X I L I N X _ M I C R O B L A Z E 0 _ U S E _ M S R _ I N S T R
.macro clear_bip
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ B I P
2009-05-26 16:30:21 +02:00
.endm
.macro set_bip
2010-06-22 17:52:47 +02:00
msrset r0 , M S R _ B I P
2009-05-26 16:30:21 +02:00
.endm
.macro clear_eip
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ E I P
2009-05-26 16:30:21 +02:00
.endm
.macro set_ee
2010-06-22 17:52:47 +02:00
msrset r0 , M S R _ E E
2009-05-26 16:30:21 +02:00
.endm
.macro disable_irq
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ I E
2009-05-26 16:30:21 +02:00
.endm
.macro enable_irq
2010-06-22 17:52:47 +02:00
msrset r0 , M S R _ I E
2009-05-26 16:30:21 +02:00
.endm
.macro set_ums
2010-06-22 17:52:47 +02:00
msrset r0 , M S R _ U M S
msrclr r0 , M S R _ V M S
2009-05-26 16:30:21 +02:00
.endm
.macro set_vms
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ U M S
msrset r0 , M S R _ V M S
2009-05-26 16:30:21 +02:00
.endm
2010-06-22 17:46:27 +02:00
.macro clear_ums
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ U M S
2010-06-22 17:46:27 +02:00
.endm
2009-05-26 16:30:21 +02:00
.macro clear_vms_ums
2010-06-22 17:52:47 +02:00
msrclr r0 , M S R _ V M S | M S R _ U M S
2009-05-26 16:30:21 +02:00
.endm
# else
.macro clear_bip
mfs r11 , r m s r
andi r11 , r11 , ~ M S R _ B I P
mts r m s r , r11
.endm
.macro set_bip
mfs r11 , r m s r
ori r11 , r11 , M S R _ B I P
mts r m s r , r11
.endm
.macro clear_eip
mfs r11 , r m s r
andi r11 , r11 , ~ M S R _ E I P
mts r m s r , r11
.endm
.macro set_ee
mfs r11 , r m s r
ori r11 , r11 , M S R _ E E
mts r m s r , r11
.endm
.macro disable_irq
mfs r11 , r m s r
andi r11 , r11 , ~ M S R _ I E
mts r m s r , r11
.endm
.macro enable_irq
mfs r11 , r m s r
ori r11 , r11 , M S R _ I E
mts r m s r , r11
.endm
.macro set_ums
mfs r11 , r m s r
ori r11 , r11 , M S R _ V M S
andni r11 , r11 , M S R _ U M S
mts r m s r , r11
.endm
.macro set_vms
mfs r11 , r m s r
ori r11 , r11 , M S R _ V M S
andni r11 , r11 , M S R _ U M S
mts r m s r , r11
.endm
2010-06-22 17:46:27 +02:00
.macro clear_ums
mfs r11 , r m s r
andni r11 , r11 , M S R _ U M S
mts r m s r ,r11
.endm
2009-05-26 16:30:21 +02:00
.macro clear_vms_ums
mfs r11 , r m s r
andni r11 , r11 , ( M S R _ V M S | M S R _ U M S )
mts r m s r ,r11
.endm
# endif
/ * Define h o w t o c a l l h i g h - l e v e l f u n c t i o n s . W i t h M M U , v i r t u a l m o d e m u s t b e
* enabled w h e n c a l l i n g t h e h i g h - l e v e l f u n c t i o n . C l o b b e r s R 1 1 .
* VM_ O N , V M _ O F F , D O _ J U M P _ B I P C L R , D O _ C A L L
* /
/* turn on virtual protected mode save */
# define V M _ O N \
2010-06-22 13:15:53 +02:00
set_ u m s ; \
2009-05-26 16:30:21 +02:00
rted r0 , 2 f ; \
2010-06-22 13:15:53 +02:00
nop; \
2 :
2009-05-26 16:30:21 +02:00
/* turn off virtual protected mode save and user mode save*/
# define V M _ O F F \
2010-06-22 13:15:53 +02:00
clear_ v m s _ u m s ; \
2009-05-26 16:30:21 +02:00
rted r0 , T O P H Y S ( 1 f ) ; \
2010-06-22 13:15:53 +02:00
nop; \
1 :
2009-05-26 16:30:21 +02:00
# define S A V E _ R E G S \
2011-01-31 15:10:04 +01:00
swi r2 , r1 , P T _ R 2 ; /* Save SDA */ \
swi r3 , r1 , P T _ R 3 ; \
swi r4 , r1 , P T _ R 4 ; \
swi r5 , r1 , P T _ R 5 ; \
swi r6 , r1 , P T _ R 6 ; \
swi r7 , r1 , P T _ R 7 ; \
swi r8 , r1 , P T _ R 8 ; \
swi r9 , r1 , P T _ R 9 ; \
swi r10 , r1 , P T _ R 1 0 ; \
swi r11 , r1 , P T _ R 1 1 ; /* save clobbered regs after rval */\
swi r12 , r1 , P T _ R 1 2 ; \
swi r13 , r1 , P T _ R 1 3 ; /* Save SDA2 */ \
swi r14 , r1 , P T _ P C ; /* PC, before IRQ/trap */ \
swi r15 , r1 , P T _ R 1 5 ; /* Save LP */ \
swi r16 , r1 , P T _ R 1 6 ; \
swi r17 , r1 , P T _ R 1 7 ; \
swi r18 , r1 , P T _ R 1 8 ; /* Save asm scratch reg */ \
swi r19 , r1 , P T _ R 1 9 ; \
swi r20 , r1 , P T _ R 2 0 ; \
swi r21 , r1 , P T _ R 2 1 ; \
swi r22 , r1 , P T _ R 2 2 ; \
swi r23 , r1 , P T _ R 2 3 ; \
swi r24 , r1 , P T _ R 2 4 ; \
swi r25 , r1 , P T _ R 2 5 ; \
swi r26 , r1 , P T _ R 2 6 ; \
swi r27 , r1 , P T _ R 2 7 ; \
swi r28 , r1 , P T _ R 2 8 ; \
swi r29 , r1 , P T _ R 2 9 ; \
swi r30 , r1 , P T _ R 3 0 ; \
swi r31 , r1 , P T _ R 3 1 ; /* Save current task reg */ \
2009-05-26 16:30:21 +02:00
mfs r11 , r m s r ; /* save MSR */ \
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ M S R ;
2009-05-26 16:30:21 +02:00
2016-02-24 11:31:14 +01:00
# define R E S T O R E _ R E G S _ G P \
2011-01-31 15:10:04 +01:00
lwi r2 , r1 , P T _ R 2 ; /* restore SDA */ \
lwi r3 , r1 , P T _ R 3 ; \
lwi r4 , r1 , P T _ R 4 ; \
lwi r5 , r1 , P T _ R 5 ; \
lwi r6 , r1 , P T _ R 6 ; \
lwi r7 , r1 , P T _ R 7 ; \
lwi r8 , r1 , P T _ R 8 ; \
lwi r9 , r1 , P T _ R 9 ; \
lwi r10 , r1 , P T _ R 1 0 ; \
lwi r11 , r1 , P T _ R 1 1 ; /* restore clobbered regs after rval */\
lwi r12 , r1 , P T _ R 1 2 ; \
lwi r13 , r1 , P T _ R 1 3 ; /* restore SDA2 */ \
lwi r14 , r1 , P T _ P C ; /* RESTORE_LINK PC, before IRQ/trap */\
lwi r15 , r1 , P T _ R 1 5 ; /* restore LP */ \
lwi r16 , r1 , P T _ R 1 6 ; \
lwi r17 , r1 , P T _ R 1 7 ; \
lwi r18 , r1 , P T _ R 1 8 ; /* restore asm scratch reg */ \
lwi r19 , r1 , P T _ R 1 9 ; \
lwi r20 , r1 , P T _ R 2 0 ; \
lwi r21 , r1 , P T _ R 2 1 ; \
lwi r22 , r1 , P T _ R 2 2 ; \
lwi r23 , r1 , P T _ R 2 3 ; \
lwi r24 , r1 , P T _ R 2 4 ; \
lwi r25 , r1 , P T _ R 2 5 ; \
lwi r26 , r1 , P T _ R 2 6 ; \
lwi r27 , r1 , P T _ R 2 7 ; \
lwi r28 , r1 , P T _ R 2 8 ; \
lwi r29 , r1 , P T _ R 2 9 ; \
lwi r30 , r1 , P T _ R 3 0 ; \
lwi r31 , r1 , P T _ R 3 1 ; /* Restore cur task reg */
2009-05-26 16:30:21 +02:00
2016-02-24 11:31:14 +01:00
# define R E S T O R E _ R E G S \
lwi r11 , r1 , P T _ M S R ; \
mts r m s r , r11 ; \
RESTORE_ R E G S _ G P
2016-02-24 11:30:04 +01:00
# define R E S T O R E _ R E G S _ R T B D \
lwi r11 , r1 , P T _ M S R ; \
andni r11 , r11 , M S R _ E I P ; /* clear EIP */ \
ori r11 , r11 , M S R _ E E | M S R _ B I P ; /* set EE and BIP */ \
mts r m s r , r11 ; \
RESTORE_ R E G S _ G P
2010-06-22 17:58:26 +02:00
# define S A V E _ S T A T E \
swi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ; /* save stack */ \
/* See if already in kernel mode.*/ \
mfs r1 , r m s r ; \
andi r1 , r1 , M S R _ U M S ; \
bnei r1 , 1 f ; \
/* Kernel-mode state save. */ \
/* Reload kernel stack-ptr. */ \
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ; \
2010-06-22 18:16:07 +02:00
/* FIXME: I can add these two lines to one */ \
/* tophys(r1,r1); */ \
2011-01-31 15:10:04 +01:00
/* addik r1, r1, -PT_SIZE; */ \
addik r1 , r1 , C O N F I G _ K E R N E L _ B A S E _ A D D R - C O N F I G _ K E R N E L _ S T A R T - P T _ S I Z E ; \
2010-06-22 17:58:26 +02:00
SAVE_ R E G S \
brid 2 f ; \
2011-01-31 15:10:04 +01:00
swi r1 , r1 , P T _ M O D E ; \
2010-06-22 17:58:26 +02:00
1 : /* User-mode state save. */ \
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ; /* get saved current */\
tophys( r1 ,r1 ) ; \
lwi r1 , r1 , T S _ T H R E A D _ I N F O ; /* get the thread info */ \
2010-06-22 18:16:07 +02:00
/* MS these three instructions can be added to one */ \
/* addik r1, r1, THREAD_SIZE; */ \
/* tophys(r1,r1); */ \
2011-01-31 15:10:04 +01:00
/* addik r1, r1, -PT_SIZE; */ \
addik r1 , r1 , T H R E A D _ S I Z E + C O N F I G _ K E R N E L _ B A S E _ A D D R - C O N F I G _ K E R N E L _ S T A R T - P T _ S I Z E ; \
2010-06-22 17:58:26 +02:00
SAVE_ R E G S \
lwi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ; \
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ R 1 ; /* Store user SP. */ \
swi r0 , r1 , P T _ M O D E ; /* Was in user-mode. */ \
2010-06-22 17:58:26 +02:00
/* MS: I am clearing UMS even in case when I come from kernel space */ \
clear_ u m s ; \
2 : lwi C U R R E N T _ T A S K , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ;
2009-05-26 16:30:21 +02:00
.text
/ *
* User t r a p .
*
* System c a l l s a r e h a n d l e d h e r e .
*
* Syscall p r o t o c o l :
* Syscall n u m b e r i n r12 , a r g s i n r5 - r10
* Return v a l u e i n r3
*
* Trap e n t e r e d v i a b r k i i n s t r u c t i o n , s o B I P b i t i s s e t , a n d i n t e r r u p t s
* are m a s k e d . T h i s i s n i c e , m e a n s w e d o n ' t h a v e t o C L I b e f o r e s t a t e s a v e
* /
C_ E N T R Y ( _ u s e r _ e x c e p t i o n ) :
2010-06-22 21:11:49 +02:00
swi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) / * s a v e s t a c k * /
2010-10-22 15:48:58 +10:00
addi r14 , r14 , 4 / * r e t u r n a d d r e s s i s 4 b y t e a f t e r c a l l * /
2009-05-26 16:30:21 +02:00
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ; /* get saved current */
tophys( r1 ,r1 ) ;
lwi r1 , r1 , T S _ T H R E A D _ I N F O ; /* get stack from task_struct */
2010-10-22 15:48:58 +10:00
/* calculate kernel stack pointer from task struct 8k */
addik r1 , r1 , T H R E A D _ S I Z E ;
tophys( r1 ,r1 ) ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , - P T _ S I Z E ; /* Make room on the stack. */
2009-05-26 16:30:21 +02:00
SAVE_ R E G S
2011-01-31 15:10:04 +01:00
swi r0 , r1 , P T _ R 3
swi r0 , r1 , P T _ R 4
2009-05-26 16:30:21 +02:00
2011-01-31 15:10:04 +01:00
swi r0 , r1 , P T _ M O D E ; /* Was in user-mode. */
2009-05-26 16:30:21 +02:00
lwi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ R 1 ; /* Store user SP. */
2010-06-22 18:29:05 +02:00
clear_ u m s ;
2010-10-22 15:48:58 +10:00
2 : lwi C U R R E N T _ T A S K , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ;
2009-05-26 16:30:21 +02:00
/* Save away the syscall number. */
2011-01-31 15:10:04 +01:00
swi r12 , r1 , P T _ R 0 ;
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 )
/* where the trap should return need -8 to adjust for rtsd r15, 8*/
/ * Jump t o t h e a p p r o p r i a t e f u n c t i o n f o r t h e s y s t e m c a l l n u m b e r i n r12
* ( r1 2 i s n o t p r e s e r v e d ) , o r r e t u r n a n e r r o r i f r12 i s n o t v a l i d . T h e L P
* register s h o u l d p o i n t t o t h e l o c a t i o n w h e r e
* the c a l l e d f u n c t i o n s h o u l d r e t u r n . [ n o t e t h a t M A K E _ S Y S _ C A L L u s e s l a b e l 1 ] * /
2009-08-24 13:26:04 +02:00
2010-06-22 18:29:05 +02:00
/* Step into virtual mode */
rtbd r0 , 3 f
2009-08-24 13:26:04 +02:00
nop
3 :
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O / * g e t t h r e a d i n f o * /
2009-08-24 13:26:04 +02:00
lwi r11 , r11 , T I _ F L A G S / * g e t f l a g s i n t h r e a d i n f o * /
andi r11 , r11 , _ T I F _ W O R K _ S Y S C A L L _ M A S K
beqi r11 , 4 f
addik r3 , r0 , - E N O S Y S
2011-01-31 15:10:04 +01:00
swi r3 , r1 , P T _ R 3
2009-08-24 13:26:04 +02:00
brlid r15 , d o _ s y s c a l l _ t r a c e _ e n t e r
2011-01-31 15:10:04 +01:00
addik r5 , r1 , P T _ R 0
2009-08-24 13:26:04 +02:00
# do_ s y s c a l l _ t r a c e _ e n t e r r e t u r n s t h e n e w s y s c a l l n r .
addk r12 , r0 , r3
2011-01-31 15:10:04 +01:00
lwi r5 , r1 , P T _ R 5 ;
lwi r6 , r1 , P T _ R 6 ;
lwi r7 , r1 , P T _ R 7 ;
lwi r8 , r1 , P T _ R 8 ;
lwi r9 , r1 , P T _ R 9 ;
lwi r10 , r1 , P T _ R 1 0 ;
2009-08-24 13:26:04 +02:00
4 :
/ * Jump t o t h e a p p r o p r i a t e f u n c t i o n f o r t h e s y s t e m c a l l n u m b e r i n r12
* ( r1 2 i s n o t p r e s e r v e d ) , o r r e t u r n a n e r r o r i f r12 i s n o t v a l i d .
* The L P r e g i s t e r s h o u l d p o i n t t o t h e l o c a t i o n w h e r e t h e c a l l e d f u n c t i o n
* should r e t u r n . [ n o t e t h a t M A K E _ S Y S _ C A L L u s e s l a b e l 1 ] * /
/* See if the system call number is valid */
2015-02-23 15:35:35 +00:00
blti r12 , 5 f
2009-05-26 16:30:21 +02:00
addi r11 , r12 , - _ _ N R _ s y s c a l l s ;
2015-03-04 15:10:55 +01:00
bgei r11 , 5 f ;
2009-05-26 16:30:21 +02:00
/* Figure out which function to use for this system call. */
/* Note Microblaze barrel shift is optional, so don't rely on it */
add r12 , r12 , r12 ; /* convert num -> ptr */
add r12 , r12 , r12 ;
2012-09-17 11:18:24 +02:00
addi r30 , r0 , 1 / * r e s t a r t s a l l o w e d * /
2009-05-26 16:30:21 +02:00
2009-12-07 08:21:34 +01:00
# ifdef D E B U G
2011-01-31 15:04:43 +01:00
/* Trac syscalls and stored them to syscall_debug_table */
/* The first syscall location stores total syscall number */
lwi r3 , r0 , s y s c a l l _ d e b u g _ t a b l e
addi r3 , r3 , 1
swi r3 , r0 , s y s c a l l _ d e b u g _ t a b l e
lwi r3 , r12 , s y s c a l l _ d e b u g _ t a b l e
2009-05-26 16:30:21 +02:00
addi r3 , r3 , 1
2011-01-31 15:04:43 +01:00
swi r3 , r12 , s y s c a l l _ d e b u g _ t a b l e
2009-12-07 08:21:34 +01:00
# endif
2009-08-24 13:26:04 +02:00
# Find a n d j u m p i n t o t h e s y s c a l l h a n d l e r .
lwi r12 , r12 , s y s _ c a l l _ t a b l e
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
2010-07-28 12:40:02 +02:00
addi r15 , r0 , r e t _ f r o m _ t r a p - 8
2009-08-24 13:26:04 +02:00
bra r12
2009-05-26 16:30:21 +02:00
/* The syscall number is invalid, return an error. */
2009-08-24 13:26:04 +02:00
5 :
2015-02-23 15:35:35 +00:00
braid r e t _ f r o m _ t r a p
2009-05-26 16:30:21 +02:00
addi r3 , r0 , - E N O S Y S ;
2009-08-24 13:26:04 +02:00
/* Entry point used to return from a syscall/trap */
2009-05-26 16:30:21 +02:00
/* We re-enable BIP bit before state restore */
C_ E N T R Y ( r e t _ f r o m _ t r a p ) :
2011-01-31 15:10:04 +01:00
swi r3 , r1 , P T _ R 3
swi r4 , r1 , P T _ R 4
2010-01-22 10:24:06 +01:00
2011-01-31 15:10:04 +01:00
lwi r11 , r1 , P T _ M O D E ;
2010-10-22 15:48:58 +10:00
/* See if returning to kernel mode, if so, skip resched &c. */
bnei r11 , 2 f ;
2009-08-24 13:26:04 +02:00
/ * We' r e r e t u r n i n g t o u s e r m o d e , s o c h e c k f o r v a r i o u s c o n d i t i o n s t h a t
* trigger r e s c h e d u l i n g . * /
2010-01-22 10:24:06 +01:00
/* FIXME: Restructure all these flag checks. */
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ; /* get thread info */
2009-08-24 13:26:04 +02:00
lwi r11 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r11 , r11 , _ T I F _ W O R K _ S Y S C A L L _ M A S K
beqi r11 , 1 f
brlid r15 , d o _ s y s c a l l _ t r a c e _ l e a v e
2011-01-31 15:10:04 +01:00
addik r5 , r1 , P T _ R 0
2009-08-24 13:26:04 +02:00
1 :
2009-05-26 16:30:21 +02:00
/ * We' r e r e t u r n i n g t o u s e r m o d e , s o c h e c k f o r v a r i o u s c o n d i t i o n s t h a t
* trigger r e s c h e d u l i n g . * /
2010-01-22 10:24:06 +01:00
/* get thread info from current task */
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ;
2012-04-29 04:43:50 -04:00
lwi r19 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r11 , r19 , _ T I F _ N E E D _ R E S C H E D ;
2009-05-26 16:30:21 +02:00
beqi r11 , 5 f ;
bralid r15 , s c h e d u l e ; /* Call scheduler */
nop; /* delay slot */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Maybe handle a signal */
2015-03-04 15:10:55 +01:00
5 :
2012-04-29 04:43:50 -04:00
andi r11 , r19 , _ T I F _ S I G P E N D I N G | _ T I F _ N O T I F Y _ R E S U M E ;
beqi r11 , 4 f ; /* Signals to handle, handle them */
2009-05-26 16:30:21 +02:00
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ; /* Arg 1: struct pt_regs *regs */
2012-04-24 02:03:06 -04:00
bralid r15 , d o _ n o t i f y _ r e s u m e ; /* Handle any signals */
2012-04-29 04:11:34 -04:00
add r6 , r30 , r0 ; /* Arg 2: int in_syscall */
2012-04-29 04:43:50 -04:00
add r30 , r0 , r0 / * n o m o r e r e s t a r t s * /
bri 1 b
2010-01-22 10:24:06 +01:00
/* Finally, return to user state. */
2012-04-29 04:43:50 -04:00
4 : set_ b i p ; /* Ints masked for state restore */
2010-02-22 13:24:43 +01:00
swi C U R R E N T _ T A S K , r0 , P E R _ C P U ( C U R R E N T _ S A V E ) ; /* save current */
2009-05-26 16:30:21 +02:00
VM_ O F F ;
tophys( r1 ,r1 ) ;
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * C l e a n u p s t a c k s p a c e . * /
2009-05-26 16:30:21 +02:00
lwi r1 , r1 , P T _ R 1 - P T _ S I Z E ;/* Restore user stack pointer. */
2010-10-22 15:48:58 +10:00
bri 6 f ;
/* Return to kernel state. */
2 : set_ b i p ; /* Ints masked for state restore */
VM_ O F F ;
tophys( r1 ,r1 ) ;
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * C l e a n u p s t a c k s p a c e . * /
2010-10-22 15:48:58 +10:00
tovirt( r1 ,r1 ) ;
6 :
2009-05-26 16:30:21 +02:00
TRAP_return : /* Make global symbol for debugging */
rtbd r14 , 0 ; /* Instructions to return from an IRQ */
nop;
/ * This t h e i n i t i a l e n t r y p o i n t f o r a n e w c h i l d t h r e a d , w i t h a n a p p r o p r i a t e
stack i n p l a c e t h a t m a k e s i t l o o k t h e t h e c h i l d i s i n t h e m i d d l e o f a n
syscall. T h i s f u n c t i o n i s a c t u a l l y ` r e t u r n e d t o ' f r o m s w i t c h _ t h r e a d
( copy_ t h r e a d m a k e s r e t _ f r o m _ f o r k t h e r e t u r n a d d r e s s i n e a c h n e w t h r e a d ' s
saved c o n t e x t ) . * /
C_ E N T R Y ( r e t _ f r o m _ f o r k ) :
bralid r15 , s c h e d u l e _ t a i l ; /* ...which is schedule_tail's arg */
2012-10-09 09:32:32 +02:00
add r5 , r3 , r0 ; /* switch_thread returns the prev task */
2009-05-26 16:30:21 +02:00
/* ( in the delay slot ) */
brid r e t _ f r o m _ t r a p ; /* Do normal trap return */
2010-06-22 18:09:29 +02:00
add r3 , r0 , r0 ; /* Child's fork call should return 0. */
2009-05-26 16:30:21 +02:00
2012-10-06 13:52:37 -04:00
C_ E N T R Y ( r e t _ f r o m _ k e r n e l _ t h r e a d ) :
bralid r15 , s c h e d u l e _ t a i l ; /* ...which is schedule_tail's arg */
add r5 , r3 , r0 ; /* switch_thread returns the prev task */
/* ( in the delay slot ) */
brald r15 , r20 / * f n w a s l e f t i n r20 * /
addk r5 , r0 , r19 / * . . . a n d a r g u m e n t - i n r19 * /
2012-10-10 11:52:44 -04:00
brid r e t _ f r o m _ t r a p
add r3 , r0 , r0
2012-10-06 13:52:37 -04:00
2009-05-26 16:30:21 +02:00
C_ E N T R Y ( s y s _ r t _ s i g r e t u r n _ w r a p p e r ) :
2012-04-29 04:11:34 -04:00
addik r30 , r0 , 0 / * n o r e s t a r t s * /
2010-08-06 10:36:02 +02:00
brid s y s _ r t _ s i g r e t u r n / * D o r e a l w o r k * /
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ; /* add user context as 1st arg */
2009-05-26 16:30:21 +02:00
/ *
* HW E X C E P T I O N r u t i n e s t a r t
* /
C_ E N T R Y ( f u l l _ e x c e p t i o n _ t r a p ) :
/ * adjust e x c e p t i o n a d d r e s s f o r p r i v i l e g e d i n s t r u c t i o n
* for f i n d i n g w h e r e i s i t * /
addik r17 , r17 , - 4
SAVE_ S T A T E / * S a v e r e g i s t e r s * /
2010-06-22 16:22:01 +02:00
/* PC, before IRQ/trap - this is one instruction above */
2011-01-31 15:10:04 +01:00
swi r17 , r1 , P T _ P C ;
2010-06-22 16:22:01 +02:00
tovirt( r1 ,r1 )
2009-05-26 16:30:21 +02:00
/ * FIXME t h i s c a n b e s t o r e d i r e c t l y i n P T _ E S R r e g .
* I t e s t e d i t b u t t h e r e i s a f a u l t * /
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
2010-07-28 12:40:02 +02:00
addik r15 , r0 , r e t _ f r o m _ e x c - 8
2009-05-26 16:30:21 +02:00
mfs r6 , r e s r
mfs r7 , r f s r ; /* save FSR */
2009-09-28 08:50:53 +02:00
mts r f s r , r0 ; /* Clear sticky fsr */
2010-06-22 16:25:31 +02:00
rted r0 , f u l l _ e x c e p t i o n
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 / * p a r a m e t e r s t r u c t p t _ r e g s * r e g s * /
2009-05-26 16:30:21 +02:00
/ *
* Unaligned d a t a t r a p .
*
* Unaligned d a t a t r a p l a s t o n 4 k p a g e i s h a n d l e d h e r e .
*
* Trap e n t e r e d v i a e x c e p t i o n , s o E E b i t i s s e t , a n d i n t e r r u p t s
* are m a s k e d . T h i s i s n i c e , m e a n s w e d o n ' t h a v e t o C L I b e f o r e s t a t e s a v e
*
* The a s s e m b l e r r o u t i n e i s i n " a r c h / m i c r o b l a z e / k e r n e l / h w _ e x c e p t i o n _ h a n d l e r . S "
* /
C_ E N T R Y ( u n a l i g n e d _ d a t a _ t r a p ) :
2010-06-17 16:03:05 +02:00
/ * MS : I h a v e t o s a v e r11 v a l u e a n d t h e n r e s t o r e i t b e c a u s e
* set_ b i t , c l e a r _ e i p , s e t _ e e u s e r11 a s t e m p r e g i s t e r i f M S R
* instructions a r e n o t u s e d . W e d o n ' t n e e d t o d o i f M S R i n s t r u c t i o n s
* are u s e d a n d t h e y u s e r0 i n s t e a d o f r11 .
* I a m u s i n g E N T R Y _ S P w h i c h s h o u l d b e p r i m a r y u s e d o n l y f o r s t a c k
* pointer s a v i n g . * /
swi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ;
set_ b i p ; /* equalize initial state for all possible entries */
clear_ e i p ;
set_ e e ;
lwi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ;
2009-05-26 16:30:21 +02:00
SAVE_ S T A T E / * S a v e r e g i s t e r s . * /
2010-06-22 16:22:01 +02:00
/* PC, before IRQ/trap - this is one instruction above */
2011-01-31 15:10:04 +01:00
swi r17 , r1 , P T _ P C ;
2010-06-22 16:22:01 +02:00
tovirt( r1 ,r1 )
2009-05-26 16:30:21 +02:00
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
2010-07-28 12:40:02 +02:00
addik r15 , r0 , r e t _ f r o m _ e x c - 8
2009-05-26 16:30:21 +02:00
mfs r3 , r e s r / * E S R * /
mfs r4 , r e a r / * E A R * /
2010-06-22 16:25:31 +02:00
rtbd r0 , _ u n a l i g n e d _ d a t a _ e x c e p t i o n
2011-01-31 15:10:04 +01:00
addik r7 , r1 , 0 / * p a r a m e t e r s t r u c t p t _ r e g s * r e g s * /
2009-05-26 16:30:21 +02:00
/ *
* Page f a u l t t r a p s .
*
* If t h e r e a l e x c e p t i o n h a n d l e r ( f r o m h w _ e x c e p t i o n _ h a n d l e r . S ) d i d n ' t f i n d
* the m a p p i n g f o r t h e p r o c e s s , t h e n w e ' r e t h r o w n h e r e t o h a n d l e s u c h s i t u a t i o n .
*
* Trap e n t e r e d v i a e x c e p t i o n s , s o E E b i t i s s e t , a n d i n t e r r u p t s
* are m a s k e d . T h i s i s n i c e , m e a n s w e d o n ' t h a v e t o C L I b e f o r e s t a t e s a v e
*
* Build a s t a n d a r d e x c e p t i o n f r a m e f o r T L B A c c e s s e r r o r s . A l l T L B e x c e p t i o n s
* will b a i l o u t t o t h i s p o i n t i f t h e y c a n ' t r e s o l v e t h e l i g h t w e i g h t T L B f a u l t .
*
* The C f u n c t i o n c a l l e d i s i n " a r c h / m i c r o b l a z e / m m / f a u l t . c " , d e c l a r e d a s :
* void d o _ p a g e _ f a u l t ( s t r u c t p t _ r e g s * r e g s ,
* unsigned l o n g a d d r e s s ,
* unsigned l o n g e r r o r _ c o d e )
* /
/* data and intruction trap - which is choose is resolved int fault.c */
C_ E N T R Y ( p a g e _ f a u l t _ d a t a _ t r a p ) :
SAVE_ S T A T E / * S a v e r e g i s t e r s . * /
2010-06-22 16:22:01 +02:00
/* PC, before IRQ/trap - this is one instruction above */
2011-01-31 15:10:04 +01:00
swi r17 , r1 , P T _ P C ;
2010-06-22 16:22:01 +02:00
tovirt( r1 ,r1 )
2009-05-26 16:30:21 +02:00
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
2010-07-28 12:40:02 +02:00
addik r15 , r0 , r e t _ f r o m _ e x c - 8
2009-05-26 16:30:21 +02:00
mfs r6 , r e a r / * p a r a m e t e r u n s i g n e d l o n g a d d r e s s * /
mfs r7 , r e s r / * p a r a m e t e r u n s i g n e d l o n g e r r o r _ c o d e * /
2010-06-22 16:25:31 +02:00
rted r0 , d o _ p a g e _ f a u l t
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 / * p a r a m e t e r s t r u c t p t _ r e g s * r e g s * /
2009-05-26 16:30:21 +02:00
C_ E N T R Y ( p a g e _ f a u l t _ i n s t r _ t r a p ) :
SAVE_ S T A T E / * S a v e r e g i s t e r s . * /
2010-06-22 16:22:01 +02:00
/* PC, before IRQ/trap - this is one instruction above */
2011-01-31 15:10:04 +01:00
swi r17 , r1 , P T _ P C ;
2010-06-22 16:22:01 +02:00
tovirt( r1 ,r1 )
2009-05-26 16:30:21 +02:00
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
2010-07-28 12:40:02 +02:00
addik r15 , r0 , r e t _ f r o m _ e x c - 8
2009-05-26 16:30:21 +02:00
mfs r6 , r e a r / * p a r a m e t e r u n s i g n e d l o n g a d d r e s s * /
ori r7 , r0 , 0 / * p a r a m e t e r u n s i g n e d l o n g e r r o r _ c o d e * /
2010-06-22 18:09:29 +02:00
rted r0 , d o _ p a g e _ f a u l t
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 / * p a r a m e t e r s t r u c t p t _ r e g s * r e g s * /
2009-05-26 16:30:21 +02:00
/* Entry point used to return from an exception. */
C_ E N T R Y ( r e t _ f r o m _ e x c ) :
2011-01-31 15:10:04 +01:00
lwi r11 , r1 , P T _ M O D E ;
2009-05-26 16:30:21 +02:00
bnei r11 , 2 f ; /* See if returning to kernel mode, */
/* ... if so, skip resched &c. */
/ * We' r e r e t u r n i n g t o u s e r m o d e , s o c h e c k f o r v a r i o u s c o n d i t i o n s t h a t
trigger r e s c h e d u l i n g . * /
2012-04-29 04:43:50 -04:00
1 :
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ; /* get thread info */
2012-04-29 04:43:50 -04:00
lwi r19 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r11 , r19 , _ T I F _ N E E D _ R E S C H E D ;
2009-05-26 16:30:21 +02:00
beqi r11 , 5 f ;
/* Call the scheduler before returning from a syscall/trap. */
bralid r15 , s c h e d u l e ; /* Call scheduler */
nop; /* delay slot */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Maybe handle a signal */
2012-04-29 04:43:50 -04:00
5 : andi r11 , r19 , _ T I F _ S I G P E N D I N G | _ T I F _ N O T I F Y _ R E S U M E ;
beqi r11 , 4 f ; /* Signals to handle, handle them */
2009-05-26 16:30:21 +02:00
/ *
* Handle a s i g n a l r e t u r n ; Pending signals should be in r18.
*
* Not a l l r e g i s t e r s a r e s a v e d b y t h e n o r m a l t r a p / i n t e r r u p t e n t r y
* points ( f o r i n s t a n c e , c a l l - s a v e d r e g i s t e r s ( b e c a u s e t h e n o r m a l
* C- c o m p i l e r c a l l i n g s e q u e n c e i n t h e k e r n e l m a k e s s u r e t h e y ' r e
* preserved) , a n d c a l l - c l o b b e r e d r e g i s t e r s i n t h e c a s e o f
* traps) , b u t s i g n a l h a n d l e r s m a y w a n t t o e x a m i n e o r c h a n g e t h e
* complete r e g i s t e r s t a t e . H e r e w e s a v e a n y t h i n g n o t s a v e d b y
* the n o r m a l e n t r y s e q u e n c e , s o t h a t i t m a y b e s a f e l y r e s t o r e d
2012-04-24 02:03:06 -04:00
* ( in a p o s s i b l y m o d i f i e d f o r m ) a f t e r d o _ n o t i f y _ r e s u m e r e t u r n s . * /
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ; /* Arg 1: struct pt_regs *regs */
2012-04-24 02:03:06 -04:00
bralid r15 , d o _ n o t i f y _ r e s u m e ; /* Handle any signals */
2012-04-24 02:21:18 -04:00
addi r6 , r0 , 0 ; /* Arg 2: int in_syscall */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Finally, return to user state. */
2012-04-29 04:43:50 -04:00
4 : set_ b i p ; /* Ints masked for state restore */
2010-02-22 13:24:43 +01:00
swi C U R R E N T _ T A S K , r0 , P E R _ C P U ( C U R R E N T _ S A V E ) ; /* save current */
2009-05-26 16:30:21 +02:00
VM_ O F F ;
tophys( r1 ,r1 ) ;
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * C l e a n u p s t a c k s p a c e . * /
2009-05-26 16:30:21 +02:00
lwi r1 , r1 , P T _ R 1 - P T _ S I Z E ; /* Restore user stack pointer. */
bri 6 f ;
/* Return to kernel state. */
2010-06-22 14:05:43 +02:00
2 : set_ b i p ; /* Ints masked for state restore */
VM_ O F F ;
2009-05-26 16:30:21 +02:00
tophys( r1 ,r1 ) ;
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * C l e a n u p s t a c k s p a c e . * /
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 ) ;
6 :
EXC_return : /* Make global symbol for debugging */
rtbd r14 , 0 ; /* Instructions to return from an IRQ */
nop;
/ *
* HW E X C E P T I O N r u t i n e e n d
* /
/ *
* Hardware m a s k a b l e i n t e r r u p t s .
*
* The s t a c k - p o i n t e r ( r1 ) s h o u l d h a v e a l r e a d y b e e n s a v e d t o t h e m e m o r y
* location P E R _ C P U ( E N T R Y _ S P ) .
* /
C_ E N T R Y ( _ i n t e r r u p t ) :
/* MS: we are in physical address */
/* Save registers, switch to proper stack, convert SP to virtual.*/
swi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) )
/* MS: See if already in kernel mode. */
2010-06-22 14:51:45 +02:00
mfs r1 , r m s r
2010-06-22 14:00:12 +02:00
nop
2010-06-22 14:51:45 +02:00
andi r1 , r1 , M S R _ U M S
bnei r1 , 1 f
2009-05-26 16:30:21 +02:00
/* Kernel-mode state save. */
2010-06-22 14:51:45 +02:00
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) )
tophys( r1 ,r1 ) ; /* MS: I have in r1 physical address where stack is */
2009-05-26 16:30:21 +02:00
/* save registers */
/* MS: Make room on the stack -> activation record */
2011-01-31 15:10:04 +01:00
addik r1 , r1 , - P T _ S I Z E ;
2009-05-26 16:30:21 +02:00
SAVE_ R E G S
brid 2 f ;
2011-01-31 15:10:04 +01:00
swi r1 , r1 , P T _ M O D E ; /* 0 - user mode, 1 - kernel mode */
2009-05-26 16:30:21 +02:00
1 :
/* User-mode state save. */
/* MS: get the saved current */
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ;
tophys( r1 ,r1 ) ;
lwi r1 , r1 , T S _ T H R E A D _ I N F O ;
addik r1 , r1 , T H R E A D _ S I Z E ;
tophys( r1 ,r1 ) ;
/* save registers */
2011-01-31 15:10:04 +01:00
addik r1 , r1 , - P T _ S I Z E ;
2009-05-26 16:30:21 +02:00
SAVE_ R E G S
/* calculate mode */
2011-01-31 15:10:04 +01:00
swi r0 , r1 , P T _ M O D E ;
2009-05-26 16:30:21 +02:00
lwi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ R 1 ;
2010-06-22 18:50:31 +02:00
clear_ u m s ;
2009-05-26 16:30:21 +02:00
2 :
2010-01-22 10:24:06 +01:00
lwi C U R R E N T _ T A S K , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ;
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 )
2010-07-28 12:40:02 +02:00
addik r15 , r0 , i r q _ c a l l ;
2010-06-22 18:50:31 +02:00
irq_call : rtbd r0 , d o _ I R Q ;
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ;
2009-05-26 16:30:21 +02:00
/* MS: we are in virtual mode */
ret_from_irq :
2011-01-31 15:10:04 +01:00
lwi r11 , r1 , P T _ M O D E ;
2009-05-26 16:30:21 +02:00
bnei r11 , 2 f ;
2012-04-29 04:43:50 -04:00
1 :
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ;
2012-04-29 04:43:50 -04:00
lwi r19 , r11 , T I _ F L A G S ; /* MS: get flags from thread info */
andi r11 , r19 , _ T I F _ N E E D _ R E S C H E D ;
2009-05-26 16:30:21 +02:00
beqi r11 , 5 f
bralid r15 , s c h e d u l e ;
nop; /* delay slot */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Maybe handle a signal */
2012-04-29 04:43:50 -04:00
5 : andi r11 , r19 , _ T I F _ S I G P E N D I N G | _ T I F _ N O T I F Y _ R E S U M E ;
2009-05-26 16:30:21 +02:00
beqid r11 , n o _ i n t r _ r e s c h e d
/* Handle a signal return; Pending signals should be in r18. */
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ; /* Arg 1: struct pt_regs *regs */
2012-04-24 02:03:06 -04:00
bralid r15 , d o _ n o t i f y _ r e s u m e ; /* Handle any signals */
2012-04-24 02:21:18 -04:00
addi r6 , r0 , 0 ; /* Arg 2: int in_syscall */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Finally, return to user state. */
no_intr_resched :
/* Disable interrupts, we are now committed to the state restore */
disable_ i r q
2010-02-22 13:24:43 +01:00
swi C U R R E N T _ T A S K , r0 , P E R _ C P U ( C U R R E N T _ S A V E ) ;
2009-05-26 16:30:21 +02:00
VM_ O F F ;
tophys( r1 ,r1 ) ;
RESTORE_ R E G S
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * M S : C l e a n u p s t a c k s p a c e . * /
2009-05-26 16:30:21 +02:00
lwi r1 , r1 , P T _ R 1 - P T _ S I Z E ;
bri 6 f ;
/* MS: Return to kernel state. */
2010-01-12 09:55:10 +01:00
2 :
# ifdef C O N F I G _ P R E E M P T
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ;
2010-01-12 09:55:10 +01:00
/* MS: get preempt_count from thread info */
lwi r5 , r11 , T I _ P R E E M P T _ C O U N T ;
bgti r5 , r e s t o r e ;
lwi r5 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r5 , r5 , _ T I F _ N E E D _ R E S C H E D ;
beqi r5 , r e s t o r e / * i f z e r o j u m p o v e r * /
preempt :
/* interrupts are off that's why I am calling preempt_chedule_irq */
bralid r15 , p r e e m p t _ s c h e d u l e _ i r q
nop
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ; /* get thread info */
2010-01-12 09:55:10 +01:00
lwi r5 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r5 , r5 , _ T I F _ N E E D _ R E S C H E D ;
bnei r5 , p r e e m p t / * i f n o n z e r o j u m p t o r e s c h e d * /
restore :
# endif
VM_ O F F / * M S : t u r n o f f M M U * /
2009-05-26 16:30:21 +02:00
tophys( r1 ,r1 )
RESTORE_ R E G S
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * M S : C l e a n u p s t a c k s p a c e . * /
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 ) ;
6 :
IRQ_return : /* MS: Make global symbol for debugging */
rtid r14 , 0
nop
/ *
2010-08-03 11:45:08 +02:00
* Debug t r a p f o r K G D B . E n t e r t o _ d e b u g _ e x c e p t i o n b y b r k i r16 , 0 x18
* and c a l l h a n d l i n g f u n c t i o n w i t h s a v e d p t _ r e g s
2009-05-26 16:30:21 +02:00
* /
C_ E N T R Y ( _ d e b u g _ e x c e p t i o n ) :
/* BIP bit is set on entry, no interrupts can occur */
swi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) )
2010-06-22 14:51:45 +02:00
mfs r1 , r m s r
2010-06-22 14:00:12 +02:00
nop
2010-06-22 14:51:45 +02:00
andi r1 , r1 , M S R _ U M S
bnei r1 , 1 f
2010-08-03 11:45:08 +02:00
/* MS: Kernel-mode state save - kgdb */
2010-06-22 14:51:45 +02:00
lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ; /* Reload kernel stack-ptr*/
2009-05-26 16:30:21 +02:00
2010-08-03 11:45:08 +02:00
/* BIP bit is set on entry, no interrupts can occur */
2011-01-31 15:10:04 +01:00
addik r1 , r1 , C O N F I G _ K E R N E L _ B A S E _ A D D R - C O N F I G _ K E R N E L _ S T A R T - P T _ S I Z E ;
2009-05-26 16:30:21 +02:00
SAVE_ R E G S ;
2010-08-03 11:45:08 +02:00
/* save all regs to pt_reg structure */
2011-01-31 15:10:04 +01:00
swi r0 , r1 , P T _ R 0 ; /* R0 must be saved too */
swi r14 , r1 , P T _ R 1 4 / * r e w r i t e s a v e d R 1 4 v a l u e * /
swi r16 , r1 , P T _ P C ; /* PC and r16 are the same */
2010-08-03 11:45:08 +02:00
/* save special purpose registers to pt_regs */
mfs r11 , r e a r ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ E A R ;
2010-08-03 11:45:08 +02:00
mfs r11 , r e s r ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ E S R ;
2010-08-03 11:45:08 +02:00
mfs r11 , r f s r ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ F S R ;
2010-08-03 11:45:08 +02:00
/ * stack p o i n t e r i s i n p h y s i c a l a d d r e s s a t i t i s d e c r e a s e
2011-01-31 15:10:04 +01:00
* by P T _ S I Z E b u t w e n e e d t o g e t c o r r e c t R 1 v a l u e * /
addik r11 , r1 , C O N F I G _ K E R N E L _ S T A R T - C O N F I G _ K E R N E L _ B A S E _ A D D R + P T _ S I Z E ;
swi r11 , r1 , P T _ R 1
2010-08-03 11:45:08 +02:00
/* MS: r31 - current pointer isn't changed */
tovirt( r1 ,r1 )
# ifdef C O N F I G _ K G D B
2011-01-31 15:10:04 +01:00
addi r5 , r1 , 0 / * p a s s p t _ r e g a d d r e s s a s t h e f i r s t a r g * /
2011-02-01 09:00:57 +01:00
addik r15 , r0 , d b t r a p _ c a l l ; /* return address */
2010-08-03 11:45:08 +02:00
rtbd r0 , m i c r o b l a z e _ k g d b _ b r e a k
nop;
# endif
/ * MS : Place h a n d l e r f o r b r k i f r o m k e r n e l s p a c e i f K G D B i s O F F .
* It i s v e r y u n l i k e l y t h a t a n o t h e r b r k i i n s t r u c t i o n i s c a l l e d . * /
bri 0
2009-05-26 16:30:21 +02:00
2010-08-03 11:45:08 +02:00
/* MS: User-mode state save - gdb */
1 : lwi r1 , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ; /* get saved current */
2009-05-26 16:30:21 +02:00
tophys( r1 ,r1 ) ;
lwi r1 , r1 , T S _ T H R E A D _ I N F O ; /* get the thread info */
addik r1 , r1 , T H R E A D _ S I Z E ; /* calculate kernel stack pointer */
tophys( r1 ,r1 ) ;
2011-01-31 15:10:04 +01:00
addik r1 , r1 , - P T _ S I Z E ; /* Make room on the stack. */
2009-05-26 16:30:21 +02:00
SAVE_ R E G S ;
2011-01-31 15:10:04 +01:00
swi r16 , r1 , P T _ P C ; /* Save LP */
swi r0 , r1 , P T _ M O D E ; /* Was in user-mode. */
2009-05-26 16:30:21 +02:00
lwi r11 , r0 , T O P H Y S ( P E R _ C P U ( E N T R Y _ S P ) ) ;
2011-01-31 15:10:04 +01:00
swi r11 , r1 , P T _ R 1 ; /* Store user SP. */
2010-08-03 11:45:08 +02:00
lwi C U R R E N T _ T A S K , r0 , T O P H Y S ( P E R _ C P U ( C U R R E N T _ S A V E ) ) ;
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 )
2010-06-22 15:25:24 +02:00
set_ v m s ;
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ;
2010-07-28 12:40:02 +02:00
addik r15 , r0 , d b t r a p _ c a l l ;
2010-08-03 11:45:08 +02:00
dbtrap_call : /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
2010-08-03 11:26:51 +02:00
rtbd r0 , s w _ e x c e p t i o n
nop
2009-05-26 16:30:21 +02:00
2010-08-03 11:45:08 +02:00
/* MS: The first instruction for the second part of the gdb/kgdb */
set_ b i p ; /* Ints masked for state restore */
2011-01-31 15:10:04 +01:00
lwi r11 , r1 , P T _ M O D E ;
2009-05-26 16:30:21 +02:00
bnei r11 , 2 f ;
2010-08-03 11:45:08 +02:00
/* MS: Return to user space - gdb */
2012-04-29 04:43:50 -04:00
1 :
2009-05-26 16:30:21 +02:00
/* Get current task ptr into r11 */
2010-01-22 10:24:06 +01:00
lwi r11 , C U R R E N T _ T A S K , T S _ T H R E A D _ I N F O ; /* get thread info */
2012-04-29 04:43:50 -04:00
lwi r19 , r11 , T I _ F L A G S ; /* get flags in thread info */
andi r11 , r19 , _ T I F _ N E E D _ R E S C H E D ;
2009-05-26 16:30:21 +02:00
beqi r11 , 5 f ;
2010-08-03 11:45:08 +02:00
/* Call the scheduler before returning from a syscall/trap. */
2009-05-26 16:30:21 +02:00
bralid r15 , s c h e d u l e ; /* Call scheduler */
nop; /* delay slot */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Maybe handle a signal */
2012-04-29 04:43:50 -04:00
5 : andi r11 , r19 , _ T I F _ S I G P E N D I N G | _ T I F _ N O T I F Y _ R E S U M E ;
beqi r11 , 4 f ; /* Signals to handle, handle them */
2009-05-26 16:30:21 +02:00
2011-01-31 15:10:04 +01:00
addik r5 , r1 , 0 ; /* Arg 1: struct pt_regs *regs */
2012-04-24 02:03:06 -04:00
bralid r15 , d o _ n o t i f y _ r e s u m e ; /* Handle any signals */
2012-04-24 02:21:18 -04:00
addi r6 , r0 , 0 ; /* Arg 2: int in_syscall */
2012-04-29 04:43:50 -04:00
bri 1 b
2009-05-26 16:30:21 +02:00
/* Finally, return to user state. */
2012-04-29 04:43:50 -04:00
4 : swi C U R R E N T _ T A S K , r0 , P E R _ C P U ( C U R R E N T _ S A V E ) ; /* save current */
2009-05-26 16:30:21 +02:00
VM_ O F F ;
tophys( r1 ,r1 ) ;
2010-08-03 11:45:08 +02:00
/* MS: Restore all regs */
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D
2011-01-31 15:10:04 +01:00
addik r1 , r1 , P T _ S I Z E / * C l e a n u p s t a c k s p a c e * /
2010-08-03 11:45:08 +02:00
lwi r1 , r1 , P T _ R 1 - P T _ S I Z E ; /* Restore user stack pointer */
DBTRAP_return_user : /* MS: Make global symbol for debugging */
rtbd r16 , 0 ; /* MS: Instructions to return from a debug trap */
nop;
2009-05-26 16:30:21 +02:00
2010-08-03 11:45:08 +02:00
/* MS: Return to kernel state - kgdb */
2009-05-26 16:30:21 +02:00
2 : VM_ O F F ;
tophys( r1 ,r1 ) ;
2010-08-03 11:45:08 +02:00
/* MS: Restore all regs */
2016-02-24 11:30:04 +01:00
RESTORE_ R E G S _ R T B D
2011-01-31 15:10:04 +01:00
lwi r14 , r1 , P T _ R 1 4 ;
lwi r16 , r1 , P T _ P C ;
addik r1 , r1 , P T _ S I Z E ; /* MS: Clean up stack space */
2009-05-26 16:30:21 +02:00
tovirt( r1 ,r1 ) ;
2010-08-03 11:45:08 +02:00
DBTRAP_return_kernel : /* MS: Make global symbol for debugging */
rtbd r16 , 0 ; /* MS: Instructions to return from a debug trap */
2009-05-26 16:30:21 +02:00
nop;
ENTRY( _ s w i t c h _ t o )
/* prepare return value */
2010-01-22 10:24:06 +01:00
addk r3 , r0 , C U R R E N T _ T A S K
2009-05-26 16:30:21 +02:00
/* save registers in cpu_context */
/* use r11 and r12, volatile registers, as temp register */
/* give start of cpu_context for previous process */
addik r11 , r5 , T I _ C P U _ C O N T E X T
swi r1 , r11 , C C _ R 1
swi r2 , r11 , C C _ R 2
/ * skip v o l a t i l e r e g i s t e r s .
* they a r e s a v e d o n s t a c k w h e n w e j u m p e d t o _ s w i t c h _ t o ( ) * /
/* dedicated registers */
swi r13 , r11 , C C _ R 1 3
swi r14 , r11 , C C _ R 1 4
swi r15 , r11 , C C _ R 1 5
swi r16 , r11 , C C _ R 1 6
swi r17 , r11 , C C _ R 1 7
swi r18 , r11 , C C _ R 1 8
/* save non-volatile registers */
swi r19 , r11 , C C _ R 1 9
swi r20 , r11 , C C _ R 2 0
swi r21 , r11 , C C _ R 2 1
swi r22 , r11 , C C _ R 2 2
swi r23 , r11 , C C _ R 2 3
swi r24 , r11 , C C _ R 2 4
swi r25 , r11 , C C _ R 2 5
swi r26 , r11 , C C _ R 2 6
swi r27 , r11 , C C _ R 2 7
swi r28 , r11 , C C _ R 2 8
swi r29 , r11 , C C _ R 2 9
swi r30 , r11 , C C _ R 3 0
/* special purpose registers */
mfs r12 , r m s r
swi r12 , r11 , C C _ M S R
mfs r12 , r e a r
swi r12 , r11 , C C _ E A R
mfs r12 , r e s r
swi r12 , r11 , C C _ E S R
mfs r12 , r f s r
swi r12 , r11 , C C _ F S R
2010-01-22 10:24:06 +01:00
/* update r31, the current-give me pointer to task which will be next */
lwi C U R R E N T _ T A S K , r6 , T I _ T A S K
2009-05-26 16:30:21 +02:00
/* stored it to current_save too */
2010-01-22 10:24:06 +01:00
swi C U R R E N T _ T A S K , r0 , P E R _ C P U ( C U R R E N T _ S A V E )
2009-05-26 16:30:21 +02:00
/* get new process' cpu context and restore */
/* give me start where start context of next task */
addik r11 , r6 , T I _ C P U _ C O N T E X T
/* non-volatile registers */
lwi r30 , r11 , C C _ R 3 0
lwi r29 , r11 , C C _ R 2 9
lwi r28 , r11 , C C _ R 2 8
lwi r27 , r11 , C C _ R 2 7
lwi r26 , r11 , C C _ R 2 6
lwi r25 , r11 , C C _ R 2 5
lwi r24 , r11 , C C _ R 2 4
lwi r23 , r11 , C C _ R 2 3
lwi r22 , r11 , C C _ R 2 2
lwi r21 , r11 , C C _ R 2 1
lwi r20 , r11 , C C _ R 2 0
lwi r19 , r11 , C C _ R 1 9
/* dedicated registers */
lwi r18 , r11 , C C _ R 1 8
lwi r17 , r11 , C C _ R 1 7
lwi r16 , r11 , C C _ R 1 6
lwi r15 , r11 , C C _ R 1 5
lwi r14 , r11 , C C _ R 1 4
lwi r13 , r11 , C C _ R 1 3
/* skip volatile registers */
lwi r2 , r11 , C C _ R 2
lwi r1 , r11 , C C _ R 1
/* special purpose registers */
lwi r12 , r11 , C C _ F S R
mts r f s r , r12
lwi r12 , r11 , C C _ M S R
mts r m s r , r12
rtsd r15 , 8
nop
ENTRY( _ r e s e t )
2011-03-10 10:56:21 +01:00
brai 0 ; /* Jump to reset vector */
2009-05-26 16:30:21 +02:00
/ * These a r e c o m p i l e d a n d l o a d e d i n t o h i g h m e m o r y , t h e n
* copied i n t o p l a c e i n m a c h _ e a r l y _ s e t u p * /
.section .init .ivt , " ax"
2010-11-08 12:37:40 +01:00
# if C O N F I G _ M A N U A L _ R E S E T _ V E C T O R
2009-05-26 16:30:21 +02:00
.org 0x0
2010-11-08 12:37:40 +01:00
brai C O N F I G _ M A N U A L _ R E S E T _ V E C T O R
# endif
2011-03-10 10:51:27 +01:00
.org 0x8
2009-05-26 16:30:21 +02:00
brai T O P H Y S ( _ u s e r _ e x c e p t i o n ) ; /* syscall handler */
2011-03-10 10:51:27 +01:00
.org 0x10
2009-05-26 16:30:21 +02:00
brai T O P H Y S ( _ i n t e r r u p t ) ; /* Interrupt handler */
2011-03-10 10:51:27 +01:00
.org 0x18
2010-08-03 11:26:51 +02:00
brai T O P H Y S ( _ d e b u g _ e x c e p t i o n ) ; /* debug trap handler */
2011-03-10 10:51:27 +01:00
.org 0x20
2009-05-26 16:30:21 +02:00
brai T O P H Y S ( _ h w _ e x c e p t i o n _ h a n d l e r ) ; /* HW exception handler */
.section .rodata , " a"
# include " s y s c a l l _ t a b l e . S "
syscall_ t a b l e _ s i z e = ( . - s y s _ c a l l _ t a b l e )
2010-04-27 12:37:54 -05:00
type_SYSCALL :
.ascii " SYSCALL\ 0 "
type_IRQ :
.ascii " IRQ\ 0 "
type_IRQ_PREEMPT :
.ascii " IRQ ( P R E E M P T E D ) \ 0 "
type_SYSCALL_PREEMPT :
.ascii " SYSCALL ( P R E E M P T E D ) \ 0 "
/ *
* Trap d e c o d i n g f o r s t a c k u n w i n d e r
* Tuples a r e ( s t a r t a d d r , e n d a d d r , s t r i n g )
* If r e t u r n a d d r e s s l i e s o n [ s t a r t a d d r , e n d a d d r ] ,
* unwinder d i s p l a y s ' s t r i n g '
* /
.align 4
.global microblaze_trap_handlers
microblaze_trap_handlers :
/* Exact matches come first */
.word ret_ f r o m _ t r a p ; .word ret_from_trap ; .word type_SYSCALL
.word ret_from_irq ; .word ret_from_irq ; .word type_IRQ
/* Fuzzy matches go here */
.word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT
.word ret_ f r o m _ t r a p ; .word TRAP_return ; .word type_SYSCALL_PREEMPT
/* End of table */
.word 0 ; .word 0 ; .word 0