in mm/tlb.c [45:86]
static void replace_tlb_one_pid(unsigned long addr, unsigned long mmu_pid, unsigned long tlbacc)
{
unsigned int way;
unsigned long org_misc, pid_misc;
/* remember pid/way until we return. */
get_misc_and_pid(&org_misc, &pid_misc);
WRCTL(CTL_PTEADDR, (addr >> PAGE_SHIFT) << 2);
for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
unsigned long pteaddr;
unsigned long tlbmisc;
unsigned long pid;
tlbmisc = TLBMISC_RD | (way << TLBMISC_WAY_SHIFT);
WRCTL(CTL_TLBMISC, tlbmisc);
pteaddr = RDCTL(CTL_PTEADDR);
if (((pteaddr >> 2) & 0xfffff) != (addr >> PAGE_SHIFT))
continue;
tlbmisc = RDCTL(CTL_TLBMISC);
pid = (tlbmisc >> TLBMISC_PID_SHIFT) & TLBMISC_PID_MASK;
if (pid != mmu_pid)
continue;
tlbmisc = (mmu_pid << TLBMISC_PID_SHIFT) | TLBMISC_WE |
(way << TLBMISC_WAY_SHIFT);
WRCTL(CTL_TLBMISC, tlbmisc);
if (tlbacc == 0)
WRCTL(CTL_PTEADDR, pteaddr_invalid(addr));
WRCTL(CTL_TLBACC, tlbacc);
/*
* There should be only a single entry that maps a
* particular {address,pid} so break after a match.
*/
break;
}
WRCTL(CTL_TLBMISC, org_misc);
}