xref: /openbmc/linux/arch/xtensa/mm/highmem.c (revision 33ac9dba)
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