aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/head.S
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-10-10 19:12:13 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-10-10 19:12:13 -0400
commit5d8e1b181c4ad63e6ca90d51287b31afd400d2eb (patch)
tree555d79c07b00def9f5eab72431ae95ebd5af4f86 /arch/sparc64/kernel/head.S
parentf96c3bbe91117402f13119ce9e609db9087ed58f (diff)
[SPARC64]: Fix Ultra5, Ultra60, et al. boot failures.
On the boot processor, we need to do the move onto the Linux trap table a little bit differently else we'll take unhandlable faults in the firmware address space. Previously we would do the following: 1) Disable PSTATE_IE in %pstate. 2) Set %tba by hand to sparc64_ttable_tl0 3) Initialize alternate, mmu, and interrupt global trap registers. 4) Call prom_set_traptable() That doesn't work very well actually with the way we boot the kernel VM these days. It worked by luck on many systems because the firmware accesses for the prom_set_traptable() call happened to be loaded into the TLB already, something we cannot assume. So the new scheme is this: 1) Clear PSTATE_IE in %pstate and set %pil to 15 2) Call prom_set_traptable() 3) Initialize alternate, mmu, and interrupt global trap registers. and this works quite well. This sequence has been moved into a callable function in assembler named setup-trap_table(). The idea is that eventually trampoline.S can use this code as well. That isn't possible currently due to some complications, but eventually we should be able to do it. Thanks to Meelis Roos for the Ultra5 boot failure report. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r--arch/sparc64/kernel/head.S127
1 files changed, 91 insertions, 36 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 24340496cdd3..f1dcdf8f7433 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -382,32 +382,79 @@ tlb_fixup_done:
382 nop 382 nop
383 /* Not reached... */ 383 /* Not reached... */
384 384
385/* IMPORTANT NOTE: Whenever making changes here, check 385 /* This is meant to allow the sharing of this code between
386 * trampoline.S as well. -jj */ 386 * boot processor invocation (via setup_tba() below) and
387 .globl setup_tba 387 * secondary processor startup (via trampoline.S). The
388setup_tba: /* i0 = is_starfire */ 388 * former does use this code, the latter does not yet due
389 save %sp, -160, %sp 389 * to some complexities. That should be fixed up at some
390 * point.
391 */
392 .globl setup_trap_table
393setup_trap_table:
394 save %sp, -192, %sp
395
396 /* Force interrupts to be disabled. Transferring over to
397 * the Linux trap table is a very delicate operation.
398 * Until we are actually on the Linux trap table, we cannot
399 * get the PAGE_OFFSET linear mappings translated. We need
400 * that mapping to be setup in order to initialize the firmware
401 * page tables.
402 *
403 * So there is this window of time, from the return from
404 * prom_set_trap_table() until inherit_prom_mappings_post()
405 * (in arch/sparc64/mm/init.c) completes, during which no
406 * firmware address space accesses can be made.
407 */
408 rdpr %pstate, %o1
409 andn %o1, PSTATE_IE, %o1
410 wrpr %o1, 0x0, %pstate
411 wrpr %g0, 15, %pil
390 412
391 rdpr %tba, %g7 413 /* Ok, now make the final valid firmware call to jump over
392 sethi %hi(prom_tba), %o1 414 * to the Linux trap table.
393 or %o1, %lo(prom_tba), %o1 415 */
394 stx %g7, [%o1] 416 call prom_set_trap_table
417 sethi %hi(sparc64_ttable_tl0), %o0
418
419 /* Start using proper page size encodings in ctx register. */
420 sethi %hi(sparc64_kern_pri_context), %g3
421 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
422 mov PRIMARY_CONTEXT, %g1
423 stxa %g2, [%g1] ASI_DMMU
424 membar #Sync
425
426 /* The Linux trap handlers expect various trap global registers
427 * to be setup with some fixed values. So here we set these
428 * up very carefully. These globals are:
429 *
430 * Alternate Globals (PSTATE_AG):
431 *
432 * %g6 --> current_thread_info()
433 *
434 * MMU Globals (PSTATE_MG):
435 *
436 * %g1 --> TLB_SFSR
437 * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
438 * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
439 * ^ 0xfffff80000000000)
440 * (this %g2 value is used for computing the PAGE_OFFSET kernel
441 * TLB entries quickly, the virtual address of the fault XOR'd
442 * with this %g2 value is the PTE to load into the TLB)
443 * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
444 *
445 * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
446 *
447 * %g6 --> __irq_work[smp_processor_id()]
448 */
395 449
396 /* Setup "Linux" globals 8-) */
397 rdpr %pstate, %o1 450 rdpr %pstate, %o1
398 mov %g6, %o2 451 mov %g6, %o2
399 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate 452 wrpr %o1, PSTATE_AG, %pstate
400 sethi %hi(sparc64_ttable_tl0), %g1
401 wrpr %g1, %tba
402 mov %o2, %g6 453 mov %o2, %g6
403 454
404 /* Set up MMU globals */
405 wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
406
407 /* Set fixed globals used by dTLB miss handler. */
408#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) 455#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
409#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) 456#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
410 457 wrpr %o1, PSTATE_MG, %pstate
411 mov TSB_REG, %g1 458 mov TSB_REG, %g1
412 stxa %g0, [%g1] ASI_DMMU 459 stxa %g0, [%g1] ASI_DMMU
413 membar #Sync 460 membar #Sync
@@ -419,17 +466,17 @@ setup_tba: /* i0 = is_starfire */
419 sllx %g2, 32, %g2 466 sllx %g2, 32, %g2
420 or %g2, KERN_LOWBITS, %g2 467 or %g2, KERN_LOWBITS, %g2
421 468
422 BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) 469 BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
423 ba,pt %xcc, spitfire_vpte_base 470 ba,pt %xcc, 9f
424 nop 471 nop
425 472
426cheetah_vpte_base: 4738:
427 sethi %uhi(VPTE_BASE_CHEETAH), %g3 474 sethi %uhi(VPTE_BASE_CHEETAH), %g3
428 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 475 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
429 ba,pt %xcc, 2f 476 ba,pt %xcc, 2f
430 sllx %g3, 32, %g3 477 sllx %g3, 32, %g3
431 478
432spitfire_vpte_base: 4799:
433 sethi %uhi(VPTE_BASE_SPITFIRE), %g3 480 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
434 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 481 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
435 sllx %g3, 32, %g3 482 sllx %g3, 32, %g3
@@ -455,29 +502,37 @@ spitfire_vpte_base:
455 sllx %o2, 32, %o2 502 sllx %o2, 32, %o2
456 wr %o2, %asr25 503 wr %o2, %asr25
457 504
458 /* Ok, we're done setting up all the state our trap mechanims needs,
459 * now get back into normal globals and let the PROM know what is up.
460 */
4612: 5052:
462 wrpr %g0, %g0, %wstate 506 wrpr %g0, %g0, %wstate
463 wrpr %o1, PSTATE_IE, %pstate 507 wrpr %o1, 0x0, %pstate
464 508
465 call init_irqwork_curcpu 509 call init_irqwork_curcpu
466 nop 510 nop
467 511
468 call prom_set_trap_table 512 /* Now we can turn interrupts back on. */
469 sethi %hi(sparc64_ttable_tl0), %o0
470
471 /* Start using proper page size encodings in ctx register. */
472 sethi %hi(sparc64_kern_pri_context), %g3
473 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
474 mov PRIMARY_CONTEXT, %g1
475 stxa %g2, [%g1] ASI_DMMU
476 membar #Sync
477
478 rdpr %pstate, %o1 513 rdpr %pstate, %o1
479 or %o1, PSTATE_IE, %o1 514 or %o1, PSTATE_IE, %o1
480 wrpr %o1, 0, %pstate 515 wrpr %o1, 0, %pstate
516 wrpr %g0, 0x0, %pil
517
518 ret
519 restore
520
521 .globl setup_tba
522setup_tba: /* i0 = is_starfire */
523 save %sp, -192, %sp
524
525 /* The boot processor is the only cpu which invokes this
526 * routine, the other cpus set things up via trampoline.S.
527 * So save the OBP trap table address here.
528 */
529 rdpr %tba, %g7
530 sethi %hi(prom_tba), %o1
531 or %o1, %lo(prom_tba), %o1
532 stx %g7, [%o1]
533
534 call setup_trap_table
535 nop
481 536
482 ret 537 ret
483 restore 538 restore