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