diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-09 05:52:44 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:12:03 -0500 |
commit | d82ace7dc4073b090a55b9740700e32b9a9ae302 (patch) | |
tree | d5aa8e10664b05bbfe31eacf95e2066c03cab102 /arch/sparc64/mm/init.c | |
parent | 1d2f1f90a1e004b0c1b8a73ed4394a93f09104b3 (diff) |
[SPARC64]: Detect sun4v early in boot process.
We look for "SUNW,sun4v" in the 'compatible' property
of the root OBP device tree node.
Protect every %ver register access, to make sure it is
not touched on sun4v, as %ver is hyperprivileged there.
Lock kernel TLB entries using hypervisor calls instead of
calls into OBP.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/mm/init.c')
-rw-r--r-- | arch/sparc64/mm/init.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 6504d6eb5372..e602b857071a 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
@@ -514,6 +514,29 @@ static void __init read_obp_translations(void) | |||
514 | } | 514 | } |
515 | } | 515 | } |
516 | 516 | ||
517 | static void __init hypervisor_tlb_lock(unsigned long vaddr, | ||
518 | unsigned long pte, | ||
519 | unsigned long mmu) | ||
520 | { | ||
521 | register unsigned long func asm("%o0"); | ||
522 | register unsigned long arg0 asm("%o1"); | ||
523 | register unsigned long arg1 asm("%o2"); | ||
524 | register unsigned long arg2 asm("%o3"); | ||
525 | register unsigned long arg3 asm("%o4"); | ||
526 | |||
527 | func = HV_FAST_MMU_MAP_PERM_ADDR; | ||
528 | arg0 = vaddr; | ||
529 | arg1 = 0; | ||
530 | arg2 = pte; | ||
531 | arg3 = mmu; | ||
532 | __asm__ __volatile__("ta 0x80" | ||
533 | : "=&r" (func), "=&r" (arg0), | ||
534 | "=&r" (arg1), "=&r" (arg2), | ||
535 | "=&r" (arg3) | ||
536 | : "0" (func), "1" (arg0), "2" (arg1), | ||
537 | "3" (arg2), "4" (arg3)); | ||
538 | } | ||
539 | |||
517 | static void __init remap_kernel(void) | 540 | static void __init remap_kernel(void) |
518 | { | 541 | { |
519 | unsigned long phys_page, tte_vaddr, tte_data; | 542 | unsigned long phys_page, tte_vaddr, tte_data; |
@@ -527,19 +550,30 @@ static void __init remap_kernel(void) | |||
527 | 550 | ||
528 | kern_locked_tte_data = tte_data; | 551 | kern_locked_tte_data = tte_data; |
529 | 552 | ||
530 | /* Now lock us into the TLBs via OBP. */ | 553 | /* Now lock us into the TLBs via Hypervisor or OBP. */ |
531 | prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); | 554 | if (tlb_type == hypervisor) { |
532 | prom_itlb_load(tlb_ent, tte_data, tte_vaddr); | 555 | hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_DMMU); |
533 | if (bigkernel) { | 556 | hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_IMMU); |
534 | tlb_ent -= 1; | 557 | if (bigkernel) { |
535 | prom_dtlb_load(tlb_ent, | 558 | tte_vaddr += 0x400000; |
536 | tte_data + 0x400000, | 559 | tte_data += 0x400000; |
537 | tte_vaddr + 0x400000); | 560 | hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_DMMU); |
538 | prom_itlb_load(tlb_ent, | 561 | hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_IMMU); |
539 | tte_data + 0x400000, | 562 | } |
540 | tte_vaddr + 0x400000); | 563 | } else { |
564 | prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); | ||
565 | prom_itlb_load(tlb_ent, tte_data, tte_vaddr); | ||
566 | if (bigkernel) { | ||
567 | tlb_ent -= 1; | ||
568 | prom_dtlb_load(tlb_ent, | ||
569 | tte_data + 0x400000, | ||
570 | tte_vaddr + 0x400000); | ||
571 | prom_itlb_load(tlb_ent, | ||
572 | tte_data + 0x400000, | ||
573 | tte_vaddr + 0x400000); | ||
574 | } | ||
575 | sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; | ||
541 | } | 576 | } |
542 | sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; | ||
543 | if (tlb_type == cheetah_plus) { | 577 | if (tlb_type == cheetah_plus) { |
544 | sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | | 578 | sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | |
545 | CTX_CHEETAH_PLUS_NUC); | 579 | CTX_CHEETAH_PLUS_NUC); |