]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/powerpc/booke/locore.S
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / powerpc / booke / locore.S
1 /*-
2  * Copyright (C) 2007-2009 Semihalf, Rafal Jaworowski <raj@semihalf.com>
3  * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
18  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include "assym.s"
30
31 #include <machine/asm.h>
32 #include <machine/hid.h>
33 #include <machine/param.h>
34 #include <machine/spr.h>
35 #include <machine/pte.h>
36 #include <machine/trap.h>
37 #include <machine/vmparam.h>
38 #include <machine/tlb.h>
39
40 #define TMPSTACKSZ      16384
41
42         .text
43         .globl  btext
44 btext:
45
46 /*
47  * This symbol is here for the benefit of kvm_mkdb, and is supposed to
48  * mark the start of kernel text.
49  */
50         .globl  kernel_text
51 kernel_text:
52
53 /*
54  * Startup entry.  Note, this must be the first thing in the text segment!
55  */
56         .text
57         .globl  __start
58 __start:
59
60 /*
61  * Assumptions on the boot loader:
62  *  - system memory starts from physical address 0
63  *  - it's mapped by a single TBL1 entry
64  *  - TLB1 mapping is 1:1 pa to va
65  *  - kernel is loaded at 16MB boundary
66  *  - all PID registers are set to the same value
67  *  - CPU is running in AS=0
68  *
69  * Registers contents provided by the loader(8):
70  *      r1      : stack pointer
71  *      r3      : metadata pointer
72  *
73  * We rearrange the TLB1 layout as follows:
74  *  - find TLB1 entry we started in
75  *  - make sure it's protected, ivalidate other entries
76  *  - create temp entry in the second AS (make sure it's not TLB[1])
77  *  - switch to temp mapping
78  *  - map 16MB of RAM in TLB1[1]
79  *  - use AS=1, set EPN to KERNBASE and RPN to kernel load address
80  *  - switch to to TLB1[1] mapping
81  *  - invalidate temp mapping
82  *
83  * locore registers use:
84  *      r1      : stack pointer
85  *      r2      : trace pointer (AP only, for early diagnostics)
86  *      r3-r27  : scratch registers
87  *      r28     : temp TLB1 entry
88  *      r29     : initial TLB1 entry we started in
89  *      r30-r31 : arguments (metadata pointer)
90  */
91
92 /*
93  * Keep arguments in r30 & r31 for later use.
94  */
95         mr      %r30, %r3
96         mr      %r31, %r4
97
98 /*
99  * Initial cleanup
100  */
101         li      %r3, PSL_DE     /* Keep debug exceptions for CodeWarrior. */
102         mtmsr   %r3
103         isync
104
105         lis     %r3, HID0_E500_DEFAULT_SET@h
106         ori     %r3, %r3, HID0_E500_DEFAULT_SET@l
107         mtspr   SPR_HID0, %r3
108         isync
109         lis     %r3, HID1_E500_DEFAULT_SET@h
110         ori     %r3, %r3, HID1_E500_DEFAULT_SET@l
111         mtspr   SPR_HID1, %r3
112         isync
113
114         /* Invalidate all entries in TLB0 */
115         li      %r3, 0
116         bl      tlb_inval_all
117
118         cmpwi   %r30, 0
119         beq     done_mapping
120
121 /*
122  * Locate the TLB1 entry that maps this code
123  */
124         bl      1f
125 1:      mflr    %r3
126         bl      tlb1_find_current       /* the entry found is returned in r29 */
127
128         bl      tlb1_inval_all_but_current
129 /*
130  * Create temporary mapping in AS=1 and switch to it
131  */
132         bl      tlb1_temp_mapping_as1
133
134         mfmsr   %r3
135         ori     %r3, %r3, (PSL_IS | PSL_DS)
136         bl      2f
137 2:      mflr    %r4
138         addi    %r4, %r4, 20
139         mtspr   SPR_SRR0, %r4
140         mtspr   SPR_SRR1, %r3
141         rfi                             /* Switch context */
142
143 /*
144  * Invalidate initial entry
145  */
146         mr      %r3, %r29
147         bl      tlb1_inval_entry
148
149 /*
150  * Setup final mapping in TLB1[1] and switch to it
151  */
152         /* Final kernel mapping, map in 16 MB of RAM */
153         lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
154         li      %r4, 0                  /* Entry 0 */
155         rlwimi  %r3, %r4, 16, 12, 15
156         mtspr   SPR_MAS0, %r3
157         isync
158
159         li      %r3, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
160         oris    %r3, %r3, (MAS1_VALID | MAS1_IPROT)@h
161         mtspr   SPR_MAS1, %r3           /* note TS was not filled, so it's TS=0 */
162         isync
163
164         lis     %r3, KERNBASE@h
165         ori     %r3, %r3, KERNBASE@l    /* EPN = KERNBASE */
166 #ifdef SMP
167         ori     %r3, %r3, MAS2_M@l      /* WIMGE = 0b00100 */
168 #endif
169         mtspr   SPR_MAS2, %r3
170         isync
171
172         /* Discover phys load address */
173         bl      3f
174 3:      mflr    %r4                     /* Use current address */
175         rlwinm  %r4, %r4, 0, 0, 7       /* 16MB alignment mask */
176         ori     %r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
177         mtspr   SPR_MAS3, %r4           /* Set RPN and protection */
178         isync
179         tlbwe
180         isync
181         msync
182
183         /* Switch to the above TLB1[1] mapping */
184         bl      4f
185 4:      mflr    %r4
186         rlwinm  %r4, %r4, 0, 8, 31      /* Current offset from kernel load address */
187         rlwinm  %r3, %r3, 0, 0, 19
188         add     %r4, %r4, %r3           /* Convert to kernel virtual address */
189         addi    %r4, %r4, 36
190         li      %r3, PSL_DE             /* Note AS=0 */
191         mtspr   SPR_SRR0, %r4
192         mtspr   SPR_SRR1, %r3
193         rfi
194
195 /*
196  * Invalidate temp mapping
197  */
198         mr      %r3, %r28
199         bl      tlb1_inval_entry
200
201 done_mapping:
202
203 /*
204  * Setup a temporary stack
205  */
206         lis     %r1, tmpstack@ha
207         addi    %r1, %r1, tmpstack@l
208         addi    %r1, %r1, (TMPSTACKSZ - 8)
209
210 /*
211  * Initialise exception vector offsets
212  */
213         bl      ivor_setup
214
215 /*
216  * Set up arguments and jump to system initialization code
217  */
218         mr      %r3, %r30
219         mr      %r4, %r31
220
221         /* Prepare e500 core */
222         bl      booke_init
223
224         /* Switch to thread0.td_kstack now */
225         mr      %r1, %r3
226         li      %r3, 0
227         stw     %r3, 0(%r1)
228
229         /* Machine independet part, does not return */
230         bl      mi_startup
231         /* NOT REACHED */
232 5:      b       5b
233
234
235 #ifdef SMP
236 /************************************************************************/
237 /* AP Boot page */
238 /************************************************************************/
239         .text
240         .globl  __boot_page
241         .align  12
242 __boot_page:
243         bl      1f
244
245         .globl  kernload_ap
246 kernload_ap:
247         .long   0
248
249 /*
250  * Initial configuration
251  */
252 1:
253         /* Set HIDs */
254         lis     %r3, HID0_E500_DEFAULT_SET@h
255         ori     %r3, %r3, HID0_E500_DEFAULT_SET@l
256         mtspr   SPR_HID0, %r3
257         isync
258         lis     %r3, HID1_E500_DEFAULT_SET@h
259         ori     %r3, %r3, HID1_E500_DEFAULT_SET@l
260         mtspr   SPR_HID1, %r3
261         isync
262
263         /* Enable branch prediction */
264         li      %r3, BUCSR_BPEN
265         mtspr   SPR_BUCSR, %r3
266         isync
267
268         /* Invalidate all entries in TLB0 */
269         li      %r3, 0
270         bl      tlb_inval_all
271
272 /*
273  * Find TLB1 entry which is translating us now
274  */
275         bl      2f
276 2:      mflr    %r3
277         bl      tlb1_find_current       /* the entry number found is in r29 */
278
279         bl      tlb1_inval_all_but_current
280 /*
281  * Create temporary translation in AS=1 and switch to it
282  */
283         bl      tlb1_temp_mapping_as1
284
285         mfmsr   %r3
286         ori     %r3, %r3, (PSL_IS | PSL_DS)
287         bl      3f
288 3:      mflr    %r4
289         addi    %r4, %r4, 20
290         mtspr   SPR_SRR0, %r4
291         mtspr   SPR_SRR1, %r3
292         rfi                             /* Switch context */
293
294 /*
295  * Invalidate initial entry
296  */
297         mr      %r3, %r29
298         bl      tlb1_inval_entry
299
300 /*
301  * Setup final mapping in TLB1[1] and switch to it
302  */
303         /* Final kernel mapping, map in 16 MB of RAM */
304         lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
305         li      %r4, 0                  /* Entry 0 */
306         rlwimi  %r3, %r4, 16, 4, 15
307         mtspr   SPR_MAS0, %r3
308         isync
309
310         li      %r3, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
311         oris    %r3, %r3, (MAS1_VALID | MAS1_IPROT)@h
312         mtspr   SPR_MAS1, %r3           /* note TS was not filled, so it's TS=0 */
313         isync
314
315         lis     %r3, KERNBASE@h
316         ori     %r3, %r3, KERNBASE@l    /* EPN = KERNBASE */
317         ori     %r3, %r3, MAS2_M@l      /* WIMGE = 0b00100 */
318         mtspr   SPR_MAS2, %r3
319         isync
320
321         /* Retrieve kernel load [physical] address from kernload_ap */
322         bl      4f
323 4:      mflr    %r3
324         rlwinm  %r3, %r3, 0, 0, 19
325         lis     %r4, kernload_ap@h
326         ori     %r4, %r4, kernload_ap@l
327         lis     %r5, __boot_page@h
328         ori     %r5, %r5, __boot_page@l
329         sub     %r4, %r4, %r5   /* offset of kernload_ap within __boot_page */
330         lwzx    %r3, %r4, %r3
331
332         /* Set RPN and protection */
333         ori     %r3, %r3, (MAS3_SX | MAS3_SW | MAS3_SR)@l
334         mtspr   SPR_MAS3, %r3
335         isync
336         tlbwe
337         isync
338         msync
339
340         /* Switch to the final mapping */
341         bl      5f
342 5:      mflr    %r3
343         rlwinm  %r3, %r3, 0, 0xfff      /* Offset from boot page start */
344         add     %r3, %r3, %r5           /* Make this virtual address */
345         addi    %r3, %r3, 32
346         li      %r4, 0                  /* Note AS=0 */
347         mtspr   SPR_SRR0, %r3
348         mtspr   SPR_SRR1, %r4
349         rfi
350
351 /*
352  * At this point we're running at virtual addresses KERNBASE and beyond so
353  * it's allowed to directly access all locations the kernel was linked
354  * against.
355  */
356
357 /*
358  * Invalidate temp mapping
359  */
360         mr      %r3, %r28
361         bl      tlb1_inval_entry
362
363 /*
364  * Setup a temporary stack
365  */
366         lis     %r1, tmpstack@ha
367         addi    %r1, %r1, tmpstack@l
368         addi    %r1, %r1, (TMPSTACKSZ - 8)
369
370 /*
371  * Initialise exception vector offsets
372  */
373         bl      ivor_setup
374
375         /*
376          * Assign our pcpu instance
377          */
378         lis     %r3, ap_pcpu@h
379         ori     %r3, %r3, ap_pcpu@l
380         lwz     %r3, 0(%r3)
381         mtsprg0 %r3
382
383         bl      pmap_bootstrap_ap
384
385         bl      cpudep_ap_bootstrap
386         /* Switch to the idle thread's kstack */
387         mr      %r1, %r3
388         
389         bl      machdep_ap_bootstrap
390
391         /* NOT REACHED */
392 6:      b       6b
393 #endif /* SMP */
394
395 /*
396  * Invalidate all entries in the given TLB.
397  *
398  * r3   TLBSEL
399  */
400 tlb_inval_all:
401         rlwinm  %r3, %r3, 3, 0x18       /* TLBSEL */
402         ori     %r3, %r3, 0x4           /* INVALL */
403         tlbivax 0, %r3
404         isync
405         msync
406
407         tlbsync
408         msync
409         blr
410
411 /*
412  * expects address to look up in r3, returns entry number in r29
413  *
414  * FIXME: the hidden assumption is we are now running in AS=0, but we should
415  * retrieve actual AS from MSR[IS|DS] and put it in MAS6[SAS]
416  */
417 tlb1_find_current:
418         mfspr   %r17, SPR_PID0
419         slwi    %r17, %r17, MAS6_SPID0_SHIFT
420         mtspr   SPR_MAS6, %r17
421         isync
422         tlbsx   0, %r3
423         mfspr   %r17, SPR_MAS0
424         rlwinm  %r29, %r17, 16, 20, 31          /* MAS0[ESEL] -> r29 */
425
426         /* Make sure we have IPROT set on the entry */
427         mfspr   %r17, SPR_MAS1
428         oris    %r17, %r17, MAS1_IPROT@h
429         mtspr   SPR_MAS1, %r17
430         isync
431         tlbwe
432         isync
433         msync
434         blr
435
436 /*
437  * Invalidates a single entry in TLB1.
438  *
439  * r3           ESEL
440  * r4-r5        scratched
441  */
442 tlb1_inval_entry:
443         lis     %r4, MAS0_TLBSEL1@h     /* Select TLB1 */
444         rlwimi  %r4, %r3, 16, 12, 15    /* Select our entry */
445         mtspr   SPR_MAS0, %r4
446         isync
447         tlbre
448         li      %r5, 0                  /* MAS1[V] = 0 */
449         mtspr   SPR_MAS1, %r5
450         isync
451         tlbwe
452         isync
453         msync
454         blr
455
456 /*
457  * r29          current entry number
458  * r28          returned temp entry
459  * r3-r5        scratched
460  */
461 tlb1_temp_mapping_as1:
462         /* Read our current translation */
463         lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
464         rlwimi  %r3, %r29, 16, 12, 15   /* Select our current entry */
465         mtspr   SPR_MAS0, %r3
466         isync
467         tlbre
468
469         /*
470          * Prepare and write temp entry
471          *
472          * FIXME this is not robust against overflow i.e. when the current
473          * entry is the last in TLB1
474          */
475         lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
476         addi    %r28, %r29, 1           /* Use next entry. */
477         rlwimi  %r3, %r28, 16, 12, 15   /* Select temp entry */
478         mtspr   SPR_MAS0, %r3
479         isync
480         mfspr   %r5, SPR_MAS1
481         li      %r4, 1                  /* AS=1 */
482         rlwimi  %r5, %r4, 12, 19, 19
483         li      %r4, 0                  /* Global mapping, TID=0 */
484         rlwimi  %r5, %r4, 16, 8, 15
485         oris    %r5, %r5, (MAS1_VALID | MAS1_IPROT)@h
486         mtspr   SPR_MAS1, %r5
487         isync
488         tlbwe
489         isync
490         msync
491         blr
492
493 /*
494  * Loops over TLB1, invalidates all entries skipping the one which currently
495  * maps this code.
496  *
497  * r29          current entry
498  * r3-r5        scratched
499  */
500 tlb1_inval_all_but_current:
501         mr      %r6, %r3
502         mfspr   %r3, SPR_TLB1CFG        /* Get number of entries */
503         andi.   %r3, %r3, TLBCFG_NENTRY_MASK@l
504         li      %r4, 0                  /* Start from Entry 0 */
505 1:      lis     %r5, MAS0_TLBSEL1@h
506         rlwimi  %r5, %r4, 16, 12, 15
507         mtspr   SPR_MAS0, %r5
508         isync
509         tlbre
510         mfspr   %r5, SPR_MAS1
511         cmpw    %r4, %r29               /* our current entry? */
512         beq     2f
513         rlwinm  %r5, %r5, 0, 2, 31      /* clear VALID and IPROT bits */
514         mtspr   SPR_MAS1, %r5
515         isync
516         tlbwe
517         isync
518         msync
519 2:      addi    %r4, %r4, 1
520         cmpw    %r4, %r3                /* Check if this is the last entry */
521         bne     1b
522         blr
523
524 #ifdef SMP
525 __boot_page_padding:
526         /*
527          * Boot page needs to be exactly 4K, with the last word of this page
528          * acting as the reset vector, so we need to stuff the remainder.
529          * Upon release from holdoff CPU fetches the last word of the boot
530          * page.
531          */
532         .space  4092 - (__boot_page_padding - __boot_page)
533         b       __boot_page
534 #endif /* SMP */
535
536 /************************************************************************/
537 /* locore subroutines */
538 /************************************************************************/
539
540 ivor_setup:
541         /* Set base address of interrupt handler routines */
542         lis     %r3, interrupt_vector_base@h
543         mtspr   SPR_IVPR, %r3
544
545         /* Assign interrupt handler routines offsets */
546         li      %r3, int_critical_input@l
547         mtspr   SPR_IVOR0, %r3
548         li      %r3, int_machine_check@l
549         mtspr   SPR_IVOR1, %r3
550         li      %r3, int_data_storage@l
551         mtspr   SPR_IVOR2, %r3
552         li      %r3, int_instr_storage@l
553         mtspr   SPR_IVOR3, %r3
554         li      %r3, int_external_input@l
555         mtspr   SPR_IVOR4, %r3
556         li      %r3, int_alignment@l
557         mtspr   SPR_IVOR5, %r3
558         li      %r3, int_program@l
559         mtspr   SPR_IVOR6, %r3
560         li      %r3, int_syscall@l
561         mtspr   SPR_IVOR8, %r3
562         li      %r3, int_decrementer@l
563         mtspr   SPR_IVOR10, %r3
564         li      %r3, int_fixed_interval_timer@l
565         mtspr   SPR_IVOR11, %r3
566         li      %r3, int_watchdog@l
567         mtspr   SPR_IVOR12, %r3
568         li      %r3, int_data_tlb_error@l
569         mtspr   SPR_IVOR13, %r3
570         li      %r3, int_inst_tlb_error@l
571         mtspr   SPR_IVOR14, %r3
572         li      %r3, int_debug@l
573         mtspr   SPR_IVOR15, %r3
574         blr
575
576 /*
577  * void tid_flush(tlbtid_t tid);
578  *
579  * Invalidate all TLB0 entries which match the given TID. Note this is
580  * dedicated for cases when invalidation(s) should NOT be propagated to other
581  * CPUs.
582  *
583  * Global vars tlb0_ways, tlb0_entries_per_way are assumed to have been set up
584  * correctly (by tlb0_get_tlbconf()).
585  *
586  */
587 ENTRY(tid_flush)
588         cmpwi   %r3, TID_KERNEL
589         beq     tid_flush_end   /* don't evict kernel translations */
590
591         /* Number of TLB0 ways */
592         lis     %r4, tlb0_ways@h
593         ori     %r4, %r4, tlb0_ways@l
594         lwz     %r4, 0(%r4)
595
596         /* Number of entries / way */
597         lis     %r5, tlb0_entries_per_way@h
598         ori     %r5, %r5, tlb0_entries_per_way@l
599         lwz     %r5, 0(%r5)
600
601         /* Disable interrupts */
602         mfmsr   %r10
603         wrteei  0
604
605         li      %r6, 0          /* ways counter */
606 loop_ways:
607         li      %r7, 0          /* entries [per way] counter */
608 loop_entries:
609         /* Select TLB0 and ESEL (way) */
610         lis     %r8, MAS0_TLBSEL0@h
611         rlwimi  %r8, %r6, 16, 14, 15
612         mtspr   SPR_MAS0, %r8
613         isync
614
615         /* Select EPN (entry within the way) */
616         rlwinm  %r8, %r7, 12, 13, 19
617         mtspr   SPR_MAS2, %r8
618         isync
619         tlbre
620
621         /* Check if valid entry */
622         mfspr   %r8, SPR_MAS1
623         andis.  %r9, %r8, MAS1_VALID@h
624         beq     next_entry      /* invalid entry */
625
626         /* Check if this is our TID */
627         rlwinm  %r9, %r8, 16, 24, 31
628
629         cmplw   %r9, %r3
630         bne     next_entry      /* not our TID */
631
632         /* Clear VALID bit */
633         rlwinm  %r8, %r8, 0, 1, 31
634         mtspr   SPR_MAS1, %r8
635         isync
636         tlbwe
637         isync
638         msync
639
640 next_entry:
641         addi    %r7, %r7, 1
642         cmpw    %r7, %r5
643         bne     loop_entries
644
645         /* Next way */
646         addi    %r6, %r6, 1
647         cmpw    %r6, %r4
648         bne     loop_ways
649
650         /* Restore MSR (possibly re-enable interrupts) */
651         mtmsr   %r10
652         isync
653
654 tid_flush_end:
655         blr
656
657 /*
658  * Cache disable/enable/inval sequences according
659  * to section 2.16 of E500CORE RM.
660  */
661 ENTRY(dcache_inval)
662         /* Invalidate d-cache */
663         mfspr   %r3, SPR_L1CSR0
664         ori     %r3, %r3, (L1CSR0_DCFI | L1CSR0_DCLFR)@l
665         msync
666         isync
667         mtspr   SPR_L1CSR0, %r3
668         isync
669 1:      mfspr   %r3, SPR_L1CSR0
670         andi.   %r3, %r3, L1CSR0_DCFI
671         bne     1b
672         blr
673
674 ENTRY(dcache_disable)
675         /* Disable d-cache */
676         mfspr   %r3, SPR_L1CSR0
677         li      %r4, L1CSR0_DCE@l
678         not     %r4, %r4
679         and     %r3, %r3, %r4
680         msync
681         isync
682         mtspr   SPR_L1CSR0, %r3
683         isync
684         blr
685
686 ENTRY(dcache_enable)
687         /* Enable d-cache */
688         mfspr   %r3, SPR_L1CSR0
689         oris    %r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@h
690         ori     %r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@l
691         msync
692         isync
693         mtspr   SPR_L1CSR0, %r3
694         isync
695         blr
696
697 ENTRY(icache_inval)
698         /* Invalidate i-cache */
699         mfspr   %r3, SPR_L1CSR1
700         ori     %r3, %r3, (L1CSR1_ICFI | L1CSR1_ICLFR)@l
701         isync
702         mtspr   SPR_L1CSR1, %r3
703         isync
704 1:      mfspr   %r3, SPR_L1CSR1
705         andi.   %r3, %r3, L1CSR1_ICFI
706         bne     1b
707         blr
708
709 ENTRY(icache_disable)
710         /* Disable i-cache */
711         mfspr   %r3, SPR_L1CSR1
712         li      %r4, L1CSR1_ICE@l
713         not     %r4, %r4
714         and     %r3, %r3, %r4
715         isync
716         mtspr   SPR_L1CSR1, %r3
717         isync
718         blr
719
720 ENTRY(icache_enable)
721         /* Enable i-cache */
722         mfspr   %r3, SPR_L1CSR1
723         oris    %r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@h
724         ori     %r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@l
725         isync
726         mtspr   SPR_L1CSR1, %r3
727         isync
728         blr
729
730 /*
731  * int setfault()
732  *
733  * Similar to setjmp to setup for handling faults on accesses to user memory.
734  * Any routine using this may only call bcopy, either the form below,
735  * or the (currently used) C code optimized, so it doesn't use any non-volatile
736  * registers.
737  */
738         .globl  setfault
739 setfault:
740         mflr    %r0
741         mfsprg0 %r4
742         lwz     %r4, PC_CURTHREAD(%r4)
743         lwz     %r4, TD_PCB(%r4)
744         stw     %r3, PCB_ONFAULT(%r4)
745         mfcr    %r10
746         mfctr   %r11
747         mfxer   %r12
748         stw     %r0, 0(%r3)
749         stw     %r1, 4(%r3)
750         stw     %r2, 8(%r3)
751         stmw    %r10, 12(%r3)           /* store CR, CTR, XER, [r13 .. r31] */
752         li      %r3, 0                  /* return FALSE */
753         blr
754
755 /************************************************************************/
756 /* Data section                                                         */
757 /************************************************************************/
758         .data
759         .align  4
760 tmpstack:
761         .space  TMPSTACKSZ
762
763 /*
764  * Compiled KERNBASE locations
765  */
766         .globl  kernbase
767         .set    kernbase, KERNBASE
768
769 /*
770  * Globals
771  */
772 #define INTRCNT_COUNT   256             /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
773
774 GLOBAL(intrnames)
775         .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
776 GLOBAL(sintrnames)
777         .long   INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
778
779         .align 4
780 GLOBAL(intrcnt)
781         .space  INTRCNT_COUNT * 4 * 2
782 GLOBAL(sintrcnt)
783         .long   INTRCNT_COUNT * 4 * 2
784
785 #include <powerpc/booke/trap_subr.S>