2 * High memory support for Xtensa architecture
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.
8 * Copyright (C) 2014 Cadence Design Systems Inc.
11 #include <linux/export.h>
12 #include <linux/highmem.h>
13 #include <asm/tlbflush.h>
15 static pte_t *kmap_pte;
17 void *kmap_atomic(struct page *page)
19 enum fixed_addresses idx;
24 if (!PageHighMem(page))
25 return page_address(page);
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)));
33 set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
37 EXPORT_SYMBOL(kmap_atomic);
39 void __kunmap_atomic(void *kvaddr)
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();
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.
54 pte_clear(&init_mm, kvaddr, kmap_pte - idx);
55 local_flush_tlb_kernel_range((unsigned long)kvaddr,
56 (unsigned long)kvaddr + PAGE_SIZE);
58 kmap_atomic_idx_pop();
63 EXPORT_SYMBOL(__kunmap_atomic);
65 void __init kmap_init(void)
67 unsigned long kmap_vstart;
69 /* cache the first kmap pte */
70 kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
71 kmap_pte = kmap_get_fixmap_pte(kmap_vstart);