source: trunk/packages/xen-common/xen-common/patches/linux-2.6.18/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

  • Property svn:mime-type set to text/x-patch
File size: 10.8 KB
RevLine 
[34]1diff -pruN ../orig-linux-2.6.18/arch/i386/kernel/machine_kexec.c ./arch/i386/kernel/machine_kexec.c
2--- ../orig-linux-2.6.18/arch/i386/kernel/machine_kexec.c       2006-09-20 04:42:06.000000000 +0100
3+++ ./arch/i386/kernel/machine_kexec.c  2007-01-12 16:03:23.000000000 +0000
4@@ -20,70 +20,13 @@
5 #include <asm/system.h>
6 
7 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
8-
9-#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
10-#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
11-#define L2_ATTR (_PAGE_PRESENT)
12-
13-#define LEVEL0_SIZE (1UL << 12UL)
14-
15-#ifndef CONFIG_X86_PAE
16-#define LEVEL1_SIZE (1UL << 22UL)
17-static u32 pgtable_level1[1024] PAGE_ALIGNED;
18-
19-static void identity_map_page(unsigned long address)
20-{
21-       unsigned long level1_index, level2_index;
22-       u32 *pgtable_level2;
23-
24-       /* Find the current page table */
25-       pgtable_level2 = __va(read_cr3());
26-
27-       /* Find the indexes of the physical address to identity map */
28-       level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
29-       level2_index = address / LEVEL1_SIZE;
30-
31-       /* Identity map the page table entry */
32-       pgtable_level1[level1_index] = address | L0_ATTR;
33-       pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
34-
35-       /* Flush the tlb so the new mapping takes effect.
36-        * Global tlb entries are not flushed but that is not an issue.
37-        */
38-       load_cr3(pgtable_level2);
39-}
40-
41-#else
42-#define LEVEL1_SIZE (1UL << 21UL)
43-#define LEVEL2_SIZE (1UL << 30UL)
44-static u64 pgtable_level1[512] PAGE_ALIGNED;
45-static u64 pgtable_level2[512] PAGE_ALIGNED;
46-
47-static void identity_map_page(unsigned long address)
48-{
49-       unsigned long level1_index, level2_index, level3_index;
50-       u64 *pgtable_level3;
51-
52-       /* Find the current page table */
53-       pgtable_level3 = __va(read_cr3());
54-
55-       /* Find the indexes of the physical address to identity map */
56-       level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
57-       level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
58-       level3_index = address / LEVEL2_SIZE;
59-
60-       /* Identity map the page table entry */
61-       pgtable_level1[level1_index] = address | L0_ATTR;
62-       pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
63-       set_64bit(&pgtable_level3[level3_index],
64-                                              __pa(pgtable_level2) | L2_ATTR);
65-
66-       /* Flush the tlb so the new mapping takes effect.
67-        * Global tlb entries are not flushed but that is not an issue.
68-        */
69-       load_cr3(pgtable_level3);
70-}
71+static u32 kexec_pgd[1024] PAGE_ALIGNED;
72+#ifdef CONFIG_X86_PAE
73+static u32 kexec_pmd0[1024] PAGE_ALIGNED;
74+static u32 kexec_pmd1[1024] PAGE_ALIGNED;
75 #endif
76+static u32 kexec_pte0[1024] PAGE_ALIGNED;
77+static u32 kexec_pte1[1024] PAGE_ALIGNED;
78 
79 static void set_idt(void *newidt, __u16 limit)
80 {
81@@ -127,16 +70,6 @@ static void load_segments(void)
82 #undef __STR
83 }
84 
85-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
86-                                       unsigned long indirection_page,
87-                                       unsigned long reboot_code_buffer,
88-                                       unsigned long start_address,
89-                                       unsigned int has_pae) ATTRIB_NORET;
90-
91-extern const unsigned char relocate_new_kernel[];
92-extern void relocate_new_kernel_end(void);
93-extern const unsigned int relocate_new_kernel_size;
94-
95 /*
96  * A architecture hook called to validate the
97  * proposed image and prepare the control pages
98@@ -169,25 +102,29 @@ void machine_kexec_cleanup(struct kimage
99  */
100 NORET_TYPE void machine_kexec(struct kimage *image)
101 {
102-       unsigned long page_list;
103-       unsigned long reboot_code_buffer;
104-
105-       relocate_new_kernel_t rnk;
106+       unsigned long page_list[PAGES_NR];
107+       void *control_page;
108 
109        /* Interrupts aren't acceptable while we reboot */
110        local_irq_disable();
111 
112-       /* Compute some offsets */
113-       reboot_code_buffer = page_to_pfn(image->control_code_page)
114-                                                               << PAGE_SHIFT;
115-       page_list = image->head;
116-
117-       /* Set up an identity mapping for the reboot_code_buffer */
118-       identity_map_page(reboot_code_buffer);
119-
120-       /* copy it out */
121-       memcpy((void *)reboot_code_buffer, relocate_new_kernel,
122-                                               relocate_new_kernel_size);
123+       control_page = page_address(image->control_code_page);
124+       memcpy(control_page, relocate_kernel, PAGE_SIZE);
125+
126+       page_list[PA_CONTROL_PAGE] = __pa(control_page);
127+       page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
128+       page_list[PA_PGD] = __pa(kexec_pgd);
129+       page_list[VA_PGD] = (unsigned long)kexec_pgd;
130+#ifdef CONFIG_X86_PAE
131+       page_list[PA_PMD_0] = __pa(kexec_pmd0);
132+       page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
133+       page_list[PA_PMD_1] = __pa(kexec_pmd1);
134+       page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
135+#endif
136+       page_list[PA_PTE_0] = __pa(kexec_pte0);
137+       page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
138+       page_list[PA_PTE_1] = __pa(kexec_pte1);
139+       page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
140 
141        /* The segment registers are funny things, they have both a
142         * visible and an invisible part.  Whenever the visible part is
143@@ -206,6 +143,6 @@ NORET_TYPE void machine_kexec(struct kim
144        set_idt(phys_to_virt(0),0);
145 
146        /* now call it */
147-       rnk = (relocate_new_kernel_t) reboot_code_buffer;
148-       (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
149+       relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
150+                       image->start, cpu_has_pae);
151 }
152diff -pruN ../orig-linux-2.6.18/arch/i386/kernel/relocate_kernel.S ./arch/i386/kernel/relocate_kernel.S
153--- ../orig-linux-2.6.18/arch/i386/kernel/relocate_kernel.S     2006-09-20 04:42:06.000000000 +0100
154+++ ./arch/i386/kernel/relocate_kernel.S        2007-01-12 16:03:23.000000000 +0000
155@@ -7,16 +7,138 @@
156  */
157 
158 #include <linux/linkage.h>
159+#include <asm/page.h>
160+#include <asm/kexec.h>
161+
162+/*
163+ * Must be relocatable PIC code callable as a C function
164+ */
165+
166+#define PTR(x) (x << 2)
167+#define PAGE_ALIGNED (1 << PAGE_SHIFT)
168+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
169+#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
170+
171+       .text
172+       .align PAGE_ALIGNED
173+       .globl relocate_kernel
174+relocate_kernel:
175+       movl    8(%esp), %ebp /* list of pages */
176+
177+#ifdef CONFIG_X86_PAE
178+       /* map the control page at its virtual address */
179+
180+       movl    PTR(VA_PGD)(%ebp), %edi
181+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
182+       andl    $0xc0000000, %eax
183+       shrl    $27, %eax
184+       addl    %edi, %eax
185+
186+       movl    PTR(PA_PMD_0)(%ebp), %edx
187+       orl     $PAE_PGD_ATTR, %edx
188+       movl    %edx, (%eax)
189+
190+       movl    PTR(VA_PMD_0)(%ebp), %edi
191+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
192+       andl    $0x3fe00000, %eax
193+       shrl    $18, %eax
194+       addl    %edi, %eax
195+
196+       movl    PTR(PA_PTE_0)(%ebp), %edx
197+       orl     $PAGE_ATTR, %edx
198+       movl    %edx, (%eax)
199+
200+       movl    PTR(VA_PTE_0)(%ebp), %edi
201+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
202+       andl    $0x001ff000, %eax
203+       shrl    $9, %eax
204+       addl    %edi, %eax
205+
206+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
207+       orl     $PAGE_ATTR, %edx
208+       movl    %edx, (%eax)
209+
210+       /* identity map the control page at its physical address */
211+
212+       movl    PTR(VA_PGD)(%ebp), %edi
213+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
214+       andl    $0xc0000000, %eax
215+       shrl    $27, %eax
216+       addl    %edi, %eax
217+
218+       movl    PTR(PA_PMD_1)(%ebp), %edx
219+       orl     $PAE_PGD_ATTR, %edx
220+       movl    %edx, (%eax)
221+
222+       movl    PTR(VA_PMD_1)(%ebp), %edi
223+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
224+       andl    $0x3fe00000, %eax
225+       shrl    $18, %eax
226+       addl    %edi, %eax
227+
228+       movl    PTR(PA_PTE_1)(%ebp), %edx
229+       orl     $PAGE_ATTR, %edx
230+       movl    %edx, (%eax)
231+
232+       movl    PTR(VA_PTE_1)(%ebp), %edi
233+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
234+       andl    $0x001ff000, %eax
235+       shrl    $9, %eax
236+       addl    %edi, %eax
237+
238+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
239+       orl     $PAGE_ATTR, %edx
240+       movl    %edx, (%eax)
241+#else
242+       /* map the control page at its virtual address */
243+
244+       movl    PTR(VA_PGD)(%ebp), %edi
245+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
246+       andl    $0xffc00000, %eax
247+       shrl    $20, %eax
248+       addl    %edi, %eax
249+
250+       movl    PTR(PA_PTE_0)(%ebp), %edx
251+       orl     $PAGE_ATTR, %edx
252+       movl    %edx, (%eax)
253+
254+       movl    PTR(VA_PTE_0)(%ebp), %edi
255+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
256+       andl    $0x003ff000, %eax
257+       shrl    $10, %eax
258+       addl    %edi, %eax
259+
260+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
261+       orl     $PAGE_ATTR, %edx
262+       movl    %edx, (%eax)
263+
264+       /* identity map the control page at its physical address */
265+
266+       movl    PTR(VA_PGD)(%ebp), %edi
267+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
268+       andl    $0xffc00000, %eax
269+       shrl    $20, %eax
270+       addl    %edi, %eax
271+
272+       movl    PTR(PA_PTE_1)(%ebp), %edx
273+       orl     $PAGE_ATTR, %edx
274+       movl    %edx, (%eax)
275+
276+       movl    PTR(VA_PTE_1)(%ebp), %edi
277+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
278+       andl    $0x003ff000, %eax
279+       shrl    $10, %eax
280+       addl    %edi, %eax
281+
282+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
283+       orl     $PAGE_ATTR, %edx
284+       movl    %edx, (%eax)
285+#endif
286 
287-       /*
288-        * Must be relocatable PIC code callable as a C function, that once
289-        * it starts can not use the previous processes stack.
290-        */
291-       .globl relocate_new_kernel
292 relocate_new_kernel:
293        /* read the arguments and say goodbye to the stack */
294        movl  4(%esp), %ebx /* page_list */
295-       movl  8(%esp), %ebp /* reboot_code_buffer */
296+       movl  8(%esp), %ebp /* list of pages */
297        movl  12(%esp), %edx /* start address */
298        movl  16(%esp), %ecx /* cpu_has_pae */
299 
300@@ -24,11 +146,26 @@ relocate_new_kernel:
301        pushl $0
302        popfl
303 
304-       /* set a new stack at the bottom of our page... */
305-       lea   4096(%ebp), %esp
306+       /* get physical address of control page now */
307+       /* this is impossible after page table switch */
308+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edi
309+
310+       /* switch to new set of page tables */
311+       movl    PTR(PA_PGD)(%ebp), %eax
312+       movl    %eax, %cr3
313+
314+       /* setup a new stack at the end of the physical control page */
315+       lea     4096(%edi), %esp
316 
317-       /* store the parameters back on the stack */
318-       pushl   %edx /* store the start address */
319+       /* jump to identity mapped page */
320+       movl    %edi, %eax
321+       addl    $(identity_mapped - relocate_kernel), %eax
322+       pushl   %eax
323+       ret
324+
325+identity_mapped:
326+       /* store the start address on the stack */
327+       pushl   %edx
328 
329        /* Set cr0 to a known state:
330         * 31 0 == Paging disabled
331@@ -113,8 +250,3 @@ relocate_new_kernel:
332        xorl    %edi, %edi
333        xorl    %ebp, %ebp
334        ret
335-relocate_new_kernel_end:
336-
337-       .globl relocate_new_kernel_size
338-relocate_new_kernel_size:
339-       .long relocate_new_kernel_end - relocate_new_kernel
340diff -pruN ../orig-linux-2.6.18/include/asm-i386/kexec.h ./include/asm-i386/kexec.h
341--- ../orig-linux-2.6.18/include/asm-i386/kexec.h       2006-09-20 04:42:06.000000000 +0100
342+++ ./include/asm-i386/kexec.h  2007-01-12 16:03:23.000000000 +0000
343@@ -1,6 +1,26 @@
344 #ifndef _I386_KEXEC_H
345 #define _I386_KEXEC_H
346 
347+#define PA_CONTROL_PAGE  0
348+#define VA_CONTROL_PAGE  1
349+#define PA_PGD           2
350+#define VA_PGD           3
351+#define PA_PTE_0         4
352+#define VA_PTE_0         5
353+#define PA_PTE_1         6
354+#define VA_PTE_1         7
355+#ifdef CONFIG_X86_PAE
356+#define PA_PMD_0         8
357+#define VA_PMD_0         9
358+#define PA_PMD_1         10
359+#define VA_PMD_1         11
360+#define PAGES_NR         12
361+#else
362+#define PAGES_NR         8
363+#endif
364+
365+#ifndef __ASSEMBLY__
366+
367 #include <asm/fixmap.h>
368 #include <asm/ptrace.h>
369 #include <asm/string.h>
370@@ -72,5 +92,12 @@ static inline void crash_setup_regs(stru
371                newregs->eip = (unsigned long)current_text_addr();
372        }
373 }
374+asmlinkage NORET_TYPE void
375+relocate_kernel(unsigned long indirection_page,
376+               unsigned long control_page,
377+               unsigned long start_address,
378+               unsigned int has_pae) ATTRIB_NORET;
379+
380+#endif /* __ASSEMBLY__ */
381 
382 #endif /* _I386_KEXEC_H */
Note: See TracBrowser for help on using the repository browser.