arch/mips/mm/cache.c

Source file repositories/reference/linux-study-clean/arch/mips/mm/cache.c

File Facts

System
Linux kernel
Corpus path
arch/mips/mm/cache.c
Extension
.c
Size
6266 bytes
Lines
219
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
	unsigned int, cache)
{
	if (bytes == 0)
		return 0;
	if (!access_ok((void __user *) addr, bytes))
		return -EFAULT;

	__flush_icache_user_range(addr, addr + bytes);

	return 0;
}

void __flush_dcache_folio_pages(struct folio *folio, struct page *page,
		unsigned int nr)
{
	struct address_space *mapping = folio_flush_mapping(folio);
	unsigned long addr;
	unsigned int i;

	if (mapping && !mapping_mapped(mapping)) {
		folio_set_dcache_dirty(folio);
		return;
	}

	/*
	 * We could delay the flush for the !folio_mapping case too.  But that
	 * case is for exec env/arg pages and those are %99 certainly going to
	 * get faulted into the tlb (and thus flushed) anyways.
	 */
	for (i = 0; i < nr; i++) {
		addr = (unsigned long)kmap_local_page(page + i);
		flush_data_cache_page(addr);
		kunmap_local((void *)addr);
	}
}
EXPORT_SYMBOL(__flush_dcache_folio_pages);

void __flush_anon_page(struct page *page, unsigned long vmaddr)
{
	unsigned long addr = (unsigned long) page_address(page);
	struct folio *folio = page_folio(page);

	if (pages_do_alias(addr, vmaddr)) {
		if (folio_mapped(folio) && !folio_test_dcache_dirty(folio)) {
			void *kaddr;

			kaddr = kmap_coherent(page, vmaddr);
			flush_data_cache_page((unsigned long)kaddr);
			kunmap_coherent();
		} else
			flush_data_cache_page(addr);
	}
}

EXPORT_SYMBOL(__flush_anon_page);

void __update_cache(unsigned long address, pte_t pte)
{
	struct folio *folio;
	unsigned long pfn, addr;
	int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;
	unsigned int i;

	pfn = pte_pfn(pte);
	if (unlikely(!pfn_valid(pfn)))
		return;

	folio = page_folio(pfn_to_page(pfn));
	address &= PAGE_MASK;
	address -= offset_in_folio(folio, pfn << PAGE_SHIFT);

	if (folio_test_dcache_dirty(folio)) {
		for (i = 0; i < folio_nr_pages(folio); i++) {
			addr = (unsigned long)kmap_local_folio(folio, i);

			if (exec || pages_do_alias(addr, address))
				flush_data_cache_page(addr);
			kunmap_local((void *)addr);
			address += PAGE_SIZE;
		}
		folio_clear_dcache_dirty(folio);
	}
}

unsigned long _page_cachable_default;
EXPORT_SYMBOL(_page_cachable_default);

#define PM(p)	__pgprot(_page_cachable_default | (p))

Annotation

Implementation Notes