From: Huang Pei <huangpei@loongson.cn>
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org, linux-mm@kvack.org,
yijun@loongson.cn, Yang Tiezhu <yangtiezhu@loongson.cn>,
lixuefeng@loongson.cn
Subject: [bug report]: high memory and cache alias handing
Date: Fri, 2 Jul 2021 15:59:02 +0800 [thread overview]
Message-ID: <20210702075902.7wxuyom6cic4ceaq@ambrosehua-HP-xw6600-Workstation> (raw)
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()
reply other threads:[~2021-07-02 7:59 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210702075902.7wxuyom6cic4ceaq@ambrosehua-HP-xw6600-Workstation \
--to=huangpei@loongson.cn \
--cc=linux-mips@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lixuefeng@loongson.cn \
--cc=tsbogend@alpha.franken.de \
--cc=yangtiezhu@loongson.cn \
--cc=yijun@loongson.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox