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:
parent
b3a3c64940
commit
acb941ef8f
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user