aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2012-09-12 10:43:32 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2012-09-14 14:53:03 +0100
commite2b3930626432f5961201e9233acd73267f67601 (patch)
treedc86f2f750eb65df24fbdf8c65f180b614de5acc
parent0759dfc2ec0dfb8ac5747357bf37459d621f891b (diff)
downloadlinux-aarch64-e2b3930626432f5961201e9233acd73267f67601.tar.gz
arm64: Optimise the cache flushing for user processes
The AArch64 port used deferred cache flushing for user processes via flush_dcache_page() and __sync_icache_dcache() (called from set_pte_at()). Anonymous pages were always flushed in flush_dcache_page. This patch adds deferred flushing for anonymous pages and also avoids the I-cache invalidation in __sync_icache_dcache() for clean pages with VIPT I-cache configurations. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/pgtable.h4
-rw-r--r--arch/arm64/mm/flush.c25
-rw-r--r--arch/arm64/mm/mm.h2
-rw-r--r--arch/arm64/mm/mmu.c2
4 files changed, 17 insertions, 16 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6981da0179f..8960239be72 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -152,13 +152,13 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
*ptep = pte;
}
-extern void __sync_icache_dcache(pte_t pteval);
+extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
if (pte_present_exec_user(pte))
- __sync_icache_dcache(pte);
+ __sync_icache_dcache(pte, addr);
set_pte(ptep, pte);
}
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index 9cbcd13412e..c144adb1682 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -79,12 +79,12 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
#endif
}
-void __flush_dcache_page(struct address_space *mapping, struct page *page)
+void __flush_dcache_page(struct page *page)
{
__flush_dcache_area(page_address(page), PAGE_SIZE);
}
-void __sync_icache_dcache(pte_t pte)
+void __sync_icache_dcache(pte_t pte, unsigned long addr)
{
unsigned long pfn;
struct page *page;
@@ -94,9 +94,12 @@ void __sync_icache_dcache(pte_t pte)
return;
page = pfn_to_page(pfn);
- if (!test_and_set_bit(PG_dcache_clean, &page->flags))
- __flush_dcache_page(NULL, page);
- __flush_icache_all();
+ if (!test_and_set_bit(PG_dcache_clean, &page->flags)) {
+ __flush_dcache_page(page);
+ __flush_icache_all();
+ } else if (icache_is_aivivt()) {
+ __flush_icache_all();
+ }
}
/*
@@ -115,14 +118,12 @@ void flush_dcache_page(struct page *page)
return;
mapping = page_mapping(page);
-
- if (mapping && !mapping_mapped(mapping))
- clear_bit(PG_dcache_clean, &page->flags);
- else {
- __flush_dcache_page(mapping, page);
- if (mapping)
- __flush_icache_all();
+ if (mapping && mapping_mapped(mapping)) {
+ __flush_dcache_page(page);
+ __flush_icache_all();
set_bit(PG_dcache_clean, &page->flags);
+ } else {
+ clear_bit(PG_dcache_clean, &page->flags);
}
}
EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm64/mm/mm.h b/arch/arm64/mm/mm.h
index c84f68bf8d7..d8d6e7851c1 100644
--- a/arch/arm64/mm/mm.h
+++ b/arch/arm64/mm/mm.h
@@ -1,2 +1,2 @@
-extern void __flush_dcache_page(struct address_space *mapping, struct page *page);
+extern void __flush_dcache_page(struct page *page);
extern void __init bootmem_init(void);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index d2dd438180e..a6885d896ab 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -297,7 +297,7 @@ void __init paging_init(void)
bootmem_init();
empty_zero_page = virt_to_page(zero_page);
- __flush_dcache_page(NULL, empty_zero_page);
+ __flush_dcache_page(empty_zero_page);
/*
* TTBR0 is only used for the identity mapping at this stage. Make it