/** * flush_coherent_icache() - if a CPU has a coherent icache, flush it * Return true if the cache was flushed, false otherwise
*/ staticinlinebool flush_coherent_icache(void)
{ /* * For a snooping icache, we still need a dummy icbi to purge all the * prefetched instructions from the ifetch buffers. We also need a sync * before the icbi to order the actual stores to memory that might * have modified instructions with the icbi.
*/ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) {
mb(); /* sync */
icbi((void *)PAGE_OFFSET);
mb(); /* sync */
isync(); returntrue;
}
returnfalse;
}
/** * invalidate_icache_range() - Flush the icache by issuing icbi across an address range * @start: the start address * @stop: the stop address (exclusive)
*/ staticvoid invalidate_icache_range(unsignedlong start, unsignedlong stop)
{ unsignedlong shift = l1_icache_shift(); unsignedlong bytes = l1_icache_bytes(); char *addr = (char *)(start & ~(bytes - 1)); unsignedlong size = stop - (unsignedlong)addr + (bytes - 1); unsignedlong i;
for (i = 0; i < size >> shift; i++, addr += bytes)
icbi(addr);
mb(); /* sync */
isync();
}
/** * flush_icache_range: Write any modified data cache blocks out to memory * and invalidate the corresponding blocks in the instruction cache * * Generic code will call this after writing memory, before executing from it. * * @start: the start address * @stop: the stop address (exclusive)
*/ void flush_icache_range(unsignedlong start, unsignedlong stop)
{ if (flush_coherent_icache()) return;
clean_dcache_range(start, stop);
if (IS_ENABLED(CONFIG_44x)) { /* * Flash invalidate on 44x because we are passed kmapped * addresses and this doesn't work for userspace pages due to * the virtually tagged icache.
*/
iccci((void *)start);
mb(); /* sync */
isync();
} else
invalidate_icache_range(start, stop);
}
EXPORT_SYMBOL(flush_icache_range);
#ifdef CONFIG_HIGHMEM /** * flush_dcache_icache_phys() - Flush a page by its physical address * @physaddr: the physical address of the page
*/ staticvoid flush_dcache_icache_phys(unsignedlong physaddr)
{ unsignedlong bytes = l1_dcache_bytes(); unsignedlong nb = PAGE_SIZE / bytes; unsignedlong addr = physaddr & PAGE_MASK; unsignedlong msr, msr0; unsignedlong loop1 = addr, loop2 = addr;
/** * __flush_dcache_icache(): Flush a particular page from the data cache to RAM. * Note: this is necessary because the instruction cache does *not* * snoop from the data cache. * * @p: the address of the page to flush
*/ staticvoid __flush_dcache_icache(void *p)
{ unsignedlong addr = (unsignedlong)p & PAGE_MASK;
clean_dcache_range(addr, addr + PAGE_SIZE);
/* * We don't flush the icache on 44x. Those have a virtual icache and we * don't have access to the virtual address here (it's not the page * vaddr but where it's mapped in user space). The flushing of the * icache on these is handled elsewhere, when a change in the address * space occurs, before returning to user space.
*/
void flush_dcache_icache_folio(struct folio *folio)
{ unsignedint i, nr = folio_nr_pages(folio);
if (flush_coherent_icache()) return;
if (!folio_test_highmem(folio)) { void *addr = folio_address(folio); for (i = 0; i < nr; i++)
__flush_dcache_icache(addr + i * PAGE_SIZE);
} elseif (IS_ENABLED(CONFIG_BOOKE) || sizeof(phys_addr_t) > sizeof(void *)) { for (i = 0; i < nr; i++) { void *start = kmap_local_folio(folio, i * PAGE_SIZE);
__flush_dcache_icache(start);
kunmap_local(start);
}
} else { unsignedlong pfn = folio_pfn(folio); for (i = 0; i < nr; i++)
flush_dcache_icache_phys((pfn + i) * PAGE_SIZE);
}
}
EXPORT_SYMBOL(flush_dcache_icache_folio);
/* * We shouldn't have to do this, but some versions of glibc * require it (ld.so assumes zero filled pages are icache clean) * - Anton
*/
flush_dcache_page(pg);
}
EXPORT_SYMBOL(clear_user_page);
/* * We should be able to use the following optimisation, however * there are two problems. * Firstly a bug in some versions of binutils meant PLT sections * were not marked executable. * Secondly the first word in the GOT section is blrl, used * to establish the GOT address. Until recently the GOT was * not marked executable. * - Anton
*/ #if 0 if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0)) return; #endif
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.