Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
sparc
mm
highmem.c
Go to the documentation of this file.
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 <
[email protected]
>, September 2002
9
*
10
* But kmap_atomic() and kunmap_atomic() cannot be inlined in
11
* modules because they are loaded with btfixup-ped functions.
12
*/
13
14
/*
15
* The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
16
* gives a more generic (and caching) interface. But kmap_atomic can
17
* be used in IRQ contexts, so in some (very limited) cases we need it.
18
*
19
* XXX This is an old text. Actually, it's good to use atomic kmaps,
20
* provided you remember that they are atomic and not try to sleep
21
* with a kmap taken, much like a spinlock. Non-atomic kmaps are
22
* shared by CPUs, and so precious, and establishing them requires IPI.
23
* Atomic kmaps are lightweight and we may have NCPUS more of them.
24
*/
25
#include <
linux/highmem.h
>
26
#include <linux/export.h>
27
#include <
linux/mm.h
>
28
29
#include <asm/cacheflush.h>
30
#include <asm/tlbflush.h>
31
#include <asm/pgalloc.h>
32
#include <
asm/vaddrs.h
>
33
34
pgprot_t
kmap_prot
;
35
36
static
pte_t
*kmap_pte;
37
38
void
__init
kmap_init
(
void
)
39
{
40
unsigned
long
address
;
41
pmd_t
*
dir
;
42
43
address =
__fix_to_virt
(
FIX_KMAP_BEGIN
);
44
dir =
pmd_offset
(
pgd_offset_k
(address), address);
45
46
/* cache the first kmap pte */
47
kmap_pte =
pte_offset_kernel
(dir, address);
48
kmap_prot =
__pgprot
(
SRMMU_ET_PTE
|
SRMMU_PRIV
|
SRMMU_CACHE
);
49
}
50
51
void
*
kmap_atomic
(
struct
page
*
page
)
52
{
53
unsigned
long
vaddr
;
54
long
idx
,
type
;
55
56
/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
57
pagefault_disable();
58
if
(!PageHighMem(page))
59
return
page_address
(page);
60
61
type = kmap_atomic_idx_push();
62
idx = type +
KM_TYPE_NR
*
smp_processor_id
();
63
vaddr =
__fix_to_virt
(
FIX_KMAP_BEGIN
+ idx);
64
65
/* XXX Fix - Anton */
66
#if 0
67
__flush_cache_one(vaddr);
68
#else
69
flush_cache_all
();
70
#endif
71
72
#ifdef CONFIG_DEBUG_HIGHMEM
73
BUG_ON
(!
pte_none
(*(kmap_pte-idx)));
74
#endif
75
set_pte
(kmap_pte-idx,
mk_pte
(page, kmap_prot));
76
/* XXX Fix - Anton */
77
#if 0
78
__flush_tlb_one
(vaddr);
79
#else
80
flush_tlb_all
();
81
#endif
82
83
return
(
void
*)
vaddr
;
84
}
85
EXPORT_SYMBOL
(
kmap_atomic
);
86
87
void
__kunmap_atomic
(
void
*kvaddr)
88
{
89
unsigned
long
vaddr
= (
unsigned
long
) kvaddr &
PAGE_MASK
;
90
int
type
;
91
92
if
(vaddr <
FIXADDR_START
) {
// FIXME
93
pagefault_enable();
94
return
;
95
}
96
97
type = kmap_atomic_idx();
98
99
#ifdef CONFIG_DEBUG_HIGHMEM
100
{
101
unsigned
long
idx
;
102
103
idx = type +
KM_TYPE_NR
*
smp_processor_id
();
104
BUG_ON
(vaddr !=
__fix_to_virt
(
FIX_KMAP_BEGIN
+idx));
105
106
/* XXX Fix - Anton */
107
#if 0
108
__flush_cache_one(vaddr);
109
#else
110
flush_cache_all
();
111
#endif
112
113
/*
114
* force other mappings to Oops if they'll try to access
115
* this pte without first remap it
116
*/
117
pte_clear
(&
init_mm
, vaddr, kmap_pte-idx);
118
/* XXX Fix - Anton */
119
#if 0
120
__flush_tlb_one
(vaddr);
121
#else
122
flush_tlb_all
();
123
#endif
124
}
125
#endif
126
127
kmap_atomic_idx_pop();
128
pagefault_enable();
129
}
130
EXPORT_SYMBOL
(
__kunmap_atomic
);
Generated on Thu Jan 10 2013 13:02:40 for Linux Kernel by
1.8.2