summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r--arch/sparc64/kernel/head.S255
1 files changed, 130 insertions, 125 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 3844c24c3..0ed975aff 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.31 1997/05/30 22:35:28 davem Exp $
+/* $Id: head.S,v 1.43 1997/07/07 03:05:25 davem Exp $
* head.S: Initial boot code for the Sparc64 port of Linux.
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -8,20 +8,25 @@
*/
#include <linux/version.h>
+#include <linux/errno.h>
+#include <asm/asm_offsets.h>
+#include <asm/asi.h>
#include <asm/pstate.h>
#include <asm/ptrace.h>
#include <asm/spitfire.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/errno.h>
+#include <asm/signal.h>
+#include <asm/processor.h>
#include <asm/lsu.h>
#include <asm/head.h>
/* This section from from _start to sparc64_boot_end should fit into
- * 0xffff.f800.0000.4000 to 0xffff.f800.0000.8000 and will be sharing space
- * with bootup_user_stack, which is from 0xffff.f800.0000.4000 to
- * 0xffff.f800.0000.6000 and bootup_kernel_stack, which is from
- * 0xffff.f800.0000.6000 to 0xffff.f800.0000.8000.
+ * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
+ * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
+ * 0x0000.0000.0040.6000 and bootup_kernel_stack, which is from
+ * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
*/
.text
@@ -31,7 +36,7 @@ start:
_stext:
stext:
bootup_user_stack:
-! 0xfffff80000004000
+! 0x0000000000404000
b sparc64_boot
flushw /* Flush register file. */
@@ -41,10 +46,11 @@ bootup_user_stack:
*/
.global root_flags, ram_flags, root_dev
.global ramdisk_image, ramdisk_size
+ .globl silo_args
.ascii "HdrS"
.word LINUX_VERSION_CODE
- .half 0x0201 /* HdrS version */
+ .half 0x0202 /* HdrS version */
root_flags:
.half 1
root_dev:
@@ -55,7 +61,8 @@ ramdisk_image:
.word 0
ramdisk_size:
.word 0
- .xword reboot_command
+ .xword reboot_command
+ .xword bootstr_len
/* We must be careful, 32-bit OpenBOOT will get confused if it
* tries to save away a register window to a 64-bit kernel
@@ -80,26 +87,7 @@ sparc64_boot:
* Again, typically PROM has left %pil at 13 or similar, and
* (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
*/
- wrpr %g0, 0xf, %pil /* Interrupts off. */
- wrpr %g0, (PSTATE_PRIV|PSTATE_PEF), %pstate
-
- /* Check if we are mapped where we expect to be in virtual
- * memory. The Solaris /boot elf format bootloader
- * will peek into our elf header and load us where
- * we want to be, otherwise we have to re-map.
- */
-current_pc:
- rd %pc, %g3
- sethi %uhi(KERNBASE), %g4
- sllx %g4, 32, %g4
-
- /* Check the run time program counter. */
-
- set current_pc, %g5
- add %g5, %g4, %g5
- cmp %g3, %g5
- be %xcc, sun4u_init
- nop
+ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
create_mappings:
/* %g5 holds the tlb data */
@@ -136,15 +124,10 @@ create_mappings:
cmp %g1, %g2
be,a,pn %xcc, got_tlbentry
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
- cmp %l1, (63 << 3)
+ cmp %l0, (63 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
-boot_failed:
- /* Debugging 8-) */
- set 0xdeadbeef, %g1
- t 0x11
-
got_tlbentry:
/* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
nop
@@ -159,33 +142,73 @@ got_tlbentry:
or %g5, %g1, %g5 /* Or it into TAG being built. */
+ clr %l0 /* TLB entry walker. */
+ sethi %hi(KERNBASE), %g3 /* 4M lower limit */
+ sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */
+ mov TLB_TAG_ACCESS, %l7
+1:
+ /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
+ ldxa [%l0] ASI_ITLB_TAG_READ, %g1
+ nop
+ nop
+ nop
+ andn %g1, %l2, %g1 /* Get vaddr */
+ cmp %g1, %g3
+ blu,pn %xcc, 2f
+ cmp %g1, %g7
+ bgeu,pn %xcc, 2f
+ nop
+ stxa %g0, [%l7] ASI_IMMU
+ stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
+2:
+ cmp %l0, (63 << 3)
+ blu,pt %xcc, 1b
+ add %l0, (1 << 3), %l0
+
+ nop; nop; nop
+
+ clr %l0 /* TLB entry walker. */
+1:
+ /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
+ ldxa [%l0] ASI_DTLB_TAG_READ, %g1
+ nop
+ nop
+ nop
+ andn %g1, %l2, %g1 /* Get vaddr */
+ cmp %g1, %g3
+ blu,pn %xcc, 2f
+ cmp %g1, %g7
+ bgeu,pn %xcc, 2f
+ nop
+ stxa %g0, [%l7] ASI_DMMU
+ stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
+2:
+ cmp %l0, (63 << 3)
+ blu,pt %xcc, 1b
+ add %l0, (1 << 3), %l0
+
+ nop; nop; nop
+
+
/* PROM never puts any TLB entries into the MMU with the lock bit
- * set. So we gladly use tlb entry 63 for KERNBASE, 62 for
- * boot time locked PROM CIF handler page, we remove the locked
- * bit for the CIF page in paging_init().
+ * set. So we gladly use tlb entry 63 for KERNBASE.
*/
- mov TLB_TAG_ACCESS, %g3
- mov (63 << 3), %g7
- stxa %g4, [%g3] ASI_IMMU /* KERNBASE into TLB TAG */
- stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
- membar #Sync
- /* Same for DTLB */
- stxa %g4, [%g3] ASI_DMMU /* KERNBASE into TLB TAG */
+ sethi %hi(KERNBASE), %g3
+ mov (63 << 3), %g7
+ stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */
stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
membar #Sync
-
- /* Kill instruction prefetch queues. */
- flush %g4
+ stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */
+ stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
membar #Sync
-
- ba,pt %xcc, go_to_highmem
+ flush %g3
+ membar #Sync
+ ba,pt %xcc, 1f
nop
-
-go_to_highmem:
- /* Now do a non-relative jump so that PC is in high-memory */
+1:
set sun4u_init, %g2
- jmpl %g2 + %g4, %g0
+ jmpl %g2 + %g0, %g0
nop
sun4u_init:
@@ -198,42 +221,16 @@ sun4u_init:
stxa %g0, [%g7] ASI_DMMU
membar #Sync
- /* The lock bit has to be removed from this page later on,
- * but before firing up init we will use PROM a lot, so we
- * lock it there now...
- */
-
- /* Compute PROM CIF interface page TTE. */
- sethi %hi(__p1275_loc), %g7
- or %g7, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W | _PAGE_L), %g7
- sethi %uhi(_PAGE_VALID), %g5
- sethi %hi(0x8000), %g3
- sllx %g5, 32, %g5
- mov TLB_TAG_ACCESS, %g6
- or %g5, %g7, %g5
- add %g5, %g1, %g5 /* Add in physbase. */
-
- mov (62 << 3), %g7 /* TLB entry 62 */
- stxa %g3, [%g6] ASI_IMMU /* CIF page into TLB TAG */
- stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
- membar #Sync
-
- /* Same for DTLB */
- stxa %g3, [%g6] ASI_DMMU /* CIF page into TLB TAG */
- stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
- membar #Sync
-
- /* Kill instruction prefetch queues. */
- flush %g3
- membar #Sync
+ sethi %uhi(PAGE_OFFSET), %g4
+ sllx %g4, 32, %g4
/* We are now safely (we hope) in Nucleus context (0), rewrite
* the KERNBASE TTE's so they no longer have the global bit set.
* Don't forget to setup TAG_ACCESS first 8-)
*/
mov TLB_TAG_ACCESS, %g2
- stxa %g4, [%g2] ASI_IMMU
- stxa %g4, [%g2] ASI_DMMU
+ stxa %g3, [%g2] ASI_IMMU
+ stxa %g3, [%g2] ASI_DMMU
mov (63 << 3), %g7
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
@@ -247,30 +244,22 @@ sun4u_init:
membar #Sync
/* Kill instruction prefetch queues. */
- flush %g4
+ flush %g3
membar #Sync
- /* Compute the number of windows in this machine
- * store this in nwindows and nwindowsm1
- */
- rdpr %ver, %g1 /* Get VERSION register. */
- sethi %hi(nwindows), %g2
- and %g1, VERS_MAXWIN, %g5
- or %g2,%lo(nwindows),%g2
- add %g5, 1, %g6
- add %g2, (nwindows - nwindowsm1), %g3
- stx %g6, [%g2 + %g4]
- stx %g5, [%g3 + %g4]
-
sethi %hi(init_task_union), %g6
or %g6, %lo(init_task_union), %g6
- add %g6, %g4, %g6 ! g6 usage is fixed as well
mov %sp, %l6
mov %o4, %l7
+#if 0 /* We don't do it like this anymore, but for historical hack value
+ * I leave this snippet here to show how crazy we can be sometimes. 8-)
+ */
+
/* Setup "Linux Current Register", thanks Sun 8-) */
wr %g0, 0x1, %pcr
wr %g6, 0x0, %pic
+#endif
mov 1, %g5
sllx %g5, (PAGE_SHIFT + 1), %g5
@@ -291,23 +280,19 @@ sun4u_init:
add %l1, %l2, %l1
andn %l1, %l2, %l1
add %l2, 1, %l2
- add %l0, %g4, %o0
+ add %l0, %g0, %o0
1:
- clr %o1
- sethi %hi(PAGE_SIZE), %o2
- or %o2, %lo(PAGE_SIZE), %o2
- call __memset
+ mov %l2, %o1
+ call __bzero
add %l0, %l2, %l0
cmp %l0, %l1
blu,pt %xcc, 1b
- add %l0, %g4, %o0
+ add %l0, %g0, %o0
/* Now clear empty_zero_page */
- clr %o1
- sethi %hi(PAGE_SIZE), %o2
- or %o2, %lo(PAGE_SIZE), %o2
- call __memset
- mov %g4, %o0
+ mov %l2, %o1
+ call __bzero
+ mov %g3, %o0
mov %l6, %o1 ! OpenPROM stack
call prom_init
@@ -320,36 +305,45 @@ sun4u_init:
.globl setup_tba
setup_tba:
+ save %sp, -160, %sp
+
+ rdpr %tba, %g7
+ sethi %hi(prom_tba), %o1
+ or %o1, %lo(prom_tba), %o1
+ stx %g7, [%o1]
+
+ /* Setup "Linux" globals 8-) */
+ rdpr %pstate, %o1
+ mov %g6, %o2
+ wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate
sethi %hi(sparc64_ttable_tl0), %g5
- add %g5, %g4, %g5
wrpr %g5, %tba
+ mov %o2, %g6
/* Set up MMU globals */
- rdpr %pstate, %o1
- wrpr %o1, PSTATE_MG, %pstate
+ wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
/* PGD/PMD offset mask, used by TLB miss handlers. */
sethi %hi(0x1ff8), %g2
or %g2, %lo(0x1ff8), %g2
/* Kernel PGDIR used by TLB miss handlers. */
- mov %o0, %g6
+ mov %i0, %g6
/* To catch bootup bugs, this is user PGDIR for TLB miss handlers. */
clr %g7
/* Setup Interrupt globals */
- wrpr %o1, PSTATE_IG, %pstate
- sethi %uhi(ivector_to_mask), %g4
- or %g4, %ulo(ivector_to_mask), %g4
+ wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate
sethi %hi(ivector_to_mask), %g5
- or %g5, %lo(ivector_to_mask), %g5
- or %g5, %g4, %g1 /* IVECTOR table */
+ or %g5, %lo(ivector_to_mask), %g1 /* IVECTOR table */
mov 0x40, %g2 /* INTR data 0 register */
- andn %o1, PSTATE_IE, %o1
+ /* Ok, we're done setting up all the state our trap mechanims needs,
+ * now get back into normal globals and let the PROM know what it up.
+ */
wrpr %g0, %g0, %wstate
- wrpr %o1, %g0, %pstate
+ wrpr %o1, PSTATE_IE, %pstate
/* Zap TSB BASE to zero with TSB_size==1. */
mov TSB_REG, %o4
@@ -359,8 +353,16 @@ setup_tba:
membar #Sync
- retl
- nop
+ sethi %hi(sparc64_ttable_tl0), %g5
+ call prom_set_trap_table
+ mov %g5, %o0
+
+ rdpr %pstate, %o1
+ or %o1, PSTATE_IE, %o1
+ wrpr %o1, 0, %pstate
+
+ ret
+ restore
sparc64_boot_end:
.skip 0x2000 + _start - sparc64_boot_end
@@ -369,18 +371,21 @@ bootup_user_stack_end:
bootup_kernel_stack:
.skip 0x2000
-! 0xfffff80000008000
+! 0x0000000000408000
#include "ttable.S"
+#include "etrap.S"
+#include "rtrap.S"
+#include "winfixup.S"
+#include "entry.S"
/* This is just anal retentiveness on my part... */
.align 16384
.data
.align 8
- .globl nwindows, nwindowsm1
-nwindows: .xword 0
-nwindowsm1: .xword 0
+ .globl prom_tba
+prom_tba: .xword 0
.section ".fixup",#alloc,#execinstr
.globl __ret_efault
__ret_efault: