x86: relocate_kernel - use predefined macroses for processor state
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / relocate_kernel_64.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 #include <asm/page.h>
11 #include <asm/kexec.h>
12 #include <asm/processor-flags.h>
13
14 /*
15  * Must be relocatable PIC code callable as a C function
16  */
17
18 #define PTR(x) (x << 3)
19 #define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
20
21         .text
22         .align PAGE_SIZE
23         .code64
24         .globl relocate_kernel
25 relocate_kernel:
26         /* %rdi indirection_page
27          * %rsi page_list
28          * %rdx start address
29          */
30
31         /* map the control page at its virtual address */
32
33         movq    $0x0000ff8000000000, %r10        /* mask */
34         mov     $(39 - 3), %cl                   /* bits to shift */
35         movq    PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
36
37         movq    %r11, %r9
38         andq    %r10, %r9
39         shrq    %cl, %r9
40
41         movq    PTR(VA_PGD)(%rsi), %r8
42         addq    %r8, %r9
43         movq    PTR(PA_PUD_0)(%rsi), %r8
44         orq     $PAGE_ATTR, %r8
45         movq    %r8, (%r9)
46
47         shrq    $9, %r10
48         sub     $9, %cl
49
50         movq    %r11, %r9
51         andq    %r10, %r9
52         shrq    %cl, %r9
53
54         movq    PTR(VA_PUD_0)(%rsi), %r8
55         addq    %r8, %r9
56         movq    PTR(PA_PMD_0)(%rsi), %r8
57         orq     $PAGE_ATTR, %r8
58         movq    %r8, (%r9)
59
60         shrq    $9, %r10
61         sub     $9, %cl
62
63         movq    %r11, %r9
64         andq    %r10, %r9
65         shrq    %cl, %r9
66
67         movq    PTR(VA_PMD_0)(%rsi), %r8
68         addq    %r8, %r9
69         movq    PTR(PA_PTE_0)(%rsi), %r8
70         orq     $PAGE_ATTR, %r8
71         movq    %r8, (%r9)
72
73         shrq    $9, %r10
74         sub     $9, %cl
75
76         movq    %r11, %r9
77         andq    %r10, %r9
78         shrq    %cl, %r9
79
80         movq    PTR(VA_PTE_0)(%rsi), %r8
81         addq    %r8, %r9
82         movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
83         orq     $PAGE_ATTR, %r8
84         movq    %r8, (%r9)
85
86         /* identity map the control page at its physical address */
87
88         movq    $0x0000ff8000000000, %r10        /* mask */
89         mov     $(39 - 3), %cl                   /* bits to shift */
90         movq    PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
91
92         movq    %r11, %r9
93         andq    %r10, %r9
94         shrq    %cl, %r9
95
96         movq    PTR(VA_PGD)(%rsi), %r8
97         addq    %r8, %r9
98         movq    PTR(PA_PUD_1)(%rsi), %r8
99         orq     $PAGE_ATTR, %r8
100         movq    %r8, (%r9)
101
102         shrq    $9, %r10
103         sub     $9, %cl
104
105         movq    %r11, %r9
106         andq    %r10, %r9
107         shrq    %cl, %r9
108
109         movq    PTR(VA_PUD_1)(%rsi), %r8
110         addq    %r8, %r9
111         movq    PTR(PA_PMD_1)(%rsi), %r8
112         orq     $PAGE_ATTR, %r8
113         movq    %r8, (%r9)
114
115         shrq    $9, %r10
116         sub     $9, %cl
117
118         movq    %r11, %r9
119         andq    %r10, %r9
120         shrq    %cl, %r9
121
122         movq    PTR(VA_PMD_1)(%rsi), %r8
123         addq    %r8, %r9
124         movq    PTR(PA_PTE_1)(%rsi), %r8
125         orq     $PAGE_ATTR, %r8
126         movq    %r8, (%r9)
127
128         shrq    $9, %r10
129         sub     $9, %cl
130
131         movq    %r11, %r9
132         andq    %r10, %r9
133         shrq    %cl, %r9
134
135         movq    PTR(VA_PTE_1)(%rsi), %r8
136         addq    %r8, %r9
137         movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
138         orq     $PAGE_ATTR, %r8
139         movq    %r8, (%r9)
140
141 relocate_new_kernel:
142         /* %rdi indirection_page
143          * %rsi page_list
144          * %rdx start address
145          */
146
147         /* zero out flags, and disable interrupts */
148         pushq $0
149         popfq
150
151         /* get physical address of control page now */
152         /* this is impossible after page table switch */
153         movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
154
155         /* get physical address of page table now too */
156         movq    PTR(PA_TABLE_PAGE)(%rsi), %rcx
157
158         /* switch to new set of page tables */
159         movq    PTR(PA_PGD)(%rsi), %r9
160         movq    %r9, %cr3
161
162         /* setup a new stack at the end of the physical control page */
163         lea     PAGE_SIZE(%r8), %rsp
164
165         /* jump to identity mapped page */
166         addq    $(identity_mapped - relocate_kernel), %r8
167         pushq   %r8
168         ret
169
170 identity_mapped:
171         /* store the start address on the stack */
172         pushq   %rdx
173
174         /* Set cr0 to a known state:
175          *  - Paging enabled
176          *  - Alignment check disabled
177          *  - Write protect disabled
178          *  - No task switch
179          *  - Don't do FP software emulation.
180          *  - Proctected mode enabled
181          */
182         movq    %cr0, %rax
183         andq    $~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
184         orl     $(X86_CR0_PG | X86_CR0_PE), %eax
185         movq    %rax, %cr0
186
187         /* Set cr4 to a known state:
188          *  - physical address extension enabled
189          */
190         movq    $X86_CR4_PAE, %rax
191         movq    %rax, %cr4
192
193         jmp 1f
194 1:
195
196         /* Switch to the identity mapped page tables,
197          * and flush the TLB.
198         */
199         movq    %rcx, %cr3
200
201         /* Do the copies */
202         movq    %rdi, %rcx      /* Put the page_list in %rcx */
203         xorq    %rdi, %rdi
204         xorq    %rsi, %rsi
205         jmp     1f
206
207 0:      /* top, read another word for the indirection page */
208
209         movq    (%rbx), %rcx
210         addq    $8,     %rbx
211 1:
212         testq   $0x1,   %rcx  /* is it a destination page? */
213         jz      2f
214         movq    %rcx,   %rdi
215         andq    $0xfffffffffffff000, %rdi
216         jmp     0b
217 2:
218         testq   $0x2,   %rcx  /* is it an indirection page? */
219         jz      2f
220         movq    %rcx,   %rbx
221         andq    $0xfffffffffffff000, %rbx
222         jmp     0b
223 2:
224         testq   $0x4,   %rcx  /* is it the done indicator? */
225         jz      2f
226         jmp     3f
227 2:
228         testq   $0x8,   %rcx  /* is it the source indicator? */
229         jz      0b            /* Ignore it otherwise */
230         movq    %rcx,   %rsi  /* For ever source page do a copy */
231         andq    $0xfffffffffffff000, %rsi
232
233         movq    $512,   %rcx
234         rep ; movsq
235         jmp     0b
236 3:
237
238         /* To be certain of avoiding problems with self-modifying code
239          * I need to execute a serializing instruction here.
240          * So I flush the TLB by reloading %cr3 here, it's handy,
241          * and not processor dependent.
242          */
243         movq    %cr3, %rax
244         movq    %rax, %cr3
245
246         /* set all of the registers to known values */
247         /* leave %rsp alone */
248
249         xorq    %rax, %rax
250         xorq    %rbx, %rbx
251         xorq    %rcx, %rcx
252         xorq    %rdx, %rdx
253         xorq    %rsi, %rsi
254         xorq    %rdi, %rdi
255         xorq    %rbp, %rbp
256         xorq    %r8,  %r8
257         xorq    %r9,  %r9
258         xorq    %r10, %r9
259         xorq    %r11, %r11
260         xorq    %r12, %r12
261         xorq    %r13, %r13
262         xorq    %r14, %r14
263         xorq    %r15, %r15
264
265         ret