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