1 /* $Id: head.S,v 1.87 2002/02/09 19:49:31 davem Exp $
2 * head.S: Initial boot code for the Sparc64 port of Linux.
4 * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1996 David Sitsky (David.Sitsky@anu.edu.au)
6 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
10 #include <linux/config.h>
11 #include <linux/version.h>
12 #include <linux/errno.h>
13 #include <asm/thread_info.h>
15 #include <asm/pstate.h>
16 #include <asm/ptrace.h>
17 #include <asm/spitfire.h>
19 #include <asm/pgtable.h>
20 #include <asm/errno.h>
21 #include <asm/signal.h>
22 #include <asm/processor.h>
27 #include <asm/ttable.h>
29 /* This section from from _start to sparc64_boot_end should fit into
30 * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
31 * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
32 * 0x0000.0000.0040.6000 and empty_bad_page, which is from
33 * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
37 .globl start, _start, stext, _stext
45 flushw /* Flush register file. */
47 /* This stuff has to be in sync with SILO and other potential boot loaders
48 * Fields should be kept upward compatible and whenever any change is made,
49 * HdrS version should be incremented.
51 .global root_flags, ram_flags, root_dev
52 .global sparc_ramdisk_image, sparc_ramdisk_size
55 .word LINUX_VERSION_CODE
59 * 0x0300 : Supports being located at other than 0x4000
60 * 0x0202 : Supports kernel params string
61 * 0x0201 : Supports reboot_command
63 .half 0x0300 /* HdrS version */
79 /* We must be careful, 32-bit OpenBOOT will get confused if it
80 * tries to save away a register window to a 64-bit kernel
81 * stack address. Flush all windows, disable interrupts,
82 * remap if necessary, jump onto kernel trap table, then kernel
83 * stack, or else we die.
85 * PROM entry point is on %o4
88 BRANCH_IF_CHEETAH_BASE(g1,g5,cheetah_boot)
89 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g5,cheetah_plus_boot)
90 ba,pt %xcc, spitfire_boot
94 /* Preserve OBP chosen DCU and DCR register settings. */
95 ba,pt %xcc, cheetah_generic_boot
99 mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
102 sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5
103 or %g5, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5
105 or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5
106 stxa %g5, [%g0] ASI_DCU_CONTROL_REG
109 cheetah_generic_boot:
110 mov TSB_EXTENSION_P, %g3
111 stxa %g0, [%g3] ASI_DMMU
112 stxa %g0, [%g3] ASI_IMMU
115 mov TSB_EXTENSION_S, %g3
116 stxa %g0, [%g3] ASI_DMMU
119 mov TSB_EXTENSION_N, %g3
120 stxa %g0, [%g3] ASI_DMMU
121 stxa %g0, [%g3] ASI_IMMU
124 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
127 /* Just like for Spitfire, we probe itlb-2 for a mapping which
128 * matches our current %pc. We take the physical address in
129 * that mapping and use it to make our own.
132 /* %g5 holds the tlb data */
133 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
135 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
137 /* Put PADDR tlb data mask into %g3. */
138 sethi %uhi(_PAGE_PADDR), %g3
139 or %g3, %ulo(_PAGE_PADDR), %g3
141 sethi %hi(_PAGE_PADDR), %g7
142 or %g7, %lo(_PAGE_PADDR), %g7
145 set 2 << 16, %l0 /* TLB entry walker. */
146 set 0x1fff, %l2 /* Page mask. */
148 andn %l3, %l2, %g2 /* vaddr comparator */
150 1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
154 be,pn %xcc, cheetah_got_tlbentry
156 and %l0, (127 << 3), %g1
159 add %l0, (1 << 3), %l0
161 /* Search the small TLB. OBP never maps us like that but
166 1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
170 be,pn %xcc, cheetah_got_tlbentry
174 add %l0, (1 << 3), %l0
176 /* BUG() if we get here... */
179 cheetah_got_tlbentry:
180 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0
181 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
188 /* Clear out any KERNBASE area entries. */
190 sethi %hi(KERNBASE), %g3
191 sethi %hi(KERNBASE<<1), %g7
192 mov TLB_TAG_ACCESS, %l7
194 /* First, check ITLB */
195 1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
203 stxa %g0, [%l7] ASI_IMMU
205 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
208 2: and %l0, (127 << 3), %g1
211 add %l0, (1 << 3), %l0
213 /* Next, check DTLB */
215 1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
223 stxa %g0, [%l7] ASI_DMMU
225 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
228 2: and %l0, (511 << 3), %g1
231 add %l0, (1 << 3), %l0
233 /* On Cheetah+, have to check second DTLB. */
234 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,l0,2f)
239 1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
247 stxa %g0, [%l7] ASI_DMMU
249 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
252 2: and %l0, (511 << 3), %g1
255 add %l0, (1 << 3), %l0
259 /* Now lock the TTE we created into ITLB-0 and DTLB-0,
260 * entry 15 (and maybe 14 too).
262 sethi %hi(KERNBASE), %g3
263 set (0 << 16) | (15 << 3), %g7
264 stxa %g3, [%l7] ASI_DMMU
266 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
268 stxa %g3, [%l7] ASI_IMMU
270 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
274 sethi %hi(_end), %g3 /* Check for bigkernel case */
275 or %g3, %lo(_end), %g3
276 srl %g3, 23, %g3 /* Check if _end > 8M */
278 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
279 sethi %hi(0x400000), %g3
280 or %g3, %lo(0x400000), %g3
281 add %g5, %g3, %g5 /* New tte data */
282 andn %g5, (_PAGE_G), %g5
283 sethi %hi(KERNBASE+0x400000), %g3
284 or %g3, %lo(KERNBASE+0x400000), %g3
285 set (0 << 16) | (14 << 3), %g7
286 stxa %g3, [%l7] ASI_DMMU
288 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
290 stxa %g3, [%l7] ASI_IMMU
292 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
296 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
300 1: set sun4u_init, %g2
305 /* Typically PROM has already enabled both MMU's and both on-chip
306 * caches, but we do it here anyway just to be paranoid.
308 mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1
309 stxa %g1, [%g0] ASI_LSU_CONTROL
313 * Make sure we are in privileged mode, have address masking,
314 * using the ordinary globals and have enabled floating
317 * Again, typically PROM has left %pil at 13 or similar, and
318 * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
320 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
323 spitfire_create_mappings:
324 /* %g5 holds the tlb data */
325 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
327 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
329 /* Base of physical memory cannot reliably be assumed to be
330 * at 0x0! Figure out where it happens to be. -DaveM
333 /* Put PADDR tlb data mask into %g3. */
334 sethi %uhi(_PAGE_PADDR_SF), %g3
335 or %g3, %ulo(_PAGE_PADDR_SF), %g3
337 sethi %hi(_PAGE_PADDR_SF), %g7
338 or %g7, %lo(_PAGE_PADDR_SF), %g7
341 /* Walk through entire ITLB, looking for entry which maps
342 * our %pc currently, stick PADDR from there into %g5 tlb data.
344 clr %l0 /* TLB entry walker. */
345 set 0x1fff, %l2 /* Page mask. */
347 andn %l3, %l2, %g2 /* vaddr comparator */
349 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
350 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
354 andn %g1, %l2, %g1 /* Get vaddr */
356 be,a,pn %xcc, spitfire_got_tlbentry
357 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
360 add %l0, (1 << 3), %l0
362 /* BUG() if we get here... */
365 spitfire_got_tlbentry:
366 /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
370 and %g1, %g3, %g1 /* Mask to just get paddr bits. */
371 set 0x5fff, %l3 /* Mask offset to get phys base. */
374 /* NOTE: We hold on to %g1 paddr base as we need it below to lock
375 * NOTE: the PROM cif code into the TLB.
378 or %g5, %g1, %g5 /* Or it into TAG being built. */
380 clr %l0 /* TLB entry walker. */
381 sethi %hi(KERNBASE), %g3 /* 4M lower limit */
382 sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */
383 mov TLB_TAG_ACCESS, %l7
385 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
386 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
390 andn %g1, %l2, %g1 /* Get vaddr */
396 stxa %g0, [%l7] ASI_IMMU
397 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
402 add %l0, (1 << 3), %l0
406 clr %l0 /* TLB entry walker. */
408 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
409 ldxa [%l0] ASI_DTLB_TAG_READ, %g1
413 andn %g1, %l2, %g1 /* Get vaddr */
419 stxa %g0, [%l7] ASI_DMMU
420 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
425 add %l0, (1 << 3), %l0
430 /* PROM never puts any TLB entries into the MMU with the lock bit
431 * set. So we gladly use tlb entry 63 for KERNBASE. And maybe 62 too.
434 sethi %hi(KERNBASE), %g3
436 stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */
437 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
439 stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */
440 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
444 sethi %hi(_end), %g3 /* Check for bigkernel case */
445 or %g3, %lo(_end), %g3
446 srl %g3, 23, %g3 /* Check if _end > 8M */
448 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
449 sethi %hi(0x400000), %g3
450 or %g3, %lo(0x400000), %g3
451 add %g5, %g3, %g5 /* New tte data */
452 andn %g5, (_PAGE_G), %g5
453 sethi %hi(KERNBASE+0x400000), %g3
454 or %g3, %lo(KERNBASE+0x400000), %g3
456 stxa %g3, [%l7] ASI_DMMU
457 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
459 stxa %g3, [%l7] ASI_IMMU
460 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
464 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
474 mov PRIMARY_CONTEXT, %g7
475 stxa %g0, [%g7] ASI_DMMU
478 mov SECONDARY_CONTEXT, %g7
479 stxa %g0, [%g7] ASI_DMMU
482 /* We are now safely (we hope) in Nucleus context (0), rewrite
483 * the KERNBASE TTE's so they no longer have the global bit set.
484 * Don't forget to setup TAG_ACCESS first 8-)
486 mov TLB_TAG_ACCESS, %g2
487 stxa %g3, [%g2] ASI_IMMU
488 stxa %g3, [%g2] ASI_DMMU
491 BRANCH_IF_ANY_CHEETAH(g1,g5,cheetah_tlb_fixup)
493 ba,pt %xcc, spitfire_tlb_fixup
497 set (0 << 16) | (15 << 3), %g7
498 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g0
499 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
500 andn %g1, (_PAGE_G), %g1
501 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
504 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g0
505 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
506 andn %g1, (_PAGE_G), %g1
507 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
510 /* Kill instruction prefetch queues. */
514 mov 2, %g2 /* Set TLB type to cheetah+. */
515 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g5,g7,1f)
517 mov 1, %g2 /* Set TLB type to cheetah. */
519 1: sethi %hi(tlb_type), %g5
520 stw %g2, [%g5 + %lo(tlb_type)]
522 /* Patch copy/page operations to cheetah optimized versions. */
523 call cheetah_patch_copyops
525 call cheetah_patch_cachetlbops
528 ba,pt %xcc, tlb_fixup_done
533 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
534 andn %g1, (_PAGE_G), %g1
535 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
538 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
539 andn %g1, (_PAGE_G), %g1
540 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
543 /* Kill instruction prefetch queues. */
547 /* Set TLB type to spitfire. */
549 sethi %hi(tlb_type), %g5
550 stw %g2, [%g5 + %lo(tlb_type)]
553 sethi %hi(init_thread_union), %g6
554 or %g6, %lo(init_thread_union), %g6
555 ldx [%g6 + TI_TASK], %g4
559 #if 0 /* We don't do it like this anymore, but for historical hack value
560 * I leave this snippet here to show how crazy we can be sometimes. 8-)
563 /* Setup "Linux Current Register", thanks Sun 8-) */
566 /* Blackbird errata workaround. See commentary in
567 * smp.c:smp_percpu_timer_interrupt() for more
573 99: wr %g6, %g0, %pic
579 sllx %g5, THREAD_SHIFT, %g5
580 sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
588 sethi %hi(__bss_start), %o0
589 or %o0, %lo(__bss_start), %o0
591 or %o1, %lo(_end), %o1
595 mov %l6, %o1 ! OpenPROM stack
597 mov %l7, %o0 ! OpenPROM cif handler
604 /* IMPORTANT NOTE: Whenever making changes here, check
605 * trampoline.S as well. -jj */
607 setup_tba: /* i0 = is_starfire */
611 sethi %hi(prom_tba), %o1
612 or %o1, %lo(prom_tba), %o1
615 /* Setup "Linux" globals 8-) */
618 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate
619 sethi %hi(sparc64_ttable_tl0), %g5
623 /* Set up MMU globals */
624 wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
626 /* Set fixed globals used by dTLB miss handler. */
627 #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
628 #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
631 stxa %g0, [%g1] ASI_DMMU
634 sethi %uhi(KERN_HIGHBITS), %g2
635 or %g2, %ulo(KERN_HIGHBITS), %g2
637 or %g2, KERN_LOWBITS, %g2
639 BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base)
640 ba,pt %xcc, spitfire_vpte_base
644 sethi %uhi(VPTE_BASE_CHEETAH), %g3
645 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
650 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
651 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
659 /* Kill PROM timer */
660 sethi %hi(0x80000000), %o2
662 wr %o2, 0, %tick_cmpr
664 BRANCH_IF_ANY_CHEETAH(o2,o3,1f)
669 /* Disable STICK_INT interrupts. */
671 sethi %hi(0x80000000), %o2
675 /* Ok, we're done setting up all the state our trap mechanims needs,
676 * now get back into normal globals and let the PROM know what is up.
679 wrpr %g0, %g0, %wstate
680 wrpr %o1, PSTATE_IE, %pstate
682 call init_irqwork_curcpu
685 sethi %hi(sparc64_ttable_tl0), %g5
686 call prom_set_trap_table
690 or %o1, PSTATE_IE, %o1
697 * The following skips make sure the trap table in ttable.S is aligned
698 * on a 32K boundary as required by the v9 specs for TBA register.
701 .skip 0x2000 + _start - sparc64_boot_end
702 bootup_user_stack_end:
706 /* This is just a hack to fool make depend config.h discovering
707 strategy: As the .S files below need config.h, but
708 make depend does not find it for them, we include config.h
718 .globl swapper_pg_dir
724 #include "winfixup.S"
727 /* This is just anal retentiveness on my part... */
732 .globl prom_tba, tlb_type
734 tlb_type: .word 0 /* Must NOT end up in BSS */
735 .section ".fixup",#alloc,#execinstr
739 restore %g0, -EFAULT, %o0