/[pkg-src]/trunk/kernel26-xen/patches-2.6.25-r1/1065-2.6.25-xen-Trying-to-make-the-pagetable-initialization-code-wor.patch |
Contents of /trunk/kernel26-xen/patches-2.6.25-r1/1065-2.6.25-xen-Trying-to-make-the-pagetable-initialization-code-wor.patch
Parent Directory | Revision Log
Revision 606 -
(show annotations)
(download)
Thu May 22 23:13:13 2008 UTC (15 years, 11 months ago) by niro
File size: 8557 byte(s)
Thu May 22 23:13:13 2008 UTC (15 years, 11 months ago) by niro
File size: 8557 byte(s)
-ver bump to 2.6.25-magellan-r1: - linux-2.6.25.4 - fbcondecor-0.9.4 - squashfs-3.3 - unionfs-2.3.3 - tuxonice-3.0-rc7 - linux-phc-0.3.0 - acpi-dstd-0.9a - reiser4 - xen-3.2.0 . ipw3945-1.2.2
1 | From 0e9f82c8cfc17b0fb15ca0e0951687cc7c2df281 Mon Sep 17 00:00:00 2001 |
2 | From: Eduardo Habkost <ehabkost@redhat.com> |
3 | Date: Wed, 12 Dec 2007 16:26:56 -0200 |
4 | Subject: [PATCH] Trying to make the pagetable initialization code work under Xen |
5 | |
6 | To be fixed: |
7 | |
8 | - Lots of #ifdef CONFIG_XEN that will break bare metal |
9 | - Make it actually work |
10 | |
11 | Wrt. pse_available() in pgtable_64.h: |
12 | |
13 | - Probably we may use the CPU feature code to handle this |
14 | - We need it to be variable (not constant 0) if Xen is supported |
15 | |
16 | Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> |
17 | --- |
18 | arch/x86/mm/init_64.c | 153 ++++++++++++++++++++++++++++++++++++++++-- |
19 | include/asm-x86/paravirt.h | 10 +++ |
20 | include/asm-x86/pgalloc_64.h | 1 + |
21 | include/asm-x86/pgtable.h | 4 + |
22 | 4 files changed, 161 insertions(+), 7 deletions(-) |
23 | |
24 | diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c |
25 | index b5f1f6e..69d1056 100644 |
26 | --- a/arch/x86/mm/init_64.c |
27 | +++ b/arch/x86/mm/init_64.c |
28 | @@ -47,6 +47,22 @@ |
29 | #include <asm/numa.h> |
30 | #include <asm/cacheflush.h> |
31 | |
32 | +#ifdef CONFIG_XEN |
33 | +/*FIXME: ouch. */ |
34 | +#include <xen/features.h> |
35 | +#include <xen/page.h> |
36 | +#include <xen/hvc-console.h> |
37 | +#include <asm/xen/hypercall.h> |
38 | +#include "../xen/init.h" |
39 | +#include "../xen/xen-ops.h" |
40 | +#endif |
41 | + |
42 | +#ifdef CONFIG_XEN |
43 | +/*FIXME: ouch again */ |
44 | +#define PTE_SIZE PAGE_SIZE |
45 | +#else |
46 | +#endif |
47 | + |
48 | const struct dma_mapping_ops *dma_ops; |
49 | EXPORT_SYMBOL(dma_ops); |
50 | |
51 | @@ -102,6 +118,9 @@ void show_mem(void) |
52 | |
53 | int after_bootmem; |
54 | |
55 | +static unsigned long __initdata table_start; |
56 | +static unsigned long __meminitdata table_end; |
57 | + |
58 | static __init void *spp_getpage(void) |
59 | { |
60 | void *ptr; |
61 | @@ -232,8 +251,75 @@ native_set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) |
62 | __native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, prot)); |
63 | } |
64 | |
65 | -static unsigned long __initdata table_start; |
66 | -static unsigned long __meminitdata table_end; |
67 | + |
68 | +#ifdef CONFIG_XEN |
69 | + |
70 | +/*FIXME: this code should be enabled at runtime, somehow */ |
71 | + |
72 | +unsigned long start_pfn; |
73 | + |
74 | +static __meminit void *alloc_low_page(unsigned long *phys) |
75 | +{ |
76 | + unsigned long pfn; |
77 | + void *adr; |
78 | + |
79 | + if (after_bootmem) { |
80 | + adr = (void *)get_zeroed_page(GFP_ATOMIC); |
81 | + *phys = __pa(adr); |
82 | + return adr; |
83 | + } |
84 | + |
85 | + pfn = start_pfn++; |
86 | + *phys = pfn << PAGE_SHIFT; |
87 | + |
88 | + /* The address returned by __va() is not available yet. |
89 | + * This function is used by init_memory_mapping(). We will |
90 | + * use the mapping that was set by Xen for us. |
91 | + */ |
92 | + adr = (void*)((*phys) + __START_KERNEL_map); |
93 | + memset(adr, 0, PAGE_SIZE); |
94 | + |
95 | + return adr; |
96 | +} |
97 | + |
98 | + |
99 | +static inline void __set_pte(pte_t *dst, pte_t val) |
100 | +{ |
101 | + *dst = val; |
102 | +} |
103 | + |
104 | + |
105 | +int make_readonly(unsigned long paddr) |
106 | +{ |
107 | + extern char __vsyscall_0; |
108 | + int readonly = 0; |
109 | + |
110 | + /* Make new page tables read-only. */ |
111 | + if (!xen_feature(XENFEAT_writable_page_tables) |
112 | + && (paddr >= (table_start << PAGE_SHIFT)) |
113 | + && (paddr < (table_end << PAGE_SHIFT))) |
114 | + readonly = 1; |
115 | + /* Make old page tables read-only. */ |
116 | + if (!xen_feature(XENFEAT_writable_page_tables) |
117 | + && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map)) |
118 | + && (paddr < (start_pfn << PAGE_SHIFT))) |
119 | + readonly = 1; |
120 | + |
121 | + /* |
122 | + * No need for writable mapping of kernel image. This also ensures that |
123 | + * page and descriptor tables embedded inside don't have writable |
124 | + * mappings. Exclude the vsyscall area here, allowing alternative |
125 | + * instruction patching to work. |
126 | + */ |
127 | + if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)) |
128 | + && !(paddr >= __pa_symbol(&__vsyscall_0) |
129 | + && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE)) |
130 | + readonly = 1; |
131 | + |
132 | + return readonly; |
133 | +} |
134 | + |
135 | +#else /* !XEN */ |
136 | |
137 | static __meminit void *alloc_low_page(unsigned long *phys) |
138 | { |
139 | @@ -256,12 +342,18 @@ static __meminit void *alloc_low_page(unsigned long *phys) |
140 | return adr; |
141 | } |
142 | |
143 | +#endif /* !XEN */ |
144 | + |
145 | + |
146 | static __meminit void unmap_low_page(void *adr) |
147 | { |
148 | if (after_bootmem) |
149 | return; |
150 | |
151 | +#ifndef CONFIG_XEN |
152 | + /*FIXME: this behaviour should be changed in runtime, also */ |
153 | early_iounmap(adr, PAGE_SIZE); |
154 | +#endif |
155 | } |
156 | |
157 | /* Must run before zap_low_mappings */ |
158 | @@ -284,8 +376,9 @@ __meminit void *early_ioremap(unsigned long addr, unsigned long size) |
159 | vaddr += addr & ~PMD_MASK; |
160 | addr &= PMD_MASK; |
161 | |
162 | - for (i = 0; i < pmds; i++, addr += PMD_SIZE) |
163 | + for (i = 0; i < pmds; i++, addr += PMD_SIZE) { |
164 | set_pmd(pmd+i, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); |
165 | + } /* for pmds */ |
166 | __flush_tlb_all(); |
167 | |
168 | return (void *)vaddr; |
169 | @@ -321,7 +414,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) |
170 | { |
171 | int i = pmd_index(address); |
172 | |
173 | - for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) { |
174 | + for (; i < PTRS_PER_PMD; i++) { |
175 | pmd_t *pmd = pmd_page + pmd_index(address); |
176 | |
177 | if (address >= end) { |
178 | @@ -335,8 +428,46 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) |
179 | if (pmd_val(*pmd)) |
180 | continue; |
181 | |
182 | - set_pte((pte_t *)pmd, |
183 | - pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
184 | + if (pse_available()) { |
185 | + /* Lucky us :) */ |
186 | + set_pte((pte_t *)pmd, |
187 | + pfn_pte(address >> PAGE_SHIFT, |
188 | + PAGE_KERNEL_LARGE)); |
189 | + address += PMD_SIZE; |
190 | + } else { |
191 | + /* No PSE support. Must make lots of PTEs */ |
192 | + unsigned long pte_phys; |
193 | + pte_t *pte, *pte_save; |
194 | + int k; |
195 | + |
196 | + pte = alloc_low_page(&pte_phys); |
197 | + pte_save = pte; |
198 | + for (k = 0; k < PTRS_PER_PTE; pte++, k++, address += PTE_SIZE) { |
199 | + pteval_t attrs; |
200 | + if ((address >= end)) { |
201 | + __set_pte(pte, __pte(0)); |
202 | + continue; |
203 | + } |
204 | + |
205 | + /*FIXME: _PAGE_GLOBAL is skipped here, |
206 | + * but this is Xen-specific. Use pvops |
207 | + * to handle this |
208 | + */ |
209 | + attrs = __PAGE_KERNEL; |
210 | + |
211 | + /*FIXME: somehow we need to make those |
212 | + * pages readonly on some other place |
213 | + */ |
214 | + if (make_readonly(address)) |
215 | + attrs &= ~_PAGE_RW; |
216 | + __set_pte(pte, __pte(address | attrs)); |
217 | + } |
218 | + pte = pte_save; |
219 | + |
220 | + /*FIXME: this should be done somewhere else */ |
221 | + early_make_page_readonly(pte, XENFEAT_writable_page_tables); |
222 | + set_pmd(pmd, pfn_pmd(pte_phys>>PAGE_SHIFT, PAGE_KERNEL)); |
223 | + } /* !pse_available() */ |
224 | } |
225 | } |
226 | |
227 | @@ -363,11 +494,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) |
228 | if (addr >= end) |
229 | break; |
230 | |
231 | +#ifndef CONFIG_XEN |
232 | + /*FIXME: how to make this enabled on runtime */ |
233 | if (!after_bootmem && |
234 | !e820_any_mapped(addr, addr+PUD_SIZE, 0)) { |
235 | set_pud(pud, __pud(0)); |
236 | continue; |
237 | } |
238 | +#endif |
239 | |
240 | if (pud_val(*pud)) { |
241 | phys_pmd_update(pud, addr, end); |
242 | @@ -375,6 +509,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) |
243 | } |
244 | |
245 | pmd = alloc_low_page(&pmd_phys); |
246 | + /*FIXME: this (making page readonly) should be done somewhere else */ |
247 | + early_make_page_readonly(pmd, XENFEAT_writable_page_tables); |
248 | |
249 | spin_lock(&init_mm.page_table_lock); |
250 | set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); |
251 | @@ -440,8 +576,11 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end) |
252 | |
253 | if (after_bootmem) |
254 | pud = pud_offset(pgd, start & PGDIR_MASK); |
255 | - else |
256 | + else { |
257 | pud = alloc_low_page(&pud_phys); |
258 | + /*FIXME: this (making page readonly) should be done somewhere else */ |
259 | + early_make_page_readonly(pud, XENFEAT_writable_page_tables); |
260 | + } |
261 | |
262 | next = start + PGDIR_SIZE; |
263 | if (next > end) |
264 | diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h |
265 | index c7c4e34..7edbeda 100644 |
266 | --- a/include/asm-x86/paravirt.h |
267 | +++ b/include/asm-x86/paravirt.h |
268 | @@ -153,6 +153,16 @@ struct pv_cpu_ops { |
269 | struct pv_lazy_ops lazy_mode; |
270 | }; |
271 | |
272 | + |
273 | +#ifdef CONFIG_XEN |
274 | +/*FIXME: return 0 only if we are really running under Xen */ |
275 | +#define pse_available() (0) |
276 | +#else |
277 | +/* No Xen support, PSE is always available */ |
278 | +#define pse_available() (1) |
279 | +#endif |
280 | + |
281 | + |
282 | struct pv_irq_ops { |
283 | void (*init_IRQ)(void); |
284 | |
285 | diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h |
286 | index 982e1cb..b9835d6 100644 |
287 | --- a/include/asm-x86/pgalloc_64.h |
288 | +++ b/include/asm-x86/pgalloc_64.h |
289 | @@ -2,6 +2,7 @@ |
290 | #define _X86_64_PGALLOC_H |
291 | |
292 | #include <asm/pda.h> |
293 | +#include <asm/vsyscall.h> |
294 | #include <linux/threads.h> |
295 | #include <linux/mm.h> |
296 | |
297 | diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h |
298 | index 9cf472a..6b3979e 100644 |
299 | --- a/include/asm-x86/pgtable.h |
300 | +++ b/include/asm-x86/pgtable.h |
301 | @@ -232,6 +232,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
302 | |
303 | #define pte_update(mm, addr, ptep) do { } while (0) |
304 | #define pte_update_defer(mm, addr, ptep) do { } while (0) |
305 | + |
306 | +/*FIXME: this have a better place than here */ |
307 | +#define pse_available() (1) |
308 | + |
309 | #endif /* CONFIG_PARAVIRT */ |
310 | |
311 | #endif /* __ASSEMBLY__ */ |
312 | -- |
313 | 1.5.4.1 |
314 |