Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / i386 / kernel / relocate_kernel.S
1 /*
2  * relocate_kernel.S - put the kernel image in place to boot
3  * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
4  *
5  * This source code is licensed under the GNU General Public License,
6  * Version 2.  See the file COPYING for more details.
7  */
8
9 #include <linux/linkage.h>
10
11         /*
12          * Must be relocatable PIC code callable as a C function, that once
13          * it starts can not use the previous processes stack.
14          */
15         .globl relocate_new_kernel
16 relocate_new_kernel:
17         /* read the arguments and say goodbye to the stack */
18         movl  4(%esp), %ebx /* page_list */
19         movl  8(%esp), %ebp /* reboot_code_buffer */
20         movl  12(%esp), %edx /* start address */
21         movl  16(%esp), %ecx /* cpu_has_pae */
22
23         /* zero out flags, and disable interrupts */
24         pushl $0
25         popfl
26
27         /* set a new stack at the bottom of our page... */
28         lea   4096(%ebp), %esp
29
30         /* store the parameters back on the stack */
31         pushl   %edx /* store the start address */
32
33         /* Set cr0 to a known state:
34          * 31 0 == Paging disabled
35          * 18 0 == Alignment check disabled
36          * 16 0 == Write protect disabled
37          * 3  0 == No task switch
38          * 2  0 == Don't do FP software emulation.
39          * 0  1 == Proctected mode enabled
40          */
41         movl    %cr0, %eax
42         andl    $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
43         orl     $(1<<0), %eax
44         movl    %eax, %cr0
45
46         /* clear cr4 if applicable */
47         testl   %ecx, %ecx
48         jz      1f
49         /* Set cr4 to a known state:
50          * Setting everything to zero seems safe.
51          */
52         movl    %cr4, %eax
53         andl    $0, %eax
54         movl    %eax, %cr4
55
56         jmp 1f
57 1:
58
59         /* Flush the TLB (needed?) */
60         xorl    %eax, %eax
61         movl    %eax, %cr3
62
63         /* Do the copies */
64         movl    %ebx, %ecx
65         jmp     1f
66
67 0:      /* top, read another word from the indirection page */
68         movl    (%ebx), %ecx
69         addl    $4, %ebx
70 1:
71         testl   $0x1,   %ecx  /* is it a destination page */
72         jz      2f
73         movl    %ecx,   %edi
74         andl    $0xfffff000, %edi
75         jmp     0b
76 2:
77         testl   $0x2,   %ecx  /* is it an indirection page */
78         jz      2f
79         movl    %ecx,   %ebx
80         andl    $0xfffff000, %ebx
81         jmp     0b
82 2:
83         testl   $0x4,   %ecx /* is it the done indicator */
84         jz      2f
85         jmp     3f
86 2:
87         testl   $0x8,   %ecx /* is it the source indicator */
88         jz      0b           /* Ignore it otherwise */
89         movl    %ecx,   %esi /* For every source page do a copy */
90         andl    $0xfffff000, %esi
91
92         movl    $1024, %ecx
93         rep ; movsl
94         jmp     0b
95
96 3:
97
98         /* To be certain of avoiding problems with self-modifying code
99          * I need to execute a serializing instruction here.
100          * So I flush the TLB, it's handy, and not processor dependent.
101          */
102         xorl    %eax, %eax
103         movl    %eax, %cr3
104
105         /* set all of the registers to known values */
106         /* leave %esp alone */
107
108         xorl    %eax, %eax
109         xorl    %ebx, %ebx
110         xorl    %ecx, %ecx
111         xorl    %edx, %edx
112         xorl    %esi, %esi
113         xorl    %edi, %edi
114         xorl    %ebp, %ebp
115         ret
116 relocate_new_kernel_end:
117
118         .globl relocate_new_kernel_size
119 relocate_new_kernel_size:
120         .long relocate_new_kernel_end - relocate_new_kernel