/* * Nios2 TLB handling * * Copyright (C) 2009, Wind River Systems Inc * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details.
*/
/* * This provides a PTEADDR value for addr that will cause a TLB miss * (fast TLB miss). TLB invalidation replaces entries with this value.
*/ staticunsignedlong pteaddr_invalid(unsignedlong addr)
{ return ((addr | 0xC0000000UL) >> PAGE_SHIFT) << 2;
}
/* * This one is only used for pages with the global bit set so we don't care * much about the ASID.
*/ staticvoid replace_tlb_one_pid(unsignedlong addr, unsignedlong mmu_pid, unsignedlong tlbacc)
{ unsignedint way; unsignedlong 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++) { unsignedlong pteaddr; unsignedlong tlbmisc; unsignedlong pid;
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;
}
/* * This one is only used for pages with the global bit set so we don't care * much about the ASID.
*/ staticvoid flush_tlb_one(unsignedlong addr)
{ unsignedint way; unsignedlong org_misc, pid_misc;
pr_debug("Flush tlb-entry for vaddr=%#lx\n", addr);
/* 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++) { unsignedlong pteaddr; unsignedlong tlbmisc;
/* * All entries common to a mm share an asid. To effectively flush these * entries, we just bump the asid.
*/ void flush_tlb_mm(struct mm_struct *mm)
{ if (current->mm == mm) { unsignedlong mmu_pid = get_pid_from_context(&mm->context);
flush_tlb_pid(mmu_pid);
} else {
memset(&mm->context, 0, sizeof(mm_context_t));
}
}
/* remember pid/way until we return */
get_misc_and_pid(&org_misc, &pid_misc);
/* Map each TLB entry to physcal address 0 with no-access and a
bad ptbase */ for (line = 0; line < cpuinfo.tlb_num_lines; line++) {
WRCTL(CTL_PTEADDR, pteaddr_invalid(addr)); for (way = 0; way < cpuinfo.tlb_num_ways; way++) { // Code such as replace_tlb_one_pid assumes that no duplicate entries exist // for a single address across ways, so also use way as a dummy PID
WRCTL(CTL_TLBMISC, TLBMISC_WE | (way << TLBMISC_WAY_SHIFT) |
(way << TLBMISC_PID_SHIFT));
WRCTL(CTL_TLBACC, 0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.