2016-04-27 19:47:12 +03:00
/ *
* Hibernate l o w - l e v e l s u p p o r t
*
* Copyright ( C ) 2 0 1 6 A R M L t d .
* Author : James M o r s e < j a m e s . m o r s e @arm.com>
*
* 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 .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
* but W I T H O U T A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY o r F I T N E S S F O R A P A R T I C U L A R P U R P O S E . S e e t h e
* GNU G e n e r a l P u b l i c L i c e n s e f o r m o r e d e t a i l s .
*
* You s h o u l d h a v e r e c e i v e d a c o p y 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
* along w i t h t h i s p r o g r a m . I f n o t , s e e < h t t p : / / w w w . g n u . o r g / l i c e n s e s / > .
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / e r r n o . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / c p u t y p e . h >
# include < a s m / m e m o r y . h >
# include < a s m / p a g e . h >
# include < a s m / v i r t . h >
/ *
* To p r e v e n t t h e p o s s i b i l i t y o f o l d a n d n e w p a r t i a l t a b l e w a l k s b e i n g v i s i b l e
* in t h e t l b , s w i t c h t h e t t b r t o a z e r o p a g e w h e n w e i n v a l i d a t e t h e o l d
* records. D 4 . 7 . 1 ' G e n e r a l T L B m a i n t e n a n c e r e q u i r e m e n t s ' i n A R M D D I 0 4 8 7 A . i
* Even s w i t c h i n g t o o u r c o p i e d t a b l e s w i l l c a u s e a c h a n g e d o u t p u t a d d r e s s a t
* each s t a g e o f t h e w a l k .
* /
.macro break_before_make_ttbr_switch zero_ p a g e , p a g e _ t a b l e
msr t t b r1 _ e l 1 , \ z e r o _ p a g e
isb
2016-08-08 13:12:07 +03:00
tlbi v m a l l e 1
dsb n s h
2016-04-27 19:47:12 +03:00
msr t t b r1 _ e l 1 , \ p a g e _ t a b l e
isb
.endm
/ *
* Resume f r o m h i b e r n a t e
*
* Loads t e m p o r a r y p a g e t a b l e s t h e n r e s t o r e s t h e m e m o r y i m a g e .
* Finally b r a n c h e s t o c p u _ r e s u m e ( ) t o r e s t o r e t h e s t a t e s a v e d b y
* swsusp_ a r c h _ s u s p e n d ( ) .
*
* Because t h i s c o d e h a s t o b e c o p i e d t o a ' s a f e ' p a g e , i t c a n ' t c a l l o u t t o
* other f u n c t i o n s b y P C - r e l a t i v e a d d r e s s . A l s o r e m e m b e r t h a t i t m a y b e
* mid- w a y t h r o u g h o v e r - w r i t i n g o t h e r f u n c t i o n s . F o r t h i s r e a s o n i t c o n t a i n s
* code f r o m f l u s h _ i c a c h e _ r a n g e ( ) a n d u s e s t h e c o p y _ p a g e ( ) m a c r o .
*
* This ' s a f e ' p a g e i s m a p p e d v i a t t b r0 , a n d e x e c u t e d f r o m t h e r e . T h i s f u n c t i o n
* switches t o a c o p y o f t h e l i n e a r m a p i n t t b r1 , p e r f o r m s t h e r e s t o r e , t h e n
* switches t t b r1 t o t h e o r i g i n a l k e r n e l ' s s w a p p e r _ p g _ d i r .
*
* All o f m e m o r y g e t s w r i t t e n t o , i n c l u d i n g c o d e . W e n e e d t o c l e a n t h e k e r n e l
* text t o t h e P o i n t o f C o h e r e n c e ( P o C ) b e f o r e s e c o n d a r y c o r e s c a n b e b o o t e d .
* Because t h e k e r n e l m o d u l e s a n d e x e c u t a b l e p a g e s m a p p e d t o u s e r s p a c e a r e
* also w r i t t e n a s d a t a , w e c l e a n a l l p a g e s w e t o u c h t o t h e P o i n t o f
* Unification ( P o U ) .
*
* x0 : physical a d d r e s s o f t e m p o r a r y p a g e t a b l e s
* x1 : physical a d d r e s s o f s w a p p e r p a g e t a b l e s
* x2 : address o f c p u _ r e s u m e
* x3 : linear m a p a d d r e s s o f r e s t o r e _ p b l i s t i n t h e c u r r e n t k e r n e l
* x4 : physical a d d r e s s o f _ _ h y p _ s t u b _ v e c t o r s , o r 0
* x5 : physical a d d r e s s o f a z e r o p a g e t h a t r e m a i n s z e r o a f t e r r e s u m e
* /
.pushsection " .hibernate_exit .text " , " ax"
ENTRY( s w s u s p _ a r c h _ s u s p e n d _ e x i t )
/ *
* We e x e c u t e f r o m t t b r0 , c h a n g e t t b r1 t o o u r c o p i e d l i n e a r m a p t a b l e s
* with a b r e a k - b e f o r e - m a k e v i a t h e z e r o p a g e
* /
break_ b e f o r e _ m a k e _ t t b r _ s w i t c h x5 , x0
mov x21 , x1
mov x30 , x2
mov x24 , x4
mov x25 , x5
/* walk the restore_pblist and use copy_page() to over-write memory */
mov x19 , x3
1 : ldr x10 , [ x19 , #H I B E R N _ P B E _ O R I G ]
mov x0 , x10
ldr x1 , [ x19 , #H I B E R N _ P B E _ A D D R ]
copy_ p a g e x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9
add x1 , x10 , #P A G E _ S I Z E
/* Clean the copied page to PoU - based on flush_icache_range() */
2016-09-09 16:07:14 +03:00
raw_ d c a c h e _ l i n e _ s i z e x2 , x3
2016-04-27 19:47:12 +03:00
sub x3 , x2 , #1
bic x4 , x10 , x3
2 : dc c v a u , x4 / * c l e a n D l i n e / u n i f i e d l i n e * /
add x4 , x4 , x2
cmp x4 , x1
b. l o 2 b
ldr x19 , [ x19 , #H I B E R N _ P B E _ N E X T ]
cbnz x19 , 1 b
dsb i s h / * w a i t f o r P o U c l e a n i n g t o f i n i s h * /
/* switch to the restored kernels page tables */
break_ b e f o r e _ m a k e _ t t b r _ s w i t c h x25 , x21
ic i a l l u i s
dsb i s h
isb
cbz x24 , 3 f / * D o w e n e e d t o r e - i n i t i a l i s e E L 2 ? * /
hvc #0
3 : ret
.ltorg
ENDPROC( s w s u s p _ a r c h _ s u s p e n d _ e x i t )
/ *
* Restore t h e h y p s t u b .
* This m u s t b e d o n e b e f o r e t h e h i b e r n a t e p a g e i s u n m a p p e d b y _ c p u _ r e s u m e ( ) ,
* but h a p p e n s b e f o r e a n y o f t h e h y p - s t u b ' s c o d e i s c l e a n e d t o P o C .
*
* x24 : The p h y s i c a l a d d r e s s o f _ _ h y p _ s t u b _ v e c t o r s
* /
el1_sync :
msr v b a r _ e l 2 , x24
eret
ENDPROC( e l 1 _ s y n c )
.macro invalid_vector label
\ label :
b \ l a b e l
ENDPROC( \ l a b e l )
.endm
invalid_ v e c t o r e l 2 _ s y n c _ i n v a l i d
invalid_ v e c t o r e l 2 _ i r q _ i n v a l i d
invalid_ v e c t o r e l 2 _ f i q _ i n v a l i d
invalid_ v e c t o r e l 2 _ e r r o r _ i n v a l i d
invalid_ v e c t o r e l 1 _ s y n c _ i n v a l i d
invalid_ v e c t o r e l 1 _ i r q _ i n v a l i d
invalid_ v e c t o r e l 1 _ f i q _ i n v a l i d
invalid_ v e c t o r e l 1 _ e r r o r _ i n v a l i d
/* el2 vectors - switch el2 here while we restore the memory image. */
.align 11
ENTRY( h i b e r n a t e _ e l 2 _ v e c t o r s )
ventry e l 2 _ s y n c _ i n v a l i d / / S y n c h r o n o u s E L 2 t
ventry e l 2 _ i r q _ i n v a l i d / / I R Q E L 2 t
ventry e l 2 _ f i q _ i n v a l i d / / F I Q E L 2 t
ventry e l 2 _ e r r o r _ i n v a l i d / / E r r o r E L 2 t
ventry e l 2 _ s y n c _ i n v a l i d / / S y n c h r o n o u s E L 2 h
ventry e l 2 _ i r q _ i n v a l i d / / I R Q E L 2 h
ventry e l 2 _ f i q _ i n v a l i d / / F I Q E L 2 h
ventry e l 2 _ e r r o r _ i n v a l i d / / E r r o r E L 2 h
ventry e l 1 _ s y n c / / S y n c h r o n o u s 6 4 - b i t E L 1
ventry e l 1 _ i r q _ i n v a l i d / / I R Q 6 4 - b i t E L 1
ventry e l 1 _ f i q _ i n v a l i d / / F I Q 6 4 - b i t E L 1
ventry e l 1 _ e r r o r _ i n v a l i d / / E r r o r 6 4 - b i t E L 1
ventry e l 1 _ s y n c _ i n v a l i d / / S y n c h r o n o u s 3 2 - b i t E L 1
ventry e l 1 _ i r q _ i n v a l i d / / I R Q 3 2 - b i t E L 1
ventry e l 1 _ f i q _ i n v a l i d / / F I Q 3 2 - b i t E L 1
ventry e l 1 _ e r r o r _ i n v a l i d / / E r r o r 3 2 - b i t E L 1
END( h i b e r n a t e _ e l 2 _ v e c t o r s )
.popsection