xref: /kvm-unit-tests/x86/cstart64.S (revision 7d36db351752e29ad27eaafe3f102de7064e429b)
1
2#include "apic-defs.h"
3
4.globl boot_idt
5boot_idt = 0
6
7ipi_vector = 0x20
8
9max_cpus = 4
10
11.bss
12
13	. = . + 4096 * max_cpus
14	.align 16
15stacktop:
16
17	. = . + 4096
18	.align 16
19ring0stacktop:
20
21.data
22
23.align 4096
24ptl2:
25i = 0
26	.rept 512 * 4
27	.quad 0x1e7 | (i << 21)
28	i = i + 1
29	.endr
30
31.align 4096
32ptl3:
33	.quad ptl2 + 7 + 0 * 4096
34	.quad ptl2 + 7 + 1 * 4096
35	.quad ptl2 + 7 + 2 * 4096
36	.quad ptl2 + 7 + 3 * 4096
37
38.align 4096
39ptl4:
40	.quad ptl3 + 7
41
42.align 4096
43
44gdt64_desc:
45	.word gdt64_end - gdt64 - 1
46	.quad gdt64
47
48gdt64:
49	.quad 0
50	.quad 0x00af9b000000ffff // 64-bit code segment
51	.quad 0x00cf93000000ffff // 64-bit data segment
52	.quad 0x00affb000000ffff // 64-bit code segment (user)
53	.quad 0x00cff3000000ffff // 64-bit data segment (user)
54	.quad 0x00cf9b000000ffff // 32-bit code segment
55	.quad 0x00cf92000000ffff // 32-bit code segment
56	.quad 0x008F9A000000FFFF // 16-bit code segment
57	.quad 0x008F92000000FFFF // 16-bit data segment
58
59tss_descr:
60	.rept max_cpus
61	.quad 0x000089000000ffff // 64-bit avail tss
62	.quad 0                  // tss high addr
63	.endr
64gdt64_end:
65
66i = 0
67tss:
68	.rept max_cpus
69	.long 0
70	.quad ring0stacktop - i * 4096
71	.quad 0, 0, 0
72	.quad 0, 0, 0, 0, 0, 0, 0, 0
73	.long 0, 0, 0
74i = i + 1
75	.endr
76tss_end:
77
78.section .init
79
80.code32
81
82mb_magic = 0x1BADB002
83mb_flags = 0x0
84
85	# multiboot header
86	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
87
88MSR_GS_BASE = 0xc0000101
89
90.macro setup_percpu_area
91	lea -4096(%esp), %eax
92	mov $0, %edx
93	mov $MSR_GS_BASE, %ecx
94	wrmsr
95.endm
96
97.globl start
98start:
99	mov $stacktop, %esp
100	setup_percpu_area
101	call prepare_64
102	jmpl $8, $start64
103
104prepare_64:
105	lgdt gdt64_desc
106
107	mov %cr4, %eax
108	bts $5, %eax  // pae
109	mov %eax, %cr4
110
111	mov $ptl4, %eax
112	mov %eax, %cr3
113
114efer = 0xc0000080
115	mov $efer, %ecx
116	rdmsr
117	bts $8, %eax
118	wrmsr
119
120	mov %cr0, %eax
121	bts $0, %eax
122	bts $31, %eax
123	mov %eax, %cr0
124	ret
125
126smp_stacktop:	.long 0xa0000
127
128.align 16
129
130gdt32:
131	.quad 0
132	.quad 0x00cf9b000000ffff // flat 32-bit code segment
133	.quad 0x00cf93000000ffff // flat 32-bit data segment
134gdt32_end:
135
136.code16
137sipi_entry:
138	mov %cr0, %eax
139	or $1, %eax
140	mov %eax, %cr0
141	lgdtl gdt32_descr - sipi_entry
142	ljmpl $8, $ap_start32
143
144gdt32_descr:
145	.word gdt32_end - gdt32 - 1
146	.long gdt32
147
148sipi_end:
149
150.code32
151ap_start32:
152	mov $0x10, %ax
153	mov %ax, %ds
154	mov %ax, %es
155	mov %ax, %fs
156	mov %ax, %gs
157	mov %ax, %ss
158	mov $-4096, %esp
159	lock/xaddl %esp, smp_stacktop
160	setup_percpu_area
161	call prepare_64
162	ljmpl $8, $ap_start64
163
164.code64
165ap_start64:
166	call load_tss
167	call enable_apic
168	call enable_x2apic
169	sti
170	nop
171	lock incw cpu_online_count
172
1731:	hlt
174	jmp 1b
175
176start64:
177	call load_tss
178	call mask_pic_interrupts
179	call enable_apic
180	call smp_init
181	call enable_x2apic
182	call main
183	mov %eax, %edi
184	call exit
185
186idt_descr:
187	.word 16 * 256 - 1
188	.quad boot_idt
189
190load_tss:
191	lidtq idt_descr
192	mov $0, %eax
193	mov %ax, %ss
194	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
195	mov (%rax), %eax
196	shr $24, %eax
197	mov %eax, %ebx
198	shl $4, %ebx
199	mov $((tss_end - tss) / max_cpus), %edx
200	imul %edx
201	add $tss, %rax
202	mov %ax, tss_descr+2(%rbx)
203	shr $16, %rax
204	mov %al, tss_descr+4(%rbx)
205	shr $8, %rax
206	mov %al, tss_descr+7(%rbx)
207	shr $8, %rax
208	mov %eax, tss_descr+8(%rbx)
209	lea tss_descr-gdt64(%rbx), %rax
210	ltr %ax
211	ret
212
213smp_init:
214	cld
215	lea sipi_entry, %rsi
216	xor %rdi, %rdi
217	mov $(sipi_end - sipi_entry), %rcx
218	rep/movsb
219	mov $APIC_DEFAULT_PHYS_BASE, %eax
220	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
221	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT), APIC_ICR(%rax)
222	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
223	call fwcfg_get_nb_cpus
2241:	pause
225	cmpw %ax, cpu_online_count
226	jne 1b
227smp_init_done:
228	ret
229
230cpu_online_count:	.word 1
231