xref: /kvm-unit-tests/x86/cstart64.S (revision a41100276a89128703db61361f6be878c6473005)
1
2#include "apic-defs.h"
3
4.globl boot_idt
5
6.globl idt_descr
7.globl tss_descr
8.globl gdt64_desc
9.globl online_cpus
10
11ipi_vector = 0x20
12
13max_cpus = MAX_TEST_CPUS
14
15.bss
16
17	. = . + 4096 * max_cpus
18	.align 16
19stacktop:
20
21	. = . + 4096 * max_cpus
22	.align 16
23ring0stacktop:
24
25.data
26
27.align 4096
28.globl ptl2
29ptl2:
30i = 0
31	.rept 512 * 4
32	.quad 0x1e7 | (i << 21)
33	i = i + 1
34	.endr
35
36.align 4096
37ptl3:
38	.quad ptl2 + 7 + 0 * 4096
39	.quad ptl2 + 7 + 1 * 4096
40	.quad ptl2 + 7 + 2 * 4096
41	.quad ptl2 + 7 + 3 * 4096
42
43.align 4096
44ptl4:
45	.quad ptl3 + 7
46
47.align 4096
48ptl5:
49	.quad ptl4 + 7
50
51.align 4096
52
53boot_idt:
54	.rept 256
55	.quad 0
56	.quad 0
57	.endr
58end_boot_idt:
59
60gdt64_desc:
61	.word gdt64_end - gdt64 - 1
62	.quad gdt64
63
64gdt64:
65	.quad 0
66	.quad 0x00af9b000000ffff // 64-bit code segment
67	.quad 0x00cf93000000ffff // 32/64-bit data segment
68	.quad 0x00af1b000000ffff // 64-bit code segment, not present
69	.quad 0x00cf9b000000ffff // 32-bit code segment
70	.quad 0x008f9b000000FFFF // 16-bit code segment
71	.quad 0x008f93000000FFFF // 16-bit data segment
72	.quad 0x00cffb000000ffff // 32-bit code segment (user)
73	.quad 0x00cff3000000ffff // 32/64-bit data segment (user)
74	.quad 0x00affb000000ffff // 64-bit code segment (user)
75
76	.quad 0			 // 6 spare selectors
77	.quad 0
78	.quad 0
79	.quad 0
80	.quad 0
81	.quad 0
82
83tss_descr:
84	.rept max_cpus
85	.quad 0x000089000000ffff // 64-bit avail tss
86	.quad 0                  // tss high addr
87	.endr
88gdt64_end:
89
90i = 0
91.globl tss
92tss:
93	.rept max_cpus
94	.long 0
95	.quad ring0stacktop - i * 4096
96	.quad 0, 0
97	.quad 0, 0, 0, 0, 0, 0, 0, 0
98	.long 0, 0, 0
99i = i + 1
100	.endr
101tss_end:
102
103mb_boot_info:	.quad 0
104
105pt_root:	.quad ptl4
106
107.section .init
108
109.code32
110
111mb_magic = 0x1BADB002
112mb_flags = 0x0
113
114	# multiboot header
115	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
116mb_cmdline = 16
117
118MSR_GS_BASE = 0xc0000101
119
120.macro setup_percpu_area
121	lea -4096(%esp), %eax
122	mov $0, %edx
123	mov $MSR_GS_BASE, %ecx
124	wrmsr
125.endm
126
127.macro setup_segments
128	mov $MSR_GS_BASE, %ecx
129	rdmsr
130
131	mov $0x10, %bx
132	mov %bx, %ds
133	mov %bx, %es
134	mov %bx, %fs
135	mov %bx, %gs
136	mov %bx, %ss
137
138	/* restore MSR_GS_BASE */
139	wrmsr
140.endm
141
142.globl start
143start:
144	mov %ebx, mb_boot_info
145	mov $stacktop, %esp
146	setup_percpu_area
147	call prepare_64
148	jmpl $8, $start64
149
150switch_to_5level:
151	/* Disable CR4.PCIDE */
152	mov %cr4, %eax
153	btr $17, %eax
154	mov %eax, %cr4
155
156	mov %cr0, %eax
157	btr $31, %eax
158	mov %eax, %cr0
159
160	mov $ptl5, %eax
161	mov %eax, pt_root
162
163	/* Enable CR4.LA57 */
164	mov %cr4, %eax
165	bts $12, %eax
166	mov %eax, %cr4
167
168	mov $0x10, %ax
169	mov %ax, %ss
170
171	call enter_long_mode
172	jmpl $8, $lvl5
173
174prepare_64:
175	lgdt gdt64_desc
176	setup_segments
177
178	xor %eax, %eax
179	mov %eax, %cr4
180
181enter_long_mode:
182	mov %cr4, %eax
183	bts $5, %eax  // pae
184	mov %eax, %cr4
185
186	mov pt_root, %eax
187	mov %eax, %cr3
188
189efer = 0xc0000080
190	mov $efer, %ecx
191	rdmsr
192	bts $8, %eax
193	wrmsr
194
195	mov %cr0, %eax
196	bts $0, %eax
197	bts $31, %eax
198	mov %eax, %cr0
199	ret
200
201smp_stacktop:	.long stacktop - 4096
202
203.align 16
204
205gdt32:
206	.quad 0
207	.quad 0x00cf9b000000ffff // flat 32-bit code segment
208	.quad 0x00cf93000000ffff // flat 32-bit data segment
209gdt32_end:
210
211.code16
212sipi_entry:
213	mov %cr0, %eax
214	or $1, %eax
215	mov %eax, %cr0
216	lgdtl gdt32_descr - sipi_entry
217	ljmpl $8, $ap_start32
218
219gdt32_descr:
220	.word gdt32_end - gdt32 - 1
221	.long gdt32
222
223sipi_end:
224
225.code32
226ap_start32:
227	setup_segments
228	mov $-4096, %esp
229	lock/xaddl %esp, smp_stacktop
230	setup_percpu_area
231	call prepare_64
232	ljmpl $8, $ap_start64
233
234.code64
235save_id:
236	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
237	movl (%rax), %eax
238	shrl $24, %eax
239	lock btsl %eax, online_cpus
240	retq
241
242ap_start64:
243	call reset_apic
244	call load_tss
245	call enable_apic
246	call save_id
247	call enable_x2apic
248	sti
249	nop
250	lock incw cpu_online_count
251
2521:	hlt
253	jmp 1b
254
255start64:
256	call reset_apic
257	call load_tss
258	call mask_pic_interrupts
259	call enable_apic
260	call save_id
261	mov mb_boot_info(%rip), %rbx
262	mov %rbx, %rdi
263	call setup_multiboot
264	call setup_libcflat
265	mov mb_cmdline(%rbx), %eax
266	mov %rax, __args(%rip)
267	call __setup_args
268
269	call ap_init
270	call enable_x2apic
271	call smp_init
272
273	mov __argc(%rip), %edi
274	lea __argv(%rip), %rsi
275	lea __environ(%rip), %rdx
276	call main
277	mov %eax, %edi
278	call exit
279
280.globl setup_5level_page_table
281setup_5level_page_table:
282	/* Check if 5-level paging has already enabled */
283	mov %cr4, %rax
284	test $0x1000, %eax
285	jnz lvl5
286
287	pushq $32
288	pushq $switch_to_5level
289	lretq
290lvl5:
291	retq
292
293idt_descr:
294	.word end_boot_idt - boot_idt - 1
295	.quad boot_idt
296
297online_cpus:
298	.fill (max_cpus + 7) / 8, 1, 0
299
300load_tss:
301	lidtq idt_descr
302	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
303	mov (%rax), %eax
304	shr $24, %eax
305	mov %eax, %ebx
306	shl $4, %ebx
307	mov $((tss_end - tss) / max_cpus), %edx
308	imul %edx
309	add $tss, %rax
310	mov %ax, tss_descr+2(%rbx)
311	shr $16, %rax
312	mov %al, tss_descr+4(%rbx)
313	shr $8, %rax
314	mov %al, tss_descr+7(%rbx)
315	shr $8, %rax
316	mov %eax, tss_descr+8(%rbx)
317	lea tss_descr-gdt64(%rbx), %rax
318	ltr %ax
319	ret
320
321ap_init:
322	cld
323	lea sipi_entry, %rsi
324	xor %rdi, %rdi
325	mov $(sipi_end - sipi_entry), %rcx
326	rep/movsb
327	mov $APIC_DEFAULT_PHYS_BASE, %eax
328	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
329	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
330	call fwcfg_get_nb_cpus
3311:	pause
332	cmpw %ax, cpu_online_count
333	jne 1b
334	ret
335
336cpu_online_count:	.word 1
337