[PATCH] kexec: x86_64 kexec implementation
[linux-2.6.git] / arch / x86_64 / kernel / relocate_kernel.S
1 /*
2  * relocate_kernel.S - put the kernel image in place to boot
3  * Copyright (C) 2002-2005 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         .code64
17 relocate_new_kernel:
18         /* %rdi page_list
19          * %rsi reboot_code_buffer
20          * %rdx start address
21          * %rcx page_table
22          * %r8  arg5
23          * %r9  arg6
24          */
25
26         /* zero out flags, and disable interrupts */
27         pushq $0
28         popfq
29
30         /* set a new stack at the bottom of our page... */
31         lea   4096(%rsi), %rsp
32
33         /* store the parameters back on the stack */
34         pushq   %rdx /* store the start address */
35
36         /* Set cr0 to a known state:
37          * 31 1 == Paging enabled
38          * 18 0 == Alignment check disabled
39          * 16 0 == Write protect disabled
40          * 3  0 == No task switch
41          * 2  0 == Don't do FP software emulation.
42          * 0  1 == Proctected mode enabled
43          */
44         movq    %cr0, %rax
45         andq    $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
46         orl     $((1<<31)|(1<<0)), %eax
47         movq    %rax, %cr0
48
49         /* Set cr4 to a known state:
50          * 10 0 == xmm exceptions disabled
51          * 9  0 == xmm registers instructions disabled
52          * 8  0 == performance monitoring counter disabled
53          * 7  0 == page global disabled
54          * 6  0 == machine check exceptions disabled
55          * 5  1 == physical address extension enabled
56          * 4  0 == page size extensions disabled
57          * 3  0 == Debug extensions disabled
58          * 2  0 == Time stamp disable (disabled)
59          * 1  0 == Protected mode virtual interrupts disabled
60          * 0  0 == VME disabled
61          */
62
63         movq    $((1<<5)), %rax
64         movq    %rax, %cr4
65
66         jmp 1f
67 1:
68
69         /* Switch to the identity mapped page tables,
70          * and flush the TLB.
71         */
72         movq    %rcx, %cr3
73
74         /* Do the copies */
75         movq    %rdi, %rcx      /* Put the page_list in %rcx */
76         xorq    %rdi, %rdi
77         xorq    %rsi, %rsi
78         jmp     1f
79
80 0:      /* top, read another word for the indirection page */
81
82         movq    (%rbx), %rcx
83         addq    $8,     %rbx
84 1:
85         testq   $0x1,   %rcx  /* is it a destination page? */
86         jz      2f
87         movq    %rcx,   %rdi
88         andq    $0xfffffffffffff000, %rdi
89         jmp     0b
90 2:
91         testq   $0x2,   %rcx  /* is it an indirection page? */
92         jz      2f
93         movq    %rcx,   %rbx
94         andq    $0xfffffffffffff000, %rbx
95         jmp     0b
96 2:
97         testq   $0x4,   %rcx  /* is it the done indicator? */
98         jz      2f
99         jmp     3f
100 2:
101         testq   $0x8,   %rcx  /* is it the source indicator? */
102         jz      0b            /* Ignore it otherwise */
103         movq    %rcx,   %rsi  /* For ever source page do a copy */
104         andq    $0xfffffffffffff000, %rsi
105
106         movq    $512,   %rcx
107         rep ; movsq
108         jmp     0b
109 3:
110
111         /* To be certain of avoiding problems with self-modifying code
112          * I need to execute a serializing instruction here.
113          * So I flush the TLB by reloading %cr3 here, it's handy,
114          * and not processor dependent.
115          */
116         movq    %cr3, %rax
117         movq    %rax, %cr3
118
119         /* set all of the registers to known values */
120         /* leave %rsp alone */
121
122         xorq    %rax, %rax
123         xorq    %rbx, %rbx
124         xorq    %rcx, %rcx
125         xorq    %rdx, %rdx
126         xorq    %rsi, %rsi
127         xorq    %rdi, %rdi
128         xorq    %rbp, %rbp
129         xorq    %r8,  %r8
130         xorq    %r9,  %r9
131         xorq    %r10, %r9
132         xorq    %r11, %r11
133         xorq    %r12, %r12
134         xorq    %r13, %r13
135         xorq    %r14, %r14
136         xorq    %r15, %r15
137
138         ret
139 relocate_new_kernel_end:
140
141         .globl relocate_new_kernel_size
142 relocate_new_kernel_size:
143         .quad relocate_new_kernel_end - relocate_new_kernel