xref: /kvm-unit-tests/x86/cstart.S (revision a991ed2fb5eef30af4e402cc79bcbae067d43e6b)
1
2#include "apic-defs.h"
3
4.globl boot_idt
5.global online_cpus
6
7ipi_vector = 0x20
8
9max_cpus = MAX_TEST_CPUS
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
24pt:
25i = 0
26        .rept 1024
27        .long 0x1e7 | (i << 22)
28        i = i + 1
29        .endr
30
31boot_idt:
32	.rept 256
33	.quad 0
34	.endr
35end_boot_idt:
36
37.globl gdt32
38gdt32:
39	.quad 0
40	.quad 0x00cf9b000000ffff // flat 32-bit code segment
41	.quad 0x00cf93000000ffff // flat 32-bit data segment
42	.quad 0x00cf1b000000ffff // flat 32-bit code segment, not present
43	.quad 0                  // TSS for task gates
44	.quad 0x008f9b000000FFFF // 16-bit code segment
45	.quad 0x008f93000000FFFF // 16-bit data segment
46	.quad 0x00cffb000000ffff // 32-bit code segment (user)
47	.quad 0x00cff3000000ffff // 32-bit data segment (user)
48	.quad 0                  // unused
49
50	.quad 0			 // 6 spare selectors
51	.quad 0
52	.quad 0
53	.quad 0
54	.quad 0
55	.quad 0
56
57tss_descr:
58        .rept max_cpus
59        .quad 0x000089000000ffff // 32-bit avail tss
60        .endr
61gdt32_end:
62
63i = 0
64.globl tss
65tss:
66        .rept max_cpus
67        .long 0
68        .long ring0stacktop - i * 4096
69        .long 16
70        .quad 0, 0
71        .quad 0, 0, 0, 0, 0, 0, 0, 0
72        .long 0, 0, 0
73        i = i + 1
74        .endr
75tss_end:
76
77idt_descr:
78	.word end_boot_idt - boot_idt - 1
79	.long boot_idt
80
81.section .init
82
83.code32
84
85mb_magic = 0x1BADB002
86mb_flags = 0x0
87
88	# multiboot header
89	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
90mb_cmdline = 16
91
92MSR_GS_BASE = 0xc0000101
93
94.macro setup_percpu_area
95	lea -4096(%esp), %eax
96	mov $0, %edx
97	mov $MSR_GS_BASE, %ecx
98	wrmsr
99.endm
100
101.macro setup_segments
102	mov $0x10, %ax
103	mov %ax, %ds
104	mov %ax, %es
105	mov %ax, %fs
106	mov %ax, %gs
107	mov %ax, %ss
108.endm
109
110.globl start
111start:
112        lgdtl gdt32_descr
113        setup_segments
114        mov $stacktop, %esp
115        setup_percpu_area
116
117        push %ebx
118        call setup_multiboot
119        addl $4, %esp
120        call setup_libcflat
121        mov mb_cmdline(%ebx), %eax
122        mov %eax, __args
123        call __setup_args
124        call prepare_32
125        jmpl $8, $start32
126
127prepare_32:
128	mov $(1 << 4), %eax // pse
129	mov %eax, %cr4
130
131	mov $pt, %eax
132	mov %eax, %cr3
133
134	mov %cr0, %eax
135	bts $0, %eax
136	bts $31, %eax
137	mov %eax, %cr0
138	ret
139
140smp_stacktop:	.long stacktop - 4096
141
142save_id:
143	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
144	movl (%eax), %eax
145	shrl $24, %eax
146	lock btsl %eax, online_cpus
147	retl
148
149ap_start32:
150	setup_segments
151	mov $-4096, %esp
152	lock xaddl %esp, smp_stacktop
153	setup_percpu_area
154	call prepare_32
155	call reset_apic
156	call save_id
157	call load_tss
158	call enable_apic
159	call enable_x2apic
160	sti
161	nop
162	lock incw cpu_online_count
163
1641:	hlt
165	jmp 1b
166
167start32:
168	call reset_apic
169	call save_id
170	call load_tss
171	call mask_pic_interrupts
172	call enable_apic
173	call ap_init
174	call enable_x2apic
175	call smp_init
176        push $__environ
177        push $__argv
178        push __argc
179        call main
180	push %eax
181	call exit
182
183load_tss:
184	lidt idt_descr
185	mov $16, %eax
186	mov %ax, %ss
187	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
188	mov (%eax), %eax
189	shr $24, %eax
190	mov %eax, %ebx
191	shl $3, %ebx
192	mov $((tss_end - tss) / max_cpus), %edx
193	imul %edx
194	add $tss, %eax
195	mov %ax, tss_descr+2(%ebx)
196	shr $16, %eax
197	mov %al, tss_descr+4(%ebx)
198	shr $8, %eax
199	mov %al, tss_descr+7(%ebx)
200	lea tss_descr-gdt32(%ebx), %eax
201	ltr %ax
202	ret
203
204ap_init:
205	cld
206	lea sipi_entry, %esi
207	xor %edi, %edi
208	mov $(sipi_end - sipi_entry), %ecx
209	rep movsb
210	mov $APIC_DEFAULT_PHYS_BASE, %eax
211	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%eax)
212	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%eax)
213	call fwcfg_get_nb_cpus
2141:	pause
215	cmpw %ax, cpu_online_count
216	jne 1b
217	ret
218
219online_cpus:
220	.fill (max_cpus + 7) / 8, 1, 0
221
222cpu_online_count:	.word 1
223
224.code16
225sipi_entry:
226	mov %cr0, %eax
227	or $1, %eax
228	mov %eax, %cr0
229	lgdtl gdt32_descr - sipi_entry
230	ljmpl $8, $ap_start32
231
232gdt32_descr:
233	.word gdt32_end - gdt32 - 1
234	.long gdt32
235
236sipi_end:
237