1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#ifndef _ASM_HIGHMEM_H
19#define _ASM_HIGHMEM_H
20
21#ifdef __KERNEL__
22
23#include <linux/config.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <asm/kmap_types.h>
27#include <asm/pgtable.h>
28
29#ifdef CONFIG_DEBUG_HIGHMEM
30#define HIGHMEM_DEBUG 1
31#else
32#define HIGHMEM_DEBUG 0
33#endif
34
35
36extern unsigned long highstart_pfn, highend_pfn;
37
38extern pte_t *kmap_pte;
39extern pgprot_t kmap_prot;
40extern pte_t *pkmap_page_table;
41
42extern void kmap_init(void) __init;
43
44
45
46
47
48
49#define PKMAP_BASE (0xff800000UL)
50#ifdef CONFIG_X86_PAE
51#define LAST_PKMAP 512
52#else
53#define LAST_PKMAP 1024
54#endif
55#define LAST_PKMAP_MASK (LAST_PKMAP-1)
56#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
57#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
58
59extern void * FASTCALL(kmap_high(struct page *page, int nonblocking));
60extern void FASTCALL(kunmap_high(struct page *page));
61
62#define kmap(page) __kmap(page, 0)
63#define kmap_nonblock(page) __kmap(page, 1)
64
65static inline void *__kmap(struct page *page, int nonblocking)
66{
67 if (in_interrupt())
68 out_of_line_bug();
69 if (page < highmem_start_page)
70 return page_address(page);
71 return kmap_high(page, nonblocking);
72}
73
74static inline void kunmap(struct page *page)
75{
76 if (in_interrupt())
77 out_of_line_bug();
78 if (page < highmem_start_page)
79 return;
80 kunmap_high(page);
81}
82
83
84
85
86
87
88
89static inline void *kmap_atomic(struct page *page, enum km_type type)
90{
91 enum fixed_addresses idx;
92 unsigned long vaddr;
93
94 if (page < highmem_start_page)
95 return page_address(page);
96
97 idx = type + KM_TYPE_NR*smp_processor_id();
98 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
99#if HIGHMEM_DEBUG
100 if (!pte_none(*(kmap_pte-idx)))
101 out_of_line_bug();
102#endif
103 set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
104 __flush_tlb_one(vaddr);
105
106 return (void*) vaddr;
107}
108
109static inline void kunmap_atomic(void *kvaddr, enum km_type type)
110{
111#if HIGHMEM_DEBUG
112 unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
113 enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
114
115 if (vaddr < FIXADDR_START)
116 return;
117
118 if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
119 out_of_line_bug();
120
121
122
123
124
125 pte_clear(kmap_pte-idx);
126 __flush_tlb_one(vaddr);
127#endif
128}
129
130#endif
131
132#endif
133