diff options
-rw-r--r-- | arch/sparc64/kernel/head.S | 127 |
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 |
388 | setup_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 | ||
393 | setup_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 | ||
426 | cheetah_vpte_base: | 473 | 8: |
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 | ||
432 | spitfire_vpte_base: | 479 | 9: |
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 | */ | ||
461 | 2: | 505 | 2: |
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 | ||
522 | setup_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 |