xref: /kvm-unit-tests/x86/cstart64.S (revision 03b1e4570f9678c59a1fdcd0428d21681541602e)
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	call enter_long_mode
163	jmpl $8, $lvl5
164
165prepare_64:
166	lgdt gdt64_desc
167	setup_segments
168
169enter_long_mode:
170	mov %cr4, %eax
171	bts $5, %eax  // pae
172	mov %eax, %cr4
173
174	mov pt_root, %eax
175	mov %eax, %cr3
176
177efer = 0xc0000080
178	mov $efer, %ecx
179	rdmsr
180	bts $8, %eax
181	wrmsr
182
183	mov %cr0, %eax
184	bts $0, %eax
185	bts $31, %eax
186	mov %eax, %cr0
187	ret
188
189smp_stacktop:	.long stacktop - 4096
190
191.align 16
192
193gdt32:
194	.quad 0
195	.quad 0x00cf9b000000ffff // flat 32-bit code segment
196	.quad 0x00cf93000000ffff // flat 32-bit data segment
197gdt32_end:
198
199.code16
200sipi_entry:
201	mov %cr0, %eax
202	or $1, %eax
203	mov %eax, %cr0
204	lgdtl gdt32_descr - sipi_entry
205	ljmpl $8, $ap_start32
206
207gdt32_descr:
208	.word gdt32_end - gdt32 - 1
209	.long gdt32
210
211sipi_end:
212
213.code32
214ap_start32:
215	setup_segments
216	mov $-4096, %esp
217	lock/xaddl %esp, smp_stacktop
218	setup_percpu_area
219	call prepare_64
220	ljmpl $8, $ap_start64
221
222.code64
223save_id:
224	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
225	movl (%rax), %eax
226	shrl $24, %eax
227	lock btsl %eax, online_cpus
228	retq
229
230ap_start64:
231	call reset_apic
232	call load_tss
233	call enable_apic
234	call save_id
235	call enable_x2apic
236	sti
237	nop
238	lock incw cpu_online_count
239
2401:	hlt
241	jmp 1b
242
243start64:
244	call reset_apic
245	call load_tss
246	call mask_pic_interrupts
247	call enable_apic
248	call save_id
249	mov mb_boot_info(%rip), %rbx
250	mov %rbx, %rdi
251	call setup_multiboot
252	call setup_libcflat
253	mov mb_cmdline(%rbx), %eax
254	mov %rax, __args(%rip)
255	call __setup_args
256
257	/* Read the configuration before running smp_init */
258	call read_cfg_override
259	call smp_init
260	call enable_x2apic
261
262	mov __argc(%rip), %edi
263	lea __argv(%rip), %rsi
264	lea __environ(%rip), %rdx
265	call main
266	mov %eax, %edi
267	call exit
268
269.globl setup_5level_page_table
270setup_5level_page_table:
271	/* Check if 5-level paging has already enabled */
272	mov %cr4, %rax
273	test $0x1000, %eax
274	jnz lvl5
275
276	pushq $32
277	pushq $switch_to_5level
278	lretq
279lvl5:
280	retq
281
282idt_descr:
283	.word 16 * 256 - 1
284	.quad boot_idt
285
286online_cpus:
287	.quad 0
288
289load_tss:
290	lidtq idt_descr
291	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
292	mov (%rax), %eax
293	shr $24, %eax
294	mov %eax, %ebx
295	shl $4, %ebx
296	mov $((tss_end - tss) / max_cpus), %edx
297	imul %edx
298	add $tss, %rax
299	mov %ax, tss_descr+2(%rbx)
300	shr $16, %rax
301	mov %al, tss_descr+4(%rbx)
302	shr $8, %rax
303	mov %al, tss_descr+7(%rbx)
304	shr $8, %rax
305	mov %eax, tss_descr+8(%rbx)
306	lea tss_descr-gdt64(%rbx), %rax
307	ltr %ax
308	ret
309
310smp_init:
311	cld
312	lea sipi_entry, %rsi
313	xor %rdi, %rdi
314	mov $(sipi_end - sipi_entry), %rcx
315	rep/movsb
316	mov $APIC_DEFAULT_PHYS_BASE, %eax
317	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
318	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
319	call fwcfg_get_nb_cpus
3201:	pause
321	cmpw %ax, cpu_online_count
322	jne 1b
323smp_init_done:
324	ret
325
326cpu_online_count:	.word 1
327