aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/head.S
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-10-12 15:22:46 -0400
committerDavid S. Miller <davem@davemloft.net>2005-10-12 15:22:46 -0400
commitc9c10830740df1b5e7848d6fbb68c93a73e8f7cd (patch)
treeb614058c3291ebccb996b27cee9b709956df7791 /arch/sparc64/kernel/head.S
parentd8e998c58a870770905495a1d45ebf7285b5b1c5 (diff)
[SPARC64]: Fix boot failures on SunBlade-150
The sequence to move over to the Linux trap tables from the firmware ones needs to be more air tight. It turns out that to be %100 safe we do need to be able to translate OBP mappings in our TLB miss handlers early. In order not to eat up a lot of kernel image memory with static page tables, just use the translations array in the OBP TLB miss handlers. That solves the bulk of the problem. Furthermore, to make sure the OBP TLB miss path will work even before the fixed MMU globals are loaded, explicitly load %g1 to TLB_SFSR at the beginning of the i-TLB and d-TLB miss handlers. To ease the OBP TLB miss walking of the prom_trans[] array, we sort it then delete all of the non-OBP entries in there (for example, there are entries for the kernel image itself which we're not interested in at all). We also save about 32K of kernel image size with this change. Not a bad side effect :-) There are still some reasons why trampoline.S can't use the setup_trap_table() yet. The most noteworthy are: 1) OBP boots secondary processors with non-bias'd stack for some reason. This is easily fixed by using a small bootup stack in the kernel image explicitly for this purpose. 2) Doing a firmware call via the normal C call prom_set_trap_table() goes through the whole OBP enter/exit sequence that saves and restores OBP and Linux kernel state in the MMUs. This path unfortunately does a "flush %g6" while loading up the OBP locked TLB entries for the firmware call. If we setup the %g6 in the trampoline.S code properly, that is in the PAGE_OFFSET linear mapping, but we're not on the kernel trap table yet so those addresses won't translate properly. One idea is to do a by-hand firmware call like we do in the early bootup code and elsewhere here in trampoline.S But this fails as well, as aparently the secondary processors are not booted with OBP's special locked TLB entries loaded. These are necessary for the firwmare to processes TLB misses correctly up until the point where we take over the trap table. This does need to be resolved at some point. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r--arch/sparc64/kernel/head.S61
1 files changed, 26 insertions, 35 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 4c942f71184d..b49dcd4504b0 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -28,19 +28,14 @@
28#include <asm/mmu.h> 28#include <asm/mmu.h>
29 29
30/* This section from from _start to sparc64_boot_end should fit into 30/* This section from from _start to sparc64_boot_end should fit into
31 * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space 31 * 0x0000000000404000 to 0x0000000000408000.
32 * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
33 * 0x0000.0000.0040.6000 and empty_bad_page, which is from
34 * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
35 */ 32 */
36
37 .text 33 .text
38 .globl start, _start, stext, _stext 34 .globl start, _start, stext, _stext
39_start: 35_start:
40start: 36start:
41_stext: 37_stext:
42stext: 38stext:
43bootup_user_stack:
44! 0x0000000000404000 39! 0x0000000000404000
45 b sparc64_boot 40 b sparc64_boot
46 flushw /* Flush register file. */ 41 flushw /* Flush register file. */
@@ -392,31 +387,30 @@ tlb_fixup_done:
392 * former does use this code, the latter does not yet due 387 * former does use this code, the latter does not yet due
393 * to some complexities. That should be fixed up at some 388 * to some complexities. That should be fixed up at some
394 * point. 389 * point.
390 *
391 * There used to be enormous complexity wrt. transferring
392 * over from the firwmare's trap table to the Linux kernel's.
393 * For example, there was a chicken & egg problem wrt. building
394 * the OBP page tables, yet needing to be on the Linux kernel
395 * trap table (to translate PAGE_OFFSET addresses) in order to
396 * do that.
397 *
398 * We now handle OBP tlb misses differently, via linear lookups
399 * into the prom_trans[] array. So that specific problem no
400 * longer exists. Yet, unfortunately there are still some issues
401 * preventing trampoline.S from using this code... ho hum.
395 */ 402 */
396 .globl setup_trap_table 403 .globl setup_trap_table
397setup_trap_table: 404setup_trap_table:
398 save %sp, -192, %sp 405 save %sp, -192, %sp
399 406
400 /* Force interrupts to be disabled. Transferring over to 407 /* Force interrupts to be disabled. */
401 * the Linux trap table is a very delicate operation.
402 * Until we are actually on the Linux trap table, we cannot
403 * get the PAGE_OFFSET linear mappings translated. We need
404 * that mapping to be setup in order to initialize the firmware
405 * page tables.
406 *
407 * So there is this window of time, from the return from
408 * prom_set_trap_table() until inherit_prom_mappings_post()
409 * (in arch/sparc64/mm/init.c) completes, during which no
410 * firmware address space accesses can be made.
411 */
412 rdpr %pstate, %o1 408 rdpr %pstate, %o1
413 andn %o1, PSTATE_IE, %o1 409 andn %o1, PSTATE_IE, %o1
414 wrpr %o1, 0x0, %pstate 410 wrpr %o1, 0x0, %pstate
415 wrpr %g0, 15, %pil 411 wrpr %g0, 15, %pil
416 412
417 /* Ok, now make the final valid firmware call to jump over 413 /* Make the firmware call to jump over to the Linux trap table. */
418 * to the Linux trap table.
419 */
420 call prom_set_trap_table 414 call prom_set_trap_table
421 sethi %hi(sparc64_ttable_tl0), %o0 415 sethi %hi(sparc64_ttable_tl0), %o0
422 416
@@ -540,15 +534,21 @@ setup_tba: /* i0 = is_starfire */
540 534
541 ret 535 ret
542 restore 536 restore
537sparc64_boot_end:
538
539#include "systbls.S"
540#include "ktlb.S"
541#include "etrap.S"
542#include "rtrap.S"
543#include "winfixup.S"
544#include "entry.S"
543 545
544/* 546/*
545 * The following skips make sure the trap table in ttable.S is aligned 547 * The following skip makes sure the trap table in ttable.S is aligned
546 * on a 32K boundary as required by the v9 specs for TBA register. 548 * on a 32K boundary as required by the v9 specs for TBA register.
547 */ 549 */
548sparc64_boot_end: 5501:
549 .skip 0x2000 + _start - sparc64_boot_end 551 .skip 0x4000 + _start - 1b
550bootup_user_stack_end:
551 .skip 0x2000
552 552
553#ifdef CONFIG_SBUS 553#ifdef CONFIG_SBUS
554/* This is just a hack to fool make depend config.h discovering 554/* This is just a hack to fool make depend config.h discovering
@@ -560,15 +560,6 @@ bootup_user_stack_end:
560! 0x0000000000408000 560! 0x0000000000408000
561 561
562#include "ttable.S" 562#include "ttable.S"
563#include "systbls.S"
564#include "ktlb.S"
565#include "etrap.S"
566#include "rtrap.S"
567#include "winfixup.S"
568#include "entry.S"
569
570 /* This is just anal retentiveness on my part... */
571 .align 16384
572 563
573 .data 564 .data
574 .align 8 565 .align 8