xref: /kvm-unit-tests/x86/cstart64.S (revision 3c50214c97f173f5e0f82c7f248a7c62707d8748)
1
2#include "apic-defs.h"
3
4.globl online_cpus
5
6ipi_vector = 0x20
7
8max_cpus = MAX_TEST_CPUS
9
10.bss
11
12	. = . + 4096 * max_cpus
13	.align 16
14stacktop:
15
16.data
17
18.align 4096
19ptl2:
20i = 0
21	.rept 512 * 4
22	.quad 0x1e7 | (i << 21)
23	i = i + 1
24	.endr
25
26.align 4096
27ptl3:
28	.quad ptl2 + 7 + 0 * 4096
29	.quad ptl2 + 7 + 1 * 4096
30	.quad ptl2 + 7 + 2 * 4096
31	.quad ptl2 + 7 + 3 * 4096
32
33.align 4096
34ptl4:
35	.quad ptl3 + 7
36
37.align 4096
38ptl5:
39	.quad ptl4 + 7
40
41.align 4096
42
43mb_boot_info:	.quad 0
44
45pt_root:	.quad ptl4
46
47#include "trampolines.S"
48
49.section .init
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	movq %rsp, %rdi
70	call setup_tss
71	ltr %ax
72.endm
73
74.macro setup_segments
75	mov $MSR_GS_BASE, %ecx
76	rdmsr
77
78	mov $0x10, %bx
79	mov %bx, %ds
80	mov %bx, %es
81	mov %bx, %fs
82	mov %bx, %gs
83	mov %bx, %ss
84
85	/* restore MSR_GS_BASE */
86	wrmsr
87.endm
88
89.globl start
90start:
91	mov %ebx, mb_boot_info
92	mov $stacktop, %esp
93	setup_percpu_area
94	call prepare_64
95	jmpl $8, $start64
96
97switch_to_5level:
98	/* Disable CR4.PCIDE */
99	mov %cr4, %eax
100	btr $17, %eax
101	mov %eax, %cr4
102
103	mov %cr0, %eax
104	btr $31, %eax
105	mov %eax, %cr0
106
107	mov $ptl5, %eax
108	mov %eax, pt_root
109
110	/* Enable CR4.LA57 */
111	mov %cr4, %eax
112	bts $12, %eax
113	mov %eax, %cr4
114
115	mov $0x10, %ax
116	mov %ax, %ss
117
118	call enter_long_mode
119	jmpl $8, $lvl5
120
121prepare_64:
122	lgdt gdt_descr
123	setup_segments
124
125	xor %eax, %eax
126	mov %eax, %cr4
127
128enter_long_mode:
129	mov %cr4, %eax
130	bts $5, %eax  // pae
131	mov %eax, %cr4
132
133	mov pt_root, %eax
134	mov %eax, %cr3
135
136efer = 0xc0000080
137	mov $efer, %ecx
138	rdmsr
139	bts $8, %eax
140	wrmsr
141
142	mov %cr0, %eax
143	bts $0, %eax
144	bts $31, %eax
145	mov %eax, %cr0
146	ret
147
148smp_stacktop:	.long stacktop - 4096
149
150.align 16
151
152gdt32:
153	.quad 0
154	.quad 0x00cf9b000000ffff // flat 32-bit code segment
155	.quad 0x00cf93000000ffff // flat 32-bit data segment
156gdt32_end:
157
158.code32
159ap_start32:
160	setup_segments
161	mov $-4096, %esp
162	lock xaddl %esp, smp_stacktop
163	setup_percpu_area
164	call prepare_64
165	ljmpl $8, $ap_start64
166
167.code64
168save_id:
169	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
170	movl (%rax), %eax
171	shrl $24, %eax
172	lock btsl %eax, online_cpus
173	retq
174
175ap_start64:
176	call load_idt
177	load_tss
178	call reset_apic
179	call enable_apic
180	call save_id
181	call enable_x2apic
182	sti
183	nop
184	lock incw cpu_online_count
185
1861:	hlt
187	jmp 1b
188
189start64:
190	call load_idt
191	load_tss
192	call reset_apic
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