summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2002-06-08 07:10:28 +0000
committerjake <jake@FreeBSD.org>2002-06-08 07:10:28 +0000
commit51d015a4b692034f1f4136c41618f2c29f4de7f8 (patch)
treee1b9f093d67ee190182607aff28d3c94194e4bde /sys
parentfa2a4fdbfc8dc75c23468a42a90ea39f371b787b (diff)
downloadFreeBSD-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.h3
-rw-r--r--sys/sparc64/sparc64/machdep.c2
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c19
-rw-r--r--sys/sparc64/sparc64/pmap.c2
-rw-r--r--sys/sparc64/sparc64/tlb.c26
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);
+ }
+ }
+}
OpenPOWER on IntegriCloud