[PATCH RFC 18/18] loongarch: make set_direct_map_*_noflush actually noflush
Mike Rapoport (Microsoft)
rppt at kernel.org
Tue Jul 21 09:23:41 PDT 2026
loongarch versions of set_direct_memory_{default,invalid,valid}_noflush
call core CPA API (change_page_attr_set_clr()) that actually flush TLB
after the page table update.
This was also the case before the conversion of loongarch to use generic
CPA core, loongarch::__set_memory() always flushed TLBs, even when it
was called from _noflush API variants.
Switch the _noflush APIs to use __change_page_attr_set_clr() that does
not flush TLB unless there was an error or there was a split of higher
level page tables.
Assisted-by: Copilot:claude-opus-4.8
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
arch/loongarch/mm/pageattr.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/arch/loongarch/mm/pageattr.c b/arch/loongarch/mm/pageattr.c
index 4500769ccf6a..dbbd408bd3d5 100644
--- a/arch/loongarch/mm/pageattr.c
+++ b/arch/loongarch/mm/pageattr.c
@@ -134,40 +134,53 @@ bool kernel_page_present(struct page *page)
int set_direct_map_default_noflush(struct page *page)
{
unsigned long addr = (unsigned long)page_address(page);
+ struct cpa_data cpa = { .vaddr = &addr,
+ .pgd = NULL,
+ .numpages = 1,
+ .mask_set = PAGE_KERNEL,
+ .mask_clr = __pgprot(0),
+ .flags = CPA_NO_CHECK_ALIAS };
if (addr < vm_map_base)
return 0;
- return change_page_attr_set_clr(&addr, 1, PAGE_KERNEL,
- __pgprot(0), 0, 0, NULL);
+ return __change_page_attr_set_clr(&cpa, 1);
}
int set_direct_map_invalid_noflush(struct page *page)
{
unsigned long addr = (unsigned long)page_address(page);
+ struct cpa_data cpa = { .vaddr = &addr,
+ .pgd = NULL,
+ .numpages = 1,
+ .mask_set = __pgprot(0),
+ .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_VALID),
+ .flags = CPA_NO_CHECK_ALIAS };
if (addr < vm_map_base)
return 0;
- return change_page_attr_clear(&addr, 1,
- __pgprot(_PAGE_PRESENT | _PAGE_VALID), 0);
+ return __change_page_attr_set_clr(&cpa, 1);
}
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
{
unsigned long addr = (unsigned long)page_address(page);
- pgprot_t set, clear;
+ struct cpa_data cpa = { .vaddr = &addr,
+ .pgd = NULL,
+ .numpages = nr,
+ .flags = CPA_NO_CHECK_ALIAS };
if (addr < vm_map_base)
return 0;
if (valid) {
- set = PAGE_KERNEL;
- clear = __pgprot(0);
+ cpa.mask_set = PAGE_KERNEL;
+ cpa.mask_clr = __pgprot(0);
} else {
- set = __pgprot(0);
- clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
+ cpa.mask_set = __pgprot(0);
+ cpa.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
}
- return change_page_attr_set_clr(&addr, nr, set, clear, 0, 0, NULL);
+ return __change_page_attr_set_clr(&cpa, 1);
}
--
2.53.0
More information about the linux-riscv
mailing list