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