1 /* $Id: head.S,v 1.82 2001/10/04 23:37:04 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/asm_offsets.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
56 .word LINUX_VERSION_CODE
57 .half 0x0203 /* HdrS version */
72 /* We must be careful, 32-bit OpenBOOT will get confused if it
73 * tries to save away a register window to a 64-bit kernel
74 * stack address. Flush all windows, disable interrupts,
75 * remap if necessary, jump onto kernel trap table, then kernel
76 * stack, or else we die.
78 * PROM entry point is on %o4
82 sethi %hi(0x003e0014), %g5
84 or %g5, %lo(0x003e0014), %g5
86 bne,pt %icc, spitfire_boot
90 mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
93 sethi %uhi(DCU_ME | DCU_RE | /*DCU_PE |*/ DCU_HPE | DCU_SPE | DCU_SL | DCU_WE), %g5
94 or %g5, %ulo(DCU_ME | DCU_RE | /*DCU_PE |*/ DCU_HPE | DCU_SPE | DCU_SL | DCU_WE), %g5
96 or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5
97 stxa %g5, [%g0] ASI_DCU_CONTROL_REG
100 mov TSB_EXTENSION_P, %g3
101 stxa %g0, [%g3] ASI_DMMU
102 stxa %g0, [%g3] ASI_IMMU
105 mov TSB_EXTENSION_S, %g3
106 stxa %g0, [%g3] ASI_DMMU
109 mov TSB_EXTENSION_N, %g3
110 stxa %g0, [%g3] ASI_DMMU
111 stxa %g0, [%g3] ASI_IMMU
114 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
117 /* Just like for Spitfire, we probe itlb-2 for a mapping which
118 * matches our current %pc. We take the physical address in
119 * that mapping and use it to make our own.
122 /* %g5 holds the tlb data */
123 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
125 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
127 /* Put PADDR tlb data mask into %g3. */
128 sethi %uhi(_PAGE_PADDR), %g3
129 or %g3, %ulo(_PAGE_PADDR), %g3
131 sethi %hi(_PAGE_PADDR), %g7
132 or %g7, %lo(_PAGE_PADDR), %g7
135 set 2 << 16, %l0 /* TLB entry walker. */
136 set 0x1fff, %l2 /* Page mask. */
138 andn %l3, %l2, %g2 /* vaddr comparator */
140 1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
144 be,pn %xcc, cheetah_got_tlbentry
146 and %l0, (127 << 3), %g1
149 add %l0, (1 << 3), %l0
151 cheetah_got_tlbentry:
152 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
158 /* Clear out any KERNBASE area entries. */
160 sethi %hi(KERNBASE), %g3
161 sethi %hi(KERNBASE<<1), %g7
162 mov TLB_TAG_ACCESS, %l7
164 /* First, check ITLB */
165 1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
173 stxa %g0, [%l7] ASI_IMMU
175 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
178 2: and %l0, (127 << 3), %g1
181 add %l0, (1 << 3), %l0
183 /* Next, check DTLB */
185 1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
193 stxa %g0, [%l7] ASI_DMMU
195 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
198 2: and %l0, (511 << 3), %g1
201 add %l0, (1 << 3), %l0
203 /* Now lock the TTE we created into ITLB-0 and DTLB-0,
206 sethi %hi(KERNBASE), %g3
207 set (0 << 16) | (15 << 3), %g7
208 stxa %g3, [%l7] ASI_DMMU
210 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
212 stxa %g3, [%l7] ASI_IMMU
214 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
221 1: set sun4u_init, %g2
226 /* Typically PROM has already enabled both MMU's and both on-chip
227 * caches, but we do it here anyway just to be paranoid.
229 mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1
230 stxa %g1, [%g0] ASI_LSU_CONTROL
234 * Make sure we are in privileged mode, have address masking,
235 * using the ordinary globals and have enabled floating
238 * Again, typically PROM has left %pil at 13 or similar, and
239 * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
241 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
244 spitfire_create_mappings:
245 /* %g5 holds the tlb data */
246 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
248 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
250 /* Base of physical memory cannot reliably be assumed to be
251 * at 0x0! Figure out where it happens to be. -DaveM
254 /* Put PADDR tlb data mask into %g3. */
255 sethi %uhi(_PAGE_PADDR_SF), %g3
256 or %g3, %ulo(_PAGE_PADDR_SF), %g3
258 sethi %hi(_PAGE_PADDR_SF), %g7
259 or %g7, %lo(_PAGE_PADDR_SF), %g7
262 /* Walk through entire ITLB, looking for entry which maps
263 * our %pc currently, stick PADDR from there into %g5 tlb data.
265 clr %l0 /* TLB entry walker. */
266 set 0x1fff, %l2 /* Page mask. */
268 andn %l3, %l2, %g2 /* vaddr comparator */
270 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
271 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
275 andn %g1, %l2, %g1 /* Get vaddr */
277 be,a,pn %xcc, spitfire_got_tlbentry
278 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
281 add %l0, (1 << 3), %l0
283 spitfire_got_tlbentry:
284 /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
288 and %g1, %g3, %g1 /* Mask to just get paddr bits. */
289 sub %g1, %g2, %g1 /* Get rid of %pc offset to get base. */
291 /* NOTE: We hold on to %g1 paddr base as we need it below to lock
292 * NOTE: the PROM cif code into the TLB.
295 or %g5, %g1, %g5 /* Or it into TAG being built. */
297 clr %l0 /* TLB entry walker. */
298 sethi %hi(KERNBASE), %g3 /* 4M lower limit */
299 sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */
300 mov TLB_TAG_ACCESS, %l7
302 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
303 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
307 andn %g1, %l2, %g1 /* Get vaddr */
313 stxa %g0, [%l7] ASI_IMMU
314 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
319 add %l0, (1 << 3), %l0
323 clr %l0 /* TLB entry walker. */
325 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
326 ldxa [%l0] ASI_DTLB_TAG_READ, %g1
330 andn %g1, %l2, %g1 /* Get vaddr */
336 stxa %g0, [%l7] ASI_DMMU
337 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
342 add %l0, (1 << 3), %l0
347 /* PROM never puts any TLB entries into the MMU with the lock bit
348 * set. So we gladly use tlb entry 63 for KERNBASE.
351 sethi %hi(KERNBASE), %g3
353 stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */
354 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
356 stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */
357 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
370 mov PRIMARY_CONTEXT, %g7
371 stxa %g0, [%g7] ASI_DMMU
374 mov SECONDARY_CONTEXT, %g7
375 stxa %g0, [%g7] ASI_DMMU
378 sethi %uhi(PAGE_OFFSET), %g4
381 /* We are now safely (we hope) in Nucleus context (0), rewrite
382 * the KERNBASE TTE's so they no longer have the global bit set.
383 * Don't forget to setup TAG_ACCESS first 8-)
385 mov TLB_TAG_ACCESS, %g2
386 stxa %g3, [%g2] ASI_IMMU
387 stxa %g3, [%g2] ASI_DMMU
391 sethi %hi(0x003e0014), %g5
393 or %g5, %lo(0x003e0014), %g5
395 bne,pt %icc, spitfire_tlb_fixup
399 set (0 << 16) | (15 << 3), %g7
400 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
401 andn %g1, (_PAGE_G), %g1
402 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
405 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
406 andn %g1, (_PAGE_G), %g1
407 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
410 /* Kill instruction prefetch queues. */
414 /* Set TLB type to cheetah. */
416 sethi %hi(tlb_type), %g5
417 stw %g2, [%g5 + %lo(tlb_type)]
419 /* Patch copy/page operations to cheetah optimized versions. */
420 call cheetah_patch_copyops
422 call cheetah_patch_pgcopyops
425 ba,pt %xcc, tlb_fixup_done
430 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
431 andn %g1, (_PAGE_G), %g1
432 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
435 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
436 andn %g1, (_PAGE_G), %g1
437 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
440 /* Kill instruction prefetch queues. */
444 /* Set TLB type to spitfire. */
446 sethi %hi(tlb_type), %g5
447 stw %g2, [%g5 + %lo(tlb_type)]
450 sethi %hi(init_task_union), %g6
451 or %g6, %lo(init_task_union), %g6
455 #if 0 /* We don't do it like this anymore, but for historical hack value
456 * I leave this snippet here to show how crazy we can be sometimes. 8-)
459 /* Setup "Linux Current Register", thanks Sun 8-) */
462 /* Blackbird errata workaround. See commentary in
463 * smp.c:smp_percpu_timer_interrupt() for more
469 99: wr %g6, %g0, %pic
475 sllx %g5, THREAD_SHIFT, %g5
476 sub %g5, (REGWIN_SZ + STACK_BIAS), %g5
484 sethi %hi(__bss_start), %o0
485 or %o0, %lo(__bss_start), %o0
487 or %o1, %lo(_end), %o1
491 mov %l6, %o1 ! OpenPROM stack
493 mov %l7, %o0 ! OpenPROM cif handler
500 /* IMPORTANT NOTE: Whenever making changes here, check
501 * trampoline.S as well. -jj */
503 setup_tba: /* i0 = is_starfire */
507 sethi %hi(prom_tba), %o1
508 or %o1, %lo(prom_tba), %o1
511 /* Setup "Linux" globals 8-) */
514 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate
515 sethi %hi(sparc64_ttable_tl0), %g5
519 /* Set up MMU globals */
520 wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
522 /* Set fixed globals used by dTLB miss handler. */
523 #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
524 #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
526 #define VPTE_BASE_SPITFIRE 0xfffffffe00000000
528 #define VPTE_BASE_CHEETAH VPTE_BASE_SPITFIRE
530 #define VPTE_BASE_CHEETAH 0xffe0000000000000
534 stxa %g0, [%g1] ASI_DMMU
537 sethi %uhi(KERN_HIGHBITS), %g2
538 or %g2, %ulo(KERN_HIGHBITS), %g2
540 or %g2, KERN_LOWBITS, %g2
543 sethi %hi(0x003e0014), %g7
545 or %g7, %lo(0x003e0014), %g7
550 sethi %uhi(VPTE_BASE_CHEETAH), %g3
551 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
555 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
556 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
563 #undef VPTE_BASE_SPITFIRE
564 #undef VPTE_BASE_CHEETAH
566 /* Setup Interrupt globals */
567 wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate
569 sethi %hi(__up_workvec), %g5
570 or %g5, %lo(__up_workvec), %g6
572 /* By definition of where we are, this is boot_cpu. */
573 brz,pt %i0, not_starfire
574 sethi %hi(0x1fff4000), %g1
575 or %g1, %lo(0x1fff4000), %g1
578 lduwa [%g1] ASI_PHYS_BYPASS_EC_E, %g1
579 b,pt %xcc, set_worklist
584 sethi %hi(0x003e0014), %g5
586 or %g7, %lo(0x003e0014), %g5
588 bne,pt %icc, not_cheetah
591 ldxa [%g0] ASI_SAFARI_CONFIG, %g1
593 ba,pt %xcc, set_worklist
594 and %g1, 0x3ff, %g1 ! 10bit Safari Agent ID
597 ldxa [%g0] ASI_UPA_CONFIG, %g1
601 /* In theory this is: &(cpu_data[boot_cpu_id].irq_worklists[0]) */
603 sethi %hi(cpu_data), %g5
604 or %g5, %lo(cpu_data), %g5
610 /* Kill PROM timer */
611 wr %g0, 0, %tick_cmpr
614 sethi %hi(0x003e0014), %g5
616 or %g7, %lo(0x003e0014), %g5
621 /* Disable STICK_INT interrupts. */
622 sethi %hi(0x80000000), %g1
626 /* Ok, we're done setting up all the state our trap mechanims needs,
627 * now get back into normal globals and let the PROM know what is up.
630 wrpr %g0, %g0, %wstate
631 wrpr %o1, PSTATE_IE, %pstate
633 sethi %hi(sparc64_ttable_tl0), %g5
634 call prom_set_trap_table
638 or %o1, PSTATE_IE, %o1
645 * The following skips make sure the trap table in ttable.S is aligned
646 * on a 32K boundary as required by the v9 specs for TBA register.
649 .skip 0x2000 + _start - sparc64_boot_end
650 bootup_user_stack_end:
654 /* This is just a hack to fool make depend config.h discovering
655 strategy: As the .S files below need config.h, but
656 make depend does not find it for them, we include config.h
666 .globl swapper_pg_dir
672 #include "winfixup.S"
675 /* This is just anal retentiveness on my part... */
682 .section ".fixup",#alloc,#execinstr
686 restore %g0, -EFAULT, %o0