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