diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-12 10:43:32 +0100 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-14 14:53:03 +0100 |
commit | e2b3930626432f5961201e9233acd73267f67601 (patch) | |
tree | dc86f2f750eb65df24fbdf8c65f180b614de5acc | |
parent | 0759dfc2ec0dfb8ac5747357bf37459d621f891b (diff) | |
download | linux-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.h | 4 | ||||
-rw-r--r-- | arch/arm64/mm/flush.c | 25 | ||||
-rw-r--r-- | arch/arm64/mm/mm.h | 2 | ||||
-rw-r--r-- | arch/arm64/mm/mmu.c | 2 |
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 |