1 /*
2  *  highmem.c: virtual kernel memory mappings for high memory
3  *
4  *  Provides kernel-static versions of atomic kmap functions originally
5  *  found as inlines in include/asm-sparc/highmem.h.  These became
6  *  needed as kmap_atomic() and kunmap_atomic() started getting
7  *  called from within modules.
8  *  -- Tomas Szepe <szepe@pinerecords.com>, September 2002
9  */
10 
11 #include <linux/mm.h>
12 #include <linux/highmem.h>
13 #include <asm/pgalloc.h>
14 
15 /*
16  * The use of kmap_atomic/kunmap_atomic is discouraged -- kmap()/kunmap()
17  * gives a more generic (and caching) interface.  But kmap_atomic() can
18  * be used in IRQ contexts, so in some (very limited) cases we need it.
19  */
kmap_atomic(struct page * page,enum km_type type)20 void *kmap_atomic(struct page *page, enum km_type type)
21 {
22 	unsigned long idx;
23 	unsigned long vaddr;
24 
25 	if (page < highmem_start_page)
26 		return page_address(page);
27 
28 	idx = type + KM_TYPE_NR * smp_processor_id();
29 	vaddr = fix_kmap_begin + idx * PAGE_SIZE;
30 
31 /* XXX Fix - Anton */
32 #if 0
33 	__flush_cache_one(vaddr);
34 #else
35 	flush_cache_all();
36 #endif
37 
38 #if HIGHMEM_DEBUG
39 	if (!pte_none(*(kmap_pte + idx)))
40 		BUG();
41 #endif
42 	set_pte(kmap_pte + idx, mk_pte(page, kmap_prot));
43 /* XXX Fix - Anton */
44 #if 0
45 	__flush_tlb_one(vaddr);
46 #else
47 	flush_tlb_all();
48 #endif
49 
50 	return (void *) vaddr;
51 }
52 
kunmap_atomic(void * kvaddr,enum km_type type)53 void kunmap_atomic(void *kvaddr, enum km_type type)
54 {
55 	unsigned long vaddr = (unsigned long) kvaddr;
56 	unsigned long idx = type + KM_TYPE_NR * smp_processor_id();
57 
58 	if (vaddr < fix_kmap_begin) /* FIXME */
59 		return;
60 
61 	if (vaddr != fix_kmap_begin + idx * PAGE_SIZE)
62 		BUG();
63 
64 /* XXX Fix - Anton */
65 #if 0
66 	__flush_cache_one(vaddr);
67 #else
68 	flush_cache_all();
69 #endif
70 
71 #ifdef HIGHMEM_DEBUG
72 	/*
73 	 *  Force other mappings to oops if they try to access
74 	 *  this pte without first remapping it.
75 	 */
76 	pte_clear(kmap_pte + idx);
77 /* XXX Fix - Anton */
78 #if 0
79 	__flush_tlb_one(vaddr);
80 #else
81 	flush_tlb_all();
82 #endif
83 #endif
84 }
85