diff options
author | jake <jake@FreeBSD.org> | 2002-06-08 07:10:28 +0000 |
---|---|---|
committer | jake <jake@FreeBSD.org> | 2002-06-08 07:10:28 +0000 |
commit | 51d015a4b692034f1f4136c41618f2c29f4de7f8 (patch) | |
tree | e1b9f093d67ee190182607aff28d3c94194e4bde /sys | |
parent | fa2a4fdbfc8dc75c23468a42a90ea39f371b787b (diff) | |
download | FreeBSD-src-51d015a4b692034f1f4136c41618f2c29f4de7f8.zip FreeBSD-src-51d015a4b692034f1f4136c41618f2c29f4de7f8.tar.gz |
Fix bizarre SMP problems. The secondary cpus sometimes start up with junk
in their tlb which the prom doesn't clear out, so we have to do so manually
before mapping the kernel page table or the cpu can hang due various
conditions which cause undefined behaviour from the tlb.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/sparc64/include/tlb.h | 3 | ||||
-rw-r--r-- | sys/sparc64/sparc64/machdep.c | 2 | ||||
-rw-r--r-- | sys/sparc64/sparc64/mp_machdep.c | 19 | ||||
-rw-r--r-- | sys/sparc64/sparc64/pmap.c | 2 | ||||
-rw-r--r-- | sys/sparc64/sparc64/tlb.c | 26 |
5 files changed, 51 insertions, 1 deletions
diff --git a/sys/sparc64/include/tlb.h b/sys/sparc64/include/tlb.h index 126af86..1a19ae3 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 51ec4d4..f44c25f 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 5314472..d1b86bd 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 e3f0355..171df8f 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 f2ecf02..221fed3 100644 --- a/sys/sparc64/sparc64/tlb.c +++ b/sys/sparc64/sparc64/tlb.c @@ -28,6 +28,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/ktr.h> #include <sys/pcpu.h> #include <sys/smp.h> @@ -38,6 +39,8 @@ #include <machine/smp.h> #include <machine/tlb.h> +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); + } + } +} |