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