1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2d73cd428SNicolas Pitre #ifndef _ASM_HIGHMEM_H 3d73cd428SNicolas Pitre #define _ASM_HIGHMEM_H 4d73cd428SNicolas Pitre 5d73cd428SNicolas Pitre #include <asm/kmap_types.h> 6d73cd428SNicolas Pitre 7d73cd428SNicolas Pitre #define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE) 8d73cd428SNicolas Pitre #define LAST_PKMAP PTRS_PER_PTE 9d73cd428SNicolas Pitre #define LAST_PKMAP_MASK (LAST_PKMAP - 1) 10d73cd428SNicolas Pitre #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) 11d73cd428SNicolas Pitre #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) 12d73cd428SNicolas Pitre 13d73cd428SNicolas Pitre #define kmap_prot PAGE_KERNEL 14d73cd428SNicolas Pitre 157e5a69e8SNicolas Pitre #define flush_cache_kmaps() \ 167e5a69e8SNicolas Pitre do { \ 177e5a69e8SNicolas Pitre if (cache_is_vivt()) \ 187e5a69e8SNicolas Pitre flush_cache_all(); \ 197e5a69e8SNicolas Pitre } while (0) 20d73cd428SNicolas Pitre 21d73cd428SNicolas Pitre extern pte_t *pkmap_page_table; 22a05e54c1SLiu Hua extern pte_t *fixmap_page_table; 23d73cd428SNicolas Pitre 24d73cd428SNicolas Pitre extern void *kmap_high(struct page *page); 25d73cd428SNicolas Pitre extern void kunmap_high(struct page *page); 26d73cd428SNicolas Pitre 277e5a69e8SNicolas Pitre /* 28aaa50048SNicolas Pitre * The reason for kmap_high_get() is to ensure that the currently kmap'd 29aaa50048SNicolas Pitre * page usage count does not decrease to zero while we're using its 30aaa50048SNicolas Pitre * existing virtual mapping in an atomic context. With a VIVT cache this 31aaa50048SNicolas Pitre * is essential to do, but with a VIPT cache this is only an optimization 32aaa50048SNicolas Pitre * so not to pay the price of establishing a second mapping if an existing 33aaa50048SNicolas Pitre * one can be used. However, on platforms without hardware TLB maintenance 34aaa50048SNicolas Pitre * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since 35aaa50048SNicolas Pitre * the locking involved must also disable IRQs which is incompatible with 36aaa50048SNicolas Pitre * the IPI mechanism used by global TLB operations. 37aaa50048SNicolas Pitre */ 38aaa50048SNicolas Pitre #define ARCH_NEEDS_KMAP_HIGH_GET 39aaa50048SNicolas Pitre #if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6) 40aaa50048SNicolas Pitre #undef ARCH_NEEDS_KMAP_HIGH_GET 41aaa50048SNicolas Pitre #if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT) 42aaa50048SNicolas Pitre #error "The sum of features in your kernel config cannot be supported together" 43aaa50048SNicolas Pitre #endif 44aaa50048SNicolas Pitre #endif 45aaa50048SNicolas Pitre 4693dc6887SCatalin Marinas /* 4793dc6887SCatalin Marinas * Needed to be able to broadcast the TLB invalidation for kmap. 4893dc6887SCatalin Marinas */ 4993dc6887SCatalin Marinas #ifdef CONFIG_ARM_ERRATA_798181 5093dc6887SCatalin Marinas #undef ARCH_NEEDS_KMAP_HIGH_GET 5193dc6887SCatalin Marinas #endif 5293dc6887SCatalin Marinas 53aaa50048SNicolas Pitre #ifdef ARCH_NEEDS_KMAP_HIGH_GET 54aaa50048SNicolas Pitre extern void *kmap_high_get(struct page *page); 55aaa50048SNicolas Pitre #else 56aaa50048SNicolas Pitre static inline void *kmap_high_get(struct page *page) 57aaa50048SNicolas Pitre { 58aaa50048SNicolas Pitre return NULL; 59aaa50048SNicolas Pitre } 60aaa50048SNicolas Pitre #endif 61aaa50048SNicolas Pitre 62aaa50048SNicolas Pitre /* 637e5a69e8SNicolas Pitre * The following functions are already defined by <linux/highmem.h> 647e5a69e8SNicolas Pitre * when CONFIG_HIGHMEM is not set. 657e5a69e8SNicolas Pitre */ 667e5a69e8SNicolas Pitre #ifdef CONFIG_HIGHMEM 67d73cd428SNicolas Pitre extern void *kmap(struct page *page); 68d73cd428SNicolas Pitre extern void kunmap(struct page *page); 69a24401bcSCong Wang extern void *kmap_atomic(struct page *page); 703e4d3af5SPeter Zijlstra extern void __kunmap_atomic(void *kvaddr); 713e4d3af5SPeter Zijlstra extern void *kmap_atomic_pfn(unsigned long pfn); 727e5a69e8SNicolas Pitre #endif 73d73cd428SNicolas Pitre 74d73cd428SNicolas Pitre #endif 75