2005-10-10 16:36:14 +04:00
/ *
* This f i l e c o n t a i n s m i s c e l l a n e o u s l o w - l e v e l f u n c t i o n s .
* Copyright ( C ) 1 9 9 5 - 1 9 9 6 G a r y T h o m a s ( g d t @linuxppc.org)
*
* Largely r e w r i t t e n b y C o r t D o u g a n ( c o r t @cs.nmt.edu)
* and P a u l M a c k e r r a s .
* Adapted f o r i S e r i e s b y M i k e C o r r i g a n ( m i k e j c @us.ibm.com)
2006-06-28 05:55:49 +04:00
* PPC6 4 u p d a t e s b y D a v e E n g e b r e t s e n ( e n g e b r e t @us.ibm.com)
*
2005-10-10 16:36:14 +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 i t 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
* as p u b l i s h e d 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 ; either version
* 2 of t h e L i c e n s e , o r ( a t y o u r o p t i o n ) a n y l a t e r v e r s i o n .
*
* /
# include < l i n u x / s y s . h >
# include < a s m / u n i s t d . h >
# include < a s m / e r r n o . h >
# include < a s m / p r o c e s s o r . h >
# include < a s m / p a g e . h >
# include < a s m / c a c h e . h >
# include < a s m / p p c _ a s m . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / c p u t a b l e . h >
[PATCH] powerpc: Merge thread_info.h
Merge ppc32 and ppc64 versions of thread_info.h. They were pretty
similar already, the chief changes are:
- Instead of inline asm to implement current_thread_info(),
which needs to be different for ppc32 and ppc64, we use C with an
asm("r1") register variable. gcc turns it into the same asm as we
used to have for both platforms.
- We replace ppc32's 'local_flags' with the ppc64
'syscall_noerror' field. The noerror flag was in fact the only thing
in the local_flags field anyway, so the ppc64 approach is simpler, and
means we only need a load-immediate/store instead of load/mask/store
when clearing the flag.
- In readiness for 64k pages, when THREAD_SIZE will be less
than a page, ppc64 used kmalloc() rather than get_free_pages() to
allocate the kernel stack. With this patch we do the same for ppc32,
since there's no strong reason not to.
- For ppc64, we no longer export THREAD_SHIFT and THREAD_SIZE
via asm-offsets, thread_info.h can now be safely included in asm, as
on ppc32.
Built and booted on G4 Powerbook (ARCH=ppc and ARCH=powerpc) and
Power5 (ARCH=ppc64 and ARCH=powerpc).
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2005-10-21 09:45:50 +04:00
# include < a s m / t h r e a d _ i n f o . h >
2010-05-13 23:40:11 +04:00
# include < a s m / k e x e c . h >
2010-11-18 18:06:17 +03:00
# include < a s m / p t r a c e . h >
2005-10-10 16:36:14 +04:00
.text
_ GLOBAL( c a l l _ d o _ s o f t i r q )
mflr r0
std r0 ,1 6 ( r1 )
2008-04-24 07:20:16 +04:00
stdu r1 ,T H R E A D _ S I Z E - S T A C K _ F R A M E _ O V E R H E A D ( r3 )
2005-10-10 16:36:14 +04:00
mr r1 ,r3
bl . _ _ d o _ s o f t i r q
ld r1 ,0 ( r1 )
ld r0 ,1 6 ( r1 )
mtlr r0
blr
2006-07-03 13:32:51 +04:00
_ GLOBAL( c a l l _ h a n d l e _ i r q )
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 17:55:46 +04:00
ld r8 ,0 ( r6 )
2005-10-10 16:36:14 +04:00
mflr r0
std r0 ,1 6 ( r1 )
2006-07-03 13:32:51 +04:00
mtctr r8
2008-04-24 07:20:16 +04:00
stdu r1 ,T H R E A D _ S I Z E - S T A C K _ F R A M E _ O V E R H E A D ( r5 )
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 17:55:46 +04:00
mr r1 ,r5
2006-07-03 13:32:51 +04:00
bctrl
2005-10-10 16:36:14 +04:00
ld r1 ,0 ( r1 )
ld r0 ,1 6 ( r1 )
mtlr r0
blr
.section " .toc " , " aw"
PPC64_CACHES :
.tc ppc6 4 _ c a c h e s [ T C ] ,p p c64 _ c a c h e s
.section " .text "
/ *
* Write a n y m o d i f i e d d a t a c a c h e b l o c k s o u t t o m e m o r y
* and i n v a l i d a t e t h e c o r r e s p o n d i n g i n s t r u c t i o n c a c h e b l o c k s .
*
* flush_ i c a c h e _ r a n g e ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g s t o p )
*
* flush a l l b y t e s f r o m s t a r t t h r o u g h s t o p - 1 i n c l u s i v e
* /
_ KPROBE( _ _ f l u s h _ i c a c h e _ r a n g e )
/ *
* Flush t h e d a t a c a c h e t o m e m o r y
*
* Different s y s t e m s h a v e d i f f e r e n t c a c h e l i n e s i z e s
* and i n s o m e c a s e s i - c a c h e a n d d - c a c h e l i n e s i z e s d i f f e r f r o m
* each o t h e r .
* /
ld r10 ,P P C 6 4 _ C A C H E S @toc(r2)
lwz r7 ,D C A C H E L 1 L I N E S I Z E ( r10 ) / * G e t c a c h e l i n e s i z e * /
addi r5 ,r7 ,- 1
andc r6 ,r3 ,r5 / * r o u n d l o w t o l i n e b d y * /
subf r8 ,r6 ,r4 / * c o m p u t e l e n g t h * /
add r8 ,r8 ,r5 / * e n s u r e w e g e t e n o u g h * /
lwz r9 ,D C A C H E L 1 L O G L I N E S I Z E ( r10 ) / * G e t l o g - 2 o f c a c h e l i n e s i z e * /
srw. r8 ,r8 ,r9 / * c o m p u t e l i n e c o u n t * /
beqlr / * n o t h i n g t o d o ? * /
mtctr r8
1 : dcbst 0 ,r6
add r6 ,r6 ,r7
bdnz 1 b
sync
/* Now invalidate the instruction cache */
lwz r7 ,I C A C H E L 1 L I N E S I Z E ( r10 ) / * G e t I c a c h e l i n e s i z e * /
addi r5 ,r7 ,- 1
andc r6 ,r3 ,r5 / * r o u n d l o w t o l i n e b d y * /
subf r8 ,r6 ,r4 / * c o m p u t e l e n g t h * /
add r8 ,r8 ,r5
lwz r9 ,I C A C H E L 1 L O G L I N E S I Z E ( r10 ) / * G e t l o g - 2 o f I c a c h e l i n e s i z e * /
srw. r8 ,r8 ,r9 / * c o m p u t e l i n e c o u n t * /
beqlr / * n o t h i n g t o d o ? * /
mtctr r8
2 : icbi 0 ,r6
add r6 ,r6 ,r7
bdnz 2 b
isync
blr
.previous .text
/ *
* Like a b o v e , b u t o n l y d o t h e D - c a c h e .
*
* flush_ d c a c h e _ r a n g e ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g s t o p )
*
* flush a l l b y t e s f r o m s t a r t t o s t o p - 1 i n c l u s i v e
* /
_ GLOBAL( f l u s h _ d c a c h e _ r a n g e )
/ *
* Flush t h e d a t a c a c h e t o m e m o r y
*
* Different s y s t e m s h a v e d i f f e r e n t c a c h e l i n e s i z e s
* /
ld r10 ,P P C 6 4 _ C A C H E S @toc(r2)
lwz r7 ,D C A C H E L 1 L I N E S I Z E ( r10 ) / * G e t d c a c h e l i n e s i z e * /
addi r5 ,r7 ,- 1
andc r6 ,r3 ,r5 / * r o u n d l o w t o l i n e b d y * /
subf r8 ,r6 ,r4 / * c o m p u t e l e n g t h * /
add r8 ,r8 ,r5 / * e n s u r e w e g e t e n o u g h * /
lwz r9 ,D C A C H E L 1 L O G L I N E S I Z E ( r10 ) / * G e t l o g - 2 o f d c a c h e l i n e s i z e * /
srw. r8 ,r8 ,r9 / * c o m p u t e l i n e c o u n t * /
beqlr / * n o t h i n g t o d o ? * /
mtctr r8
0 : dcbst 0 ,r6
add r6 ,r6 ,r7
bdnz 0 b
sync
blr
/ *
* Like a b o v e , b u t w o r k s o n n o n - m a p p e d p h y s i c a l a d d r e s s e s .
* Use o n l y f o r n o n - L P A R s e t u p s ! I t a l s o a s s u m e s r e a l m o d e
* is c a c h e a b l e . U s e d f o r f l u s h i n g o u t t h e D A R T b e f o r e u s i n g
* it a s u n c a c h e a b l e m e m o r y
*
* flush_ d c a c h e _ p h y s _ r a n g e ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g s t o p )
*
* flush a l l b y t e s f r o m s t a r t t o s t o p - 1 i n c l u s i v e
* /
_ GLOBAL( f l u s h _ d c a c h e _ p h y s _ r a n g e )
ld r10 ,P P C 6 4 _ C A C H E S @toc(r2)
lwz r7 ,D C A C H E L 1 L I N E S I Z E ( r10 ) / * G e t d c a c h e l i n e s i z e * /
addi r5 ,r7 ,- 1
andc r6 ,r3 ,r5 / * r o u n d l o w t o l i n e b d y * /
subf r8 ,r6 ,r4 / * c o m p u t e l e n g t h * /
add r8 ,r8 ,r5 / * e n s u r e w e g e t e n o u g h * /
lwz r9 ,D C A C H E L 1 L O G L I N E S I Z E ( r10 ) / * G e t l o g - 2 o f d c a c h e l i n e s i z e * /
srw. r8 ,r8 ,r9 / * c o m p u t e l i n e c o u n t * /
beqlr / * n o t h i n g t o d o ? * /
mfmsr r5 / * D i s a b l e M M U D a t a R e l o c a t i o n * /
ori r0 ,r5 ,M S R _ D R
xori r0 ,r0 ,M S R _ D R
sync
mtmsr r0
sync
isync
mtctr r8
0 : dcbst 0 ,r6
add r6 ,r6 ,r7
bdnz 0 b
sync
isync
mtmsr r5 / * R e - e n a b l e M M U D a t a R e l o c a t i o n * /
sync
isync
blr
_ GLOBAL( f l u s h _ i n v a l _ d c a c h e _ r a n g e )
ld r10 ,P P C 6 4 _ C A C H E S @toc(r2)
lwz r7 ,D C A C H E L 1 L I N E S I Z E ( r10 ) / * G e t d c a c h e l i n e s i z e * /
addi r5 ,r7 ,- 1
andc r6 ,r3 ,r5 / * r o u n d l o w t o l i n e b d y * /
subf r8 ,r6 ,r4 / * c o m p u t e l e n g t h * /
add r8 ,r8 ,r5 / * e n s u r e w e g e t e n o u g h * /
lwz r9 ,D C A C H E L 1 L O G L I N E S I Z E ( r10 ) / * G e t l o g - 2 o f d c a c h e l i n e s i z e * /
srw. r8 ,r8 ,r9 / * c o m p u t e l i n e c o u n t * /
beqlr / * n o t h i n g t o d o ? * /
sync
isync
mtctr r8
0 : dcbf 0 ,r6
add r6 ,r6 ,r7
bdnz 0 b
sync
isync
blr
/ *
* Flush a p a r t i c u l a r p a g e f r o m t h e d a t a c a c h e t o R A M .
* Note : this i s n e c e s s a r y b e c a u s e t h e i n s t r u c t i o n c a c h e d o e s * n o t *
* snoop f r o m t h e d a t a c a c h e .
*
* void _ _ f l u s h _ d c a c h e _ i c a c h e ( v o i d * p a g e )
* /
_ GLOBAL( _ _ f l u s h _ d c a c h e _ i c a c h e )
/ *
* Flush t h e d a t a c a c h e t o m e m o r y
*
* Different s y s t e m s h a v e d i f f e r e n t c a c h e l i n e s i z e s
* /
/* Flush the dcache */
ld r7 ,P P C 6 4 _ C A C H E S @toc(r2)
clrrdi r3 ,r3 ,P A G E _ S H I F T / * P a g e a l i g n * /
lwz r4 ,D C A C H E L 1 L I N E S P E R P A G E ( r7 ) / * G e t # d c a c h e l i n e s p e r p a g e * /
lwz r5 ,D C A C H E L 1 L I N E S I Z E ( r7 ) / * G e t d c a c h e l i n e s i z e * /
mr r6 ,r3
mtctr r4
0 : dcbst 0 ,r6
add r6 ,r6 ,r5
bdnz 0 b
sync
/* Now invalidate the icache */
lwz r4 ,I C A C H E L 1 L I N E S P E R P A G E ( r7 ) / * G e t # i c a c h e l i n e s p e r p a g e * /
lwz r5 ,I C A C H E L 1 L I N E S I Z E ( r7 ) / * G e t i c a c h e l i n e s i z e * /
mtctr r4
1 : icbi 0 ,r3
add r3 ,r3 ,r5
bdnz 1 b
isync
blr
2006-09-25 12:19:00 +04:00
2005-10-10 16:36:14 +04:00
# if d e f i n e d ( C O N F I G _ P P C _ P M A C ) | | d e f i n e d ( C O N F I G _ P P C _ M A P L E )
/ *
* Do a n I O a c c e s s i n r e a l m o d e
* /
_ GLOBAL( r e a l _ r e a d b )
mfmsr r7
ori r0 ,r7 ,M S R _ D R
xori r0 ,r0 ,M S R _ D R
sync
mtmsrd r0
sync
isync
mfspr r6 ,S P R N _ H I D 4
rldicl r5 ,r6 ,3 2 ,0
ori r5 ,r5 ,0 x10 0
rldicl r5 ,r5 ,3 2 ,0
sync
mtspr S P R N _ H I D 4 ,r5
isync
slbia
isync
lbz r3 ,0 ( r3 )
sync
mtspr S P R N _ H I D 4 ,r6
isync
slbia
isync
mtmsrd r7
sync
isync
blr
/ *
* Do a n I O a c c e s s i n r e a l m o d e
* /
_ GLOBAL( r e a l _ w r i t e b )
mfmsr r7
ori r0 ,r7 ,M S R _ D R
xori r0 ,r0 ,M S R _ D R
sync
mtmsrd r0
sync
isync
mfspr r6 ,S P R N _ H I D 4
rldicl r5 ,r6 ,3 2 ,0
ori r5 ,r5 ,0 x10 0
rldicl r5 ,r5 ,3 2 ,0
sync
mtspr S P R N _ H I D 4 ,r5
isync
slbia
isync
stb r3 ,0 ( r4 )
sync
mtspr S P R N _ H I D 4 ,r6
isync
slbia
isync
mtmsrd r7
sync
isync
blr
# endif / * d e f i n e d ( C O N F I G _ P P C _ P M A C ) | | d e f i n e d ( C O N F I G _ P P C _ M A P L E ) * /
2007-02-05 01:36:49 +03:00
# ifdef C O N F I G _ P P C _ P A S E M I
/* No support in all binutils for these yet, so use defines */
# define L B Z C I X ( R T ,R A ,R B ) . l o n g ( 0 x7 c00 0 6 a a | ( R T < < 2 1 ) | ( R A < < 1 6 ) | ( R B < < 1 1 ) )
# define S T B C I X ( R S ,R A ,R B ) . l o n g ( 0 x7 c00 0 7 a a | ( R S < < 2 1 ) | ( R A < < 1 6 ) | ( R B < < 1 1 ) )
_ GLOBAL( r e a l _ 2 0 5 _ r e a d b )
mfmsr r7
ori r0 ,r7 ,M S R _ D R
xori r0 ,r0 ,M S R _ D R
sync
mtmsrd r0
sync
isync
LBZCIX( r3 ,0 ,r3 )
isync
mtmsrd r7
sync
isync
blr
_ GLOBAL( r e a l _ 2 0 5 _ w r i t e b )
mfmsr r7
ori r0 ,r7 ,M S R _ D R
xori r0 ,r0 ,M S R _ D R
sync
mtmsrd r0
sync
isync
STBCIX( r3 ,0 ,r4 )
isync
mtmsrd r7
sync
isync
blr
# endif / * C O N F I G _ P P C _ P A S E M I * /
2011-06-17 07:10:06 +04:00
# if d e f i n e d ( C O N F I G _ C P U _ F R E Q _ P M A C 6 4 ) | | d e f i n e d ( C O N F I G _ C P U _ F R E Q _ M A P L E )
2005-11-07 06:27:33 +03:00
/ *
* SCOM a c c e s s f u n c t i o n s f o r 9 7 0 ( F X o n l y f o r n o w )
*
* unsigned l o n g s c o m 9 7 0 _ r e a d ( u n s i g n e d i n t a d d r e s s ) ;
* void s c o m 9 7 0 _ w r i t e ( u n s i g n e d i n t a d d r e s s , u n s i g n e d l o n g v a l u e ) ;
*
* The a d d r e s s p a s s e d i n i s t h e 2 4 b i t s r e g i s t e r a d d r e s s . T h i s c o d e
* is 9 7 0 s p e c i f i c a n d w i l l n o t c h e c k t h e s t a t u s b i t s , s o y o u s h o u l d
* know w h a t y o u a r e d o i n g .
* /
_ GLOBAL( s c o m 9 7 0 _ r e a d )
/* interrupts off */
mfmsr r4
ori r0 ,r4 ,M S R _ E E
xori r0 ,r0 ,M S R _ E E
mtmsrd r0 ,1
/ * rotate 2 4 b i t s S C O M a d d r e s s 8 b i t s l e f t a n d m a s k o u t i t ' s l o w 8 b i t s
* ( including p a r i t y ) . O n c u r r e n t C P U s t h e y m u s t b e 0 ' d ,
* and f i n a l l y o r i n R W b i t
* /
rlwinm r3 ,r3 ,8 ,0 ,1 5
ori r3 ,r3 ,0 x80 0 0
/* do the actual scom read */
sync
mtspr S P R N _ S C O M C ,r3
isync
mfspr r3 ,S P R N _ S C O M D
isync
mfspr r0 ,S P R N _ S C O M C
isync
/ * XXX : fixup r e s u l t o n s o m e b u g g y 9 7 0 ' s ( o u c h ! w e l o s t a b i t , b a h
* that' s t h e b e s t w e c a n d o ) . N o t i m p l e m e n t e d y e t a s w e d o n ' t u s e
* the s c o m o n a n y o f t h e b o g u s C P U s y e t , b u t m a y h a v e t o b e d o n e
* ultimately
* /
/* restore interrupts */
mtmsrd r4 ,1
blr
_ GLOBAL( s c o m 9 7 0 _ w r i t e )
/* interrupts off */
mfmsr r5
ori r0 ,r5 ,M S R _ E E
xori r0 ,r0 ,M S R _ E E
mtmsrd r0 ,1
/ * rotate 2 4 b i t s S C O M a d d r e s s 8 b i t s l e f t a n d m a s k o u t i t ' s l o w 8 b i t s
* ( including p a r i t y ) . O n c u r r e n t C P U s t h e y m u s t b e 0 ' d .
* /
rlwinm r3 ,r3 ,8 ,0 ,1 5
sync
mtspr S P R N _ S C O M D ,r4 / * w r i t e d a t a * /
isync
mtspr S P R N _ S C O M C ,r3 / * w r i t e c o m m a n d * /
isync
mfspr 3 ,S P R N _ S C O M C
isync
/* restore interrupts */
mtmsrd r5 ,1
blr
2011-06-17 07:10:06 +04:00
# endif / * C O N F I G _ C P U _ F R E Q _ P M A C 6 4 | | C O N F I G _ C P U _ F R E Q _ M A P L E * /
2005-11-07 06:27:33 +03:00
2005-10-10 16:36:14 +04:00
/ *
* Create a k e r n e l t h r e a d
* kernel_ t h r e a d ( f n , a r g , f l a g s )
* /
_ GLOBAL( k e r n e l _ t h r e a d )
std r29 ,- 2 4 ( r1 )
std r30 ,- 1 6 ( r1 )
stdu r1 ,- S T A C K _ F R A M E _ O V E R H E A D ( r1 )
mr r29 ,r3
mr r30 ,r4
ori r3 ,r5 ,C L O N E _ V M / * f l a g s * /
oris r3 ,r3 ,( C L O N E _ U N T R A C E D > > 1 6 )
li r4 ,0 / * n e w s p ( u n u s e d ) * /
li r0 ,_ _ N R _ c l o n e
sc
2008-10-07 10:10:03 +04:00
bns+ 1 f / * d i d s y s t e m c a l l i n d i c a t e e r r o r ? * /
neg r3 ,r3 / * i f s o , m a k e r e t u r n c o d e n e g a t i v e * /
1 : cmpdi 0 ,r3 ,0 / * p a r e n t o r c h i l d ? * /
bne 2 f / * r e t u r n i f p a r e n t * /
2005-10-10 16:36:14 +04:00
li r0 ,0
stdu r0 ,- S T A C K _ F R A M E _ O V E R H E A D ( r1 )
ld r2 ,8 ( r29 )
ld r29 ,0 ( r29 )
mtlr r29 / * f n a d d r i n l r * /
mr r3 ,r30 / * l o a d a r g a n d c a l l f n * /
blrl
li r0 ,_ _ N R _ e x i t / * e x i t a f t e r c h i l d e x i t s * /
li r3 ,0
sc
2008-10-07 10:10:03 +04:00
2 : addi r1 ,r1 ,S T A C K _ F R A M E _ O V E R H E A D
2005-10-10 16:36:14 +04:00
ld r29 ,- 2 4 ( r1 )
ld r30 ,- 1 6 ( r1 )
blr
/ *
* disable_ k e r n e l _ f p ( )
* Disable t h e F P U .
* /
_ GLOBAL( d i s a b l e _ k e r n e l _ f p )
mfmsr r3
rldicl r0 ,r3 ,( 6 3 - M S R _ F P _ L G ) ,1
rldicl r3 ,r0 ,( M S R _ F P _ L G + 1 ) ,0
mtmsrd r3 / * d i s a b l e u s e o f f p u n o w * /
isync
blr
/ * kexec_ w a i t ( p h y s _ c p u )
*
* wait f o r t h e f l a g t o c h a n g e , i n d i c a t i n g t h i s k e r n e l i s g o i n g a w a y b u t
* the s l a v e c o d e f o r t h e n e x t o n e i s a t a d d r e s s e s 0 t o 1 0 0 .
*
2011-05-10 23:28:33 +04:00
* This i s u s e d b y a l l s l a v e s , e v e n t h o s e t h a t d i d n o t f i n d a m a t c h i n g
* paca i n t h e s e c o n d a r y s t a r t u p c o d e .
2005-10-10 16:36:14 +04:00
*
* Physical ( h a r d w a r e ) c p u i d s h o u l d b e i n r3 .
* /
_ GLOBAL( k e x e c _ w a i t )
bl 1 f
1 : mflr r5
addi r5 ,r5 ,k e x e c _ f l a g - 1 b
99 : HMT_ L O W
# ifdef C O N F I G _ K E X E C / * u s e n o m e m o r y w i t h o u t k e x e c * /
lwz r4 ,0 ( r5 )
cmpwi 0 ,r4 ,0
bnea 0 x60
# endif
b 9 9 b
/ * this c a n b e i n t e x t b e c a u s e w e w o n ' t c h a n g e i t u n t i l w e a r e
* running i n r e a l a n y w a y s
* /
kexec_flag :
.long 0
# ifdef C O N F I G _ K E X E C
/ * kexec_ s m p _ w a i t ( v o i d )
*
* call w i t h i n t e r r u p t s o f f
* note : this i s a t e r m i n a l r o u t i n e , i t d o e s n o t s a v e l r
*
* get p h y s i d f r o m p a c a
* switch t o r e a l m o d e
2011-05-10 23:28:33 +04:00
* mark t h e p a c a a s n o l o n g e r u s e d
2005-10-10 16:36:14 +04:00
* join o t h e r c p u s i n k e x e c _ w a i t ( p h y s _ i d )
* /
_ GLOBAL( k e x e c _ s m p _ w a i t )
lhz r3 ,P A C A H W C P U I D ( r13 )
bl r e a l _ m o d e
2011-05-10 23:28:33 +04:00
li r4 ,K E X E C _ S T A T E _ R E A L _ M O D E
stb r4 ,P A C A K E X E C S T A T E ( r13 )
SYNC
2005-10-10 16:36:14 +04:00
b . k e x e c _ w a i t
/ *
* switch t o r e a l m o d e ( t u r n m m u o f f )
* we u s e t h e e a r l y k e r n e l t r i c k t h a t t h e h a r d w a r e i g n o r e s b i t s
* 0 and 1 ( b i g e n d i a n ) o f t h e e f f e c t i v e a d d r e s s i n r e a l m o d e
*
* don' t o v e r w r i t e r3 h e r e , i t i s l i v e f o r k e x e c _ w a i t a b o v e .
* /
real_mode : /* assume normal blr return */
1 : li r9 ,M S R _ R I
li r10 ,M S R _ D R | M S R _ I R
mflr r11 / * r e t u r n a d d r e s s t o S R R 0 * /
mfmsr r12
andc r9 ,r12 ,r9
andc r10 ,r12 ,r10
mtmsrd r9 ,1
mtspr S P R N _ S R R 1 ,r10
mtspr S P R N _ S R R 0 ,r11
rfid
/ *
2008-10-22 14:39:18 +04:00
* kexec_ s e q u e n c e ( n e w s t a c k , s t a r t , i m a g e , c o n t r o l , c l e a r _ a l l ( ) )
2005-10-10 16:36:14 +04:00
*
* does t h e g r u n g y w o r k w i t h s t a c k s w i t c h i n g a n d r e a l m o d e s w i t c h e s
* also d o e s s i m p l e c a l l s t o o t h e r c o d e
* /
_ GLOBAL( k e x e c _ s e q u e n c e )
mflr r0
std r0 ,1 6 ( r1 )
/* switch stacks to newstack -- &kexec_stack.stack */
2008-04-24 07:20:16 +04:00
stdu r1 ,T H R E A D _ S I Z E - S T A C K _ F R A M E _ O V E R H E A D ( r3 )
2005-10-10 16:36:14 +04:00
mr r1 ,r3
li r0 ,0
std r0 ,1 6 ( r1 )
/ * save r e g s f o r l o c a l v a r s o n n e w s t a c k .
* yes, w e w o n ' t g o b a c k , b u t . . .
* /
std r31 ,- 8 ( r1 )
std r30 ,- 1 6 ( r1 )
std r29 ,- 2 4 ( r1 )
std r28 ,- 3 2 ( r1 )
std r27 ,- 4 0 ( r1 )
std r26 ,- 4 8 ( r1 )
std r25 ,- 5 6 ( r1 )
2008-04-24 07:20:16 +04:00
stdu r1 ,- S T A C K _ F R A M E _ O V E R H E A D - 6 4 ( r1 )
2005-10-10 16:36:14 +04:00
/* save args into preserved regs */
mr r31 ,r3 / * n e w s t a c k ( b o t h ) * /
mr r30 ,r4 / * s t a r t ( r e a l ) * /
mr r29 ,r5 / * i m a g e ( v i r t ) * /
mr r28 ,r6 / * c o n t r o l , u n u s e d * /
mr r27 ,r7 / * c l e a r _ a l l ( ) f n d e s c * /
2008-10-22 14:39:18 +04:00
mr r26 ,r8 / * s p a r e * /
2005-10-10 16:36:14 +04:00
lhz r25 ,P A C A H W C P U I D ( r13 ) / * g e t o u r p h y s c p u f r o m p a c a * /
/* disable interrupts, we are overwriting kernel data next */
mfmsr r3
rlwinm r3 ,r3 ,0 ,1 7 ,1 5
mtmsrd r3 ,1
/* copy dest pages, flush whole dest image */
mr r3 ,r29
bl . k e x e c _ c o p y _ f l u s h / * ( i m a g e ) * /
/* turn off mmu */
bl r e a l _ m o d e
2007-04-11 12:32:17 +04:00
/* copy 0x100 bytes starting at start to 0 */
li r3 ,0
mr r4 ,r30 / * s t a r t , a k a p h y s m e m o f f s e t * /
li r5 ,0 x10 0
li r6 ,0
bl . c o p y _ a n d _ f l u s h / * ( d e s t , s r c , c o p y l i m i t , s t a r t o f f s e t ) * /
1 : /* assume normal blr return */
/* release other cpus to the new kernel secondary start at 0x60 */
mflr r5
li r6 ,1
stw r6 ,k e x e c _ f l a g - 1 b ( 5 )
2005-10-10 16:36:14 +04:00
/* clear out hardware hash page table and tlb */
ld r5 ,0 ( r27 ) / * d e r e f f u n c t i o n d e s c r i p t o r * /
mtctr r5
2006-07-26 01:05:01 +04:00
bctrl / * p p c _ m d . h p t e _ c l e a r _ a l l ( v o i d ) ; */
2005-10-10 16:36:14 +04:00
/ *
* kexec i m a g e c a l l i n g i s :
* the f i r s t 0 x10 0 b y t e s o f t h e e n t r y p o i n t a r e c o p i e d t o 0
*
* all s l a v e s b r a n c h t o s l a v e = 0 x60 ( a b s o l u t e )
* slave( p h y s _ c p u _ i d ) ;
*
* master g o e s t o s t a r t = e n t r y p o i n t
* start( p h y s _ c p u _ i d , s t a r t , 0 ) ;
*
*
* a w r a p p e r i s n e e d e d t o c a l l e x i s t i n g k e r n e l s , h e r e i s a n a p p r o x i m a t e
* description o f o n e m e t h o d :
*
* v2 : ( 2 .6 .10 )
* start w i l l b e n e a r t h e b o o t _ b l o c k ( m a y b e 0 x10 0 b y t e s b e f o r e i t ? )
* it w i l l h a v e a 0 x60 , w h i c h w i l l b t o b o o t _ b l o c k , w h e r e i t w i l l w a i t
* and 0 w i l l s t o r e p h y s i n t o s t r u c t b o o t - b l o c k a n d l o a d r3 f r o m t h e r e ,
* copy k e r n e l 0 - 0 x10 0 a n d t e l l s l a v e s t o b a c k d o w n t o 0 x60 a g a i n
*
* v1 : ( 2 .6 .9 )
* boot b l o c k w i l l h a v e a l l c p u s s c a n n i n g d e v i c e t r e e t o s e e i f t h e y
* are t h e b o o t c p u ? ? ? ? ?
* other d e v i c e t r e e d i f f e r e n c e s ( p r o p s i z e s , v a v s p a , e t c ) . . .
* /
mr r3 ,r25 # m y p h y s c p u
mr r4 ,r30 # s t a r t , a k a p h y s m e m o f f s e t
mtlr 4
li r5 ,0
2008-10-22 14:39:18 +04:00
blr / * i m a g e - > s t a r t ( p h y s i d , i m a g e - > s t a r t , 0 ) ; */
2005-10-10 16:36:14 +04:00
# endif / * C O N F I G _ K E X E C * /