xref: /kvm-unit-tests/x86/cstart64.S (revision 7e33895d3232464182a73b4f1bdfdd783ba46221)
1
2#include "apic-defs.h"
3
4.globl online_cpus
5.globl cpu_online_count
6
7ipi_vector = 0x20
8
9max_cpus = MAX_TEST_CPUS
10
11.bss
12
13	. = . + 4096 * max_cpus
14	.align 16
15stacktop:
16
17.data
18
19.align 4096
20.globl ptl2
21ptl2:
22i = 0
23	.rept 512 * 4
24	.quad 0x1e7 | (i << 21)
25	i = i + 1
26	.endr
27
28.align 4096
29ptl3:
30	.quad ptl2 + 7 + 0 * 4096
31	.quad ptl2 + 7 + 1 * 4096
32	.quad ptl2 + 7 + 2 * 4096
33	.quad ptl2 + 7 + 3 * 4096
34
35.align 4096
36ptl4:
37	.quad ptl3 + 7
38
39.align 4096
40ptl5:
41	.quad ptl4 + 7
42
43.align 4096
44
45mb_boot_info:	.quad 0
46
47pt_root:	.quad ptl4
48
49.section .init
50
51.code32
52
53mb_magic = 0x1BADB002
54mb_flags = 0x0
55
56	# multiboot header
57	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
58mb_cmdline = 16
59
60MSR_GS_BASE = 0xc0000101
61
62.macro setup_percpu_area
63	lea -4096(%esp), %eax
64	mov $0, %edx
65	mov $MSR_GS_BASE, %ecx
66	wrmsr
67.endm
68
69.macro load_tss
70	lidtq idt_descr
71	movq %rsp, %rdi
72	call setup_tss
73	ltr %ax
74.endm
75
76.macro setup_segments
77	mov $MSR_GS_BASE, %ecx
78	rdmsr
79
80	mov $0x10, %bx
81	mov %bx, %ds
82	mov %bx, %es
83	mov %bx, %fs
84	mov %bx, %gs
85	mov %bx, %ss
86
87	/* restore MSR_GS_BASE */
88	wrmsr
89.endm
90
91.globl start
92start:
93	mov %ebx, mb_boot_info
94	mov $stacktop, %esp
95	setup_percpu_area
96	call prepare_64
97	jmpl $8, $start64
98
99switch_to_5level:
100	/* Disable CR4.PCIDE */
101	mov %cr4, %eax
102	btr $17, %eax
103	mov %eax, %cr4
104
105	mov %cr0, %eax
106	btr $31, %eax
107	mov %eax, %cr0
108
109	mov $ptl5, %eax
110	mov %eax, pt_root
111
112	/* Enable CR4.LA57 */
113	mov %cr4, %eax
114	bts $12, %eax
115	mov %eax, %cr4
116
117	mov $0x10, %ax
118	mov %ax, %ss
119
120	call enter_long_mode
121	jmpl $8, $lvl5
122
123prepare_64:
124	lgdt gdt_descr
125	setup_segments
126
127	xor %eax, %eax
128	mov %eax, %cr4
129
130enter_long_mode:
131	mov %cr4, %eax
132	bts $5, %eax  // pae
133	mov %eax, %cr4
134
135	mov pt_root, %eax
136	mov %eax, %cr3
137
138efer = 0xc0000080
139	mov $efer, %ecx
140	rdmsr
141	bts $8, %eax
142	wrmsr
143
144	mov %cr0, %eax
145	bts $0, %eax
146	bts $31, %eax
147	mov %eax, %cr0
148	ret
149
150smp_stacktop:	.long stacktop - 4096
151
152.align 16
153
154gdt32:
155	.quad 0
156	.quad 0x00cf9b000000ffff // flat 32-bit code segment
157	.quad 0x00cf93000000ffff // flat 32-bit data segment
158gdt32_end:
159
160.code16
161sipi_entry:
162	mov %cr0, %eax
163	or $1, %eax
164	mov %eax, %cr0
165	lgdtl gdt32_descr - sipi_entry
166	ljmpl $8, $ap_start32
167
168gdt32_descr:
169	.word gdt32_end - gdt32 - 1
170	.long gdt32
171
172sipi_end:
173
174.code32
175ap_start32:
176	setup_segments
177	mov $-4096, %esp
178	lock xaddl %esp, smp_stacktop
179	setup_percpu_area
180	call prepare_64
181	ljmpl $8, $ap_start64
182
183.code64
184save_id:
185	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
186	movl (%rax), %eax
187	shrl $24, %eax
188	lock btsl %eax, online_cpus
189	retq
190
191ap_start64:
192	call reset_apic
193	load_tss
194	call enable_apic
195	call save_id
196	call enable_x2apic
197	sti
198	nop
199	lock incw cpu_online_count
200
2011:	hlt
202	jmp 1b
203
204start64:
205	call reset_apic
206	load_tss
207	call mask_pic_interrupts
208	call enable_apic
209	call save_id
210	mov mb_boot_info(%rip), %rbx
211	mov %rbx, %rdi
212	call setup_multiboot
213	call setup_libcflat
214	mov mb_cmdline(%rbx), %eax
215	mov %rax, __args(%rip)
216	call __setup_args
217
218	call ap_init
219	call enable_x2apic
220	call smp_init
221
222	mov __argc(%rip), %edi
223	lea __argv(%rip), %rsi
224	lea __environ(%rip), %rdx
225	call main
226	mov %eax, %edi
227	call exit
228
229.globl setup_5level_page_table
230setup_5level_page_table:
231	/* Check if 5-level paging has already enabled */
232	mov %cr4, %rax
233	test $0x1000, %eax
234	jnz lvl5
235
236	pushq $32
237	pushq $switch_to_5level
238	lretq
239lvl5:
240	retq
241
242online_cpus:
243	.fill (max_cpus + 7) / 8, 1, 0
244
245ap_init:
246	cld
247	lea sipi_entry, %rsi
248	xor %rdi, %rdi
249	mov $(sipi_end - sipi_entry), %rcx
250	rep movsb
251	mov $APIC_DEFAULT_PHYS_BASE, %eax
252	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
253	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
254	call fwcfg_get_nb_cpus
2551:	pause
256	cmpw %ax, cpu_online_count
257	jne 1b
258	ret
259
260cpu_online_count:	.word 1
261