o When not making a translation cache-inhibit and guarded (PTE_I|PTE_G)

make it memory-coherency enforced (PTE_M). This is required for SMP
   to work.
o  Serialize tlbie operations and implement the tlbie operation in a
   function called tlbie(). Hardware can end up in a live-lock if
   between the tlbsync and subsequent sync on one processor another
   processor executes a tlbie or tlbsync.
o  Eliminate the following defines:
	TLBIE, TLBSYNC, SYNC and EIEIO
   Use either inline assembly statements or inline functions defined
   in <machine/cpufunc.h>
This commit is contained in:
Marcel Moolenaar 2008-09-16 19:16:33 +00:00
parent c481551083
commit e4f72b32cb

View File

@ -157,11 +157,6 @@ __FBSDID("$FreeBSD$");
#define TODO panic("%s: not implemented", __func__);
#define TLBIE(va) __asm __volatile("tlbie %0" :: "r"(va))
#define TLBSYNC() __asm __volatile("tlbsync");
#define SYNC() __asm __volatile("sync");
#define EIEIO() __asm __volatile("eieio");
#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4))
#define VSID_TO_SR(vsid) ((vsid) & 0xf)
#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff)
@ -209,6 +204,9 @@ extern struct pmap ofw_pmap;
*/
struct mtx moea_table_mutex;
/* tlbie instruction synchronization */
static struct mtx tlbie_mtx;
/*
* PTEG data.
*/
@ -290,7 +288,6 @@ static void moea_syncicache(vm_offset_t, vm_size_t);
static boolean_t moea_query_bit(vm_page_t, int);
static u_int moea_clear_bit(vm_page_t, int, int *);
static void moea_kremove(mmu_t, vm_offset_t);
static void tlbia(void);
int moea_pte_spill(vm_offset_t);
/*
@ -384,6 +381,29 @@ static mmu_def_t oea_mmu = {
};
MMU_DEF(oea_mmu);
static void
tlbie(vm_offset_t va)
{
mtx_lock_spin(&tlbie_mtx);
__asm __volatile("tlbie %0" :: "r"(va));
__asm __volatile("tlbsync");
powerpc_sync();
mtx_unlock_spin(&tlbie_mtx);
}
static void
tlbia(void)
{
vm_offset_t va;
for (va = 0; va < 0x00040000; va += 0x00001000) {
__asm __volatile("tlbie %0" :: "r"(va));
powerpc_sync();
}
__asm __volatile("tlbsync");
powerpc_sync();
}
static __inline int
va_to_sr(u_int *sr, vm_offset_t va)
@ -499,10 +519,7 @@ moea_pte_clear(struct pte *pt, vm_offset_t va, int ptebit)
* As shown in Section 7.6.3.2.3
*/
pt->pte_lo &= ~ptebit;
TLBIE(va);
EIEIO();
TLBSYNC();
SYNC();
tlbie(va);
}
static __inline void
@ -518,9 +535,9 @@ moea_pte_set(struct pte *pt, struct pte *pvo_pt)
* been saved so this routine can restore them (if desired).
*/
pt->pte_lo = pvo_pt->pte_lo;
EIEIO();
powerpc_sync();
pt->pte_hi = pvo_pt->pte_hi;
SYNC();
powerpc_sync();
moea_pte_valid++;
}
@ -534,18 +551,14 @@ moea_pte_unset(struct pte *pt, struct pte *pvo_pt, vm_offset_t va)
/*
* Force the reg & chg bits back into the PTEs.
*/
SYNC();
powerpc_sync();
/*
* Invalidate the pte.
*/
pt->pte_hi &= ~PTE_VALID;
SYNC();
TLBIE(va);
EIEIO();
TLBSYNC();
SYNC();
tlbie(va);
/*
* Save the reg & chg bits.
@ -610,6 +623,7 @@ pmap_cpu_bootstrap(int ap)
int i;
if (ap) {
powerpc_sync();
__asm __volatile("mtdbatu 0,%0" :: "r"(battable[0].batu));
__asm __volatile("mtdbatl 0,%0" :: "r"(battable[0].batl));
isync();
@ -634,7 +648,7 @@ pmap_cpu_bootstrap(int ap)
__asm __volatile("mtsr %0,%1" :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT));
__asm __volatile("mtsr %0,%1" :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT));
__asm __volatile("sync");
powerpc_sync();
sdr = (u_int)moea_pteg_table | (moea_pteg_mask >> 10);
__asm __volatile("mtsdr1 %0" :: "r"(sdr));
@ -793,6 +807,8 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
mtx_init(&moea_table_mutex, "pmap table", NULL, MTX_DEF |
MTX_RECURSE);
mtx_init(&tlbie_mtx, "tlbie", NULL, MTX_SPIN);
/*
* Initialise the unmanaged pvo pool.
*/
@ -947,7 +963,7 @@ moea_deactivate(mmu_t mmu, struct thread *td)
pmap_t pm;
pm = &td->td_proc->p_vmspace->vm_pmap;
pm->pm_active &= ~(PCPU_GET(cpumask));
pm->pm_active &= ~PCPU_GET(cpumask);
PCPU_SET(curpmap, NULL);
}
@ -1091,7 +1107,7 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if ((VM_PAGE_TO_PHYS(m) >= pregions[i].mr_start) &&
(VM_PAGE_TO_PHYS(m) <
(pregions[i].mr_start + pregions[i].mr_size))) {
pte_lo &= ~(PTE_I | PTE_G);
pte_lo = PTE_M;
break;
}
}
@ -1275,7 +1291,7 @@ moea_remove_write(mmu_t mmu, vm_page_t m)
(m->flags & PG_WRITEABLE) == 0)
return;
lo = moea_attr_fetch(m);
SYNC();
powerpc_sync();
LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
pmap = pvo->pvo_pmap;
PMAP_LOCK(pmap);
@ -1346,7 +1362,7 @@ moea_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa)
for (i = 0; i < pregions_sz; i++) {
if ((pa >= pregions[i].mr_start) &&
(pa < (pregions[i].mr_start + pregions[i].mr_size))) {
pte_lo &= ~(PTE_I | PTE_G);
pte_lo = PTE_M;
break;
}
}
@ -1740,20 +1756,6 @@ moea_syncicache(vm_offset_t pa, vm_size_t len)
__syncicache((void *)pa, len);
}
static void
tlbia(void)
{
caddr_t i;
SYNC();
for (i = 0; i < (caddr_t)0x00040000; i += 0x00001000) {
TLBIE(i);
EIEIO();
}
TLBSYNC();
SYNC();
}
static int
moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
vm_offset_t va, vm_offset_t pa, u_int pte_lo, int flags)
@ -2200,7 +2202,7 @@ moea_query_bit(vm_page_t m, int ptebit)
* themselves. Sync so that any pending REF/CHG bits are flushed to
* the PTEs.
*/
SYNC();
powerpc_sync();
LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
MOEA_PVO_CHECK(pvo); /* sanity check */
@ -2245,7 +2247,7 @@ moea_clear_bit(vm_page_t m, int ptebit, int *origbit)
* table, we don't have to worry about further accesses setting the
* REF/CHG bits.
*/
SYNC();
powerpc_sync();
/*
* For each pvo entry, clear the pvo's ptebit. If this pvo has a
@ -2372,7 +2374,7 @@ moea_mapdev(mmu_t mmu, vm_offset_t pa, vm_size_t size)
for (tmpva = va; size > 0;) {
moea_kenter(mmu, tmpva, ppa);
TLBIE(tmpva); /* XXX or should it be invalidate-all ? */
tlbie(tmpva);
size -= PAGE_SIZE;
tmpva += PAGE_SIZE;
ppa += PAGE_SIZE;