2005-04-17 02:20:36 +04:00
/ *
* linux/ a r c h / a r m / k e r n e l / h e a d . S
*
* Copyright ( C ) 1 9 9 4 - 2 0 0 2 R u s s e l l K i n g
2005-06-18 12:33:31 +04:00
* Copyright ( c ) 2 0 0 3 A R M L i m i t e d
* All R i g h t s R e s e r v e d
2005-04-17 02:20:36 +04:00
*
* 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 .
*
* Kernel s t a r t u p c o d e f o r a l l 3 2 - b i t C P U s
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i n i t . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / d o m a i n . h >
# include < a s m / p t r a c e . h >
2005-09-09 23:08:59 +04:00
# include < a s m / a s m - o f f s e t s . h >
2005-10-30 00:44:55 +04:00
# include < a s m / m e m o r y . h >
2005-05-05 16:11:00 +04:00
# include < a s m / t h r e a d _ i n f o . h >
2005-04-17 02:20:36 +04:00
# include < a s m / s y s t e m . h >
2011-08-23 17:07:23 +04:00
# include < a s m / p g t a b l e . h >
2005-04-17 02:20:36 +04:00
2010-07-07 07:19:48 +04:00
# ifdef C O N F I G _ D E B U G _ L L
# include < m a c h / d e b u g - m a c r o . S >
# endif
2005-04-17 02:20:36 +04:00
/ *
2005-10-30 00:44:56 +04:00
* swapper_ p g _ d i r i s t h e v i r t u a l a d d r e s s o f t h e i n i t i a l p a g e t a b l e .
2006-12-12 01:29:16 +03:00
* We p l a c e t h e p a g e t a b l e s 1 6 K b e l o w K E R N E L _ R A M _ V A D D R . T h e r e f o r e , w e m u s t
* make s u r e t h a t K E R N E L _ R A M _ V A D D R i s c o r r e c t l y s e t . C u r r e n t l y , w e e x p e c t
2005-10-30 00:44:56 +04:00
* the l e a s t s i g n i f i c a n t 1 6 b i t s t o b e 0 x80 0 0 , b u t w e c o u l d p r o b a b l y
2006-12-12 01:29:16 +03:00
* relax t h i s r e s t r i c t i o n t o K E R N E L _ R A M _ V A D D R > = P A G E _ O F F S E T + 0 x40 0 0 .
2005-04-17 02:20:36 +04:00
* /
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
# define K E R N E L _ R A M _ V A D D R ( P A G E _ O F F S E T + T E X T _ O F F S E T )
2006-12-12 01:29:16 +03:00
# if ( K E R N E L _ R A M _ V A D D R & 0 x f f f f ) ! = 0 x80 0 0
# error K E R N E L _ R A M _ V A D D R m u s t s t a r t a t 0 x X X X X 8 0 0 0
2005-04-17 02:20:36 +04:00
# endif
2011-08-23 17:07:23 +04:00
# define P G _ D I R _ S I Z E 0 x40 0 0
# define P M D _ O R D E R 2
2005-04-17 02:20:36 +04:00
.globl swapper_pg_dir
2011-08-23 17:07:23 +04:00
.equ swapper_ p g _ d i r , K E R N E L _ R A M _ V A D D R - P G _ D I R _ S I Z E
2005-04-17 02:20:36 +04:00
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
.macro pgtbl, r d , p h y s
2011-08-23 17:07:23 +04:00
add \ r d , \ p h y s , #T E X T _ O F F S E T - P G _ D I R _ S I Z E
2005-04-17 02:20:36 +04:00
.endm
2005-10-30 00:44:56 +04:00
# ifdef C O N F I G _ X I P _ K E R N E L
2007-02-22 18:18:09 +03:00
# define K E R N E L _ S T A R T X I P _ V I R T _ A D D R ( C O N F I G _ X I P _ P H Y S _ A D D R )
# define K E R N E L _ E N D _ e d a t a _ l o c
2005-10-30 00:44:56 +04:00
# else
2007-02-22 18:18:09 +03:00
# define K E R N E L _ S T A R T K E R N E L _ R A M _ V A D D R
# define K E R N E L _ E N D _ e n d
2005-04-17 02:20:36 +04:00
# endif
/ *
* Kernel s t a r t u p e n t r y p o i n t .
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* This i s n o r m a l l y c a l l e d f r o m t h e d e c o m p r e s s o r c o d e . T h e r e q u i r e m e n t s
* are : MMU = o f f , D - c a c h e = o f f , I - c a c h e = d o n t c a r e , r0 = 0 ,
2011-04-29 00:27:20 +04:00
* r1 = m a c h i n e n r , r2 = a t a g s o r d t b p o i n t e r .
2005-04-17 02:20:36 +04:00
*
* This c o d e i s m o s t l y p o s i t i o n i n d e p e n d e n t , s o i f y o u l i n k t h e k e r n e l a t
* 0 xc0 0 0 8 0 0 0 , y o u c a l l t h i s a t _ _ p a ( 0 x c00 0 8 0 0 0 ) .
*
* See l i n u x / a r c h / a r m / t o o l s / m a c h - t y p e s f o r t h e c o m p l e t e l i s t o f m a c h i n e
* numbers f o r r1 .
*
* We' r e t r y i n g t o k e e p c r a p t o a m i n i m u m ; DO NOT add any machine specific
* crap h e r e - t h a t ' s w h a t t h e b o o t l o a d e r ( o r i n e x t r e m e , w e l l j u s t i f i e d
* circumstances, z I m a g e ) i s f o r .
* /
2011-07-13 18:53:30 +04:00
.arm
2009-10-03 00:32:46 +04:00
_ _ HEAD
2005-04-17 02:20:36 +04:00
ENTRY( s t e x t )
2011-07-13 18:53:30 +04:00
THUMB( a d r r9 , B S Y M ( 1 f ) ) @ Kernel is always entered in ARM.
THUMB( b x r9 ) @ If this is a Thumb-2 kernel,
THUMB( . t h u m b ) @ switch to Thumb now.
THUMB( 1 : )
2009-07-24 15:32:54 +04:00
setmode P S R _ F _ B I T | P S R _ I _ B I T | S V C _ M O D E , r9 @ ensure svc mode
2005-04-17 02:20:36 +04:00
@ and irqs disabled
2006-02-25 00:04:56 +03:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
2005-04-17 02:20:36 +04:00
bl _ _ l o o k u p _ p r o c e s s o r _ t y p e @ r5=procinfo r9=cpuid
movs r10 , r5 @ invalid processor (r5=0)?
2010-11-29 21:43:28 +03:00
THUMB( i t e q ) @ force fixup-able long branch encoding
2005-11-25 18:43:22 +03:00
beq _ _ e r r o r _ p @ yes, error 'p'
2010-11-22 15:06:28 +03:00
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
# ifndef C O N F I G _ X I P _ K E R N E L
adr r3 , 2 f
ldmia r3 , { r4 , r8 }
sub r4 , r3 , r4 @ (PHYS_OFFSET - PAGE_OFFSET)
add r8 , r8 , r4 @ PHYS_OFFSET
# else
ldr r8 , =PLAT_PHYS_OFFSET
# endif
2010-11-22 15:06:28 +03:00
/ *
2011-04-29 00:27:20 +04:00
* r1 = m a c h i n e n o , r2 = a t a g s o r d t b ,
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
* r8 = p h y s _ o f f s e t , r9 = c p u i d , r10 = p r o c i n f o
2010-11-22 15:06:28 +03:00
* /
2007-06-01 01:02:22 +04:00
bl _ _ v e t _ a t a g s
2010-09-04 13:47:48 +04:00
# ifdef C O N F I G _ S M P _ O N _ U P
bl _ _ f i x u p _ s m p
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
# endif
# ifdef C O N F I G _ A R M _ P A T C H _ P H Y S _ V I R T
bl _ _ f i x u p _ p v _ t a b l e
2010-09-04 13:47:48 +04:00
# endif
2005-04-17 02:20:36 +04:00
bl _ _ c r e a t e _ p a g e _ t a b l e s
/ *
* The f o l l o w i n g c a l l s C P U s p e c i f i c c o d e i n a p o s i t i o n i n d e p e n d e n t
* manner. S e e a r c h / a r m / m m / p r o c - * . S f o r d e t a i l s . r10 = b a s e o f
2011-01-12 20:50:42 +03:00
* xxx_ p r o c _ i n f o s t r u c t u r e s e l e c t e d b y _ _ l o o k u p _ p r o c e s s o r _ t y p e
2005-04-17 02:20:36 +04:00
* above. O n r e t u r n , t h e C P U w i l l b e r e a d y f o r t h e M M U t o b e
* turned o n , a n d r0 w i l l h o l d t h e C P U c o n t r o l r e g i s t e r v a l u e .
* /
2010-10-04 19:22:34 +04:00
ldr r13 , =__mmap_switched @ address to jump to after
2005-04-17 02:20:36 +04:00
@ mmu has been enabled
2010-10-04 20:56:13 +04:00
adr l r , B S Y M ( 1 f ) @ return (PIC) address
2011-05-26 14:22:44 +04:00
mov r8 , r4 @ set TTBR1 to swapper_pg_dir
2009-07-24 15:32:54 +04:00
ARM( a d d p c , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( a d d r12 , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( m o v p c , r12 )
2010-10-04 20:56:13 +04:00
1 : b _ _ e n a b l e _ m m u
2008-08-28 14:22:32 +04:00
ENDPROC( s t e x t )
2010-10-04 19:22:34 +04:00
.ltorg
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
# ifndef C O N F I G _ X I P _ K E R N E L
2 : .long .
.long PAGE_OFFSET
# endif
2005-04-17 02:20:36 +04:00
/ *
* Setup t h e i n i t i a l p a g e t a b l e s . W e o n l y s e t u p t h e b a r e s t
* amount w h i c h a r e r e q u i r e d t o g e t t h e k e r n e l r u n n i n g , w h i c h
* generally m e a n s m a p p i n g i n t h e k e r n e l c o d e .
*
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
* r8 = p h y s _ o f f s e t , r9 = c p u i d , r10 = p r o c i n f o
2005-04-17 02:20:36 +04:00
*
* Returns :
2010-10-04 20:51:54 +04:00
* r0 , r3 , r5 - r7 c o r r u p t e d
2005-04-17 02:20:36 +04:00
* r4 = p h y s i c a l p a g e t a b l e a d d r e s s
* /
__create_page_tables :
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
pgtbl r4 , r8 @ page table address
2005-04-17 02:20:36 +04:00
/ *
2011-08-23 17:07:23 +04:00
* Clear t h e s w a p p e r p a g e t a b l e
2005-04-17 02:20:36 +04:00
* /
mov r0 , r4
mov r3 , #0
2011-08-23 17:07:23 +04:00
add r6 , r0 , #P G _ D I R _ S I Z E
2005-04-17 02:20:36 +04:00
1 : str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
teq r0 , r6
bne 1 b
2006-06-29 21:24:21 +04:00
ldr r7 , [ r10 , #P R O C I N F O _ M M _ M M U F L A G S ] @ m m _ m m u f l a g s
2005-04-17 02:20:36 +04:00
/ *
2010-10-04 20:51:54 +04:00
* Create i d e n t i t y m a p p i n g t o c a t e r f o r _ _ e n a b l e _ m m u .
* This i d e n t i t y m a p p i n g w i l l b e r e m o v e d b y p a g i n g _ i n i t ( ) .
2005-04-17 02:20:36 +04:00
* /
2010-10-04 20:51:54 +04:00
adr r0 , _ _ e n a b l e _ m m u _ l o c
ldmia r0 , { r3 , r5 , r6 }
sub r0 , r0 , r3 @ virt->phys offset
add r5 , r5 , r0 @ phys __enable_mmu
add r6 , r6 , r0 @ phys __enable_mmu_end
2011-08-23 17:07:23 +04:00
mov r5 , r5 , l s r #S E C T I O N _ S H I F T
mov r6 , r6 , l s r #S E C T I O N _ S H I F T
2010-10-04 20:51:54 +04:00
2011-08-23 17:07:23 +04:00
1 : orr r3 , r7 , r5 , l s l #S E C T I O N _ S H I F T @ f l a g s + k e r n e l b a s e
str r3 , [ r4 , r5 , l s l #P M D _ O R D E R ] @ i d e n t i t y m a p p i n g
cmp r5 , r6
addlo r5 , r5 , #1 @ next section
blo 1 b
2005-04-17 02:20:36 +04:00
/ *
* Now s e t u p t h e p a g e t a b l e s f o r o u r k e r n e l d i r e c t
2006-09-30 00:14:05 +04:00
* mapped r e g i o n .
2005-04-17 02:20:36 +04:00
* /
2010-10-04 20:51:54 +04:00
mov r3 , p c
2011-08-23 17:07:23 +04:00
mov r3 , r3 , l s r #S E C T I O N _ S H I F T
orr r3 , r7 , r3 , l s l #S E C T I O N _ S H I F T
add r0 , r4 , #( K E R N E L _ S T A R T & 0xff000000 ) > > ( S E C T I O N _ S H I F T - P M D _ O R D E R )
str r3 , [ r0 , #( ( K E R N E L _ S T A R T & 0x00f00000 ) > > S E C T I O N _ S H I F T ) < < P M D _ O R D E R ] !
2007-02-22 18:18:09 +03:00
ldr r6 , = ( K E R N E L _ E N D - 1 )
2011-08-23 17:07:23 +04:00
add r0 , r0 , #1 < < P M D _ O R D E R
add r6 , r4 , r6 , l s r #( S E C T I O N _ S H I F T - P M D _ O R D E R )
2007-02-22 18:18:09 +03:00
1 : cmp r0 , r6
2011-08-23 17:07:23 +04:00
add r3 , r3 , #1 < < S E C T I O N _ S H I F T
strls r3 , [ r0 ] , #1 < < P M D _ O R D E R
2007-02-22 18:18:09 +03:00
bls 1 b
2005-04-17 02:20:36 +04:00
2007-02-21 17:32:28 +03:00
# ifdef C O N F I G _ X I P _ K E R N E L
/ *
* Map s o m e r a m t o c o v e r o u r . d a t a a n d . b s s a r e a s .
* /
ARM: P2V: eliminate head.S use of PHYS_OFFSET for !XIP_KERNEL
head.S makes use of PHYS_OFFSET. When it becomes a variable, the
assembler won't understand this. Compute PHYS_OFFSET by the following
method. This code is linked at its virtual address, but run at before
the MMU is enabled, so at his physical address.
1: .long .
.long PAGE_OFFSET
adr r0, 1b @ r0 = physical ','
ldmia r0, {r1, r2} @ r1 = virtual '.', r2 = PAGE_OFFSET
sub r1, r0, r1 @ r1 = physical-virtual
add r2, r2, r1 @ r2 = PAGE_OFFSET + physical-virtual
@ := PHYS_OFFSET.
Switch XIP users of PHYS_OFFSET to use PLAT_PHYS_OFFSET - we can't
use this method for XIP kernels as the code doesn't execute in RAM.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:04:00 +03:00
add r3 , r8 , #T E X T _ O F F S E T
orr r3 , r3 , r7
2011-08-23 17:07:23 +04:00
add r0 , r4 , #( K E R N E L _ R A M _ V A D D R & 0xff000000 ) > > ( S E C T I O N _ S H I F T - P M D _ O R D E R )
str r3 , [ r0 , #( K E R N E L _ R A M _ V A D D R & 0x00f00000 ) > > ( S E C T I O N _ S H I F T - P M D _ O R D E R ) ] !
2007-02-21 17:32:28 +03:00
ldr r6 , = ( _ e n d - 1 )
add r0 , r0 , #4
2011-08-23 17:07:23 +04:00
add r6 , r4 , r6 , l s r #( S E C T I O N _ S H I F T - P M D _ O R D E R )
2007-02-21 17:32:28 +03:00
1 : cmp r0 , r6
add r3 , r3 , #1 < < 2 0
strls r3 , [ r0 ] , #4
bls 1 b
# endif
2005-04-17 02:20:36 +04:00
/ *
2011-02-02 18:33:17 +03:00
* Then m a p b o o t p a r a m s a d d r e s s i n r2 o r
* the f i r s t 1 M B o f r a m i f b o o t p a r a m s a d d r e s s i s n o t s p e c i f i e d .
2005-04-17 02:20:36 +04:00
* /
2011-08-23 17:07:23 +04:00
mov r0 , r2 , l s r #S E C T I O N _ S H I F T
movs r0 , r0 , l s l #S E C T I O N _ S H I F T
2011-02-02 18:33:17 +03:00
moveq r0 , r8
sub r3 , r0 , r8
add r3 , r3 , #P A G E _ O F F S E T
2011-08-23 17:07:23 +04:00
add r3 , r4 , r3 , l s r #( S E C T I O N _ S H I F T - P M D _ O R D E R )
2011-02-02 18:33:17 +03:00
orr r6 , r7 , r0
str r6 , [ r3 ]
2005-04-17 02:20:36 +04:00
2005-07-01 14:56:55 +04:00
# ifdef C O N F I G _ D E B U G _ L L
2010-07-07 07:19:48 +04:00
# ifndef C O N F I G _ D E B U G _ I C E D C C
2005-04-17 02:20:36 +04:00
/ *
* Map i n I O s p a c e f o r s e r i a l d e b u g g i n g .
* This a l l o w s d e b u g m e s s a g e s t o b e o u t p u t
* via a s e r i a l c o n s o l e b e f o r e p a g i n g _ i n i t .
* /
2010-07-07 07:19:48 +04:00
addruart r7 , r3
2011-08-23 17:07:23 +04:00
mov r3 , r3 , l s r #S E C T I O N _ S H I F T
mov r3 , r3 , l s l #P M D _ O R D E R
2010-07-07 07:19:48 +04:00
2005-04-17 02:20:36 +04:00
add r0 , r4 , r3
rsb r3 , r3 , #0x4000 @ PTRS_PER_PGD*sizeof(long)
cmp r3 , #0x0800 @ limit to 512MB
movhi r3 , #0x0800
add r6 , r0 , r3
2011-08-23 17:07:23 +04:00
mov r3 , r7 , l s r #S E C T I O N _ S H I F T
2010-07-07 07:19:48 +04:00
ldr r7 , [ r10 , #P R O C I N F O _ I O _ M M U F L A G S ] @ i o _ m m u f l a g s
2011-08-23 17:07:23 +04:00
orr r3 , r7 , r3 , l s l #S E C T I O N _ S H I F T
2005-04-17 02:20:36 +04:00
1 : str r3 , [ r0 ] , #4
2011-08-23 17:07:23 +04:00
add r3 , r3 , #1 < < S E C T I O N _ S H I F T
cmp r0 , r6
blo 1 b
2010-07-07 07:19:48 +04:00
# else / * C O N F I G _ D E B U G _ I C E D C C * /
/* we don't need any serial debugging mappings for ICEDCC */
ldr r7 , [ r10 , #P R O C I N F O _ I O _ M M U F L A G S ] @ i o _ m m u f l a g s
# endif / * ! C O N F I G _ D E B U G _ I C E D C C * /
2005-04-17 02:20:36 +04:00
# if d e f i n e d ( C O N F I G _ A R C H _ N E T W I N D E R ) | | d e f i n e d ( C O N F I G _ A R C H _ C A T S )
/ *
2005-11-25 18:43:22 +03:00
* If w e ' r e u s i n g t h e N e t W i n d e r o r C A T S , w e a l s o n e e d t o m a p
* in t h e 1 6 5 5 0 - t y p e s e r i a l p o r t f o r t h e d e b u g m e s s a g e s
2005-04-17 02:20:36 +04:00
* /
2011-08-23 17:07:23 +04:00
add r0 , r4 , #0xff000000 > > ( S E C T I O N _ S H I F T - P M D _ O R D E R )
2005-07-01 14:56:55 +04:00
orr r3 , r7 , #0x7c000000
str r3 , [ r0 ]
2005-04-17 02:20:36 +04:00
# endif
# ifdef C O N F I G _ A R C H _ R P C
/ *
* Map i n s c r e e n a t 0 x02 0 0 0 0 0 0 & S C R E E N 2 _ B A S E
* Similar r e a s o n s h e r e - f o r d e b u g . T h i s i s
* only f o r A c o r n R i s c P C a r c h i t e c t u r e s .
* /
2011-08-23 17:07:23 +04:00
add r0 , r4 , #0x02000000 > > ( S E C T I O N _ S H I F T - P M D _ O R D E R )
2005-07-01 14:56:55 +04:00
orr r3 , r7 , #0x02000000
2005-04-17 02:20:36 +04:00
str r3 , [ r0 ]
2011-08-23 17:07:23 +04:00
add r0 , r4 , #0xd8000000 > > ( S E C T I O N _ S H I F T - P M D _ O R D E R )
2005-04-17 02:20:36 +04:00
str r3 , [ r0 ]
2005-07-01 14:56:55 +04:00
# endif
2005-04-17 02:20:36 +04:00
# endif
mov p c , l r
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ c r e a t e _ p a g e _ t a b l e s )
2005-04-17 02:20:36 +04:00
.ltorg
2010-11-29 21:43:24 +03:00
.align
2010-10-04 20:51:54 +04:00
__enable_mmu_loc :
.long .
.long __enable_mmu
.long __enable_mmu_end
2005-04-17 02:20:36 +04:00
2010-10-04 20:56:13 +04:00
# if d e f i n e d ( C O N F I G _ S M P )
_ _ CPUINIT
ENTRY( s e c o n d a r y _ s t a r t u p )
/ *
* Common e n t r y p o i n t f o r s e c o n d a r y C P U s .
*
* Ensure t h a t w e ' r e i n S V C m o d e , a n d I R Q s a r e d i s a b l e d . L o o k u p
* the p r o c e s s o r t y p e - t h e r e i s n o n e e d t o c h e c k t h e m a c h i n e t y p e
* as i t h a s a l r e a d y b e e n v a l i d a t e d b y t h e p r i m a r y p r o c e s s o r .
* /
setmode P S R _ F _ B I T | P S R _ I _ B I T | S V C _ M O D E , r9
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
bl _ _ l o o k u p _ p r o c e s s o r _ t y p e
movs r10 , r5 @ invalid processor?
moveq r0 , #' p ' @ yes, error 'p'
2010-11-29 21:43:28 +03:00
THUMB( i t e q ) @ force fixup-able long branch encoding
2010-10-04 20:56:13 +04:00
beq _ _ e r r o r _ p
/ *
* Use t h e p a g e t a b l e s s u p p l i e d f r o m _ _ c p u _ u p .
* /
adr r4 , _ _ s e c o n d a r y _ d a t a
ldmia r4 , { r5 , r7 , r12 } @ address to jump to after
2011-05-26 14:22:44 +04:00
sub l r , r4 , r5 @ mmu has been enabled
ldr r4 , [ r7 , l r ] @ get secondary_data.pgdir
add r7 , r7 , #4
ldr r8 , [ r7 , l r ] @ get secondary_data.swapper_pg_dir
2010-10-04 20:56:13 +04:00
adr l r , B S Y M ( _ _ e n a b l e _ m m u ) @ return address
mov r13 , r12 @ __secondary_switched address
ARM( a d d p c , r10 , #P R O C I N F O _ I N I T F U N C ) @ i n i t i a l i s e p r o c e s s o r
@ (return control reg)
THUMB( a d d r12 , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( m o v p c , r12 )
ENDPROC( s e c o n d a r y _ s t a r t u p )
/ *
* r6 = & s e c o n d a r y _ d a t a
* /
ENTRY( _ _ s e c o n d a r y _ s w i t c h e d )
ldr s p , [ r7 , #4 ] @ get secondary_data.stack
mov f p , #0
b s e c o n d a r y _ s t a r t _ k e r n e l
ENDPROC( _ _ s e c o n d a r y _ s w i t c h e d )
2010-11-29 21:43:24 +03:00
.align
2010-10-04 20:56:13 +04:00
.type _ _ secondary_ d a t a , % o b j e c t
__secondary_data :
.long .
.long secondary_data
.long __secondary_switched
# endif / * d e f i n e d ( C O N F I G _ S M P ) * /
/ *
* Setup c o m m o n b i t s b e f o r e f i n a l l y e n a b l i n g t h e M M U . E s s e n t i a l l y
* this i s j u s t l o a d i n g t h e p a g e t a b l e p o i n t e r a n d d o m a i n a c c e s s
* registers.
2010-10-04 21:02:59 +04:00
*
* r0 = c p #15 c o n t r o l r e g i s t e r
* r1 = m a c h i n e I D
2011-04-29 00:27:20 +04:00
* r2 = a t a g s o r d t b p o i n t e r
2010-10-04 21:02:59 +04:00
* r4 = p a g e t a b l e p o i n t e r
* r9 = p r o c e s s o r I D
* r1 3 = * v i r t u a l * a d d r e s s t o j u m p t o u p o n c o m p l e t i o n
2010-10-04 20:56:13 +04:00
* /
__enable_mmu :
# ifdef C O N F I G _ A L I G N M E N T _ T R A P
orr r0 , r0 , #C R _ A
# else
bic r0 , r0 , #C R _ A
# endif
# ifdef C O N F I G _ C P U _ D C A C H E _ D I S A B L E
bic r0 , r0 , #C R _ C
# endif
# ifdef C O N F I G _ C P U _ B P R E D I C T _ D I S A B L E
bic r0 , r0 , #C R _ Z
# endif
# ifdef C O N F I G _ C P U _ I C A C H E _ D I S A B L E
bic r0 , r0 , #C R _ I
# endif
mov r5 , #( d o m a i n _ v a l ( D O M A I N _ U S E R , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ K E R N E L , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ T A B L E , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ I O , D O M A I N _ C L I E N T ) )
mcr p15 , 0 , r5 , c3 , c0 , 0 @ load domain access register
mcr p15 , 0 , r4 , c2 , c0 , 0 @ load page table pointer
b _ _ t u r n _ m m u _ o n
ENDPROC( _ _ e n a b l e _ m m u )
/ *
* Enable t h e M M U . T h i s c o m p l e t e l y c h a n g e s t h e s t r u c t u r e o f t h e v i s i b l e
* memory s p a c e . Y o u w i l l n o t b e a b l e t o t r a c e e x e c u t i o n t h r o u g h t h i s .
* If y o u h a v e a n e n q u i r y a b o u t t h i s , * p l e a s e * c h e c k t h e l i n u x - a r m - k e r n e l
* mailing l i s t a r c h i v e s B E F O R E s e n d i n g a n o t h e r p o s t t o t h e l i s t .
*
* r0 = c p #15 c o n t r o l r e g i s t e r
2010-10-04 21:02:59 +04:00
* r1 = m a c h i n e I D
2011-04-29 00:27:20 +04:00
* r2 = a t a g s o r d t b p o i n t e r
2010-10-04 21:02:59 +04:00
* r9 = p r o c e s s o r I D
2010-10-04 20:56:13 +04:00
* r1 3 = * v i r t u a l * a d d r e s s t o j u m p t o u p o n c o m p l e t i o n
*
* other r e g i s t e r s d e p e n d o n t h e f u n c t i o n c a l l e d u p o n c o m p l e t i o n
* /
.align 5
__turn_mmu_on :
mov r0 , r0
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
mrc p15 , 0 , r3 , c0 , c0 , 0 @ read id reg
mov r3 , r3
mov r3 , r13
mov p c , r3
__enable_mmu_end :
ENDPROC( _ _ t u r n _ m m u _ o n )
2005-04-17 02:20:36 +04:00
2010-09-04 13:47:48 +04:00
# ifdef C O N F I G _ S M P _ O N _ U P
2011-02-10 18:25:18 +03:00
_ _ INIT
2010-09-04 13:47:48 +04:00
__fixup_smp :
2011-01-30 19:40:20 +03:00
and r3 , r9 , #0x000f0000 @ architecture version
teq r3 , #0x000f0000 @ CPU ID supported?
2010-09-04 13:47:48 +04:00
bne _ _ f i x u p _ s m p _ o n _ u p @ no, assume UP
2011-01-30 19:40:20 +03:00
bic r3 , r9 , #0x00ff0000
bic r3 , r3 , #0x0000000f @ mask 0xff00fff0
mov r4 , #0x41000000
2010-11-22 15:06:28 +03:00
orr r4 , r4 , #0x0000b000
2011-01-30 19:40:20 +03:00
orr r4 , r4 , #0x00000020 @ val 0x4100b020
teq r3 , r4 @ ARM 11MPCore?
2010-09-04 13:47:48 +04:00
moveq p c , l r @ yes, assume SMP
mrc p15 , 0 , r0 , c0 , c0 , 5 @ read MPIDR
2011-01-30 19:40:20 +03:00
and r0 , r0 , #0xc0000000 @ multiprocessing extensions and
teq r0 , #0x80000000 @ not part of a uniprocessor system?
moveq p c , l r @ yes, assume SMP
2010-09-04 13:47:48 +04:00
__fixup_smp_on_up :
adr r0 , 1 f
2010-11-22 15:06:28 +03:00
ldmia r0 , { r3 - r5 }
2010-09-04 13:47:48 +04:00
sub r3 , r0 , r3
2010-11-22 15:06:28 +03:00
add r4 , r4 , r3
add r5 , r5 , r3
2011-02-10 18:25:18 +03:00
b _ _ d o _ f i x u p _ s m p _ o n _ u p
2010-09-04 13:47:48 +04:00
ENDPROC( _ _ f i x u p _ s m p )
2010-11-29 21:43:24 +03:00
.align
2010-09-04 13:47:48 +04:00
1 : .word .
.word __smpalt_begin
.word __smpalt_end
.pushsection .data
.globl smp_on_up
smp_on_up :
ALT_ S M P ( . l o n g 1 )
ALT_ U P ( . l o n g 0 )
.popsection
2011-02-10 18:25:18 +03:00
# endif
2010-09-04 13:47:48 +04:00
2011-02-10 18:25:18 +03:00
.text
__do_fixup_smp_on_up :
cmp r4 , r5
movhs p c , l r
ldmia r4 ! , { r0 , r6 }
ARM( s t r r6 , [ r0 , r3 ] )
THUMB( a d d r0 , r0 , r3 )
# ifdef _ _ A R M E B _ _
THUMB( m o v r6 , r6 , r o r #16 ) @ Convert word order for big-endian.
2010-09-04 13:47:48 +04:00
# endif
2011-02-10 18:25:18 +03:00
THUMB( s t r h r6 , [ r0 ] , #2 ) @ For Thumb-2, store as two halfwords
THUMB( m o v r6 , r6 , l s r #16 ) @ to be robust against misaligned r3.
THUMB( s t r h r6 , [ r0 ] )
b _ _ d o _ f i x u p _ s m p _ o n _ u p
ENDPROC( _ _ d o _ f i x u p _ s m p _ o n _ u p )
ENTRY( f i x u p _ s m p )
stmfd s p ! , { r4 - r6 , l r }
mov r4 , r0
add r5 , r0 , r1
mov r3 , #0
bl _ _ d o _ f i x u p _ s m p _ o n _ u p
ldmfd s p ! , { r4 - r6 , p c }
ENDPROC( f i x u p _ s m p )
2010-09-04 13:47:48 +04:00
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
# ifdef C O N F I G _ A R M _ P A T C H _ P H Y S _ V I R T
/ * _ _ fixup_ p v _ t a b l e - p a t c h t h e s t u b i n s t r u c t i o n s w i t h t h e d e l t a b e t w e e n
* PHYS_ O F F S E T a n d P A G E _ O F F S E T , w h i c h i s a s s u m e d t o b e 1 6 M i B a l i g n e d a n d
* can b e e x p r e s s e d b y a n i m m e d i a t e s h i f t e r o p e r a n d . T h e s t u b i n s t r u c t i o n
* has a f o r m o f ' ( a d d | s u b ) r d , r n , #i m m ' .
* /
_ _ HEAD
__fixup_pv_table :
adr r0 , 1 f
ldmia r0 , { r3 - r5 , r7 }
sub r3 , r0 , r3 @ PHYS_OFFSET - PAGE_OFFSET
add r4 , r4 , r3 @ adjust table start address
add r5 , r5 , r3 @ adjust table end address
2011-02-21 08:53:35 +03:00
add r7 , r7 , r3 @ adjust __pv_phys_offset address
str r8 , [ r7 ] @ save computed PHYS_OFFSET to __pv_phys_offset
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
mov r6 , r3 , l s r #24 @ constant for add/sub instructions
teq r3 , r6 , l s l #24 @ must be 16MiB aligned
2011-02-21 08:53:35 +03:00
THUMB( i t n e @ cross section branch )
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
bne _ _ e r r o r
str r6 , [ r7 , #4 ] @ save to __pv_offset
b _ _ f i x u p _ a _ p v _ t a b l e
ENDPROC( _ _ f i x u p _ p v _ t a b l e )
.align
1 : .long .
.long __pv_table_begin
.long __pv_table_end
2 : .long _ _ p v _ p h y s _ o f f s e t
.text
__fixup_a_pv_table :
2011-02-21 08:53:35 +03:00
# ifdef C O N F I G _ T H U M B 2 _ K E R N E L
2011-08-12 03:14:29 +04:00
lsls r6 , #24
beq 2 f
2011-02-21 08:53:35 +03:00
clz r7 , r6
lsr r6 , #24
lsl r6 , r7
bic r6 , #0x0080
lsrs r7 , #1
orrcs r6 , #0x0080
orr r6 , r6 , r7 , l s l #12
orr r6 , #0x4000
2011-08-12 03:14:29 +04:00
b 2 f
1 : add r7 , r3
ldrh i p , [ r7 , #2 ]
2011-02-21 08:53:35 +03:00
and i p , 0 x8 f00
2011-08-12 03:14:29 +04:00
orr i p , r6 @ mask in offset bits 31-24
2011-02-21 08:53:35 +03:00
strh i p , [ r7 , #2 ]
2011-08-12 03:14:29 +04:00
2 : cmp r4 , r5
2011-02-21 08:53:35 +03:00
ldrcc r7 , [ r4 ] , #4 @ use branch for delay slot
2011-08-12 03:14:29 +04:00
bcc 1 b
2011-02-21 08:53:35 +03:00
bx l r
# else
2011-08-12 03:14:29 +04:00
b 2 f
1 : ldr i p , [ r7 , r3 ]
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
bic i p , i p , #0x000000ff
2011-08-12 03:14:29 +04:00
orr i p , i p , r6 @ mask in offset bits 31-24
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
str i p , [ r7 , r3 ]
2011-08-12 03:14:29 +04:00
2 : cmp r4 , r5
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
ldrcc r7 , [ r4 ] , #4 @ use branch for delay slot
2011-08-12 03:14:29 +04:00
bcc 1 b
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
mov p c , l r
2011-02-21 08:53:35 +03:00
# endif
ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching
This idea came from Nicolas, Eric Miao produced an initial version,
which was then rewritten into this.
Patch the physical to virtual translations at runtime. As we modify
the code, this makes it incompatible with XIP kernels, but allows us
to achieve this with minimal loss of performance.
As many translations are of the form:
physical = virtual + (PHYS_OFFSET - PAGE_OFFSET)
virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)
we generate an 'add' instruction for __virt_to_phys(), and a 'sub'
instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with
where it should be once the MMU has been initialized, and place this
constant into the above add/sub instructions.
Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calculate the real
PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for
the C-mode PHYS_OFFSET variable definition to use.
At present, we are unable to support Realview with Sparsemem enabled
as this uses a complex mapping function, and MSM as this requires a
constant which will not fit in our math instruction.
Add a module version magic string for this feature to prevent
incompatible modules being loaded.
Tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-04 22:09:43 +03:00
ENDPROC( _ _ f i x u p _ a _ p v _ t a b l e )
ENTRY( f i x u p _ p v _ t a b l e )
stmfd s p ! , { r4 - r7 , l r }
ldr r2 , 2 f @ get address of __pv_phys_offset
mov r3 , #0 @ no offset
mov r4 , r0 @ r0 = table start
add r5 , r0 , r1 @ r1 = table size
ldr r6 , [ r2 , #4 ] @ get __pv_offset
bl _ _ f i x u p _ a _ p v _ t a b l e
ldmfd s p ! , { r4 - r7 , p c }
ENDPROC( f i x u p _ p v _ t a b l e )
.align
2 : .long _ _ p v _ p h y s _ o f f s e t
.data
.globl __pv_phys_offset
.type _ _ pv_ p h y s _ o f f s e t , % o b j e c t
__pv_phys_offset :
.long 0
.size _ _ pv_ p h y s _ o f f s e t , . - _ _ p v _ p h y s _ o f f s e t
__pv_offset :
.long 0
# endif
2006-03-27 17:58:25 +04:00
# include " h e a d - c o m m o n . S "