1 2#include "apic-defs.h" 3 4.globl boot_idt 5 6.globl idt_descr 7.globl tss_descr 8.globl gdt64_desc 9.globl online_cpus 10.globl cpu_online_count 11 12ipi_vector = 0x20 13 14max_cpus = MAX_TEST_CPUS 15 16.bss 17 18 . = . + 4096 * max_cpus 19 .align 16 20stacktop: 21 22 . = . + 4096 * max_cpus 23 .align 16 24ring0stacktop: 25 26.data 27 28.align 4096 29.globl ptl2 30ptl2: 31i = 0 32 .rept 512 * 4 33 .quad 0x1e7 | (i << 21) 34 i = i + 1 35 .endr 36 37.align 4096 38ptl3: 39 .quad ptl2 + 7 + 0 * 4096 40 .quad ptl2 + 7 + 1 * 4096 41 .quad ptl2 + 7 + 2 * 4096 42 .quad ptl2 + 7 + 3 * 4096 43 44.align 4096 45ptl4: 46 .quad ptl3 + 7 47 48.align 4096 49ptl5: 50 .quad ptl4 + 7 51 52.align 4096 53 54boot_idt: 55 .rept 256 56 .quad 0 57 .quad 0 58 .endr 59end_boot_idt: 60 61gdt64_desc: 62 .word gdt64_end - gdt64 - 1 63 .quad gdt64 64 65gdt64: 66 .quad 0 67 .quad 0x00af9b000000ffff // 64-bit code segment 68 .quad 0x00cf93000000ffff // 32/64-bit data segment 69 .quad 0x00af1b000000ffff // 64-bit code segment, not present 70 .quad 0x00cf9b000000ffff // 32-bit code segment 71 .quad 0x008f9b000000FFFF // 16-bit code segment 72 .quad 0x008f93000000FFFF // 16-bit data segment 73 .quad 0x00cffb000000ffff // 32-bit code segment (user) 74 .quad 0x00cff3000000ffff // 32/64-bit data segment (user) 75 .quad 0x00affb000000ffff // 64-bit code segment (user) 76 77 .quad 0 // 6 spare selectors 78 .quad 0 79 .quad 0 80 .quad 0 81 .quad 0 82 .quad 0 83 84tss_descr: 85 .rept max_cpus 86 .quad 0x000089000000ffff // 64-bit avail tss 87 .quad 0 // tss high addr 88 .endr 89gdt64_end: 90 91i = 0 92.globl tss 93tss: 94 .rept max_cpus 95 .long 0 96 .quad ring0stacktop - i * 4096 97 .quad 0, 0 98 .quad 0, 0, 0, 0, 0, 0, 0, 0 99 .long 0, 0, 0 100i = i + 1 101 .endr 102tss_end: 103 104mb_boot_info: .quad 0 105 106pt_root: .quad ptl4 107 108.section .init 109 110.code32 111 112mb_magic = 0x1BADB002 113mb_flags = 0x0 114 115 # multiboot header 116 .long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) 117mb_cmdline = 16 118 119MSR_GS_BASE = 0xc0000101 120 121.macro setup_percpu_area 122 lea -4096(%esp), %eax 123 mov $0, %edx 124 mov $MSR_GS_BASE, %ecx 125 wrmsr 126.endm 127 128.macro setup_segments 129 mov $MSR_GS_BASE, %ecx 130 rdmsr 131 132 mov $0x10, %bx 133 mov %bx, %ds 134 mov %bx, %es 135 mov %bx, %fs 136 mov %bx, %gs 137 mov %bx, %ss 138 139 /* restore MSR_GS_BASE */ 140 wrmsr 141.endm 142 143.globl start 144start: 145 mov %ebx, mb_boot_info 146 mov $stacktop, %esp 147 setup_percpu_area 148 call prepare_64 149 jmpl $8, $start64 150 151switch_to_5level: 152 /* Disable CR4.PCIDE */ 153 mov %cr4, %eax 154 btr $17, %eax 155 mov %eax, %cr4 156 157 mov %cr0, %eax 158 btr $31, %eax 159 mov %eax, %cr0 160 161 mov $ptl5, %eax 162 mov %eax, pt_root 163 164 /* Enable CR4.LA57 */ 165 mov %cr4, %eax 166 bts $12, %eax 167 mov %eax, %cr4 168 169 mov $0x10, %ax 170 mov %ax, %ss 171 172 call enter_long_mode 173 jmpl $8, $lvl5 174 175prepare_64: 176 lgdt gdt64_desc 177 setup_segments 178 179 xor %eax, %eax 180 mov %eax, %cr4 181 182enter_long_mode: 183 mov %cr4, %eax 184 bts $5, %eax // pae 185 mov %eax, %cr4 186 187 mov pt_root, %eax 188 mov %eax, %cr3 189 190efer = 0xc0000080 191 mov $efer, %ecx 192 rdmsr 193 bts $8, %eax 194 wrmsr 195 196 mov %cr0, %eax 197 bts $0, %eax 198 bts $31, %eax 199 mov %eax, %cr0 200 ret 201 202smp_stacktop: .long stacktop - 4096 203 204.align 16 205 206gdt32: 207 .quad 0 208 .quad 0x00cf9b000000ffff // flat 32-bit code segment 209 .quad 0x00cf93000000ffff // flat 32-bit data segment 210gdt32_end: 211 212.code16 213sipi_entry: 214 mov %cr0, %eax 215 or $1, %eax 216 mov %eax, %cr0 217 lgdtl gdt32_descr - sipi_entry 218 ljmpl $8, $ap_start32 219 220gdt32_descr: 221 .word gdt32_end - gdt32 - 1 222 .long gdt32 223 224sipi_end: 225 226.code32 227ap_start32: 228 setup_segments 229 mov $-4096, %esp 230 lock xaddl %esp, smp_stacktop 231 setup_percpu_area 232 call prepare_64 233 ljmpl $8, $ap_start64 234 235.code64 236save_id: 237 movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax 238 movl (%rax), %eax 239 shrl $24, %eax 240 lock btsl %eax, online_cpus 241 retq 242 243ap_start64: 244 call reset_apic 245 call load_tss 246 call enable_apic 247 call save_id 248 call enable_x2apic 249 sti 250 nop 251 lock incw cpu_online_count 252 2531: hlt 254 jmp 1b 255 256start64: 257 call reset_apic 258 call load_tss 259 call mask_pic_interrupts 260 call enable_apic 261 call save_id 262 mov mb_boot_info(%rip), %rbx 263 mov %rbx, %rdi 264 call setup_multiboot 265 call setup_libcflat 266 mov mb_cmdline(%rbx), %eax 267 mov %rax, __args(%rip) 268 call __setup_args 269 270 call ap_init 271 call enable_x2apic 272 call smp_init 273 274 mov __argc(%rip), %edi 275 lea __argv(%rip), %rsi 276 lea __environ(%rip), %rdx 277 call main 278 mov %eax, %edi 279 call exit 280 281.globl setup_5level_page_table 282setup_5level_page_table: 283 /* Check if 5-level paging has already enabled */ 284 mov %cr4, %rax 285 test $0x1000, %eax 286 jnz lvl5 287 288 pushq $32 289 pushq $switch_to_5level 290 lretq 291lvl5: 292 retq 293 294idt_descr: 295 .word end_boot_idt - boot_idt - 1 296 .quad boot_idt 297 298online_cpus: 299 .fill (max_cpus + 7) / 8, 1, 0 300 301load_tss: 302 lidtq idt_descr 303 mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax 304 mov (%rax), %eax 305 shr $24, %eax 306 mov %eax, %ebx 307 shl $4, %ebx 308 mov $((tss_end - tss) / max_cpus), %edx 309 imul %edx 310 add $tss, %rax 311 mov %ax, tss_descr+2(%rbx) 312 shr $16, %rax 313 mov %al, tss_descr+4(%rbx) 314 shr $8, %rax 315 mov %al, tss_descr+7(%rbx) 316 shr $8, %rax 317 mov %eax, tss_descr+8(%rbx) 318 lea tss_descr-gdt64(%rbx), %rax 319 ltr %ax 320 ret 321 322ap_init: 323 cld 324 lea sipi_entry, %rsi 325 xor %rdi, %rdi 326 mov $(sipi_end - sipi_entry), %rcx 327 rep movsb 328 mov $APIC_DEFAULT_PHYS_BASE, %eax 329 movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax) 330 movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax) 331 call fwcfg_get_nb_cpus 3321: pause 333 cmpw %ax, cpu_online_count 334 jne 1b 335 ret 336 337cpu_online_count: .word 1 338