diff options
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r-- | arch/sparc64/kernel/head.S | 191 |
1 files changed, 109 insertions, 82 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 89406f9649a9..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. */ |
@@ -191,8 +186,9 @@ prom_boot_mapping_phys_low: | |||
191 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 | 186 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 |
192 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" | 187 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" |
193 | stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache | 188 | stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache |
194 | srlx %l0, 22, %l3 | 189 | /* PAGE align */ |
195 | sllx %l3, 22, %l3 | 190 | srlx %l0, 13, %l3 |
191 | sllx %l3, 13, %l3 | ||
196 | stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC | 192 | stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC |
197 | stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 | 193 | stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 |
198 | stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 | 194 | stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 |
@@ -211,6 +207,9 @@ prom_boot_mapping_phys_low: | |||
211 | ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high | 207 | ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high |
212 | stx %l2, [%l4 + 0x0] | 208 | stx %l2, [%l4 + 0x0] |
213 | ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low | 209 | ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low |
210 | /* 4MB align */ | ||
211 | srlx %l3, 22, %l3 | ||
212 | sllx %l3, 22, %l3 | ||
214 | stx %l3, [%l4 + 0x8] | 213 | stx %l3, [%l4 + 0x8] |
215 | 214 | ||
216 | /* Leave service as-is, "call-method" */ | 215 | /* Leave service as-is, "call-method" */ |
@@ -325,23 +324,7 @@ cheetah_tlb_fixup: | |||
325 | 1: sethi %hi(tlb_type), %g1 | 324 | 1: sethi %hi(tlb_type), %g1 |
326 | stw %g2, [%g1 + %lo(tlb_type)] | 325 | stw %g2, [%g1 + %lo(tlb_type)] |
327 | 326 | ||
328 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) | 327 | /* Patch copy/page operations to cheetah optimized versions. */ |
329 | ba,pt %xcc, 2f | ||
330 | nop | ||
331 | |||
332 | 1: /* Patch context register writes to support nucleus page | ||
333 | * size correctly. | ||
334 | */ | ||
335 | call cheetah_plus_patch_etrap | ||
336 | nop | ||
337 | call cheetah_plus_patch_rtrap | ||
338 | nop | ||
339 | call cheetah_plus_patch_fpdis | ||
340 | nop | ||
341 | call cheetah_plus_patch_winfixup | ||
342 | nop | ||
343 | |||
344 | 2: /* Patch copy/page operations to cheetah optimized versions. */ | ||
345 | call cheetah_patch_copyops | 328 | call cheetah_patch_copyops |
346 | nop | 329 | nop |
347 | call cheetah_patch_copy_page | 330 | call cheetah_patch_copy_page |
@@ -398,32 +381,78 @@ tlb_fixup_done: | |||
398 | nop | 381 | nop |
399 | /* Not reached... */ | 382 | /* Not reached... */ |
400 | 383 | ||
401 | /* IMPORTANT NOTE: Whenever making changes here, check | 384 | /* This is meant to allow the sharing of this code between |
402 | * trampoline.S as well. -jj */ | 385 | * boot processor invocation (via setup_tba() below) and |
403 | .globl setup_tba | 386 | * secondary processor startup (via trampoline.S). The |
404 | setup_tba: /* i0 = is_starfire */ | 387 | * former does use this code, the latter does not yet due |
405 | save %sp, -160, %sp | 388 | * to some complexities. That should be fixed up at some |
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. | ||
402 | */ | ||
403 | .globl setup_trap_table | ||
404 | setup_trap_table: | ||
405 | save %sp, -192, %sp | ||
406 | 406 | ||
407 | rdpr %tba, %g7 | 407 | /* Force interrupts to be disabled. */ |
408 | sethi %hi(prom_tba), %o1 | 408 | rdpr %pstate, %o1 |
409 | or %o1, %lo(prom_tba), %o1 | 409 | andn %o1, PSTATE_IE, %o1 |
410 | stx %g7, [%o1] | 410 | wrpr %o1, 0x0, %pstate |
411 | wrpr %g0, 15, %pil | ||
412 | |||
413 | /* Make the firmware call to jump over to the Linux trap table. */ | ||
414 | call prom_set_trap_table | ||
415 | sethi %hi(sparc64_ttable_tl0), %o0 | ||
416 | |||
417 | /* Start using proper page size encodings in ctx register. */ | ||
418 | sethi %hi(sparc64_kern_pri_context), %g3 | ||
419 | ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 | ||
420 | mov PRIMARY_CONTEXT, %g1 | ||
421 | stxa %g2, [%g1] ASI_DMMU | ||
422 | membar #Sync | ||
423 | |||
424 | /* The Linux trap handlers expect various trap global registers | ||
425 | * to be setup with some fixed values. So here we set these | ||
426 | * up very carefully. These globals are: | ||
427 | * | ||
428 | * Alternate Globals (PSTATE_AG): | ||
429 | * | ||
430 | * %g6 --> current_thread_info() | ||
431 | * | ||
432 | * MMU Globals (PSTATE_MG): | ||
433 | * | ||
434 | * %g1 --> TLB_SFSR | ||
435 | * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB | | ||
436 | * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) | ||
437 | * ^ 0xfffff80000000000) | ||
438 | * (this %g2 value is used for computing the PAGE_OFFSET kernel | ||
439 | * TLB entries quickly, the virtual address of the fault XOR'd | ||
440 | * with this %g2 value is the PTE to load into the TLB) | ||
441 | * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE | ||
442 | * | ||
443 | * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()): | ||
444 | * | ||
445 | * %g6 --> __irq_work[smp_processor_id()] | ||
446 | */ | ||
411 | 447 | ||
412 | /* Setup "Linux" globals 8-) */ | ||
413 | rdpr %pstate, %o1 | 448 | rdpr %pstate, %o1 |
414 | mov %g6, %o2 | 449 | mov %g6, %o2 |
415 | wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate | 450 | wrpr %o1, PSTATE_AG, %pstate |
416 | sethi %hi(sparc64_ttable_tl0), %g1 | ||
417 | wrpr %g1, %tba | ||
418 | mov %o2, %g6 | 451 | mov %o2, %g6 |
419 | 452 | ||
420 | /* Set up MMU globals */ | ||
421 | wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate | ||
422 | |||
423 | /* Set fixed globals used by dTLB miss handler. */ | ||
424 | #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) | 453 | #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) |
425 | #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) | 454 | #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) |
426 | 455 | wrpr %o1, PSTATE_MG, %pstate | |
427 | mov TSB_REG, %g1 | 456 | mov TSB_REG, %g1 |
428 | stxa %g0, [%g1] ASI_DMMU | 457 | stxa %g0, [%g1] ASI_DMMU |
429 | membar #Sync | 458 | membar #Sync |
@@ -435,17 +464,17 @@ setup_tba: /* i0 = is_starfire */ | |||
435 | sllx %g2, 32, %g2 | 464 | sllx %g2, 32, %g2 |
436 | or %g2, KERN_LOWBITS, %g2 | 465 | or %g2, KERN_LOWBITS, %g2 |
437 | 466 | ||
438 | BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) | 467 | BRANCH_IF_ANY_CHEETAH(g3,g7,8f) |
439 | ba,pt %xcc, spitfire_vpte_base | 468 | ba,pt %xcc, 9f |
440 | nop | 469 | nop |
441 | 470 | ||
442 | cheetah_vpte_base: | 471 | 8: |
443 | sethi %uhi(VPTE_BASE_CHEETAH), %g3 | 472 | sethi %uhi(VPTE_BASE_CHEETAH), %g3 |
444 | or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 | 473 | or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 |
445 | ba,pt %xcc, 2f | 474 | ba,pt %xcc, 2f |
446 | sllx %g3, 32, %g3 | 475 | sllx %g3, 32, %g3 |
447 | 476 | ||
448 | spitfire_vpte_base: | 477 | 9: |
449 | sethi %uhi(VPTE_BASE_SPITFIRE), %g3 | 478 | sethi %uhi(VPTE_BASE_SPITFIRE), %g3 |
450 | or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 | 479 | or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 |
451 | sllx %g3, 32, %g3 | 480 | sllx %g3, 32, %g3 |
@@ -471,48 +500,55 @@ spitfire_vpte_base: | |||
471 | sllx %o2, 32, %o2 | 500 | sllx %o2, 32, %o2 |
472 | wr %o2, %asr25 | 501 | wr %o2, %asr25 |
473 | 502 | ||
474 | /* Ok, we're done setting up all the state our trap mechanims needs, | ||
475 | * now get back into normal globals and let the PROM know what is up. | ||
476 | */ | ||
477 | 2: | 503 | 2: |
478 | wrpr %g0, %g0, %wstate | 504 | wrpr %g0, %g0, %wstate |
479 | wrpr %o1, PSTATE_IE, %pstate | 505 | wrpr %o1, 0x0, %pstate |
480 | 506 | ||
481 | call init_irqwork_curcpu | 507 | call init_irqwork_curcpu |
482 | nop | 508 | nop |
483 | 509 | ||
484 | call prom_set_trap_table | 510 | /* Now we can turn interrupts back on. */ |
485 | sethi %hi(sparc64_ttable_tl0), %o0 | ||
486 | |||
487 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) | ||
488 | ba,pt %xcc, 2f | ||
489 | nop | ||
490 | |||
491 | 1: /* Start using proper page size encodings in ctx register. */ | ||
492 | sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 | ||
493 | mov PRIMARY_CONTEXT, %g1 | ||
494 | sllx %g3, 32, %g3 | ||
495 | sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 | ||
496 | or %g3, %g2, %g3 | ||
497 | stxa %g3, [%g1] ASI_DMMU | ||
498 | membar #Sync | ||
499 | |||
500 | 2: | ||
501 | rdpr %pstate, %o1 | 511 | rdpr %pstate, %o1 |
502 | or %o1, PSTATE_IE, %o1 | 512 | or %o1, PSTATE_IE, %o1 |
503 | wrpr %o1, 0, %pstate | 513 | wrpr %o1, 0, %pstate |
514 | wrpr %g0, 0x0, %pil | ||
515 | |||
516 | ret | ||
517 | restore | ||
518 | |||
519 | .globl setup_tba | ||
520 | setup_tba: /* i0 = is_starfire */ | ||
521 | save %sp, -192, %sp | ||
522 | |||
523 | /* The boot processor is the only cpu which invokes this | ||
524 | * routine, the other cpus set things up via trampoline.S. | ||
525 | * So save the OBP trap table address here. | ||
526 | */ | ||
527 | rdpr %tba, %g7 | ||
528 | sethi %hi(prom_tba), %o1 | ||
529 | or %o1, %lo(prom_tba), %o1 | ||
530 | stx %g7, [%o1] | ||
531 | |||
532 | call setup_trap_table | ||
533 | nop | ||
504 | 534 | ||
505 | ret | 535 | ret |
506 | 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" | ||
507 | 545 | ||
508 | /* | 546 | /* |
509 | * 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 |
510 | * 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. |
511 | */ | 549 | */ |
512 | sparc64_boot_end: | 550 | 1: |
513 | .skip 0x2000 + _start - sparc64_boot_end | 551 | .skip 0x4000 + _start - 1b |
514 | bootup_user_stack_end: | ||
515 | .skip 0x2000 | ||
516 | 552 | ||
517 | #ifdef CONFIG_SBUS | 553 | #ifdef CONFIG_SBUS |
518 | /* 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 |
@@ -524,15 +560,6 @@ bootup_user_stack_end: | |||
524 | ! 0x0000000000408000 | 560 | ! 0x0000000000408000 |
525 | 561 | ||
526 | #include "ttable.S" | 562 | #include "ttable.S" |
527 | #include "systbls.S" | ||
528 | #include "ktlb.S" | ||
529 | #include "etrap.S" | ||
530 | #include "rtrap.S" | ||
531 | #include "winfixup.S" | ||
532 | #include "entry.S" | ||
533 | |||
534 | /* This is just anal retentiveness on my part... */ | ||
535 | .align 16384 | ||
536 | 563 | ||
537 | .data | 564 | .data |
538 | .align 8 | 565 | .align 8 |