diff options
Diffstat (limited to 'arch/sparc/kernel/head.S')
-rw-r--r-- | arch/sparc/kernel/head.S | 160 |
1 files changed, 130 insertions, 30 deletions
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 5e620e568..eea3528bf 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -1,13 +1,15 @@ -/* $Id: head.S,v 1.70 1996/10/31 06:28:29 davem Exp $ +/* $Id: head.S,v 1.81 1997/04/16 07:15:48 davem Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Peter Zaitcev (Zaitcev@ipmce.su) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ #include <linux/version.h> #include <linux/config.h> +#include <linux/init.h> #include <asm/cprefix.h> #include <asm/head.h> @@ -18,6 +20,7 @@ #include <asm/page.h> #include <asm/kdebug.h> #include <asm/winmacro.h> +#include <asm/errno.h> .data /* @@ -65,10 +68,6 @@ sun4e_notsup: .asciz "Sparc-Linux sun4e support does not exist\n\n" .align 4 -sun4u_notsup: - .asciz "Sparc-Linux sun4u support does not exist\n\n" - .align 4 - /* The Sparc trap table, bootloader gives us control at _start. */ .text .globl start, _stext, _start, __stext @@ -162,7 +161,7 @@ t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9 t_getcc:GETCC_TRAP /* Get Condition Codes */ t_setcc:SETCC_TRAP /* Set Condition Codes */ t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) -t_bada7:INDIRECT_SOLARIS_SYSCALL(156) +t_slowi:INDIRECT_SOLARIS_SYSCALL(156) t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) @@ -408,7 +407,7 @@ C_LABEL(cpu3_stack): .skip 0x2000 */ .globl C_LABEL(bootup_user_stack) .globl C_LABEL(bootup_kernel_stack) - .globl C_LABEL(pg0) + .globl C_LABEL(pg0), C_LABEL(pg1), C_LABEL(pg2), C_LABEL(pg3) .globl C_LABEL(empty_bad_page) .globl C_LABEL(empty_bad_page_table) .globl C_LABEL(empty_zero_page) @@ -417,6 +416,9 @@ C_LABEL(bootup_user_stack): .skip 0x2000 C_LABEL(bootup_kernel_stack): .skip 0x2000 C_LABEL(swapper_pg_dir): .skip 0x1000 C_LABEL(pg0): .skip 0x1000 +C_LABEL(pg1): .skip 0x1000 +C_LABEL(pg2): .skip 0x1000 +C_LABEL(pg3): .skip 0x1000 C_LABEL(empty_bad_page): .skip 0x1000 C_LABEL(empty_bad_page_table): .skip 0x1000 C_LABEL(empty_zero_page): .skip 0x1000 @@ -472,8 +474,11 @@ current_pc: 1: mov %o7, %g3 -got_pc: - mov %g4, %o7 /* Previous %o7. */ +#ifndef CONFIG_AP1000 + tst %o0 + be no_sun4u_here +#endif + mov %g4, %o7 /* Previous %o7. */ mov %o0, %l0 ! stash away romvec mov %o0, %g7 ! put it here too @@ -737,6 +742,10 @@ go_to_highmem: jmpl %g1, %g0 nop +/* The code above should be at beginning and we have to take care about + * short jumps, as branching to .text.init section from .text is usually + * impossible */ + __INIT /* Acquire boot time privileged register values, this will help debugging. * I figure out and store nwindows and nwindowsm1 later on. */ @@ -852,7 +861,22 @@ got_prop: nop sun4m_init: - /* All sun4m processors can do hw mul/div/rem, patch 'em. */ + /* XXX Fucking Cypress... */ + lda [%g0] ASI_M_MMUREGS, %g5 + srl %g5, 28, %g4 + + cmp %g4, 1 + bne 1f + srl %g5, 24, %g4 + + and %g4, 0xf, %g4 + cmp %g4, 7 /* This would be a HyperSparc. */ + + bne 2f + nop + +1: + #define PATCH_IT(dst, src) \ set (dst), %g5; \ set (src), %g4; \ @@ -902,7 +926,7 @@ sun4m_init: * clear them so we don't get magic faults later on. */ /* This sucks, apparently this makes Vikings call prom panic, will fix later */ - +2: rd %psr, %o1 srl %o1, 28, %o1 ! Get a type of the CPU @@ -950,8 +974,8 @@ sun4c_continue_boot: mov 0, %fp /* And for good luck */ /* Zero out our BSS section. */ - set C_LABEL(edata) , %o0 ! First address of BSS - set C_LABEL(end) , %o1 ! Last address of BSS + set C_LABEL(__bss_start) , %o0 ! First address of BSS + set C_LABEL(end) , %o1 ! Last address of BSS add %o0, 0x1, %o0 1: stb %g0, [%o0] @@ -967,8 +991,8 @@ sun4c_continue_boot: st %g6, [%g2] set C_LABEL(bootup_kernel_stack), %g3 - st %g3, [%g6 + TASK_KSTACK_PG] - st %g0, [%g6 + THREAD_UMASK] + st %g3, [%g6 + AOFF_task_kernel_stack_page] + st %g0, [%g6 + AOFF_task_tss + AOFF_thread_uwinmask] /* Compute NWINDOWS and stash it away. Now uses %wim trick explained * in the V8 manual. Ok, this method seems to work, Sparc is cool... @@ -1029,16 +1053,9 @@ sun4c_continue_boot: PATCH_INSN(rtrap_7win_patch4, rtrap_patch4) PATCH_INSN(rtrap_7win_patch5, rtrap_patch5) -#ifdef __SMP__ + /* Patch for killing user windows from the register file. */ + PATCH_INSN(kuw_patch1_7win, kuw_patch1) - /* Patch for returning from an ipi... */ - PATCH_INSN(rirq_7win_patch1, rirq_patch1) - PATCH_INSN(rirq_7win_patch2, rirq_patch2) - PATCH_INSN(rirq_7win_patch3, rirq_patch3) - PATCH_INSN(rirq_7win_patch4, rirq_patch4) - PATCH_INSN(rirq_7win_patch5, rirq_patch5) - -#endif /* Now patch the kernel window flush sequences. * This saves 2 traps on every switch and fork. */ @@ -1116,19 +1133,97 @@ no_sun4e_here: b halt_me nop + __INITDATA + +sun4u_1: + .asciz "finddevice" + .align 4 +sun4u_2: + .asciz "/chosen" + .align 4 +sun4u_3: + .asciz "getprop" + .align 4 +sun4u_4: + .asciz "stdout" + .align 4 +sun4u_5: + .asciz "write" + .align 4 +sun4u_6: + .asciz "\n\rOn sun4u you have to use UltraLinux (64bit) kernel\n\rand not a 32bit sun4[cdem] version\n\r\n\r" +sun4u_6e: + .align 4 +sun4u_7: + .asciz "exit" + .align 8 +sun4u_a1: + .word 0, sun4u_1, 0, 1, 0, 1, 0, sun4u_2, 0 +sun4u_r1: + .word 0 +sun4u_a2: + .word 0, sun4u_3, 0, 4, 0, 1, 0 +sun4u_i2: + .word 0, 0, sun4u_4, 0, sun4u_1, 0, 8, 0 +sun4u_r2: + .word 0 +sun4u_a3: + .word 0, sun4u_5, 0, 3, 0, 1, 0 +sun4u_i3: + .word 0, 0, sun4u_6, 0, sun4u_6e - sun4u_6 - 1, 0 +sun4u_r3: + .word 0 +sun4u_a4: + .word 0, sun4u_7, 0, 0, 0, 0 +sun4u_r4: + + __INIT no_sun4u_here: - ld [%g7 + 0x68], %o1 - set sun4u_notsup, %o0 - call %o1 - nop - b halt_me - nop + set sun4u_a1, %o0 + set current_pc, %l2 + cmp %l2, %g3 + be 1f + mov %o4, %l0 + sub %g3, %l2, %l6 + add %o0, %l6, %o0 + mov %o0, %l4 + mov sun4u_r4 - sun4u_a1, %l3 + ld [%l4], %l5 +2: + add %l4, 4, %l4 + cmp %l5, %l2 + add %l5, %l6, %l5 + bgeu,a 3f + st %l5, [%l4 - 4] +3: + subcc %l3, 4, %l3 + bne 2b + ld [%l4], %l5 +1: + call %l0 + mov %o0, %l1 + ld [%l1 + (sun4u_r1 - sun4u_a1)], %o1 + add %l1, (sun4u_a2 - sun4u_a1), %o0 + call %l0 + st %o1, [%o0 + (sun4u_i2 - sun4u_a2)] + + ld [%l1 + (sun4u_1 - sun4u_a1)], %o1 + add %l1, (sun4u_a3 - sun4u_a1), %o0 + call %l0 + st %o1, [%o0 + (sun4u_i3 - sun4u_a3)] + + call %l0 + add %l1, (sun4u_a4 - sun4u_a1), %o0 + + /* Not reached */ halt_me: ld [%g7 + 0x74], %o0 call %o0 ! Get us out of here... nop ! Apparently Solaris is better. +/* Ok, now we continue in the .data/.text sections */ + .data .align 4 @@ -1172,3 +1267,8 @@ C_LABEL(lvl14_save): .word 0 .word t_irq14 + .section ".fixup",#alloc,#execinstr + .globl __ret_efault +__ret_efault: + ret + restore %g0, -EFAULT, %o0 |