aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@linux.vnet.ibm.com>2010-03-05 05:43:07 -0500
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2010-05-05 08:04:36 -0400
commit795033c344d88dc6aa5106d0cc358656f29bd722 (patch)
tree0dd6eebb3626a093bd1e20af09c0d25925397788 /arch
parent471c70ff39809af783c7718defe574a9ba81dd26 (diff)
powerpc/44x: break out cpu init code into stand-alone function
The 47x platform supports multiple cores and shares code with 44x. Break out code that is common for initializing the primary and secondary cpus into a function which can be called for both. Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/head_44x.S330
1 files changed, 171 insertions, 159 deletions
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 711368b993f2..39be049a7850 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -69,165 +69,7 @@ _ENTRY(_start);
69 mr r27,r7 69 mr r27,r7
70 li r24,0 /* CPU number */ 70 li r24,0 /* CPU number */
71 71
72/* 72 bl init_cpu_state
73 * In case the firmware didn't do it, we apply some workarounds
74 * that are good for all 440 core variants here
75 */
76 mfspr r3,SPRN_CCR0
77 rlwinm r3,r3,0,0,27 /* disable icache prefetch */
78 isync
79 mtspr SPRN_CCR0,r3
80 isync
81 sync
82
83/*
84 * Set up the initial MMU state
85 *
86 * We are still executing code at the virtual address
87 * mappings set by the firmware for the base of RAM.
88 *
89 * We first invalidate all TLB entries but the one
90 * we are running from. We then load the KERNELBASE
91 * mappings so we can begin to use kernel addresses
92 * natively and so the interrupt vector locations are
93 * permanently pinned (necessary since Book E
94 * implementations always have translation enabled).
95 *
96 * TODO: Use the known TLB entry we are running from to
97 * determine which physical region we are located
98 * in. This can be used to determine where in RAM
99 * (on a shared CPU system) or PCI memory space
100 * (on a DRAMless system) we are located.
101 * For now, we assume a perfect world which means
102 * we are located at the base of DRAM (physical 0).
103 */
104
105/*
106 * Search TLB for entry that we are currently using.
107 * Invalidate all entries but the one we are using.
108 */
109 /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
110 mfspr r3,SPRN_PID /* Get PID */
111 mfmsr r4 /* Get MSR */
112 andi. r4,r4,MSR_IS@l /* TS=1? */
113 beq wmmucr /* If not, leave STS=0 */
114 oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */
115wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
116 sync
117
118 bl invstr /* Find our address */
119invstr: mflr r5 /* Make it accessible */
120 tlbsx r23,0,r5 /* Find entry we are in */
121 li r4,0 /* Start at TLB entry 0 */
122 li r3,0 /* Set PAGEID inval value */
1231: cmpw r23,r4 /* Is this our entry? */
124 beq skpinv /* If so, skip the inval */
125 tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
126skpinv: addi r4,r4,1 /* Increment */
127 cmpwi r4,64 /* Are we done? */
128 bne 1b /* If not, repeat */
129 isync /* If so, context change */
130
131/*
132 * Configure and load pinned entry into TLB slot 63.
133 */
134
135 lis r3,PAGE_OFFSET@h
136 ori r3,r3,PAGE_OFFSET@l
137
138 /* Kernel is at the base of RAM */
139 li r4, 0 /* Load the kernel physical address */
140
141 /* Load the kernel PID = 0 */
142 li r0,0
143 mtspr SPRN_PID,r0
144 sync
145
146 /* Initialize MMUCR */
147 li r5,0
148 mtspr SPRN_MMUCR,r5
149 sync
150
151 /* pageid fields */
152 clrrwi r3,r3,10 /* Mask off the effective page number */
153 ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
154
155 /* xlat fields */
156 clrrwi r4,r4,10 /* Mask off the real page number */
157 /* ERPN is 0 for first 4GB page */
158
159 /* attrib fields */
160 /* Added guarded bit to protect against speculative loads/stores */
161 li r5,0
162 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
163
164 li r0,63 /* TLB slot 63 */
165
166 tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
167 tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
168 tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
169
170 /* Force context change */
171 mfmsr r0
172 mtspr SPRN_SRR1, r0
173 lis r0,3f@h
174 ori r0,r0,3f@l
175 mtspr SPRN_SRR0,r0
176 sync
177 rfi
178
179 /* If necessary, invalidate original entry we used */
1803: cmpwi r23,63
181 beq 4f
182 li r6,0
183 tlbwe r6,r23,PPC44x_TLB_PAGEID
184 isync
185
1864:
187#ifdef CONFIG_PPC_EARLY_DEBUG_44x
188 /* Add UART mapping for early debug. */
189
190 /* pageid fields */
191 lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h
192 ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K
193
194 /* xlat fields */
195 lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h
196 ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
197
198 /* attrib fields */
199 li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)
200 li r0,62 /* TLB slot 0 */
201
202 tlbwe r3,r0,PPC44x_TLB_PAGEID
203 tlbwe r4,r0,PPC44x_TLB_XLAT
204 tlbwe r5,r0,PPC44x_TLB_ATTRIB
205
206 /* Force context change */
207 isync
208#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
209
210 /* Establish the interrupt vector offsets */
211 SET_IVOR(0, CriticalInput);
212 SET_IVOR(1, MachineCheck);
213 SET_IVOR(2, DataStorage);
214 SET_IVOR(3, InstructionStorage);
215 SET_IVOR(4, ExternalInput);
216 SET_IVOR(5, Alignment);
217 SET_IVOR(6, Program);
218 SET_IVOR(7, FloatingPointUnavailable);
219 SET_IVOR(8, SystemCall);
220 SET_IVOR(9, AuxillaryProcessorUnavailable);
221 SET_IVOR(10, Decrementer);
222 SET_IVOR(11, FixedIntervalTimer);
223 SET_IVOR(12, WatchdogTimer);
224 SET_IVOR(13, DataTLBError);
225 SET_IVOR(14, InstructionTLBError);
226 SET_IVOR(15, DebugCrit);
227
228 /* Establish the interrupt vector base */
229 lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
230 mtspr SPRN_IVPR,r4
231 73
232 /* 74 /*
233 * This is where the main kernel code starts. 75 * This is where the main kernel code starts.
@@ -647,6 +489,176 @@ _GLOBAL(set_context)
647 blr 489 blr
648 490
649/* 491/*
492 * Init CPU state. This is called at boot time or for secondary CPUs
493 * to setup initial TLB entries, setup IVORs, etc...
494 */
495_GLOBAL(init_cpu_state)
496 mflr r22
497/*
498 * In case the firmware didn't do it, we apply some workarounds
499 * that are good for all 440 core variants here
500 */
501 mfspr r3,SPRN_CCR0
502 rlwinm r3,r3,0,0,27 /* disable icache prefetch */
503 isync
504 mtspr SPRN_CCR0,r3
505 isync
506 sync
507
508/*
509 * Set up the initial MMU state
510 *
511 * We are still executing code at the virtual address
512 * mappings set by the firmware for the base of RAM.
513 *
514 * We first invalidate all TLB entries but the one
515 * we are running from. We then load the KERNELBASE
516 * mappings so we can begin to use kernel addresses
517 * natively and so the interrupt vector locations are
518 * permanently pinned (necessary since Book E
519 * implementations always have translation enabled).
520 *
521 * TODO: Use the known TLB entry we are running from to
522 * determine which physical region we are located
523 * in. This can be used to determine where in RAM
524 * (on a shared CPU system) or PCI memory space
525 * (on a DRAMless system) we are located.
526 * For now, we assume a perfect world which means
527 * we are located at the base of DRAM (physical 0).
528 */
529
530/*
531 * Search TLB for entry that we are currently using.
532 * Invalidate all entries but the one we are using.
533 */
534 /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
535 mfspr r3,SPRN_PID /* Get PID */
536 mfmsr r4 /* Get MSR */
537 andi. r4,r4,MSR_IS@l /* TS=1? */
538 beq wmmucr /* If not, leave STS=0 */
539 oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */
540wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
541 sync
542
543 bl invstr /* Find our address */
544invstr: mflr r5 /* Make it accessible */
545 tlbsx r23,0,r5 /* Find entry we are in */
546 li r4,0 /* Start at TLB entry 0 */
547 li r3,0 /* Set PAGEID inval value */
5481: cmpw r23,r4 /* Is this our entry? */
549 beq skpinv /* If so, skip the inval */
550 tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
551skpinv: addi r4,r4,1 /* Increment */
552 cmpwi r4,64 /* Are we done? */
553 bne 1b /* If not, repeat */
554 isync /* If so, context change */
555
556/*
557 * Configure and load pinned entry into TLB slot 63.
558 */
559
560 lis r3,PAGE_OFFSET@h
561 ori r3,r3,PAGE_OFFSET@l
562
563 /* Kernel is at the base of RAM */
564 li r4, 0 /* Load the kernel physical address */
565
566 /* Load the kernel PID = 0 */
567 li r0,0
568 mtspr SPRN_PID,r0
569 sync
570
571 /* Initialize MMUCR */
572 li r5,0
573 mtspr SPRN_MMUCR,r5
574 sync
575
576 /* pageid fields */
577 clrrwi r3,r3,10 /* Mask off the effective page number */
578 ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
579
580 /* xlat fields */
581 clrrwi r4,r4,10 /* Mask off the real page number */
582 /* ERPN is 0 for first 4GB page */
583
584 /* attrib fields */
585 /* Added guarded bit to protect against speculative loads/stores */
586 li r5,0
587 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
588
589 li r0,63 /* TLB slot 63 */
590
591 tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
592 tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
593 tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
594
595 /* Force context change */
596 mfmsr r0
597 mtspr SPRN_SRR1, r0
598 lis r0,3f@h
599 ori r0,r0,3f@l
600 mtspr SPRN_SRR0,r0
601 sync
602 rfi
603
604 /* If necessary, invalidate original entry we used */
6053: cmpwi r23,63
606 beq 4f
607 li r6,0
608 tlbwe r6,r23,PPC44x_TLB_PAGEID
609 isync
610
6114:
612#ifdef CONFIG_PPC_EARLY_DEBUG_44x
613 /* Add UART mapping for early debug. */
614
615 /* pageid fields */
616 lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h
617 ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K
618
619 /* xlat fields */
620 lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h
621 ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
622
623 /* attrib fields */
624 li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)
625 li r0,62 /* TLB slot 0 */
626
627 tlbwe r3,r0,PPC44x_TLB_PAGEID
628 tlbwe r4,r0,PPC44x_TLB_XLAT
629 tlbwe r5,r0,PPC44x_TLB_ATTRIB
630
631 /* Force context change */
632 isync
633#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
634
635 /* Establish the interrupt vector offsets */
636 SET_IVOR(0, CriticalInput);
637 SET_IVOR(1, MachineCheck);
638 SET_IVOR(2, DataStorage);
639 SET_IVOR(3, InstructionStorage);
640 SET_IVOR(4, ExternalInput);
641 SET_IVOR(5, Alignment);
642 SET_IVOR(6, Program);
643 SET_IVOR(7, FloatingPointUnavailable);
644 SET_IVOR(8, SystemCall);
645 SET_IVOR(9, AuxillaryProcessorUnavailable);
646 SET_IVOR(10, Decrementer);
647 SET_IVOR(11, FixedIntervalTimer);
648 SET_IVOR(12, WatchdogTimer);
649 SET_IVOR(13, DataTLBError);
650 SET_IVOR(14, InstructionTLBError);
651 SET_IVOR(15, DebugCrit);
652
653 /* Establish the interrupt vector base */
654 lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
655 mtspr SPRN_IVPR,r4
656
657 addis r22,r22,KERNELBASE@h
658 mtlr r22
659 blr
660
661/*
650 * We put a few things here that have to be page-aligned. This stuff 662 * We put a few things here that have to be page-aligned. This stuff
651 * goes at the beginning of the data segment, which is page-aligned. 663 * goes at the beginning of the data segment, which is page-aligned.
652 */ 664 */