Loading arch/sparc64/kernel/smp.c +0 −4 Original line number Diff line number Diff line Loading @@ -116,14 +116,10 @@ static void smp_setup_percpu_timer(void); static volatile unsigned long callin_flag = 0; extern void inherit_locked_prom_mappings(int save_p); void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); inherit_locked_prom_mappings(0); __local_per_cpu_offset = __per_cpu_offset(cpuid); __flush_tlb_all(); Loading arch/sparc64/kernel/tsb.S +0 −7 Original line number Diff line number Diff line Loading @@ -178,13 +178,6 @@ __tsb_context_switch: brz %o2, 9f nop /* We use entry 61 for this locked entry. This is the spitfire * TLB entry number, and luckily cheetah masks the value with * 15 ending us up with entry 13 which is what we want in that * case too. * * XXX Interactions with prom_world()... */ sethi %hi(sparc64_highest_unlocked_tlb_ent), %o4 mov TLB_TAG_ACCESS, %g1 lduw [%o4 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 Loading arch/sparc64/mm/init.c +10 −285 Original line number Diff line number Diff line Loading @@ -555,294 +555,12 @@ static void __init inherit_prom_mappings(void) prom_printf("done.\n"); } static int prom_ditlb_set; struct prom_tlb_entry { int tlb_ent; unsigned long tlb_tag; unsigned long tlb_data; }; struct prom_tlb_entry prom_itlb[16], prom_dtlb[16]; void prom_world(int enter) { unsigned long pstate; int i; if (!enter) set_fs((mm_segment_t) { get_thread_current_ds() }); if (!prom_ditlb_set) return; /* Make sure the following runs atomically. */ __asm__ __volatile__("flushw\n\t" "rdpr %%pstate, %0\n\t" "wrpr %0, %1, %%pstate" : "=r" (pstate) : "i" (PSTATE_IE)); if (enter) { /* Install PROM world. */ for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_itlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_litlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); } } } else { for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); else cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, 0x0UL); else cheetah_put_litlb_data(prom_itlb[i].tlb_ent, 0x0UL); } } } __asm__ __volatile__("wrpr %0, 0, %%pstate" : : "r" (pstate)); } void inherit_locked_prom_mappings(int save_p) { int i; int dtlb_seen = 0; int itlb_seen = 0; /* Fucking losing PROM has more mappings in the TLB, but * it (conveniently) fails to mention any of these in the * translations property. The only ones that matter are * the locked PROM tlb entries, so we impose the following * irrecovable rule on the PROM, it is allowed 8 locked * entries in the ITLB and 8 in the DTLB. * * Supposedly the upper 16GB of the address space is * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED * SOMEWHERE!!!!!!!!!!!!!!!!! Furthermore the entire interface * used between the client program and the firmware on sun5 * systems to coordinate mmu mappings is also COMPLETELY * UNDOCUMENTED!!!!!! Thanks S(t)un! */ if (save_p) { for (i = 0; i < 16; i++) { prom_itlb[i].tlb_ent = -1; prom_dtlb[i].tlb_ent = -1; } } if (tlb_type == spitfire) { int high = sparc64_highest_unlocked_tlb_ent; for (i = 0; i <= high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no cheetah+ * page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); data = spitfire_get_dtlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); tag = spitfire_get_dtlb_tag(i); if (save_p) { prom_dtlb[dtlb_seen].tlb_ent = i; prom_dtlb[dtlb_seen].tlb_tag = tag; prom_dtlb[dtlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); spitfire_put_dtlb_data(i, 0x0UL); dtlb_seen++; if (dtlb_seen > 15) break; } } for (i = 0; i < high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); data = spitfire_get_itlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); tag = spitfire_get_itlb_tag(i); if (save_p) { prom_itlb[itlb_seen].tlb_ent = i; prom_itlb[itlb_seen].tlb_tag = tag; prom_itlb[itlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); spitfire_put_itlb_data(i, 0x0UL); itlb_seen++; if (itlb_seen > 15) break; } } } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { int high = sparc64_highest_unlocked_tlb_ent; for (i = 0; i <= high; i++) { unsigned long data; data = cheetah_get_ldtlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; tag = cheetah_get_ldtlb_tag(i); if (save_p) { prom_dtlb[dtlb_seen].tlb_ent = i; prom_dtlb[dtlb_seen].tlb_tag = tag; prom_dtlb[dtlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); cheetah_put_ldtlb_data(i, 0x0UL); dtlb_seen++; if (dtlb_seen > 15) break; } } for (i = 0; i < high; i++) { unsigned long data; data = cheetah_get_litlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; tag = cheetah_get_litlb_tag(i); if (save_p) { prom_itlb[itlb_seen].tlb_ent = i; prom_itlb[itlb_seen].tlb_tag = tag; prom_itlb[itlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); cheetah_put_litlb_data(i, 0x0UL); itlb_seen++; if (itlb_seen > 15) break; } } } else { /* Implement me :-) */ BUG(); } if (save_p) prom_ditlb_set = 1; } /* Give PROM back his world, done during reboots... */ void prom_reload_locked(void) { int i; for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_itlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); else cheetah_put_litlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); } } __asm__ __volatile__("flushw"); } #ifdef DCACHE_ALIASING_POSSIBLE Loading Loading @@ -1066,6 +784,15 @@ void sparc_ultra_dump_dtlb(void) } } static inline void spitfire_errata32(void) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); } extern unsigned long cmdline_memory_size; unsigned long __init bootmem_init(unsigned long *pages_avail) Loading Loading @@ -1375,8 +1102,6 @@ void __init paging_init(void) setup_tba(this_is_starfire); } inherit_locked_prom_mappings(1); __flush_tlb_all(); /* Setup bootmem... */ Loading Loading
arch/sparc64/kernel/smp.c +0 −4 Original line number Diff line number Diff line Loading @@ -116,14 +116,10 @@ static void smp_setup_percpu_timer(void); static volatile unsigned long callin_flag = 0; extern void inherit_locked_prom_mappings(int save_p); void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); inherit_locked_prom_mappings(0); __local_per_cpu_offset = __per_cpu_offset(cpuid); __flush_tlb_all(); Loading
arch/sparc64/kernel/tsb.S +0 −7 Original line number Diff line number Diff line Loading @@ -178,13 +178,6 @@ __tsb_context_switch: brz %o2, 9f nop /* We use entry 61 for this locked entry. This is the spitfire * TLB entry number, and luckily cheetah masks the value with * 15 ending us up with entry 13 which is what we want in that * case too. * * XXX Interactions with prom_world()... */ sethi %hi(sparc64_highest_unlocked_tlb_ent), %o4 mov TLB_TAG_ACCESS, %g1 lduw [%o4 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 Loading
arch/sparc64/mm/init.c +10 −285 Original line number Diff line number Diff line Loading @@ -555,294 +555,12 @@ static void __init inherit_prom_mappings(void) prom_printf("done.\n"); } static int prom_ditlb_set; struct prom_tlb_entry { int tlb_ent; unsigned long tlb_tag; unsigned long tlb_data; }; struct prom_tlb_entry prom_itlb[16], prom_dtlb[16]; void prom_world(int enter) { unsigned long pstate; int i; if (!enter) set_fs((mm_segment_t) { get_thread_current_ds() }); if (!prom_ditlb_set) return; /* Make sure the following runs atomically. */ __asm__ __volatile__("flushw\n\t" "rdpr %%pstate, %0\n\t" "wrpr %0, %1, %%pstate" : "=r" (pstate) : "i" (PSTATE_IE)); if (enter) { /* Install PROM world. */ for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_itlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_litlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); } } } else { for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); else cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, 0x0UL); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, 0x0UL); else cheetah_put_litlb_data(prom_itlb[i].tlb_ent, 0x0UL); } } } __asm__ __volatile__("wrpr %0, 0, %%pstate" : : "r" (pstate)); } void inherit_locked_prom_mappings(int save_p) { int i; int dtlb_seen = 0; int itlb_seen = 0; /* Fucking losing PROM has more mappings in the TLB, but * it (conveniently) fails to mention any of these in the * translations property. The only ones that matter are * the locked PROM tlb entries, so we impose the following * irrecovable rule on the PROM, it is allowed 8 locked * entries in the ITLB and 8 in the DTLB. * * Supposedly the upper 16GB of the address space is * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED * SOMEWHERE!!!!!!!!!!!!!!!!! Furthermore the entire interface * used between the client program and the firmware on sun5 * systems to coordinate mmu mappings is also COMPLETELY * UNDOCUMENTED!!!!!! Thanks S(t)un! */ if (save_p) { for (i = 0; i < 16; i++) { prom_itlb[i].tlb_ent = -1; prom_dtlb[i].tlb_ent = -1; } } if (tlb_type == spitfire) { int high = sparc64_highest_unlocked_tlb_ent; for (i = 0; i <= high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no cheetah+ * page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); data = spitfire_get_dtlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); tag = spitfire_get_dtlb_tag(i); if (save_p) { prom_dtlb[dtlb_seen].tlb_ent = i; prom_dtlb[dtlb_seen].tlb_tag = tag; prom_dtlb[dtlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); spitfire_put_dtlb_data(i, 0x0UL); dtlb_seen++; if (dtlb_seen > 15) break; } } for (i = 0; i < high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); data = spitfire_get_itlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; /* Spitfire Errata #32 workaround */ /* NOTE: Always runs on spitfire, so no * cheetah+ page size encodings. */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); tag = spitfire_get_itlb_tag(i); if (save_p) { prom_itlb[itlb_seen].tlb_ent = i; prom_itlb[itlb_seen].tlb_tag = tag; prom_itlb[itlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); spitfire_put_itlb_data(i, 0x0UL); itlb_seen++; if (itlb_seen > 15) break; } } } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { int high = sparc64_highest_unlocked_tlb_ent; for (i = 0; i <= high; i++) { unsigned long data; data = cheetah_get_ldtlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; tag = cheetah_get_ldtlb_tag(i); if (save_p) { prom_dtlb[dtlb_seen].tlb_ent = i; prom_dtlb[dtlb_seen].tlb_tag = tag; prom_dtlb[dtlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); cheetah_put_ldtlb_data(i, 0x0UL); dtlb_seen++; if (dtlb_seen > 15) break; } } for (i = 0; i < high; i++) { unsigned long data; data = cheetah_get_litlb_data(i); if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { unsigned long tag; tag = cheetah_get_litlb_tag(i); if (save_p) { prom_itlb[itlb_seen].tlb_ent = i; prom_itlb[itlb_seen].tlb_tag = tag; prom_itlb[itlb_seen].tlb_data = data; } __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); cheetah_put_litlb_data(i, 0x0UL); itlb_seen++; if (itlb_seen > 15) break; } } } else { /* Implement me :-) */ BUG(); } if (save_p) prom_ditlb_set = 1; } /* Give PROM back his world, done during reboots... */ void prom_reload_locked(void) { int i; for (i = 0; i < 16; i++) { if (prom_dtlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); if (tlb_type == spitfire) spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); else if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, prom_dtlb[i].tlb_data); } if (prom_itlb[i].tlb_ent != -1) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "membar #Sync" : : "r" (prom_itlb[i].tlb_tag), "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); if (tlb_type == spitfire) spitfire_put_itlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); else cheetah_put_litlb_data(prom_itlb[i].tlb_ent, prom_itlb[i].tlb_data); } } __asm__ __volatile__("flushw"); } #ifdef DCACHE_ALIASING_POSSIBLE Loading Loading @@ -1066,6 +784,15 @@ void sparc_ultra_dump_dtlb(void) } } static inline void spitfire_errata32(void) { __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); } extern unsigned long cmdline_memory_size; unsigned long __init bootmem_init(unsigned long *pages_avail) Loading Loading @@ -1375,8 +1102,6 @@ void __init paging_init(void) setup_tba(this_is_starfire); } inherit_locked_prom_mappings(1); __flush_tlb_all(); /* Setup bootmem... */ Loading