void local_flush_tlb_all(void)
{ unsignedlong flags; unsignedlong old_ctx; int entry, ftlbhighset;
local_irq_save(flags); /* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
htw_stop();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
entry = num_wired_entries();
/* *Blast'emallaway. *Ifthereareanywiredentries,fallbacktoiterating
*/ if (cpu_has_tlbinv && !entry) { if (current_cpu_data.tlbsizevtlb) {
write_c0_index(0);
mtc0_tlbw_hazard();
tlbinvf(); /* invalidate VTLB */
}
ftlbhighset = current_cpu_data.tlbsizevtlb +
current_cpu_data.tlbsizeftlbsets; for (entry = current_cpu_data.tlbsizevtlb;
entry < ftlbhighset;
entry++) {
write_c0_index(entry);
mtc0_tlbw_hazard();
tlbinvf(); /* invalidate one FTLB set */
}
} else { while (entry < current_cpu_data.tlbsize) { /* Make sure all entries differ. */
write_c0_entryhi(UNIQUE_ENTRYHI(entry));
write_c0_index(entry);
mtc0_tlbw_hazard();
tlb_write_indexed();
entry++;
}
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
htw_start();
flush_micro_tlb();
local_irq_restore(flags);
}
EXPORT_SYMBOL(local_flush_tlb_all);
void local_flush_tlb_range(struct vm_area_struct *vma, unsignedlong start, unsignedlong end)
{ struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id();
if (cpu_context(cpu, mm) != 0) { unsignedlong size, flags;
local_irq_save(flags); if (cpu_has_mmid) {
old_mmid = read_c0_memorymapid();
write_c0_memorymapid(MMID_KERNEL_WIRED);
} /* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
htw_stop();
old_pagemask = read_c0_pagemask();
wired = num_wired_entries();
write_c0_wired(wired + 1);
write_c0_index(wired);
tlbw_use_hazard(); /* What is the hazard here? */
write_c0_pagemask(pagemask);
write_c0_entryhi(entryhi);
write_c0_entrylo0(entrylo0);
write_c0_entrylo1(entrylo1);
mtc0_tlbw_hazard();
tlb_write_indexed();
tlbw_use_hazard();
write_c0_entryhi(old_ctx); if (cpu_has_mmid)
write_c0_memorymapid(old_mmid);
tlbw_use_hazard(); /* What is the hazard here? */
htw_start();
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
local_irq_restore(flags); #endif
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
int has_transparent_hugepage(void)
{ staticunsignedint mask = -1;
if (mask == -1) { /* first call comes during __init */ unsignedlong flags;
#ifndef CONFIG_64BIT
__init int add_temporary_entry(unsignedlong entrylo0, unsignedlong entrylo1, unsignedlong entryhi, unsignedlong pagemask)
{ int ret = 0; unsignedlong flags; unsignedlong wired; unsignedlong old_pagemask; unsignedlong old_ctx;
local_irq_save(flags); /* Save old context and create impossible VPN2 value */
htw_stop();
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
wired = num_wired_entries(); if (--temp_tlb_entry < wired) {
printk(KERN_WARNING "No TLB space left for add_temporary_entry\n");
ret = -ENOSPC; goto out;
}
while (entry < current_cpu_data.tlbsize) { unsignedlong asid_mask = cpu_asid_mask(¤t_cpu_data); unsignedlong asid = 0; int idx;
/* Skip wired MMID to make ginvt_mmid work */ if (cpu_has_mmid)
asid = MMID_KERNEL_WIRED + 1;
/* Check for match before using UNIQUE_ENTRYHI */ do { if (cpu_has_mmid) {
write_c0_memorymapid(asid);
write_c0_entryhi(UNIQUE_ENTRYHI(entry));
} else {
write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid);
}
mtc0_tlbw_hazard();
tlb_probe();
tlb_probe_hazard();
idx = read_c0_index(); /* No match or match is on current entry */ if (idx < 0 || idx == entry) break; /* *Ifwehitamatch,weneedtotryagainwith *adifferentASID.
*/
asid++;
} while (asid < asid_mask);
if (idx >= 0 && idx != entry)
panic("Unable to uniquify TLB entry %d", idx);
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.