Merge remote-tracking branches 'spi/fix/qup' and 'spi/fix/topcliff-pch' into spi...
[cascardo/linux.git] / arch / xtensa / mm / highmem.c
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 }