2019-10-29 12:13:57 +00:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
/ *
* This f i l e c o n t a i n s k e x e c l o w - l e v e l f u n c t i o n s .
*
* Copyright ( C ) 2 0 0 2 - 2 0 0 3 E r i c B i e d e r m a n < e b i e d e r m @xmission.com>
* GameCube/ p p c32 p o r t C o p y r i g h t ( C ) 2 0 0 4 A l b e r t H e r r a n z
* PPC4 4 x p o r t . C o p y r i g h t ( C ) 2 0 1 1 , I B M C o r p o r a t i o n
* Author : Suzuki P o u l o s e < s u z u k i @in.ibm.com>
* /
# include < a s m / r e g . h >
# include < a s m / p a g e . h >
# include < a s m / m m u . h >
# include < a s m / p p c _ a s m . h >
# include < a s m / k e x e c . h >
.text
/ *
* Must b e r e l o c a t a b l e P I C c o d e c a l l a b l e a s a C f u n c t i o n .
* /
.globl relocate_new_kernel
relocate_new_kernel :
/* r3 = page_list */
/* r4 = reboot_code_buffer */
/* r5 = start_address */
# ifdef C O N F I G _ F S L _ B O O K E
mr r29 , r3
mr r30 , r4
mr r31 , r5
# define E N T R Y _ M A P P I N G _ K E X E C _ S E T U P
2019-10-29 12:13:58 +00:00
# include < k e r n e l / f s l _ b o o k e _ e n t r y _ m a p p i n g . S >
2019-10-29 12:13:57 +00:00
# undef E N T R Y _ M A P P I N G _ K E X E C _ S E T U P
mr r3 , r29
mr r4 , r30
mr r5 , r31
li r0 , 0
# elif d e f i n e d ( C O N F I G _ 4 4 x )
/* Save our parameters */
mr r29 , r3
mr r30 , r4
mr r31 , r5
# ifdef C O N F I G _ P P C _ 4 7 x
/* Check for 47x cores */
mfspr r3 ,S P R N _ P V R
srwi r3 ,r3 ,1 6
cmplwi c r0 ,r3 ,P V R _ 4 7 6 F P E @h
beq s e t u p _ m a p _ 4 7 x
cmplwi c r0 ,r3 ,P V R _ 4 7 6 @h
beq s e t u p _ m a p _ 4 7 x
cmplwi c r0 ,r3 ,P V R _ 4 7 6 _ I S S @h
beq s e t u p _ m a p _ 4 7 x
# endif / * C O N F I G _ P P C _ 4 7 x * /
/ *
* Code f o r s e t t i n g u p 1 : 1 m a p p i n g f o r P P C 4 4 0 x f o r K E X E C
*
* We c a n n o t s w i t c h o f f t h e M M U o n P P C 4 4 x .
* So w e :
* 1 ) Invalidate a l l t h e m a p p i n g s e x c e p t t h e o n e w e a r e r u n n i n g f r o m .
* 2 ) Create a t m p m a p p i n g f o r o u r c o d e i n t h e o t h e r a d d r e s s s p a c e ( T S ) a n d
* jump t o i t . I n v a l i d a t e t h e e n t r y w e s t a r t e d i n .
* 3 ) Create a 1 : 1 m a p p i n g f o r 0 - 2 G i B i n c h u n k s o f 2 5 6 M i n o r i g i n a l T S .
* 4 ) Jump t o t h e 1 : 1 m a p p i n g i n o r i g i n a l T S .
* 5 ) Invalidate t h e t m p m a p p i n g .
*
* - Based o n t h e k e x e c s u p p o r t c o d e f o r F S L B o o k E
*
* /
/ *
* Load t h e P I D w i t h k e r n e l P I D ( 0 ) .
* Also l o a d o u r M S R _ I S a n d T I D t o M M U C R f o r T L B s e a r c h .
* /
li r3 , 0
mtspr S P R N _ P I D , r3
mfmsr r4
andi. r4 ,r4 ,M S R _ I S @l
beq w m m u c r
oris r3 ,r3 ,P P C 4 4 x _ M M U C R _ S T S @h
wmmucr :
mtspr S P R N _ M M U C R ,r3
sync
/ *
* Invalidate a l l t h e T L B e n t r i e s e x c e p t t h e c u r r e n t e n t r y
* where w e a r e r u n n i n g f r o m
* /
bl 0 f / * F i n d o u r a d d r e s s * /
0 : mflr r5 / * M a k e i t a c c e s s i b l e * /
tlbsx r23 ,0 ,r5 / * F i n d e n t r y w e a r e i n * /
li r4 ,0 / * S t a r t a t T L B e n t r y 0 * /
li r3 ,0 / * S e t P A G E I D i n v a l v a l u e * /
1 : cmpw r23 ,r4 / * I s t h i s o u r e n t r y ? * /
beq s k i p / * I f s o , s k i p t h e i n v a l * /
tlbwe r3 ,r4 ,P P C 4 4 x _ T L B _ P A G E I D / * I f n o t , i n v a l t h e e n t r y * /
skip :
addi r4 ,r4 ,1 / * I n c r e m e n t * /
cmpwi r4 ,6 4 / * A r e w e d o n e ? * /
bne 1 b / * I f n o t , r e p e a t * /
isync
/* Create a temp mapping and jump to it */
andi. r6 , r23 , 1 / * F i n d t h e i n d e x t o u s e * /
addi r24 , r6 , 1 / * r24 w i l l c o n t a i n 1 o r 2 * /
mfmsr r9 / * g e t t h e M S R * /
rlwinm r5 , r9 , 2 7 , 3 1 , 3 1 / * E x t r a c t t h e M S R [ I S ] * /
xori r7 , r5 , 1 / * U s e t h e o t h e r a d d r e s s s p a c e * /
/* Read the current mapping entries */
tlbre r3 , r23 , P P C 4 4 x _ T L B _ P A G E I D
tlbre r4 , r23 , P P C 4 4 x _ T L B _ X L A T
tlbre r5 , r23 , P P C 4 4 x _ T L B _ A T T R I B
/* Save our current XLAT entry */
mr r25 , r4
/* Extract the TLB PageSize */
li r10 , 1 / * r10 w i l l h o l d P a g e S i z e * /
rlwinm r11 , r3 , 0 , 2 4 , 2 7 / * b i t s 2 4 - 2 7 * /
/* XXX: As of now we use 256M, 4K pages */
cmpwi r11 , P P C 4 4 x _ T L B _ 2 5 6 M
bne t l b _ 4 k
rotlwi r10 , r10 , 2 8 / * r10 = 2 5 6 M * /
b w r i t e _ o u t
tlb_4k :
cmpwi r11 , P P C 4 4 x _ T L B _ 4 K
bne d e f a u l t
rotlwi r10 , r10 , 1 2 / * r10 = 4 K * /
b w r i t e _ o u t
default :
rotlwi r10 , r10 , 1 0 / * r10 = 1 K * /
write_out :
/ *
* Write o u t t h e t m p 1 : 1 m a p p i n g f o r t h i s c o d e i n o t h e r a d d r e s s s p a c e
* Fixup E P N = R P N , T S =other a d d r e s s s p a c e
* /
insrwi r3 , r7 , 1 , 2 3 / * B i t 2 3 i s T S f o r P A G E I D f i e l d * /
/* Write out the tmp mapping entries */
tlbwe r3 , r24 , P P C 4 4 x _ T L B _ P A G E I D
tlbwe r4 , r24 , P P C 4 4 x _ T L B _ X L A T
tlbwe r5 , r24 , P P C 4 4 x _ T L B _ A T T R I B
subi r11 , r10 , 1 / * P a g e O f f s e t M a s k = P a g e S i z e - 1 * /
not r10 , r11 / * M a s k f o r P a g e N u m * /
/* Switch to other address space in MSR */
insrwi r9 , r7 , 1 , 2 6 / * S e t M S R [ I S ] = r7 * /
bl 1 f
1 : mflr r8
addi r8 , r8 , ( 2 f - 1 b ) / * F i n d t h e t a r g e t o f f s e t * /
/* Jump to the tmp mapping */
mtspr S P R N _ S R R 0 , r8
mtspr S P R N _ S R R 1 , r9
rfi
2 :
/* Invalidate the entry we were executing from */
li r3 , 0
tlbwe r3 , r23 , P P C 4 4 x _ T L B _ P A G E I D
/* attribute fields. rwx for SUPERVISOR mode */
li r5 , 0
ori r5 , r5 , ( P P C 4 4 x _ T L B _ S W | P P C 4 4 x _ T L B _ S R | P P C 4 4 x _ T L B _ S X | P P C 4 4 x _ T L B _ G )
/* Create 1:1 mapping in 256M pages */
xori r7 , r7 , 1 / * R e v e r t b a c k t o O r i g i n a l T S * /
li r8 , 0 / * P a g e N u m b e r * /
li r6 , 3 / * T L B I n d e x , s t a r t a t 3 * /
next_tlb :
rotlwi r3 , r8 , 2 8 / * C r e a t e E P N ( b i t s 0 - 3 ) * /
mr r4 , r3 / * R P N = E P N * /
ori r3 , r3 , ( P P C 4 4 x _ T L B _ V A L I D | P P C 4 4 x _ T L B _ 2 5 6 M ) / * S I Z E = 2 5 6 M , V a l i d * /
insrwi r3 , r7 , 1 , 2 3 / * S e t T S f r o m r7 * /
tlbwe r3 , r6 , P P C 4 4 x _ T L B _ P A G E I D / * P a g e I D f i e l d : E P N , V , S I Z E * /
tlbwe r4 , r6 , P P C 4 4 x _ T L B _ X L A T / * A d d r e s s t r a n s l a t i o n : R P N * /
tlbwe r5 , r6 , P P C 4 4 x _ T L B _ A T T R I B / * A t t r i b u t e s * /
addi r8 , r8 , 1 / * I n c r e m e n t P N * /
addi r6 , r6 , 1 / * I n c r e m e n t T L B I n d e x * /
cmpwi r8 , 8 / * A r e w e d o n e ? * /
bne n e x t _ t l b
isync
/* Jump to the new mapping 1:1 */
li r9 ,0
insrwi r9 , r7 , 1 , 2 6 / * S e t M S R [ I S ] = r7 * /
bl 1 f
1 : mflr r8
and r8 , r8 , r11 / * G e t o u r o f f s e t w i t h i n p a g e * /
addi r8 , r8 , ( 2 f - 1 b )
and r5 , r25 , r10 / * G e t o u r t a r g e t P a g e N u m * /
or r8 , r8 , r5 / * T a r g e t j u m p a d d r e s s * /
mtspr S P R N _ S R R 0 , r8
mtspr S P R N _ S R R 1 , r9
rfi
2 :
/* Invalidate the tmp entry we used */
li r3 , 0
tlbwe r3 , r24 , P P C 4 4 x _ T L B _ P A G E I D
sync
b p p c44 x _ m a p _ d o n e
# ifdef C O N F I G _ P P C _ 4 7 x
/* 1:1 mapping for 47x */
setup_map_47x :
/ *
* Load t h e k e r n e l p i d ( 0 ) t o P I D a n d a l s o t o M M U C R [ T I D ] .
* Also s e t t h e M S R I S - > M M U C R S T S
* /
li r3 , 0
mtspr S P R N _ P I D , r3 / * S e t P I D * /
mfmsr r4 / * G e t M S R * /
andi. r4 , r4 , M S R _ I S @l /* TS=1? */
beq 1 f / * I f n o t , l e a v e S T S =0 * /
oris r3 , r3 , P P C 4 7 x _ M M U C R _ S T S @h /* Set STS=1 */
1 : mtspr S P R N _ M M U C R , r3 / * P u t M M U C R * /
sync
/* Find the entry we are running from */
bl 2 f
2 : mflr r23
tlbsx r23 , 0 , r23
tlbre r24 , r23 , 0 / * T L B W o r d 0 * /
tlbre r25 , r23 , 1 / * T L B W o r d 1 * /
tlbre r26 , r23 , 2 / * T L B W o r d 2 * /
/ *
* Invalidates a l l t h e t l b e n t r i e s b y w r i t i n g t o 2 5 6 R P N s ( r4 )
* of 4 k p a g e s i z e i n a l l 4 w a y s ( 0 - 3 i n r3 ) .
* This w o u l d i n v a l i d a t e t h e e n t i r e U T L B i n c l u d i n g t h e o n e w e a r e
* running f r o m . H o w e v e r t h e s h a d o w T L B e n t r i e s w o u l d h e l p u s
* to c o n t i n u e t h e e x e c u t i o n , u n t i l w e f l u s h t h e m ( r f i / i s y n c ) .
* /
addis r3 , 0 , 0 x80 0 0 / * s p e c i f y t h e w a y * /
addi r4 , 0 , 0 / * T L B W o r d0 = ( E P N =0 , V A L I D = 0 ) * /
addi r5 , 0 , 0
b c l e a r _ u t l b _ e n t r y
/* Align the loop to speed things up. from head_44x.S */
.align 6
clear_utlb_entry :
tlbwe r4 , r3 , 0
tlbwe r5 , r3 , 1
tlbwe r5 , r3 , 2
addis r3 , r3 , 0 x20 0 0 / * I n c r e m e n t t h e w a y * /
cmpwi r3 , 0
bne c l e a r _ u t l b _ e n t r y
addis r3 , 0 , 0 x80 0 0
addis r4 , r4 , 0 x10 0 / * I n c r e m e n t t h e E P N * /
cmpwi r4 , 0
bne c l e a r _ u t l b _ e n t r y
/* Create the entries in the other address space */
mfmsr r5
rlwinm r7 , r5 , 2 7 , 3 1 , 3 1 / * G e t t h e T S ( B i t 2 6 ) f r o m M S R * /
xori r7 , r7 , 1 / * r7 = ! T S * /
insrwi r24 , r7 , 1 , 2 1 / * C h a n g e t h e T S i n t h e s a v e d T L B w o r d 0 * /
/ *
* write o u t t h e T L B e n t r i e s f o r t h e t m p m a p p i n g
* Use w a y ' 0 ' s o t h a t w e c o u l d e a s i l y i n v a l i d a t e i t l a t e r .
* /
lis r3 , 0 x80 0 0 / * W a y ' 0 ' * /
tlbwe r24 , r3 , 0
tlbwe r25 , r3 , 1
tlbwe r26 , r3 , 2
/* Update the msr to the new TS */
insrwi r5 , r7 , 1 , 2 6
bl 1 f
1 : mflr r6
addi r6 , r6 , ( 2 f - 1 b )
mtspr S P R N _ S R R 0 , r6
mtspr S P R N _ S R R 1 , r5
rfi
/ *
* Now w e a r e i n t h e t m p a d d r e s s s p a c e .
* Create a 1 : 1 m a p p i n g f o r 0 - 2 G i B i n t h e o r i g i n a l T S .
* /
2 :
li r3 , 0
li r4 , 0 / * T L B W o r d 0 * /
li r5 , 0 / * T L B W o r d 1 * /
li r6 , 0
ori r6 , r6 , P P C 4 7 x _ T L B 2 _ S _ R W X / * T L B w o r d 2 * /
li r8 , 0 / * P a g e I n d e x * /
xori r7 , r7 , 1 / * r e v e r t b a c k t o o r i g i n a l T S * /
write_utlb :
rotlwi r5 , r8 , 2 8 / * R P N = P a g e I n d e x * 2 5 6 M * /
/* ERPN = 0 as we don't use memory above 2G */
mr r4 , r5 / * E P N = R P N * /
ori r4 , r4 , ( P P C 4 7 x _ T L B 0 _ V A L I D | P P C 4 7 x _ T L B 0 _ 2 5 6 M )
insrwi r4 , r7 , 1 , 2 1 / * I n s e r t t h e T S t o W o r d 0 * /
tlbwe r4 , r3 , 0 / * W r i t e o u t t h e e n t r i e s * /
tlbwe r5 , r3 , 1
tlbwe r6 , r3 , 2
addi r8 , r8 , 1
cmpwi r8 , 8 / * H a v e w e c o m p l e t e d ? * /
bne w r i t e _ u t l b
/* make sure we complete the TLB write up */
isync
/ *
* Prepare t o j u m p t o t h e 1 : 1 m a p p i n g .
* 1 ) Extract p a g e s i z e o f t h e t m p m a p p i n g
* DSIZ = T L B _ W o r d0 [ 2 2 : 2 7 ]
* 2 ) Calculate t h e p h y s i c a l a d d r e s s o f t h e a d d r e s s
* to j u m p t o .
* /
rlwinm r10 , r24 , 0 , 2 2 , 2 7
cmpwi r10 , P P C 4 7 x _ T L B 0 _ 4 K
bne 0 f
li r10 , 0 x10 0 0 / * r10 = 4 k * /
bl 1 f
0 :
/* Defaults to 256M */
lis r10 , 0 x10 0 0
bl 1 f
1 : mflr r4
addi r4 , r4 , ( 2 f - 1 b ) / * v i r t u a l a d d r e s s o f 2 f * /
subi r11 , r10 , 1 / * o f f s e t m a s k = P a g e s i z e - 1 * /
not r10 , r11 / * P a g e m a s k = ~ ( o f f s e t m a s k ) * /
and r5 , r25 , r10 / * P h y s i c a l p a g e * /
and r6 , r4 , r11 / * o f f s e t w i t h i n t h e c u r r e n t p a g e * /
or r5 , r5 , r6 / * P h y s i c a l a d d r e s s f o r 2 f * /
/* Switch the TS in MSR to the original one */
mfmsr r8
insrwi r8 , r7 , 1 , 2 6
mtspr S P R N _ S R R 1 , r8
mtspr S P R N _ S R R 0 , r5
rfi
2 :
/* Invalidate the tmp mapping */
lis r3 , 0 x80 0 0 / * W a y ' 0 ' * /
clrrwi r24 , r24 , 1 2 / * C l e a r t h e v a l i d b i t * /
tlbwe r24 , r3 , 0
tlbwe r25 , r3 , 1
tlbwe r26 , r3 , 2
/* Make sure we complete the TLB write and flush the shadow TLB */
isync
# endif
ppc44x_map_done :
/* Restore the parameters */
mr r3 , r29
mr r4 , r30
mr r5 , r31
li r0 , 0
# else
li r0 , 0
/ *
* Set M a c h i n e S t a t u s R e g i s t e r t o a k n o w n s t a t u s ,
* switch t h e M M U o f f a n d j u m p t o 1 : i n a s i n g l e s t e p .
* /
mr r8 , r0
ori r8 , r8 , M S R _ R I | M S R _ M E
mtspr S P R N _ S R R 1 , r8
addi r8 , r4 , 1 f - r e l o c a t e _ n e w _ k e r n e l
mtspr S P R N _ S R R 0 , r8
sync
rfi
1 :
# endif
/* from this point address translation is turned off */
/* and interrupts are disabled */
/* set a new stack at the bottom of our page... */
/* (not really needed now) */
addi r1 , r4 , K E X E C _ C O N T R O L _ P A G E _ S I Z E - 8 / * f o r L R S a v e + B a c k C h a i n * /
stw r0 , 0 ( r1 )
/* Do the copies */
li r6 , 0 / * c h e c k s u m * /
mr r0 , r3
b 1 f
0 : /* top, read another word for the indirection page */
lwzu r0 , 4 ( r3 )
1 :
/* is it a destination page? (r8) */
rlwinm. r7 , r0 , 0 , 3 1 , 3 1 / * I N D _ D E S T I N A T I O N ( 1 < < 0 ) * /
beq 2 f
rlwinm r8 , r0 , 0 , 0 , 1 9 / * c l e a r k e x e c f l a g s , p a g e a l i g n * /
b 0 b
2 : /* is it an indirection page? (r3) */
rlwinm. r7 , r0 , 0 , 3 0 , 3 0 / * I N D _ I N D I R E C T I O N ( 1 < < 1 ) * /
beq 2 f
rlwinm r3 , r0 , 0 , 0 , 1 9 / * c l e a r k e x e c f l a g s , p a g e a l i g n * /
subi r3 , r3 , 4
b 0 b
2 : /* are we done? */
rlwinm. r7 , r0 , 0 , 2 9 , 2 9 / * I N D _ D O N E ( 1 < < 2 ) * /
beq 2 f
b 3 f
2 : /* is it a source page? (r9) */
rlwinm. r7 , r0 , 0 , 2 8 , 2 8 / * I N D _ S O U R C E ( 1 < < 3 ) * /
beq 0 b
rlwinm r9 , r0 , 0 , 0 , 1 9 / * c l e a r k e x e c f l a g s , p a g e a l i g n * /
li r7 , P A G E _ S I Z E / 4
mtctr r7
subi r9 , r9 , 4
subi r8 , r8 , 4
9 :
lwzu r0 , 4 ( r9 ) / * d o t h e c o p y * /
xor r6 , r6 , r0
stwu r0 , 4 ( r8 )
dcbst 0 , r8
sync
icbi 0 , r8
bdnz 9 b
addi r9 , r9 , 4
addi r8 , r8 , 4
b 0 b
3 :
/ * To b e c e r t a i n o f a v o i d i n g p r o b l e m s w i t h s e l f - m o d i f y i n g c o d e
* execute a s e r i a l i z i n g i n s t r u c t i o n h e r e .
* /
isync
sync
mfspr r3 , S P R N _ P I R / * c u r r e n t c o r e w e a r e r u n n i n g o n * /
mr r4 , r5 / * l o a d p h y s i c a l a d d r e s s o f c h u n k c a l l e d * /
/* jump to the entry point, usually the setup routine */
mtlr r5
blrl
1 : b 1 b
relocate_new_kernel_end :
.globl relocate_new_kernel_size
relocate_new_kernel_size :
.long relocate_new_kernel_end - relocate_ n e w _ k e r n e l