diff options
Diffstat (limited to 'sys/boot/sparc64')
-rw-r--r-- | sys/boot/sparc64/loader/main.c | 88 |
1 files changed, 63 insertions, 25 deletions
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c index 9a3ae58..be0819f 100644 --- a/sys/boot/sparc64/loader/main.c +++ b/sys/boot/sparc64/loader/main.c @@ -96,10 +96,10 @@ static struct mmu_ops { typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, void *openfirmware); -static inline u_long dtlb_get_data_sun4u(u_int); +static inline u_long dtlb_get_data_sun4u(u_int, u_int); static int dtlb_enter_sun4u(u_int, u_long data, vm_offset_t); static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t); -static inline u_long itlb_get_data_sun4u(u_int); +static inline u_long itlb_get_data_sun4u(u_int, u_int); static int itlb_enter_sun4u(u_int, u_long data, vm_offset_t); static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); static void itlb_relocate_locked0_sun4u(void); @@ -136,6 +136,7 @@ u_int itlb_slot; static int cpu_impl; static u_int dtlb_slot_max; static u_int itlb_slot_max; +static u_int tlb_locked; static vm_offset_t curkva = 0; static vm_offset_t heapva; @@ -355,42 +356,55 @@ __elfN(exec)(struct preloaded_file *fp) } static inline u_long -dtlb_get_data_sun4u(u_int slot) +dtlb_get_data_sun4u(u_int tlb, u_int slot) { + u_long data, pstate; + slot = TLB_DAR_SLOT(tlb, slot); /* - * We read ASI_DTLB_DATA_ACCESS_REG twice in order to work - * around errata of USIII and beyond. + * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to + * work around errata of USIII and beyond. */ - (void)ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG); - return (ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG)); + pstate = rdpr(pstate); + wrpr(pstate, pstate & ~PSTATE_IE, 0); + (void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); + data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); + wrpr(pstate, pstate, 0); + return (data); } static inline u_long -itlb_get_data_sun4u(u_int slot) +itlb_get_data_sun4u(u_int tlb, u_int slot) { + u_long data, pstate; + slot = TLB_DAR_SLOT(tlb, slot); /* - * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work - * around errata of USIII and beyond. + * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to + * work around errata of USIII and beyond. */ - (void)ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG); - return (ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG)); + pstate = rdpr(pstate); + wrpr(pstate, pstate & ~PSTATE_IE, 0); + (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); + data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); + wrpr(pstate, pstate, 0); + return (data); } static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t va) { u_long pstate, reg; - int i; + u_int i, tlb; pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); for (i = 0; i < dtlb_slot_max; i++) { - reg = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_TAG_READ_REG); + reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), + ASI_DTLB_TAG_READ_REG); if (TLB_TAR_VA(reg) != va) continue; - reg = dtlb_get_data_sun4u(i); + reg = dtlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; if (cpu_impl == CPU_IMPL_SPARC64V || @@ -411,10 +425,11 @@ itlb_va_to_pa_sun4u(vm_offset_t va) pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); for (i = 0; i < itlb_slot_max; i++) { - reg = ldxa(TLB_DAR_SLOT(i), ASI_ITLB_TAG_READ_REG); + reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), + ASI_ITLB_TAG_READ_REG); if (TLB_TAR_VA(reg) != va) continue; - reg = itlb_get_data_sun4u(i); + reg = itlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; if (cpu_impl == CPU_IMPL_SPARC64V || @@ -458,14 +473,14 @@ itlb_relocate_locked0_sun4u(void) pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); - data = itlb_get_data_sun4u(0); + data = itlb_get_data_sun4u(tlb_locked, 0); if ((data & (TD_V | TD_L)) != (TD_V | TD_L)) { wrpr(pstate, pstate, 0); return; } /* Flush the mapping of slot 0. */ - tag = ldxa(TLB_DAR_SLOT(0), ASI_ITLB_TAG_READ_REG); + tag = ldxa(TLB_DAR_SLOT(tlb_locked, 0), ASI_ITLB_TAG_READ_REG); stxa(TLB_DEMAP_VA(TLB_TAR_VA(tag)) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, ASI_IMMU_DEMAP, 0); flush(0); /* The USIII-family ignores the address. */ @@ -475,11 +490,12 @@ itlb_relocate_locked0_sun4u(void) * that formerly were in slot 0. */ for (i = 1; i < itlb_slot_max; i++) { - if ((itlb_get_data_sun4u(i) & TD_V) != 0) + if ((itlb_get_data_sun4u(tlb_locked, i) & TD_V) != 0) continue; stxa(AA_IMMU_TAR, ASI_IMMU, tag); - stxa(TLB_DAR_SLOT(i), ASI_ITLB_DATA_ACCESS_REG, data); + stxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_DATA_ACCESS_REG, + data); flush(0); /* The USIII-family ignores the address. */ break; } @@ -651,6 +667,26 @@ tlb_init_sun4u(void) phandle_t bsp; cpu_impl = VER_IMPL(rdpr(ver)); + switch (cpu_impl) { + case CPU_IMPL_SPARC64: + case CPU_IMPL_ULTRASPARCI: + case CPU_IMPL_ULTRASPARCII: + case CPU_IMPL_ULTRASPARCIIi: + case CPU_IMPL_ULTRASPARCIIe: + tlb_locked = TLB_DAR_T32; + break; + case CPU_IMPL_ULTRASPARCIII: + case CPU_IMPL_ULTRASPARCIIIp: + case CPU_IMPL_ULTRASPARCIIIi: + case CPU_IMPL_ULTRASPARCIIIip: + case CPU_IMPL_ULTRASPARCIV: + case CPU_IMPL_ULTRASPARCIVp: + tlb_locked = TLB_DAR_T16; + break; + case CPU_IMPL_SPARC64V: + tlb_locked = TLB_DAR_FTLB; + break; + } bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u()); if (bsp == 0) panic("%s: no node for bootcpu?!?!", __func__); @@ -821,21 +857,23 @@ pmap_print_tlb_sun4u(void) pstate = rdpr(pstate); for (i = 0; i < itlb_slot_max; i++) { wrpr(pstate, pstate & ~PSTATE_IE, 0); - tte = itlb_get_data_sun4u(i); + tte = itlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); if (!(tte & TD_V)) continue; - tag = ldxa(TLB_DAR_SLOT(i), ASI_ITLB_TAG_READ_REG); + tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), + ASI_ITLB_TAG_READ_REG); printf("iTLB-%2u: ", i); pmap_print_tte_sun4u(tag, tte); } for (i = 0; i < dtlb_slot_max; i++) { wrpr(pstate, pstate & ~PSTATE_IE, 0); - tte = dtlb_get_data_sun4u(i); + tte = dtlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); if (!(tte & TD_V)) continue; - tag = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_TAG_READ_REG); + tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), + ASI_DTLB_TAG_READ_REG); printf("dTLB-%2u: ", i); pmap_print_tte_sun4u(tag, tte); } |