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