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 #if DCACHE_WAY_SIZE > PAGE_SIZE
18 unsigned int last_pkmap_nr_arr
[DCACHE_N_COLORS
];
19 wait_queue_head_t pkmap_map_wait_arr
[DCACHE_N_COLORS
];
21 static void __init
kmap_waitqueues_init(void)
25 for (i
= 0; i
< ARRAY_SIZE(pkmap_map_wait_arr
); ++i
)
26 init_waitqueue_head(pkmap_map_wait_arr
+ i
);
29 static inline void kmap_waitqueues_init(void)
34 static inline enum fixed_addresses
kmap_idx(int type
, unsigned long color
)
36 return (type
+ KM_TYPE_NR
* smp_processor_id()) * DCACHE_N_COLORS
+
40 void *kmap_atomic(struct page
*page
)
42 enum fixed_addresses idx
;
46 if (!PageHighMem(page
))
47 return page_address(page
);
49 idx
= kmap_idx(kmap_atomic_idx_push(),
50 DCACHE_ALIAS(page_to_phys(page
)));
51 vaddr
= __fix_to_virt(FIX_KMAP_BEGIN
+ idx
);
52 #ifdef CONFIG_DEBUG_HIGHMEM
53 BUG_ON(!pte_none(*(kmap_pte
+ idx
)));
55 set_pte(kmap_pte
+ idx
, mk_pte(page
, PAGE_KERNEL_EXEC
));
59 EXPORT_SYMBOL(kmap_atomic
);
61 void __kunmap_atomic(void *kvaddr
)
63 if (kvaddr
>= (void *)FIXADDR_START
&&
64 kvaddr
< (void *)FIXADDR_TOP
) {
65 int idx
= kmap_idx(kmap_atomic_idx(),
66 DCACHE_ALIAS((unsigned long)kvaddr
));
69 * Force other mappings to Oops if they'll try to access this
70 * pte without first remap it. Keeping stale mappings around
71 * is a bad idea also, in case the page changes cacheability
72 * attributes or becomes a protected page in a hypervisor.
74 pte_clear(&init_mm
, kvaddr
, kmap_pte
+ idx
);
75 local_flush_tlb_kernel_range((unsigned long)kvaddr
,
76 (unsigned long)kvaddr
+ PAGE_SIZE
);
78 kmap_atomic_idx_pop();
83 EXPORT_SYMBOL(__kunmap_atomic
);
85 void __init
kmap_init(void)
87 unsigned long kmap_vstart
;
89 /* cache the first kmap pte */
90 kmap_vstart
= __fix_to_virt(FIX_KMAP_BEGIN
);
91 kmap_pte
= kmap_get_fixmap_pte(kmap_vstart
);
92 kmap_waitqueues_init();