Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: highmem: Switch to generic kmap atomic

No reason having the same code in every architecture.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20201103095857.582196476@linutronix.de

+26 -144
+1
arch/arm/Kconfig
··· 1498 1498 config HIGHMEM 1499 1499 bool "High Memory Support" 1500 1500 depends on MMU 1501 + select KMAP_LOCAL 1501 1502 help 1502 1503 The address space of ARM processors is only 4 Gigabytes large 1503 1504 and it has to accommodate user address space, kernel address
+2 -2
arch/arm/include/asm/fixmap.h
··· 7 7 #define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE) 8 8 9 9 #include <linux/pgtable.h> 10 - #include <asm/kmap_types.h> 10 + #include <asm/kmap_size.h> 11 11 12 12 enum fixed_addresses { 13 13 FIX_EARLYCON_MEM_BASE, 14 14 __end_of_permanent_fixed_addresses, 15 15 16 16 FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses, 17 - FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, 17 + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1, 18 18 19 19 /* Support writing RO kernel text via kprobes, jump labels, etc. */ 20 20 FIX_TEXT_POKE0,
+23 -10
arch/arm/include/asm/highmem.h
··· 2 2 #ifndef _ASM_HIGHMEM_H 3 3 #define _ASM_HIGHMEM_H 4 4 5 - #include <asm/kmap_types.h> 5 + #include <asm/fixmap.h> 6 6 7 7 #define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE) 8 8 #define LAST_PKMAP PTRS_PER_PTE ··· 46 46 47 47 #ifdef ARCH_NEEDS_KMAP_HIGH_GET 48 48 extern void *kmap_high_get(struct page *page); 49 - #else 49 + 50 + static inline void *arch_kmap_local_high_get(struct page *page) 51 + { 52 + if (IS_ENABLED(CONFIG_DEBUG_HIGHMEM) && !cache_is_vivt()) 53 + return NULL; 54 + return kmap_high_get(page); 55 + } 56 + #define arch_kmap_local_high_get arch_kmap_local_high_get 57 + 58 + #else /* ARCH_NEEDS_KMAP_HIGH_GET */ 50 59 static inline void *kmap_high_get(struct page *page) 51 60 { 52 61 return NULL; 53 62 } 54 - #endif 63 + #endif /* !ARCH_NEEDS_KMAP_HIGH_GET */ 55 64 56 - /* 57 - * The following functions are already defined by <linux/highmem.h> 58 - * when CONFIG_HIGHMEM is not set. 59 - */ 60 - #ifdef CONFIG_HIGHMEM 61 - extern void *kmap_atomic_pfn(unsigned long pfn); 62 - #endif 65 + #define arch_kmap_local_post_map(vaddr, pteval) \ 66 + local_flush_tlb_kernel_page(vaddr) 67 + 68 + #define arch_kmap_local_pre_unmap(vaddr) \ 69 + do { \ 70 + if (cache_is_vivt()) \ 71 + __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); \ 72 + } while (0) 73 + 74 + #define arch_kmap_local_post_unmap(vaddr) \ 75 + local_flush_tlb_kernel_page(vaddr) 63 76 64 77 #endif
-10
arch/arm/include/asm/kmap_types.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef __ARM_KMAP_TYPES_H 3 - #define __ARM_KMAP_TYPES_H 4 - 5 - /* 6 - * This is the "bare minimum". AIO seems to require this. 7 - */ 8 - #define KM_TYPE_NR 16 9 - 10 - #endif
-1
arch/arm/mm/Makefile
··· 19 19 obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o 20 20 21 21 obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o 22 - obj-$(CONFIG_HIGHMEM) += highmem.o 23 22 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 24 23 obj-$(CONFIG_ARM_PV_FIXUP) += pv-fixup-asm.o 25 24
-121
arch/arm/mm/highmem.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * arch/arm/mm/highmem.c -- ARM highmem support 4 - * 5 - * Author: Nicolas Pitre 6 - * Created: september 8, 2008 7 - * Copyright: Marvell Semiconductors Inc. 8 - */ 9 - 10 - #include <linux/module.h> 11 - #include <linux/highmem.h> 12 - #include <linux/interrupt.h> 13 - #include <asm/fixmap.h> 14 - #include <asm/cacheflush.h> 15 - #include <asm/tlbflush.h> 16 - #include "mm.h" 17 - 18 - static inline void set_fixmap_pte(int idx, pte_t pte) 19 - { 20 - unsigned long vaddr = __fix_to_virt(idx); 21 - pte_t *ptep = virt_to_kpte(vaddr); 22 - 23 - set_pte_ext(ptep, pte, 0); 24 - local_flush_tlb_kernel_page(vaddr); 25 - } 26 - 27 - static inline pte_t get_fixmap_pte(unsigned long vaddr) 28 - { 29 - pte_t *ptep = virt_to_kpte(vaddr); 30 - 31 - return *ptep; 32 - } 33 - 34 - void *kmap_atomic_high_prot(struct page *page, pgprot_t prot) 35 - { 36 - unsigned int idx; 37 - unsigned long vaddr; 38 - void *kmap; 39 - int type; 40 - 41 - #ifdef CONFIG_DEBUG_HIGHMEM 42 - /* 43 - * There is no cache coherency issue when non VIVT, so force the 44 - * dedicated kmap usage for better debugging purposes in that case. 45 - */ 46 - if (!cache_is_vivt()) 47 - kmap = NULL; 48 - else 49 - #endif 50 - kmap = kmap_high_get(page); 51 - if (kmap) 52 - return kmap; 53 - 54 - type = kmap_atomic_idx_push(); 55 - 56 - idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id(); 57 - vaddr = __fix_to_virt(idx); 58 - #ifdef CONFIG_DEBUG_HIGHMEM 59 - /* 60 - * With debugging enabled, kunmap_atomic forces that entry to 0. 61 - * Make sure it was indeed properly unmapped. 62 - */ 63 - BUG_ON(!pte_none(get_fixmap_pte(vaddr))); 64 - #endif 65 - /* 66 - * When debugging is off, kunmap_atomic leaves the previous mapping 67 - * in place, so the contained TLB flush ensures the TLB is updated 68 - * with the new mapping. 69 - */ 70 - set_fixmap_pte(idx, mk_pte(page, prot)); 71 - 72 - return (void *)vaddr; 73 - } 74 - EXPORT_SYMBOL(kmap_atomic_high_prot); 75 - 76 - void kunmap_atomic_high(void *kvaddr) 77 - { 78 - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; 79 - int idx, type; 80 - 81 - if (kvaddr >= (void *)FIXADDR_START) { 82 - type = kmap_atomic_idx(); 83 - idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id(); 84 - 85 - if (cache_is_vivt()) 86 - __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); 87 - #ifdef CONFIG_DEBUG_HIGHMEM 88 - BUG_ON(vaddr != __fix_to_virt(idx)); 89 - set_fixmap_pte(idx, __pte(0)); 90 - #else 91 - (void) idx; /* to kill a warning */ 92 - #endif 93 - kmap_atomic_idx_pop(); 94 - } else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) { 95 - /* this address was obtained through kmap_high_get() */ 96 - kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)])); 97 - } 98 - } 99 - EXPORT_SYMBOL(kunmap_atomic_high); 100 - 101 - void *kmap_atomic_pfn(unsigned long pfn) 102 - { 103 - unsigned long vaddr; 104 - int idx, type; 105 - struct page *page = pfn_to_page(pfn); 106 - 107 - preempt_disable(); 108 - pagefault_disable(); 109 - if (!PageHighMem(page)) 110 - return page_address(page); 111 - 112 - type = kmap_atomic_idx_push(); 113 - idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id(); 114 - vaddr = __fix_to_virt(idx); 115 - #ifdef CONFIG_DEBUG_HIGHMEM 116 - BUG_ON(!pte_none(get_fixmap_pte(vaddr))); 117 - #endif 118 - set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); 119 - 120 - return (void *)vaddr; 121 - }