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
arm
mm
highmem.c
Go to the documentation of this file.
1
/*
2
* arch/arm/mm/highmem.c -- ARM highmem support
3
*
4
* Author: Nicolas Pitre
5
* Created: september 8, 2008
6
* Copyright: Marvell Semiconductors Inc.
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*/
12
13
#include <linux/module.h>
14
#include <
linux/highmem.h
>
15
#include <
linux/interrupt.h
>
16
#include <asm/fixmap.h>
17
#include <asm/cacheflush.h>
18
#include <asm/tlbflush.h>
19
#include "
mm.h
"
20
21
void
*
kmap
(
struct
page
*
page
)
22
{
23
might_sleep
();
24
if
(!PageHighMem(page))
25
return
page_address
(page);
26
return
kmap_high
(page);
27
}
28
EXPORT_SYMBOL
(
kmap
);
29
30
void
kunmap
(
struct
page
*
page
)
31
{
32
BUG_ON
(
in_interrupt
());
33
if
(!PageHighMem(page))
34
return
;
35
kunmap_high
(page);
36
}
37
EXPORT_SYMBOL
(
kunmap
);
38
39
void
*
kmap_atomic
(
struct
page
*
page
)
40
{
41
unsigned
int
idx
;
42
unsigned
long
vaddr
;
43
void
*
kmap
;
44
int
type
;
45
46
pagefault_disable();
47
if
(!PageHighMem(page))
48
return
page_address
(page);
49
50
#ifdef CONFIG_DEBUG_HIGHMEM
51
/*
52
* There is no cache coherency issue when non VIVT, so force the
53
* dedicated kmap usage for better debugging purposes in that case.
54
*/
55
if
(!
cache_is_vivt
())
56
kmap =
NULL
;
57
else
58
#endif
59
kmap =
kmap_high_get
(page);
60
if
(kmap)
61
return
kmap
;
62
63
type = kmap_atomic_idx_push();
64
65
idx = type +
KM_TYPE_NR
*
smp_processor_id
();
66
vaddr =
__fix_to_virt
(
FIX_KMAP_BEGIN
+ idx);
67
#ifdef CONFIG_DEBUG_HIGHMEM
68
/*
69
* With debugging enabled, kunmap_atomic forces that entry to 0.
70
* Make sure it was indeed properly unmapped.
71
*/
72
BUG_ON
(!
pte_none
(get_top_pte(vaddr)));
73
#endif
74
/*
75
* When debugging is off, kunmap_atomic leaves the previous mapping
76
* in place, so the contained TLB flush ensures the TLB is updated
77
* with the new mapping.
78
*/
79
set_top_pte(vaddr,
mk_pte
(page,
kmap_prot
));
80
81
return
(
void
*)
vaddr
;
82
}
83
EXPORT_SYMBOL
(
kmap_atomic
);
84
85
void
__kunmap_atomic
(
void
*kvaddr)
86
{
87
unsigned
long
vaddr
= (
unsigned
long
) kvaddr &
PAGE_MASK
;
88
int
idx
,
type
;
89
90
if
(kvaddr >= (
void
*)
FIXADDR_START
) {
91
type = kmap_atomic_idx();
92
idx = type +
KM_TYPE_NR
*
smp_processor_id
();
93
94
if
(
cache_is_vivt
())
95
__cpuc_flush_dcache_area
((
void
*)vaddr,
PAGE_SIZE
);
96
#ifdef CONFIG_DEBUG_HIGHMEM
97
BUG_ON
(vaddr !=
__fix_to_virt
(
FIX_KMAP_BEGIN
+ idx));
98
set_top_pte(vaddr,
__pte
(0));
99
#else
100
(
void
) idx;
/* to kill a warning */
101
#endif
102
kmap_atomic_idx_pop();
103
}
else
if
(vaddr >=
PKMAP_ADDR
(0) && vaddr <
PKMAP_ADDR
(
LAST_PKMAP
)) {
104
/* this address was obtained through kmap_high_get() */
105
kunmap_high
(
pte_page
(
pkmap_page_table
[
PKMAP_NR
(vaddr)]));
106
}
107
pagefault_enable();
108
}
109
EXPORT_SYMBOL
(
__kunmap_atomic
);
110
111
void
*
kmap_atomic_pfn
(
unsigned
long
pfn)
112
{
113
unsigned
long
vaddr
;
114
int
idx
,
type
;
115
116
pagefault_disable();
117
118
type = kmap_atomic_idx_push();
119
idx = type +
KM_TYPE_NR
*
smp_processor_id
();
120
vaddr =
__fix_to_virt
(
FIX_KMAP_BEGIN
+ idx);
121
#ifdef CONFIG_DEBUG_HIGHMEM
122
BUG_ON
(!
pte_none
(get_top_pte(vaddr)));
123
#endif
124
set_top_pte(vaddr,
pfn_pte
(pfn,
kmap_prot
));
125
126
return
(
void
*)
vaddr
;
127
}
128
129
struct
page
*
kmap_atomic_to_page
(
const
void
*
ptr
)
130
{
131
unsigned
long
vaddr
= (
unsigned
long
)ptr;
132
133
if
(vaddr <
FIXADDR_START
)
134
return
virt_to_page
(ptr);
135
136
return
pte_page
(get_top_pte(vaddr));
137
}
Generated on Thu Jan 10 2013 13:02:40 for Linux Kernel by
1.8.2