1 /* 2 * High memory support for Xtensa architecture 3 * 4 * This file is subject to the terms and conditions of the GNU General 5 * Public License. See the file "COPYING" in the main directory of 6 * this archive for more details. 7 * 8 * Copyright (C) 2014 Cadence Design Systems Inc. 9 */ 10 11 #include <linux/export.h> 12 #include <linux/highmem.h> 13 #include <asm/tlbflush.h> 14 15 static pte_t *kmap_pte; 16 17 void *kmap_atomic(struct page *page) 18 { 19 enum fixed_addresses idx; 20 unsigned long vaddr; 21 int type; 22 23 pagefault_disable(); 24 if (!PageHighMem(page)) 25 return page_address(page); 26 27 type = kmap_atomic_idx_push(); 28 idx = type + KM_TYPE_NR * smp_processor_id(); 29 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 30 #ifdef CONFIG_DEBUG_HIGHMEM 31 BUG_ON(!pte_none(*(kmap_pte - idx))); 32 #endif 33 set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC)); 34 35 return (void *)vaddr; 36 } 37 EXPORT_SYMBOL(kmap_atomic); 38 39 void __kunmap_atomic(void *kvaddr) 40 { 41 int idx, type; 42 43 if (kvaddr >= (void *)FIXADDR_START && 44 kvaddr < (void *)FIXADDR_TOP) { 45 type = kmap_atomic_idx(); 46 idx = type + KM_TYPE_NR * smp_processor_id(); 47 48 /* 49 * Force other mappings to Oops if they'll try to access this 50 * pte without first remap it. Keeping stale mappings around 51 * is a bad idea also, in case the page changes cacheability 52 * attributes or becomes a protected page in a hypervisor. 53 */ 54 pte_clear(&init_mm, kvaddr, kmap_pte - idx); 55 local_flush_tlb_kernel_range((unsigned long)kvaddr, 56 (unsigned long)kvaddr + PAGE_SIZE); 57 58 kmap_atomic_idx_pop(); 59 } 60 61 pagefault_enable(); 62 } 63 EXPORT_SYMBOL(__kunmap_atomic); 64 65 void __init kmap_init(void) 66 { 67 unsigned long kmap_vstart; 68 69 /* cache the first kmap pte */ 70 kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); 71 kmap_pte = kmap_get_fixmap_pte(kmap_vstart); 72 } 73