diff options
author | David S. Miller <davem@davemloft.net> | 2005-10-12 15:22:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-10-12 15:22:46 -0400 |
commit | c9c10830740df1b5e7848d6fbb68c93a73e8f7cd (patch) | |
tree | b614058c3291ebccb996b27cee9b709956df7791 /arch/sparc64/kernel/head.S | |
parent | d8e998c58a870770905495a1d45ebf7285b5b1c5 (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.S | 61 |
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: |
40 | start: | 36 | start: |
41 | _stext: | 37 | _stext: |
42 | stext: | 38 | stext: |
43 | bootup_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 |
397 | setup_trap_table: | 404 | setup_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 |
537 | sparc64_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 | */ |
548 | sparc64_boot_end: | 550 | 1: |
549 | .skip 0x2000 + _start - sparc64_boot_end | 551 | .skip 0x4000 + _start - 1b |
550 | bootup_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 |