diff --git a/sys/sparc64/include/tlb.h b/sys/sparc64/include/tlb.h index 126af86a25fa..1a19ae3ea2b6 100644 --- a/sys/sparc64/include/tlb.h +++ b/sys/sparc64/include/tlb.h @@ -85,9 +85,12 @@ struct tlb_entry; extern int kernel_tlb_slots; extern struct tlb_entry *kernel_tlbs; +extern int tlb_slot_count; + void tlb_context_demap(struct pmap *pm); void tlb_page_demap(u_int tlb, struct pmap *pm, vm_offset_t va); void tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end); +void tlb_dump(void); #define tlb_tte_demap(tp, pm) \ tlb_page_demap(TTE_GET_TLB(tp), pm, TTE_GET_VA(tp)) diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 51ec4d4663ec..f44c25f8687d 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -158,6 +158,8 @@ cpu_startup(void *arg) if (child == 0) panic("cpu_startup: no cpu\n"); OF_getprop(child, "clock-frequency", &clock, sizeof(clock)); + OF_getprop(child, "#dtlb-entries", &tlb_slot_count, + sizeof(tlb_slot_count)); tick_tc.tc_get_timecount = tick_get_timecount; tick_tc.tc_poll_pps = NULL; diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index 531447248ca6..d1b86bdff086 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -334,6 +334,25 @@ void cpu_mp_bootstrap(struct pcpu *pc) { volatile struct cpu_start_args *csa; + u_long tag; + int i; + + /* + * When secondary cpus start up they often have junk in their tlb. + * Sometimes both the lock bit and the valid bit will be set in the + * tlb entries, which can cause our locked mappings to be replaced, + * and other random behvaiour. The tags always seems to be zero, so + * we flush all mappings with a tag of zero, regardless of the lock + * and/or valid bits. + */ + for (i = 0; i < tlb_slot_count; i++) { + tag = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_TAG_READ_REG); + if (tag == 0) + stxa_sync(TLB_DAR_SLOT(i), ASI_DTLB_DATA_ACCESS_REG, 0); + tag = ldxa(TLB_DAR_SLOT(i), ASI_ITLB_TAG_READ_REG); + if (tag == 0) + stxa_sync(TLB_DAR_SLOT(i), ASI_ITLB_DATA_ACCESS_REG, 0); + } csa = &cpu_start_args; pmap_map_tsb(); diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index e3f03554fba7..171df8f05cbf 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -471,7 +471,7 @@ pmap_context_rollover(void) mtx_assert(&sched_lock, MA_OWNED); CTR0(KTR_PMAP, "pmap_context_rollover"); - for (i = 0; i < 64; i++) { + for (i = 0; i < tlb_slot_count; i++) { /* XXX - cheetah */ data = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_DATA_ACCESS_REG); tag = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_TAG_READ_REG); diff --git a/sys/sparc64/sparc64/tlb.c b/sys/sparc64/sparc64/tlb.c index f2ecf02a944e..221fed3c84d2 100644 --- a/sys/sparc64/sparc64/tlb.c +++ b/sys/sparc64/sparc64/tlb.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -38,6 +39,8 @@ #include #include +int tlb_slot_count; + /* * Some tlb operations must be atomic, so no interrupt or trap can be allowed * while they are in progress. Traps should not happen, but interrupts need to @@ -138,3 +141,26 @@ tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end) ipi_wait(cookie); critical_exit(); } + +void +tlb_dump(void) +{ + u_long data; + u_long tag; + int slot; + + for (slot = 0; slot < tlb_slot_count; slot++) { + data = ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG); + if ((data & TD_V) != 0) { + tag = ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_TAG_READ_REG); + TR3("pmap_dump_tlb: dltb slot=%d data=%#lx tag=%#lx", + slot, data, tag); + } + data = ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG); + if ((data & TD_V) != 0) { + tag = ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_TAG_READ_REG); + TR3("pmap_dump_tlb: iltb slot=%d data=%#lx tag=%#lx", + slot, data, tag); + } + } +}