xref: /kvm-unit-tests/x86/cstart64.S (revision c8ab4c00e56b18e7d63877cb037e1b1d87bdad1c)
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#include "trampolines.S"
49
50.section .init
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.code32
161ap_start32:
162	setup_segments
163	mov $-4096, %esp
164	lock xaddl %esp, smp_stacktop
165	setup_percpu_area
166	call prepare_64
167	ljmpl $8, $ap_start64
168
169.code64
170save_id:
171	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
172	movl (%rax), %eax
173	shrl $24, %eax
174	lock btsl %eax, online_cpus
175	retq
176
177ap_start64:
178	call reset_apic
179	load_tss
180	call enable_apic
181	call save_id
182	call enable_x2apic
183	sti
184	nop
185	lock incw cpu_online_count
186
1871:	hlt
188	jmp 1b
189
190start64:
191	call reset_apic
192	load_tss
193	call mask_pic_interrupts
194	call enable_apic
195	call save_id
196	mov mb_boot_info(%rip), %rbx
197	mov %rbx, %rdi
198	call setup_multiboot
199	call setup_libcflat
200	mov mb_cmdline(%rbx), %eax
201	mov %rax, __args(%rip)
202	call __setup_args
203
204	call ap_init
205	call enable_x2apic
206	call smp_init
207
208	mov __argc(%rip), %edi
209	lea __argv(%rip), %rsi
210	lea __environ(%rip), %rdx
211	call main
212	mov %eax, %edi
213	call exit
214
215.globl setup_5level_page_table
216setup_5level_page_table:
217	/* Check if 5-level paging has already enabled */
218	mov %cr4, %rax
219	test $0x1000, %eax
220	jnz lvl5
221
222	pushq $32
223	pushq $switch_to_5level
224	lretq
225lvl5:
226	retq
227
228online_cpus:
229	.fill (max_cpus + 7) / 8, 1, 0
230
231ap_init:
232	cld
233	lea rm_trampoline, %rsi
234	xor %rdi, %rdi
235	mov $(rm_trampoline_end - rm_trampoline), %rcx
236	rep movsb
237	mov $APIC_DEFAULT_PHYS_BASE, %eax
238	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
239	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
240	call fwcfg_get_nb_cpus
2411:	pause
242	cmpw %ax, cpu_online_count
243	jne 1b
244	ret
245
246.align 2
247cpu_online_count:	.word 1
248