xref: /kvm-unit-tests/x86/cstart.S (revision e97e1c827fadc972c4efc8fc0650984b6fcc74e8)
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
61percpu_descr:
62        .rept max_cpus
63        .quad 0x00cf93000000ffff // 32-bit data segment for perCPU area
64        .endr
65gdt32_end:
66
67i = 0
68.globl tss
69tss:
70        .rept max_cpus
71        .long 0
72        .long ring0stacktop - i * 4096
73        .long 16
74        .quad 0, 0
75        .quad 0, 0, 0, 0, 0, 0, 0, 0
76        .long 0, 0, 0
77        i = i + 1
78        .endr
79tss_end:
80
81idt_descr:
82	.word end_boot_idt - boot_idt - 1
83	.long boot_idt
84
85.section .init
86
87.code32
88
89mb_magic = 0x1BADB002
90mb_flags = 0x0
91
92	# multiboot header
93	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
94mb_cmdline = 16
95
96.macro setup_percpu_area
97	lea -4096(%esp), %eax
98
99	/* fill GS_BASE in the GDT, do not clobber %ebx (multiboot info) */
100	mov (APIC_DEFAULT_PHYS_BASE + APIC_ID), %ecx
101	shr $24, %ecx
102	mov %ax, percpu_descr+2(,%ecx,8)
103
104	shr $16, %eax
105	mov %al, percpu_descr+4(,%ecx,8)
106	mov %ah, percpu_descr+7(,%ecx,8)
107
108	lea percpu_descr-gdt32(,%ecx,8), %eax
109	mov %ax, %gs
110
111.endm
112
113.macro setup_segments
114	mov $0x10, %ax
115	mov %ax, %ds
116	mov %ax, %es
117	mov %ax, %fs
118	mov %ax, %gs
119	mov %ax, %ss
120.endm
121
122.globl start
123start:
124        lgdtl gdt32_descr
125        setup_segments
126        mov $stacktop, %esp
127        setup_percpu_area
128
129        push %ebx
130        call setup_multiboot
131        addl $4, %esp
132        call setup_libcflat
133        mov mb_cmdline(%ebx), %eax
134        mov %eax, __args
135        call __setup_args
136        call prepare_32
137        jmpl $8, $start32
138
139prepare_32:
140	mov $(1 << 4), %eax // pse
141	mov %eax, %cr4
142
143	mov $pt, %eax
144	mov %eax, %cr3
145
146	mov %cr0, %eax
147	bts $0, %eax
148	bts $31, %eax
149	mov %eax, %cr0
150	ret
151
152smp_stacktop:	.long stacktop - 4096
153
154save_id:
155	movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
156	movl (%eax), %eax
157	shrl $24, %eax
158	lock btsl %eax, online_cpus
159	retl
160
161ap_start32:
162	setup_segments
163	mov $-4096, %esp
164	lock xaddl %esp, smp_stacktop
165	setup_percpu_area
166	call prepare_32
167	call reset_apic
168	call save_id
169	call load_tss
170	call enable_apic
171	call enable_x2apic
172	sti
173	nop
174	lock incw cpu_online_count
175
1761:	hlt
177	jmp 1b
178
179start32:
180	call reset_apic
181	call save_id
182	call load_tss
183	call mask_pic_interrupts
184	call enable_apic
185	call ap_init
186	call enable_x2apic
187	call smp_init
188        push $__environ
189        push $__argv
190        push __argc
191        call main
192	push %eax
193	call exit
194
195load_tss:
196	lidt idt_descr
197	mov $16, %eax
198	mov %ax, %ss
199	mov (APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
200	shr $24, %eax
201	mov %eax, %ebx
202	mov $((tss_end - tss) / max_cpus), %edx
203	imul %edx
204	add $tss, %eax
205	mov %ax, tss_descr+2(,%ebx,8)
206	shr $16, %eax
207	mov %al, tss_descr+4(,%ebx,8)
208	mov %ah, tss_descr+7(,%ebx,8)
209	lea tss_descr-gdt32(,%ebx,8), %eax
210	ltr %ax
211	ret
212
213ap_init:
214	cld
215	lea sipi_entry, %esi
216	xor %edi, %edi
217	mov $(sipi_end - sipi_entry), %ecx
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(%eax)
221	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%eax)
222	call fwcfg_get_nb_cpus
2231:	pause
224	cmpw %ax, cpu_online_count
225	jne 1b
226	ret
227
228online_cpus:
229	.fill (max_cpus + 7) / 8, 1, 0
230
231cpu_online_count:	.word 1
232
233.code16
234sipi_entry:
235	mov %cr0, %eax
236	or $1, %eax
237	mov %eax, %cr0
238	lgdtl gdt32_descr - sipi_entry
239	ljmpl $8, $ap_start32
240
241gdt32_descr:
242	.word gdt32_end - gdt32 - 1
243	.long gdt32
244
245sipi_end:
246