All of lore.kernel.org
 help / color / mirror / Atom feed
* [bug report]: high memory and cache alias handing
@ 2021-07-02  7:59 Huang Pei
  0 siblings, 0 replies; only message in thread
From: Huang Pei @ 2021-07-02  7:59 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: linux-mips, linux-mm, yijun, Yang Tiezhu, lixuefeng

I found some issue about cache alias when trying to support 4KB page 
on Loongson 3A1000 (VIPT L1D and L1C, both 4-way in total 64KB)

1.  __flush_anon_page 
.......
void __flush_anon_page(struct page *page, unsigned long vmaddr)
{
	//A:if page is in high memory, page_address does not return
	//meaningful addr
	unsigned long addr = (unsigned long) page_address(page);

	if (pages_do_alias(addr, vmaddr)) {
		if (page_mapcount(page) && !Page_dcache_dirty(page)) {
			void *kaddr;

			kaddr = kmap_coherent(page, vmaddr);
			flush_data_cache_page((unsigned long)kaddr);
			kunmap_coherent();
		} else
			//A: so can not use this addr for cache flush

			//for 64bit kernel, although addr returned is OK
			//but the flush_data_cache_page(addr) DOES NOT
			//touch the cache alias
			flush_data_cache_page(addr);
	}
}
........

to fix __flush_anon_page, I has one question

+. Why using kmap_coherent depends on !Page_dcache_dirty(page)?

I think after ce01948eb85d and 0f334a3e8c35, it is safe to
kmap_coherent without checking Page_dcache_dirty(page)

since with preempt disabled in kmap_coherent, and in interrupt use
indepent fixmap index, there is no collision in TLB  

void __flush_anon_page(struct page *page, unsigned long vmaddr)
{
	void *kaddr;
	if (page_mapcount(page)) {

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

2.  __flush_dcache_page 
........
void __flush_dcache_page(struct page *page)
{
	struct address_space *mapping = page_mapping_file(page);
	unsigned long addr;

	if (mapping && !mapping_mapped(mapping)) {
		SetPageDcacheDirty(page);
		return;
	}

	/*
	 * We could delay the flush for the !page_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.
	 */
	//B: calling __flush_dcache_page is under cpu_has_dc_aliases, so
	//we can not make sure addr returned by kmap_atomic is some
	//color with page's physical color, 
	//how can flush_data_cache_page flush cache line with this page
	if (PageHighMem(page))
		addr = (unsigned long)kmap_atomic(page);
	else
		addr = (unsigned long)page_address(page);

	flush_data_cache_page(addr);

	if (PageHighMem(page))
		kunmap_atomic((void *)addr);
}
........
3.  __update_tlb
.....
void __update_cache(unsigned long address, pte_t pte)
{
	struct page *page;
	unsigned long pfn, addr;
	int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;

	pfn = pte_pfn(pte);
	if (unlikely(!pfn_valid(pfn)))
		return;
	page = pfn_to_page(pfn);
	if (Page_dcache_dirty(page)) {
		//C: same as B, can not make sure the addr is in
		//same color with address
		if (PageHighMem(page))
			addr = (unsigned long)kmap_atomic(page);
		else
			addr = (unsigned long)page_address(page);
		//C: if exec is true and addr is NOT in same color with address
		//then flush_data_cache_page CAN NOT hit writeback and
		//invalidate page's cache line

		//C: if exec is false, page_do_alias return true, AKA
		addr is not in same color with address
		//then flush_data_cache_page(addr) 
		if (exec || pages_do_alias(addr, address & PAGE_MASK))
			flush_data_cache_page(addr);

		if (PageHighMem(page))
			kunmap_atomic((void *)addr);

		ClearPageDcacheDirty(page);
	}
}


all 3 issues need page_coherent to work without restriction of
!Page_Dcache_Dirty()


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-02  7:59 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-02  7:59 [bug report]: high memory and cache alias handing Huang Pei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.