diff options
-rw-r--r-- | arch/sparc/Kconfig | 56 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 43 | ||||
-rw-r--r-- | arch/sparc64/kernel/etrap.S | 51 | ||||
-rw-r--r-- | arch/sparc64/kernel/head.S | 33 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 23 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 8 | ||||
-rw-r--r-- | arch/sparc64/kernel/trampoline.S | 15 | ||||
-rw-r--r-- | arch/sparc64/kernel/winfixup.S | 33 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 182 |
9 files changed, 103 insertions, 341 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index aba05394d30..6537445dac0 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -25,62 +25,6 @@ source "init/Kconfig" menu "General machine setup" -config VT - bool - select INPUT - default y - ---help--- - If you say Y here, you will get support for terminal devices with - display and keyboard devices. These are called "virtual" because you - can run several virtual terminals (also called virtual consoles) on - one physical terminal. This is rather useful, for example one - virtual terminal can collect system messages and warnings, another - one can be used for a text-mode user session, and a third could run - an X session, all in parallel. Switching between virtual terminals - is done with certain key combinations, usually Alt-<function key>. - - The setterm command ("man setterm") can be used to change the - properties (such as colors or beeping) of a virtual terminal. The - man page console_codes(4) ("man console_codes") contains the special - character sequences that can be used to change those properties - directly. The fonts used on virtual terminals can be changed with - the setfont ("man setfont") command and the key bindings are defined - with the loadkeys ("man loadkeys") command. - - You need at least one virtual terminal device in order to make use - of your keyboard and monitor. Therefore, only people configuring an - embedded system would want to say N here in order to save some - memory; the only way to log into such a system is then via a serial - or network connection. - - If unsure, say Y, or else you won't be able to do much with your new - shiny Linux system :-) - -config VT_CONSOLE - bool - default y - ---help--- - The system console is the device which receives all kernel messages - and warnings and which allows logins in single user mode. If you - answer Y here, a virtual terminal (the device used to interact with - a physical terminal) can be used as system console. This is the most - common mode of operations, so you should say Y here unless you want - the kernel messages be output only to a serial port (in which case - you should say Y to "Console on serial port", below). - - If you do say Y here, by default the currently visible virtual - terminal (/dev/tty0) will be used as system console. You can change - that with a kernel command line option such as "console=tty3" which - would use the third virtual terminal as system console. (Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time.) - - If unsure, say Y. - -config HW_CONSOLE - bool - default y - config SMP bool "Symmetric multi-processing support (does not work on sun4/sun4c)" depends on BROKEN diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 2879b107292..f685035dbdb 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -97,8 +97,8 @@ do_fpdis: faddd %f0, %f2, %f4 fmuld %f0, %f2, %f6 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_1: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS + 0xc0, %g2 @@ -126,8 +126,8 @@ cplus_fptrap_insn_1: fzero %f34 ldxa [%g3] ASI_DMMU, %g5 add %g6, TI_FPREGS, %g1 -cplus_fptrap_insn_2: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS + 0x40, %g2 @@ -153,8 +153,8 @@ cplus_fptrap_insn_2: 3: mov SECONDARY_CONTEXT, %g3 add %g6, TI_FPREGS, %g1 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_3: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync mov 0x40, %g2 @@ -319,8 +319,8 @@ do_fptrap_after_fsr: stx %g3, [%g6 + TI_GSR] mov SECONDARY_CONTEXT, %g3 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_4: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS, %g2 @@ -341,33 +341,6 @@ cplus_fptrap_insn_4: ba,pt %xcc, etrap wr %g0, 0, %fprs -cplus_fptrap_1: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - - .globl cheetah_plus_patch_fpdis -cheetah_plus_patch_fpdis: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_fptrap_1), %o0 - lduw [%o0 + %lo(cplus_fptrap_1)], %o1 - - set cplus_fptrap_insn_1, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_2, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_3, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_4, %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop - /* The registers for cross calls will be: * * DATA 0: [low 32-bits] Address of function to call, jmp to this diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 50d2af1d98a..0d8eba21111 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -68,12 +68,8 @@ etrap_irq: wrpr %g3, 0, %otherwin wrpr %g2, 0, %wstate -cplus_etrap_insn_1: - sethi %hi(0), %g3 - sllx %g3, 32, %g3 -cplus_etrap_insn_2: - sethi %hi(0), %g2 - or %g3, %g2, %g3 + sethi %hi(sparc64_kern_pri_context), %g2 + ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 stxa %g3, [%l4] ASI_DMMU flush %l6 wr %g0, ASI_AIUS, %asi @@ -215,12 +211,8 @@ scetrap: rdpr %pil, %g2 mov PRIMARY_CONTEXT, %l4 wrpr %g3, 0, %otherwin wrpr %g2, 0, %wstate -cplus_etrap_insn_3: - sethi %hi(0), %g3 - sllx %g3, 32, %g3 -cplus_etrap_insn_4: - sethi %hi(0), %g2 - or %g3, %g2, %g3 + sethi %hi(sparc64_kern_pri_context), %g2 + ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 stxa %g3, [%l4] ASI_DMMU flush %l6 @@ -264,38 +256,3 @@ cplus_etrap_insn_4: #undef TASK_REGOFF #undef ETRAP_PSTATE1 - -cplus_einsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 -cplus_einsn_2: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - - .globl cheetah_plus_patch_etrap -cheetah_plus_patch_etrap: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_einsn_1), %o0 - sethi %hi(cplus_etrap_insn_1), %o2 - lduw [%o0 + %lo(cplus_einsn_1)], %o1 - or %o2, %lo(cplus_etrap_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - sethi %hi(cplus_etrap_insn_3), %o2 - or %o2, %lo(cplus_etrap_insn_3), %o2 - stw %o1, [%o2] - flush %o2 - - sethi %hi(cplus_einsn_2), %o0 - sethi %hi(cplus_etrap_insn_2), %o2 - lduw [%o0 + %lo(cplus_einsn_2)], %o1 - or %o2, %lo(cplus_etrap_insn_2), %o2 - stw %o1, [%o2] - flush %o2 - sethi %hi(cplus_etrap_insn_4), %o2 - or %o2, %lo(cplus_etrap_insn_4), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 89406f9649a..24340496cdd 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -325,23 +325,7 @@ cheetah_tlb_fixup: 1: sethi %hi(tlb_type), %g1 stw %g2, [%g1 + %lo(tlb_type)] - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) - ba,pt %xcc, 2f - nop - -1: /* Patch context register writes to support nucleus page - * size correctly. - */ - call cheetah_plus_patch_etrap - nop - call cheetah_plus_patch_rtrap - nop - call cheetah_plus_patch_fpdis - nop - call cheetah_plus_patch_winfixup - nop - -2: /* Patch copy/page operations to cheetah optimized versions. */ + /* Patch copy/page operations to cheetah optimized versions. */ call cheetah_patch_copyops nop call cheetah_patch_copy_page @@ -484,20 +468,13 @@ spitfire_vpte_base: call prom_set_trap_table sethi %hi(sparc64_ttable_tl0), %o0 - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) - ba,pt %xcc, 2f - nop - -1: /* Start using proper page size encodings in ctx register. */ - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 + /* Start using proper page size encodings in ctx register. */ + sethi %hi(sparc64_kern_pri_context), %g3 + ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 mov PRIMARY_CONTEXT, %g1 - sllx %g3, 32, %g3 - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - or %g3, %g2, %g3 - stxa %g3, [%g1] ASI_DMMU + stxa %g2, [%g1] ASI_DMMU membar #Sync -2: rdpr %pstate, %o1 or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index fafd227735f..ecfb42a69a4 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -256,9 +256,8 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 ldxa [%l7 + %l7] ASI_DMMU, %l0 -cplus_rtrap_insn_1: - sethi %hi(0), %l1 - sllx %l1, 32, %l1 + sethi %hi(sparc64_kern_pri_nuc_bits), %l1 + ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1 or %l0, %l1, %l0 stxa %l0, [%l7] ASI_DMMU flush %g6 @@ -345,21 +344,3 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5 wr %g0, FPRS_DU, %fprs ba,pt %xcc, rt_continue stb %l5, [%g6 + TI_FPDEPTH] - -cplus_rinsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 - - .globl cheetah_plus_patch_rtrap -cheetah_plus_patch_rtrap: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_rinsn_1), %o0 - sethi %hi(cplus_rtrap_insn_1), %o2 - lduw [%o0 + %lo(cplus_rinsn_1)], %o1 - or %o2, %lo(cplus_rtrap_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 4c9c8f24174..c1f34237cdf 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -187,17 +187,13 @@ int prom_callback(long *args) } if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { - unsigned long kernel_pctx = 0; - - if (tlb_type == cheetah_plus) - kernel_pctx |= (CTX_CHEETAH_PLUS_NUC | - CTX_CHEETAH_PLUS_CTX0); + extern unsigned long sparc64_kern_pri_context; /* Spitfire Errata #32 workaround */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ - : "r" (kernel_pctx), + : "r" (sparc64_kern_pri_context), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 89f2fcfcd66..9478551cb02 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -336,20 +336,13 @@ do_unlock: call init_irqwork_curcpu nop - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) - ba,pt %xcc, 2f - nop - -1: /* Start using proper page size encodings in ctx register. */ - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 + /* Start using proper page size encodings in ctx register. */ + sethi %hi(sparc64_kern_pri_context), %g3 + ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 mov PRIMARY_CONTEXT, %g1 - sllx %g3, 32, %g3 - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - or %g3, %g2, %g3 - stxa %g3, [%g1] ASI_DMMU + stxa %g2, [%g1] ASI_DMMU membar #Sync -2: rdpr %pstate, %o1 or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S index 99c809a1e5a..39160926267 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc64/kernel/winfixup.S @@ -16,23 +16,14 @@ .text set_pcontext: -cplus_winfixup_insn_1: - sethi %hi(0), %l1 + sethi %hi(sparc64_kern_pri_context), %l1 + ldx [%l1 + %lo(sparc64_kern_pri_context)], %l1 mov PRIMARY_CONTEXT, %g1 - sllx %l1, 32, %l1 -cplus_winfixup_insn_2: - sethi %hi(0), %g2 - or %l1, %g2, %l1 stxa %l1, [%g1] ASI_DMMU flush %g6 retl nop -cplus_wfinsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 -cplus_wfinsn_2: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - .align 32 /* Here are the rules, pay attention. @@ -395,23 +386,3 @@ window_dax_from_user_common: add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap clr %l6 - - - .globl cheetah_plus_patch_winfixup -cheetah_plus_patch_winfixup: - sethi %hi(cplus_wfinsn_1), %o0 - sethi %hi(cplus_winfixup_insn_1), %o2 - lduw [%o0 + %lo(cplus_wfinsn_1)], %o1 - or %o2, %lo(cplus_winfixup_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - - sethi %hi(cplus_wfinsn_2), %o0 - sethi %hi(cplus_winfixup_insn_2), %o2 - lduw [%o0 + %lo(cplus_wfinsn_2)], %o1 - or %o2, %lo(cplus_winfixup_insn_2), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 5db50524f20..0d2e967c720 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -133,6 +133,12 @@ extern unsigned int sparc_ramdisk_size; struct page *mem_map_zero __read_mostly; +unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly; + +unsigned long sparc64_kern_pri_context __read_mostly; +unsigned long sparc64_kern_pri_nuc_bits __read_mostly; +unsigned long sparc64_kern_sec_context __read_mostly; + int bigkernel = 0; /* XXX Tune this... */ @@ -362,6 +368,7 @@ struct linux_prom_translation { unsigned long data; }; static struct linux_prom_translation prom_trans[512] __initdata; +static unsigned int prom_trans_ents __initdata; extern unsigned long prom_boot_page; extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); @@ -375,57 +382,7 @@ unsigned long kern_locked_tte_data; unsigned long prom_pmd_phys __read_mostly; unsigned int swapper_pgd_zero __read_mostly; -/* Allocate power-of-2 aligned chunks from the end of the - * kernel image. Return physical address. - */ -static inline unsigned long early_alloc_phys(unsigned long size) -{ - unsigned long base; - - BUILD_BUG_ON(size & (size - 1)); - - kern_size = (kern_size + (size - 1)) & ~(size - 1); - base = kern_base + kern_size; - kern_size += size; - - return base; -} - -static inline unsigned long load_phys32(unsigned long pa) -{ - unsigned long val; - - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=&r" (val) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); - - return val; -} - -static inline unsigned long load_phys64(unsigned long pa) -{ - unsigned long val; - - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=&r" (val) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); - - return val; -} - -static inline void store_phys32(unsigned long pa, unsigned long val) -{ - __asm__ __volatile__("stwa %0, [%1] %2" - : /* no outputs */ - : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); -} - -static inline void store_phys64(unsigned long pa, unsigned long val) -{ - __asm__ __volatile__("stxa %0, [%1] %2" - : /* no outputs */ - : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); -} +static pmd_t *prompmd __read_mostly; #define BASE_PAGE_SIZE 8192 @@ -435,34 +392,28 @@ static inline void store_phys64(unsigned long pa, unsigned long val) */ unsigned long prom_virt_to_phys(unsigned long promva, int *error) { - unsigned long pmd_phys = (prom_pmd_phys + - ((promva >> 23) & 0x7ff) * sizeof(pmd_t)); - unsigned long pte_phys; - pmd_t pmd_ent; - pte_t pte_ent; + pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff); + pte_t *ptep; unsigned long base; - pmd_val(pmd_ent) = load_phys32(pmd_phys); - if (pmd_none(pmd_ent)) { + if (pmd_none(*pmdp)) { if (error) *error = 1; return 0; } - - pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; - pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t); - pte_val(pte_ent) = load_phys64(pte_phys); - if (!pte_present(pte_ent)) { + ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff); + if (!pte_present(*ptep)) { if (error) *error = 1; return 0; } if (error) { *error = 0; - return pte_val(pte_ent); + return pte_val(*ptep); } - base = pte_val(pte_ent) & _PAGE_PADDR; - return (base + (promva & (BASE_PAGE_SIZE - 1))); + base = pte_val(*ptep) & _PAGE_PADDR; + + return base + (promva & (BASE_PAGE_SIZE - 1)); } /* The obp translations are saved based on 8k pagesize, since obp can @@ -475,25 +426,20 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig unsigned long vaddr; for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { - unsigned long val, pte_phys, pmd_phys; - pmd_t pmd_ent; - int i; - - pmd_phys = (prom_pmd_phys + - (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t))); - pmd_val(pmd_ent) = load_phys32(pmd_phys); - if (pmd_none(pmd_ent)) { - pte_phys = early_alloc_phys(BASE_PAGE_SIZE); - - for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++) - store_phys64(pte_phys+i*sizeof(pte_t),0); + unsigned long val; + pmd_t *pmd; + pte_t *pte; - pmd_val(pmd_ent) = pte_phys >> 11UL; - store_phys32(pmd_phys, pmd_val(pmd_ent)); + pmd = prompmd + ((vaddr >> 23) & 0x7ff); + if (pmd_none(*pmd)) { + pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE, + PAGE_SIZE); + if (!pte) + prom_halt(); + memset(pte, 0, BASE_PAGE_SIZE); + pmd_set(pmd, pte); } - - pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; - pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t)); + pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff); val = data; @@ -501,7 +447,8 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig if (tlb_type == spitfire) val &= ~0x0003fe0000000000UL; - store_phys64(pte_phys, val | _PAGE_MODIFIED); + set_pte_at(&init_mm, vaddr, pte, + __pte(val | _PAGE_MODIFIED)); data += BASE_PAGE_SIZE; } @@ -514,13 +461,17 @@ static inline int in_obp_range(unsigned long vaddr) } #define OBP_PMD_SIZE 2048 -static void __init build_obp_pgtable(int prom_trans_ents) +static void __init build_obp_pgtable(void) { unsigned long i; - prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE); - for (i = 0; i < OBP_PMD_SIZE; i += 4) - store_phys32(prom_pmd_phys + i, 0); + prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE); + if (!prompmd) + prom_halt(); + + memset(prompmd, 0, OBP_PMD_SIZE); + + prom_pmd_phys = __pa(prompmd); for (i = 0; i < prom_trans_ents; i++) { unsigned long start, end; @@ -540,7 +491,7 @@ static void __init build_obp_pgtable(int prom_trans_ents) /* Read OBP translations property into 'prom_trans[]'. * Return the number of entries. */ -static int __init read_obp_translations(void) +static void __init read_obp_translations(void) { int n, node; @@ -561,8 +512,10 @@ static int __init read_obp_translations(void) prom_printf("prom_mappings: Couldn't get property.\n"); prom_halt(); } + n = n / sizeof(struct linux_prom_translation); - return n; + + prom_trans_ents = n; } static void __init remap_kernel(void) @@ -582,28 +535,38 @@ static void __init remap_kernel(void) prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); prom_itlb_load(tlb_ent, tte_data, tte_vaddr); if (bigkernel) { - prom_dtlb_load(tlb_ent - 1, + tlb_ent -= 1; + prom_dtlb_load(tlb_ent, tte_data + 0x400000, tte_vaddr + 0x400000); - prom_itlb_load(tlb_ent - 1, + prom_itlb_load(tlb_ent, tte_data + 0x400000, tte_vaddr + 0x400000); } + sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; + if (tlb_type == cheetah_plus) { + sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | + CTX_CHEETAH_PLUS_NUC); + sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC; + sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0; + } } -static void __init inherit_prom_mappings(void) -{ - int n; - n = read_obp_translations(); - build_obp_pgtable(n); +static void __init inherit_prom_mappings_pre(void) +{ + read_obp_translations(); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); remap_kernel(); prom_printf("done.\n"); +} +static void __init inherit_prom_mappings_post(void) +{ + build_obp_pgtable(); register_prom_callbacks(); } @@ -788,8 +751,8 @@ void inherit_locked_prom_mappings(int save_p) } } if (tlb_type == spitfire) { - int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel; - for (i = 0; i < high; i++) { + int high = sparc64_highest_unlocked_tlb_ent; + for (i = 0; i <= high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ @@ -877,9 +840,9 @@ void inherit_locked_prom_mappings(int save_p) } } } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel; + int high = sparc64_highest_unlocked_tlb_ent; - for (i = 0; i < high; i++) { + for (i = 0; i <= high; i++) { unsigned long data; data = cheetah_get_ldtlb_data(i); @@ -1556,8 +1519,7 @@ void __init paging_init(void) swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); - /* Inherit non-locked OBP mappings. */ - inherit_prom_mappings(); + inherit_prom_mappings_pre(); /* Ok, we can use our TLB miss and window trap handlers safely. * We need to do a quick peek here to see if we are on StarFire @@ -1568,15 +1530,23 @@ void __init paging_init(void) extern void setup_tba(int); setup_tba(this_is_starfire); } - - inherit_locked_prom_mappings(1); - __flush_tlb_all(); + /* Everything from this point forward, until we are done with + * inherit_prom_mappings_post(), must complete successfully + * without calling into the firmware. The firwmare page tables + * have not been built, but we are running on the Linux kernel's + * trap table. + */ + /* Setup bootmem... */ pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail); + inherit_prom_mappings_post(); + + inherit_locked_prom_mappings(1); + #ifdef CONFIG_DEBUG_PAGEALLOC kernel_physical_mapping_init(); #endif |