aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-08 06:24:29 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 06:24:29 -0400
commit6236af82d8a989e150a02800c210eb61cb1e17be (patch)
treed5e83e66b09fc405ac70925f9b83152abaf48a03
parente3ae0acf59244ecf5b023ec99cef4b6b29d649bc (diff)
parent8b7ef4ec5b1ac8b6feebf5ae9cda85a7514728f8 (diff)
Merge branch 'x86/fixmap' into x86/devel
Conflicts: arch/x86/mm/init_64.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/paravirt.c2
-rw-r--r--arch/x86/mm/init_64.c21
-rw-r--r--arch/x86/mm/pgtable.c20
-rw-r--r--arch/x86/mm/pgtable_32.c20
-rw-r--r--arch/x86/xen/enlighten.c29
-rw-r--r--include/asm-x86/fixmap.h55
-rw-r--r--include/asm-x86/fixmap_32.h42
-rw-r--r--include/asm-x86/fixmap_64.h37
-rw-r--r--include/asm-x86/paravirt.h13
-rw-r--r--include/asm-x86/pgtable.h3
10 files changed, 130 insertions, 112 deletions
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index f1ab0f727007..e9b504537212 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -420,6 +420,8 @@ struct pv_mmu_ops pv_mmu_ops = {
420 .enter = paravirt_nop, 420 .enter = paravirt_nop,
421 .leave = paravirt_nop, 421 .leave = paravirt_nop,
422 }, 422 },
423
424 .set_fixmap = native_set_fixmap,
423}; 425};
424 426
425EXPORT_SYMBOL_GPL(pv_time_ops); 427EXPORT_SYMBOL_GPL(pv_time_ops);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 18c6a006e406..97c2bc741e94 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -148,15 +148,15 @@ static __init void *spp_getpage(void)
148 return ptr; 148 return ptr;
149} 149}
150 150
151static __init void 151void
152set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) 152set_pte_vaddr(unsigned long vaddr, pte_t new_pte)
153{ 153{
154 pgd_t *pgd; 154 pgd_t *pgd;
155 pud_t *pud; 155 pud_t *pud;
156 pmd_t *pmd; 156 pmd_t *pmd;
157 pte_t *pte, new_pte; 157 pte_t *pte;
158 158
159 pr_debug("set_pte_phys %lx to %lx\n", vaddr, phys); 159 pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, native_pte_val(new_pte));
160 160
161 pgd = pgd_offset_k(vaddr); 161 pgd = pgd_offset_k(vaddr);
162 if (pgd_none(*pgd)) { 162 if (pgd_none(*pgd)) {
@@ -183,7 +183,6 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
183 return; 183 return;
184 } 184 }
185 } 185 }
186 new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
187 186
188 pte = pte_offset_kernel(pmd, vaddr); 187 pte = pte_offset_kernel(pmd, vaddr);
189 if (!pte_none(*pte) && pte_val(new_pte) && 188 if (!pte_none(*pte) && pte_val(new_pte) &&
@@ -226,18 +225,6 @@ void __init cleanup_highmap(void)
226 } 225 }
227} 226}
228 227
229/* NOTE: this is meant to be run only at boot */
230void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
231{
232 unsigned long address = __fix_to_virt(idx);
233
234 if (idx >= __end_of_fixed_addresses) {
235 printk(KERN_ERR "Invalid __set_fixmap\n");
236 return;
237 }
238 set_pte_phys(address, phys, prot);
239}
240
241static unsigned long __initdata table_start; 228static unsigned long __initdata table_start;
242static unsigned long __meminitdata table_end; 229static unsigned long __meminitdata table_end;
243 230
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index ee1d6d39edd4..45b99ac39480 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -2,6 +2,7 @@
2#include <asm/pgalloc.h> 2#include <asm/pgalloc.h>
3#include <asm/pgtable.h> 3#include <asm/pgtable.h>
4#include <asm/tlb.h> 4#include <asm/tlb.h>
5#include <asm/fixmap.h>
5 6
6pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) 7pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
7{ 8{
@@ -274,3 +275,22 @@ int ptep_clear_flush_young(struct vm_area_struct *vma,
274 275
275 return young; 276 return young;
276} 277}
278
279int fixmaps_set;
280
281void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
282{
283 unsigned long address = __fix_to_virt(idx);
284
285 if (idx >= __end_of_fixed_addresses) {
286 BUG();
287 return;
288 }
289 set_pte_vaddr(address, pte);
290 fixmaps_set++;
291}
292
293void native_set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
294{
295 __native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, flags));
296}
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index 369cf065b6a4..0662f345212f 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -71,7 +71,7 @@ void show_mem(void)
71 * Associate a virtual page frame with a given physical page frame 71 * Associate a virtual page frame with a given physical page frame
72 * and protection flags for that frame. 72 * and protection flags for that frame.
73 */ 73 */
74static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) 74void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
75{ 75{
76 pgd_t *pgd; 76 pgd_t *pgd;
77 pud_t *pud; 77 pud_t *pud;
@@ -94,8 +94,8 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
94 return; 94 return;
95 } 95 }
96 pte = pte_offset_kernel(pmd, vaddr); 96 pte = pte_offset_kernel(pmd, vaddr);
97 if (pgprot_val(flags)) 97 if (pte_val(pteval))
98 set_pte_present(&init_mm, vaddr, pte, pfn_pte(pfn, flags)); 98 set_pte_present(&init_mm, vaddr, pte, pteval);
99 else 99 else
100 pte_clear(&init_mm, vaddr, pte); 100 pte_clear(&init_mm, vaddr, pte);
101 101
@@ -145,18 +145,6 @@ static int fixmaps;
145unsigned long __FIXADDR_TOP = 0xfffff000; 145unsigned long __FIXADDR_TOP = 0xfffff000;
146EXPORT_SYMBOL(__FIXADDR_TOP); 146EXPORT_SYMBOL(__FIXADDR_TOP);
147 147
148void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
149{
150 unsigned long address = __fix_to_virt(idx);
151
152 if (idx >= __end_of_fixed_addresses) {
153 BUG();
154 return;
155 }
156 set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
157 fixmaps++;
158}
159
160/** 148/**
161 * reserve_top_address - reserves a hole in the top of kernel address space 149 * reserve_top_address - reserves a hole in the top of kernel address space
162 * @reserve - size of hole to reserve 150 * @reserve - size of hole to reserve
@@ -166,7 +154,7 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
166 */ 154 */
167void reserve_top_address(unsigned long reserve) 155void reserve_top_address(unsigned long reserve)
168{ 156{
169 BUG_ON(fixmaps > 0); 157 BUG_ON(fixmaps_set > 0);
170 printk(KERN_INFO "Reserving virtual address space above 0x%08x\n", 158 printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
171 (int)-reserve); 159 (int)-reserve);
172 __FIXADDR_TOP = -reserve - PAGE_SIZE; 160 __FIXADDR_TOP = -reserve - PAGE_SIZE;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index fe60aa9fed0a..316623cf411f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1013,6 +1013,33 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
1013 return ret; 1013 return ret;
1014} 1014}
1015 1015
1016static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot)
1017{
1018 pte_t pte;
1019
1020 phys >>= PAGE_SHIFT;
1021
1022 switch (idx) {
1023 case FIX_BTMAP_END ... FIX_BTMAP_BEGIN:
1024#ifdef CONFIG_X86_F00F_BUG
1025 case FIX_F00F_IDT:
1026#endif
1027 case FIX_WP_TEST:
1028 case FIX_VDSO:
1029#ifdef CONFIG_X86_LOCAL_APIC
1030 case FIX_APIC_BASE: /* maps dummy local APIC */
1031#endif
1032 pte = pfn_pte(phys, prot);
1033 break;
1034
1035 default:
1036 pte = mfn_pte(phys, prot);
1037 break;
1038 }
1039
1040 __native_set_fixmap(idx, pte);
1041}
1042
1016static const struct pv_info xen_info __initdata = { 1043static const struct pv_info xen_info __initdata = {
1017 .paravirt_enabled = 1, 1044 .paravirt_enabled = 1,
1018 .shared_kernel_pmd = 0, 1045 .shared_kernel_pmd = 0,
@@ -1167,6 +1194,8 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
1167 .enter = paravirt_enter_lazy_mmu, 1194 .enter = paravirt_enter_lazy_mmu,
1168 .leave = xen_leave_lazy, 1195 .leave = xen_leave_lazy,
1169 }, 1196 },
1197
1198 .set_fixmap = xen_set_fixmap,
1170}; 1199};
1171 1200
1172#ifdef CONFIG_SMP 1201#ifdef CONFIG_SMP
diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h
index 5bd206973dca..44d4f8217349 100644
--- a/include/asm-x86/fixmap.h
+++ b/include/asm-x86/fixmap.h
@@ -7,7 +7,62 @@
7# include "fixmap_64.h" 7# include "fixmap_64.h"
8#endif 8#endif
9 9
10extern int fixmaps_set;
11
12void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
13void native_set_fixmap(enum fixed_addresses idx,
14 unsigned long phys, pgprot_t flags);
15
16#ifndef CONFIG_PARAVIRT
17static inline void __set_fixmap(enum fixed_addresses idx,
18 unsigned long phys, pgprot_t flags)
19{
20 native_set_fixmap(idx, phys, flags);
21}
22#endif
23
24#define set_fixmap(idx, phys) \
25 __set_fixmap(idx, phys, PAGE_KERNEL)
26
27/*
28 * Some hardware wants to get fixmapped without caching.
29 */
30#define set_fixmap_nocache(idx, phys) \
31 __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
32
10#define clear_fixmap(idx) \ 33#define clear_fixmap(idx) \
11 __set_fixmap(idx, 0, __pgprot(0)) 34 __set_fixmap(idx, 0, __pgprot(0))
12 35
36#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
37#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
38
39extern void __this_fixmap_does_not_exist(void);
40
41/*
42 * 'index to address' translation. If anyone tries to use the idx
43 * directly without translation, we catch the bug with a NULL-deference
44 * kernel oops. Illegal ranges of incoming indices are caught too.
45 */
46static __always_inline unsigned long fix_to_virt(const unsigned int idx)
47{
48 /*
49 * this branch gets completely eliminated after inlining,
50 * except when someone tries to use fixaddr indices in an
51 * illegal way. (such as mixing up address types or using
52 * out-of-range indices).
53 *
54 * If it doesn't get removed, the linker will complain
55 * loudly with a reasonably clear error message..
56 */
57 if (idx >= __end_of_fixed_addresses)
58 __this_fixmap_does_not_exist();
59
60 return __fix_to_virt(idx);
61}
62
63static inline unsigned long virt_to_fix(const unsigned long vaddr)
64{
65 BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
66 return __virt_to_fix(vaddr);
67}
13#endif 68#endif
diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h
index f0df7ee96816..aae2f0501a40 100644
--- a/include/asm-x86/fixmap_32.h
+++ b/include/asm-x86/fixmap_32.h
@@ -109,17 +109,8 @@ enum fixed_addresses {
109 __end_of_fixed_addresses 109 __end_of_fixed_addresses
110}; 110};
111 111
112extern void __set_fixmap(enum fixed_addresses idx,
113 unsigned long phys, pgprot_t flags);
114extern void reserve_top_address(unsigned long reserve); 112extern void reserve_top_address(unsigned long reserve);
115 113
116#define set_fixmap(idx, phys) \
117 __set_fixmap(idx, phys, PAGE_KERNEL)
118/*
119 * Some hardware wants to get fixmapped without caching.
120 */
121#define set_fixmap_nocache(idx, phys) \
122 __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
123 114
124#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) 115#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
125 116
@@ -128,38 +119,5 @@ extern void reserve_top_address(unsigned long reserve);
128#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE) 119#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
129#define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE) 120#define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
130 121
131#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
132#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
133
134extern void __this_fixmap_does_not_exist(void);
135
136/*
137 * 'index to address' translation. If anyone tries to use the idx
138 * directly without tranlation, we catch the bug with a NULL-deference
139 * kernel oops. Illegal ranges of incoming indices are caught too.
140 */
141static __always_inline unsigned long fix_to_virt(const unsigned int idx)
142{
143 /*
144 * this branch gets completely eliminated after inlining,
145 * except when someone tries to use fixaddr indices in an
146 * illegal way. (such as mixing up address types or using
147 * out-of-range indices).
148 *
149 * If it doesn't get removed, the linker will complain
150 * loudly with a reasonably clear error message..
151 */
152 if (idx >= __end_of_fixed_addresses)
153 __this_fixmap_does_not_exist();
154
155 return __fix_to_virt(idx);
156}
157
158static inline unsigned long virt_to_fix(const unsigned long vaddr)
159{
160 BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
161 return __virt_to_fix(vaddr);
162}
163
164#endif /* !__ASSEMBLY__ */ 122#endif /* !__ASSEMBLY__ */
165#endif 123#endif
diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h
index 355d26a75a82..626098823a0c 100644
--- a/include/asm-x86/fixmap_64.h
+++ b/include/asm-x86/fixmap_64.h
@@ -52,17 +52,6 @@ enum fixed_addresses {
52 __end_of_fixed_addresses 52 __end_of_fixed_addresses
53}; 53};
54 54
55extern void __set_fixmap(enum fixed_addresses idx,
56 unsigned long phys, pgprot_t flags);
57
58#define set_fixmap(idx, phys) \
59 __set_fixmap(idx, phys, PAGE_KERNEL)
60/*
61 * Some hardware wants to get fixmapped without caching.
62 */
63#define set_fixmap_nocache(idx, phys) \
64 __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
65
66#define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE) 55#define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE)
67#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) 56#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
68#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) 57#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
@@ -71,30 +60,4 @@ extern void __set_fixmap(enum fixed_addresses idx,
71#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) 60#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL)
72#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) 61#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
73 62
74#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
75
76extern void __this_fixmap_does_not_exist(void);
77
78/*
79 * 'index to address' translation. If anyone tries to use the idx
80 * directly without translation, we catch the bug with a NULL-deference
81 * kernel oops. Illegal ranges of incoming indices are caught too.
82 */
83static __always_inline unsigned long fix_to_virt(const unsigned int idx)
84{
85 /*
86 * this branch gets completely eliminated after inlining,
87 * except when someone tries to use fixaddr indices in an
88 * illegal way. (such as mixing up address types or using
89 * out-of-range indices).
90 *
91 * If it doesn't get removed, the linker will complain
92 * loudly with a reasonably clear error message..
93 */
94 if (idx >= __end_of_fixed_addresses)
95 __this_fixmap_does_not_exist();
96
97 return __fix_to_virt(idx);
98}
99
100#endif 63#endif
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index e9ada314dfc1..41f5447efd88 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -279,6 +279,13 @@ struct pv_mmu_ops {
279#endif 279#endif
280 280
281 struct pv_lazy_ops lazy_mode; 281 struct pv_lazy_ops lazy_mode;
282
283 /* dom0 ops */
284
285 /* Sometimes the physical address is a pfn, and sometimes its
286 an mfn. We can tell which is which from the index. */
287 void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx,
288 unsigned long phys, pgprot_t flags);
282}; 289};
283 290
284/* This contains all the paravirt structures: we get a convenient 291/* This contains all the paravirt structures: we get a convenient
@@ -1295,6 +1302,12 @@ static inline void arch_flush_lazy_mmu_mode(void)
1295 } 1302 }
1296} 1303}
1297 1304
1305static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
1306 unsigned long phys, pgprot_t flags)
1307{
1308 pv_mmu_ops.set_fixmap(idx, phys, flags);
1309}
1310
1298void _paravirt_nop(void); 1311void _paravirt_nop(void);
1299#define paravirt_nop ((void *)_paravirt_nop) 1312#define paravirt_nop ((void *)_paravirt_nop)
1300 1313
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
index bcb5446a08d1..f048975b31a4 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -313,6 +313,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
313 unsigned long size, pgprot_t *vma_prot); 313 unsigned long size, pgprot_t *vma_prot);
314#endif 314#endif
315 315
316/* Install a pte for a particular vaddr in kernel space. */
317void set_pte_vaddr(unsigned long vaddr, pte_t pte);
318
316#ifdef CONFIG_PARAVIRT 319#ifdef CONFIG_PARAVIRT
317#include <asm/paravirt.h> 320#include <asm/paravirt.h>
318#else /* !CONFIG_PARAVIRT */ 321#else /* !CONFIG_PARAVIRT */