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.
This commit is contained in:
Jake Burkholder 2002-06-08 07:10:28 +00:00
parent b3a3c64940
commit acb941ef8f
5 changed files with 51 additions and 1 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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);
}
}
}