]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/booke/locore.S
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / powerpc / booke / locore.S
1 /*-
2  * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
19  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include "assym.s"
31
32 #include <machine/param.h>
33 #include <machine/asm.h>
34 #include <machine/spr.h>
35 #include <machine/psl.h>
36 #include <machine/pte.h>
37 #include <machine/trap.h>
38 #include <machine/vmparam.h>
39 #include <machine/tlb.h>
40 #include <machine/bootinfo.h>
41
42 #define TMPSTACKSZ      16384
43
44 /*
45  * This symbol is here for the benefit of kvm_mkdb, and is supposed to
46  * mark the start of kernel text.
47  */
48         .text
49         .globl  kernel_text
50 kernel_text:
51
52 /*
53  * Startup entry.  Note, this must be the first thing in the text segment!
54  */
55         .text
56         .globl  __start
57 __start:
58
59 /*
60  * Assumption on a boot loader:
61  *  - system memory starts from physical address 0
62  *  - kernel is loaded at 16MB boundary
63  *  - it's mapped by a single TBL1 entry
64  *  - TLB1 mapping is 1:1 pa to va
65  *  - all PID registers are set to the same value
66  *
67  * Loader register use:
68  *      r1      : stack pointer
69  *      r3      : metadata pointer
70  *
71  * We rearrange the TLB1 layout as follows:
72  *  - find AS and entry kernel started in
73  *  - make sure it's protected, ivalidate other entries
74  *  - create temp entry in the second AS (make sure it's not TLB[15])
75  *  - switch to temp mapping
76  *  - map 16MB of RAM in TLB1[15]
77  *  - use AS=1, set EPN to KERNBASE and RPN to kernel load address
78  *  - switch to to TLB1[15] mapping
79  *  - invalidate temp mapping
80  *
81  * locore register use:
82  *      r1      : stack pointer
83  *      r2      : unused
84  *      r3      : kernel_text
85  *      r4      : _end
86  *      r5      : metadata pointer
87  *      r6-r9   : unused
88  *      r10     : entry we started in
89  *      r11     : temp entry
90  *      r12     : AS we started in
91  *      r13-r31 : auxiliary registers
92  */
93
94 /*
95  * Move metadata ptr to r5
96  */
97         mr      %r5, %r3
98
99 /*
100  * Initial cleanup
101  */
102         li      %r16, 0x200             /* Keep debug exceptions for CodeWarrior. */
103         mtmsr   %r16
104         isync
105 #if 0
106         mtspr   SPR_HID0, %r16
107         isync
108         msync
109         mtspr   SPR_HID1, %r16
110         isync
111 #endif
112
113         /* Issue INV_ALL Invalidate on TLB0 */
114         li      %r16, 0x04
115         tlbivax 0, %r16
116         isync
117         msync
118
119 /*
120  * Use tblsx to locate the TLB1 entry that maps kernel code
121  */
122         bl      1f                      /* Current address */
123 1:      mflr    %r15
124
125         /* Find entry that maps current address */
126         mfspr   %r17, SPR_PID0
127         slwi    %r17, %r17, MAS6_SPID0_SHIFT
128         mtspr   SPR_MAS6, %r17
129         isync
130         tlbsx   0, %r15
131
132         /* Copy entry number to r10 */
133         mfspr   %r17, SPR_MAS0
134         rlwinm  %r10, %r17, 16, 28, 31
135
136         /* Invalidate TLB1, skipping our entry. */
137         mfspr   %r17, SPR_TLB1CFG       /* Get number of entries */
138         andi.   %r17, %r17, TLBCFG_NENTRY_MASK@l
139         li      %r16, 0                 /* Start from Entry 0 */
140
141 2:      lis     %r15, MAS0_TLBSEL1@h    /* Select TLB1 */
142         rlwimi  %r15, %r16, 16, 12, 15
143         mtspr   SPR_MAS0, %r15
144         isync
145         tlbre
146         mfspr   %r15, SPR_MAS1
147         cmpw    %r16, %r10
148         beq     3f
149         /* Clear VALID and IPROT bits for other entries */
150         rlwinm  %r15, %r15, 0, 2, 31
151         mtspr   SPR_MAS1, %r15
152         isync
153         tlbwe
154         isync
155         msync
156 3:      addi    %r16, %r16, 1
157         cmpw    %r16, %r17              /* Check if this is the last entry */
158         bne     2b
159
160 /*
161  * Create temporary mapping in the other Address Space
162  */
163         lis     %r17, MAS0_TLBSEL1@h    /* Select TLB1 */
164         rlwimi  %r17, %r10, 16, 12, 15  /* Select our entry */
165         mtspr   SPR_MAS0, %r17
166         isync
167         tlbre                           /* Read it in */
168
169         /* Prepare and write temp entry */
170         lis     %r17, MAS0_TLBSEL1@h    /* Select TLB1 */
171         addi    %r11, %r10, 0x1         /* Use next entry. */
172         rlwimi  %r17, %r11, 16, 12, 15  /* Select temp entry */
173         mtspr   SPR_MAS0, %r17
174         isync
175
176         mfspr   %r16, SPR_MAS1
177         li      %r15, 1                 /* AS 1 */
178         rlwimi  %r16, %r15, 12, 19, 19
179         mtspr   SPR_MAS1, %r16
180         li      %r17, 0
181         rlwimi  %r16, %r17, 0, 8, 15    /* Global mapping, TID=0 */
182         isync
183
184         tlbwe
185         isync
186         msync
187
188         mfmsr   %r16
189         ori     %r16, %r16, 0x30        /* Switch to AS 1. */
190
191         bl      4f                      /* Find current execution address */
192 4:      mflr    %r15
193         addi    %r15, %r15, 20          /* Increment to instruction after rfi */
194         mtspr   SPR_SRR0, %r15
195         mtspr   SPR_SRR1, %r16
196         rfi                             /* Switch context */
197
198 /*
199  * Invalidate initial entry
200  */
201         mr      %r22, %r10
202         bl      tlb1_inval_entry
203
204 /*
205  * Setup final mapping in TLB1[1] and switch to it
206  */
207         /* Final kernel mapping, map in 16 MB of RAM */
208         lis     %r16, MAS0_TLBSEL1@h    /* Select TLB1 */
209         li      %r17, 1                 /* Entry 1 */
210         rlwimi  %r16, %r17, 16, 12, 15
211         mtspr   SPR_MAS0, %r16
212         isync
213
214         li      %r16, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
215         oris    %r16, %r16, (MAS1_VALID | MAS1_IPROT)@h
216         mtspr   SPR_MAS1, %r16
217         isync
218
219         lis     %r19, KERNBASE@h
220         ori     %r19, %r19, KERNBASE@l
221         mtspr   SPR_MAS2, %r19          /* Set final EPN, clear WIMG */
222         isync
223
224         bl      5f
225 5:      mflr    %r16                    /* Use current address */
226         lis     %r18, 0xff00            /* 16MB alignment mask */
227         and     %r16, %r16, %r18
228         mr      %r25, %r16              /* Copy kernel load address */
229         ori     %r16, %r16, (MAS3_SX | MAS3_SW | MAS3_SR)@l
230         mtspr   SPR_MAS3, %r16          /* Set RPN and protection */
231         isync
232         tlbwe
233         isync
234         msync
235
236         /* Switch to the above TLB1[1] mapping */
237         lis     %r18, 0x00ff            /* 16MB offset mask */
238         ori     %r18, %r18, 0xffff
239         bl      6f
240 6:      mflr    %r20                    /* Use current address */
241         and     %r20, %r20, %r18        /* Offset from kernel load address */
242         add     %r20, %r20, %r19        /* Move to kernel virtual address */
243         addi    %r20, %r20, 32          /* Increment to instr. after rfi  */
244         li      %r21, 0x200
245         mtspr   SPR_SRR0, %r20
246         mtspr   SPR_SRR1, %r21
247         rfi
248
249         /* Save kernel load address for later use */
250         lis     %r24, kernload@ha
251         addi    %r24, %r24, kernload@l
252         stw     %r25, 0(%r24)
253
254 /*
255  * Invalidate temp mapping
256  */
257         mr      %r22, %r11
258         bl      tlb1_inval_entry
259
260 /*
261  * Setup a temporary stack
262  */
263         lis     %r1, tmpstack@ha
264         addi    %r1, %r1, tmpstack@l
265         addi    %r1, %r1, (TMPSTACKSZ - 8)
266
267 /*
268  * Intialise exception vector offsets
269  */
270         bl      ivor_setup
271
272 /*
273  * Jump to system initialization code
274  *
275  * Setup first two arguments for e500_init, metadata (r5) is already in place.
276  */
277         lis     %r3, kernel_text@ha
278         addi    %r3, %r3, kernel_text@l
279         lis     %r4, _end@ha
280         addi    %r4, %r4, _end@l
281
282         bl      e500_init
283
284         /* Switch to thread0.td_kstack */
285         mr      %r1, %r3
286         li      %r3, 0
287         stw     %r3, 0(%r1)
288
289         bl      mi_startup  /* Machine independet part, does not return */
290
291 /************************************************************************/
292 /* locore subroutines */
293 /************************************************************************/
294
295 tlb1_inval_entry:
296         lis     %r17, MAS0_TLBSEL1@h    /* Select TLB1 */
297         rlwimi  %r17, %r22, 16, 12, 15  /* Select our entry */
298         mtspr   SPR_MAS0, %r17
299         isync
300         tlbre                           /* Read it in */
301
302         li      %r16, 0
303         mtspr   SPR_MAS1, %r16
304         isync
305         tlbwe
306         isync
307         msync
308         blr
309
310 ivor_setup:
311         /* Set base address of interrupt handler routines */
312         lis     %r21, interrupt_vector_base@h
313         mtspr   SPR_IVPR, %r21
314
315         /* Assign interrupt handler routines offsets */
316         li      %r21, int_critical_input@l
317         mtspr   SPR_IVOR0, %r21
318         li      %r21, int_machine_check@l
319         mtspr   SPR_IVOR1, %r21
320         li      %r21, int_data_storage@l
321         mtspr   SPR_IVOR2, %r21
322         li      %r21, int_instr_storage@l
323         mtspr   SPR_IVOR3, %r21
324         li      %r21, int_external_input@l
325         mtspr   SPR_IVOR4, %r21
326         li      %r21, int_alignment@l
327         mtspr   SPR_IVOR5, %r21
328         li      %r21, int_program@l
329         mtspr   SPR_IVOR6, %r21
330         li      %r21, int_syscall@l
331         mtspr   SPR_IVOR8, %r21
332         li      %r21, int_decrementer@l
333         mtspr   SPR_IVOR10, %r21
334         li      %r21, int_fixed_interval_timer@l
335         mtspr   SPR_IVOR11, %r21
336         li      %r21, int_watchdog@l
337         mtspr   SPR_IVOR12, %r21
338         li      %r21, int_data_tlb_error@l
339         mtspr   SPR_IVOR13, %r21
340         li      %r21, int_inst_tlb_error@l
341         mtspr   SPR_IVOR14, %r21
342         li      %r21, int_debug@l
343         mtspr   SPR_IVOR15, %r21
344         blr
345
346 /*
347  * void tlb1_inval_va(vm_offset_t va)
348  *
349  * r3 - va to invalidate
350  */
351 ENTRY(tlb1_inval_va)
352         /* EA mask */
353         lis     %r6, 0xffff
354         ori     %r6, %r6, 0xf000
355         and     %r3, %r3, %r6
356
357         /* Select TLB1 */
358         ori     %r3, %r3, 0x08
359
360         isync
361         tlbivax 0, %r3
362         isync
363         msync
364         blr
365
366 /*
367  * void tlb0_inval_va(vm_offset_t va)
368  *
369  * r3 - va to invalidate
370  */
371 ENTRY(tlb0_inval_va)
372         /* EA mask, this also clears TLBSEL, selecting TLB0 */
373         lis     %r6, 0xffff
374         ori     %r6, %r6, 0xf000
375         and     %r3, %r3, %r6
376
377         isync
378         tlbivax 0, %r3
379         isync
380         msync
381         blr
382
383 /*
384  * Cache disable/enable/inval sequences according
385  * to section 2.16 of E500CORE RM.
386  */
387 ENTRY(dcache_inval)
388         /* Invalidate d-cache */
389         mfspr   %r3, SPR_L1CSR0
390         ori     %r3, %r3, (L1CSR0_DCFI | L1CSR0_DCLFR)@l
391         msync
392         isync
393         mtspr   SPR_L1CSR0, %r3
394         isync
395         blr
396
397 ENTRY(dcache_disable)
398         /* Disable d-cache */
399         mfspr   %r3, SPR_L1CSR0
400         li      %r4, L1CSR0_DCE@l
401         not     %r4, %r4
402         and     %r3, %r3, %r4
403         msync
404         isync
405         mtspr   SPR_L1CSR0, %r3
406         isync
407         blr
408
409 ENTRY(dcache_enable)
410         /* Enable d-cache */
411         mfspr   %r3, SPR_L1CSR0
412         oris    %r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@h
413         ori     %r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@l
414         msync
415         isync
416         mtspr   SPR_L1CSR0, %r3
417         isync
418         blr
419
420 ENTRY(icache_inval)
421         /* Invalidate i-cache */
422         mfspr   %r3, SPR_L1CSR1
423         ori     %r3, %r3, (L1CSR1_ICFI | L1CSR1_ICLFR)@l
424         isync
425         mtspr   SPR_L1CSR1, %r3
426         isync
427         blr
428
429 ENTRY(icache_disable)
430         /* Disable i-cache */
431         mfspr   %r3, SPR_L1CSR1
432         li      %r4, L1CSR1_ICE@l
433         not     %r4, %r4
434         and     %r3, %r3, %r4
435         isync
436         mtspr   SPR_L1CSR1, %r3
437         isync
438         blr
439
440 ENTRY(icache_enable)
441         /* Enable i-cache */
442         mfspr   %r3, SPR_L1CSR1
443         oris    %r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@h
444         ori     %r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@l
445         isync
446         mtspr   SPR_L1CSR1, %r3
447         isync
448         blr
449
450 /*
451  * int setfault()
452  *
453  * Similar to setjmp to setup for handling faults on accesses to user memory.
454  * Any routine using this may only call bcopy, either the form below,
455  * or the (currently used) C code optimized, so it doesn't use any non-volatile
456  * registers.
457  */
458         .globl  setfault
459 setfault:
460         mflr    %r0
461         mfsprg0 %r4
462         lwz     %r4, PC_CURTHREAD(%r4)
463         lwz     %r4, TD_PCB(%r4)
464         stw     %r3, PCB_ONFAULT(%r4)
465         mfcr    %r10
466         mfctr   %r11
467         mfxer   %r12
468         stw     %r0, 0(%r3)
469         stw     %r1, 4(%r3)
470         stw     %r2, 8(%r3)
471         stmw    %r10, 12(%r3)           /* store CR, CTR, XER, [r13 .. r31] */
472         li      %r3, 0                  /* return FALSE */
473         blr
474
475 /************************************************************************/
476 /* Data section                                                         */
477 /************************************************************************/
478         .data
479         .align  4
480 tmpstack:
481         .space  TMPSTACKSZ
482
483 /*
484  * Compiled KERNBASE locations
485  */
486         .globl  kernbase
487         .set    kernbase, KERNBASE
488
489 /*
490  * Globals
491  */
492 #define INTRCNT_COUNT   256             /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
493
494 GLOBAL(kernload)
495         .long
496 GLOBAL(intrnames)
497         .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
498 GLOBAL(eintrnames)
499         .align 4
500 GLOBAL(intrcnt)
501         .space  INTRCNT_COUNT * 4 * 2
502 GLOBAL(eintrcnt)
503
504 #include <powerpc/booke/trap_subr.S>