diff options
| author | Max Filippov <jcmvbkbc@gmail.com> | 2014-07-14 18:51:49 -0400 |
|---|---|---|
| committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-08-14 03:59:21 -0400 |
| commit | 32544d9c10c42bac3be8b87d2fc95b0aef008795 (patch) | |
| tree | 11983adf6b934cc71ba3013623d8869c867b49fd | |
| parent | a91902db2990909ea5e6b110811b448f2e8f1571 (diff) | |
xtensa: support aliasing cache in k[un]map_atomic
Map high memory pages at virtual addresses with color that match color
of their physical address. Existing cache alias management mechanisms
may be used with such pages.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
| -rw-r--r-- | arch/xtensa/include/asm/fixmap.h | 3 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/page.h | 2 | ||||
| -rw-r--r-- | arch/xtensa/mm/highmem.c | 17 |
3 files changed, 14 insertions, 8 deletions
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h index a43cd5265556..62b507deea9d 100644 --- a/arch/xtensa/include/asm/fixmap.h +++ b/arch/xtensa/include/asm/fixmap.h | |||
| @@ -38,7 +38,8 @@ enum fixed_addresses { | |||
| 38 | #ifdef CONFIG_HIGHMEM | 38 | #ifdef CONFIG_HIGHMEM |
| 39 | /* reserved pte's for temporary kernel mappings */ | 39 | /* reserved pte's for temporary kernel mappings */ |
| 40 | FIX_KMAP_BEGIN, | 40 | FIX_KMAP_BEGIN, |
| 41 | FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, | 41 | FIX_KMAP_END = FIX_KMAP_BEGIN + |
| 42 | (KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1, | ||
| 42 | #endif | 43 | #endif |
| 43 | __end_of_fixed_addresses | 44 | __end_of_fixed_addresses |
| 44 | }; | 45 | }; |
diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 11721ccd7f23..abe24c6f8b2f 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h | |||
| @@ -78,7 +78,9 @@ | |||
| 78 | # define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0) | 78 | # define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0) |
| 79 | #else | 79 | #else |
| 80 | # define DCACHE_ALIAS_ORDER 0 | 80 | # define DCACHE_ALIAS_ORDER 0 |
| 81 | # define DCACHE_ALIAS(a) ((void)(a), 0) | ||
| 81 | #endif | 82 | #endif |
| 83 | #define DCACHE_N_COLORS (1 << DCACHE_ALIAS_ORDER) | ||
| 82 | 84 | ||
| 83 | #if ICACHE_WAY_SIZE > PAGE_SIZE | 85 | #if ICACHE_WAY_SIZE > PAGE_SIZE |
| 84 | # define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT) | 86 | # define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT) |
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c index 2e95a7665bf3..466abaed5382 100644 --- a/arch/xtensa/mm/highmem.c +++ b/arch/xtensa/mm/highmem.c | |||
| @@ -14,18 +14,23 @@ | |||
| 14 | 14 | ||
| 15 | static pte_t *kmap_pte; | 15 | static pte_t *kmap_pte; |
| 16 | 16 | ||
| 17 | static inline enum fixed_addresses kmap_idx(int type, unsigned long color) | ||
| 18 | { | ||
| 19 | return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS + | ||
| 20 | color; | ||
| 21 | } | ||
| 22 | |||
| 17 | void *kmap_atomic(struct page *page) | 23 | void *kmap_atomic(struct page *page) |
| 18 | { | 24 | { |
| 19 | enum fixed_addresses idx; | 25 | enum fixed_addresses idx; |
| 20 | unsigned long vaddr; | 26 | unsigned long vaddr; |
| 21 | int type; | ||
| 22 | 27 | ||
| 23 | pagefault_disable(); | 28 | pagefault_disable(); |
| 24 | if (!PageHighMem(page)) | 29 | if (!PageHighMem(page)) |
| 25 | return page_address(page); | 30 | return page_address(page); |
| 26 | 31 | ||
| 27 | type = kmap_atomic_idx_push(); | 32 | idx = kmap_idx(kmap_atomic_idx_push(), |
| 28 | idx = type + KM_TYPE_NR * smp_processor_id(); | 33 | DCACHE_ALIAS(page_to_phys(page))); |
| 29 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 34 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
| 30 | #ifdef CONFIG_DEBUG_HIGHMEM | 35 | #ifdef CONFIG_DEBUG_HIGHMEM |
| 31 | BUG_ON(!pte_none(*(kmap_pte + idx))); | 36 | BUG_ON(!pte_none(*(kmap_pte + idx))); |
| @@ -38,12 +43,10 @@ EXPORT_SYMBOL(kmap_atomic); | |||
| 38 | 43 | ||
| 39 | void __kunmap_atomic(void *kvaddr) | 44 | void __kunmap_atomic(void *kvaddr) |
| 40 | { | 45 | { |
| 41 | int idx, type; | ||
| 42 | |||
| 43 | if (kvaddr >= (void *)FIXADDR_START && | 46 | if (kvaddr >= (void *)FIXADDR_START && |
| 44 | kvaddr < (void *)FIXADDR_TOP) { | 47 | kvaddr < (void *)FIXADDR_TOP) { |
| 45 | type = kmap_atomic_idx(); | 48 | int idx = kmap_idx(kmap_atomic_idx(), |
| 46 | idx = type + KM_TYPE_NR * smp_processor_id(); | 49 | DCACHE_ALIAS((unsigned long)kvaddr)); |
| 47 | 50 | ||
| 48 | /* | 51 | /* |
| 49 | * Force other mappings to Oops if they'll try to access this | 52 | * Force other mappings to Oops if they'll try to access this |
