blob: 3ae98d3d3a19c999d495a9996c78a42f314a94b3 [file] [log] [blame]
#include "apic-defs.h"
.globl boot_idt
.globl idt_descr
.globl tss_descr
.globl gdt64_desc
.globl online_cpus
ipi_vector = 0x20
max_cpus = MAX_TEST_CPUS
.bss
. = . + 4096 * max_cpus
.align 16
stacktop:
. = . + 4096 * max_cpus
.align 16
ring0stacktop:
.data
.align 4096
.globl ptl2
ptl2:
i = 0
.rept 512 * 4
.quad 0x1e7 | (i << 21)
i = i + 1
.endr
.align 4096
ptl3:
.quad ptl2 + 7 + 0 * 4096
.quad ptl2 + 7 + 1 * 4096
.quad ptl2 + 7 + 2 * 4096
.quad ptl2 + 7 + 3 * 4096
.align 4096
ptl4:
.quad ptl3 + 7
.align 4096
ptl5:
.quad ptl4 + 7
.align 4096
boot_idt:
.rept 256
.quad 0
.quad 0
.endr
end_boot_idt:
gdt64_desc:
.word gdt64_end - gdt64 - 1
.quad gdt64
gdt64:
.quad 0
.quad 0x00af9b000000ffff // 64-bit code segment
.quad 0x00cf93000000ffff // 32/64-bit data segment
.quad 0x00af1b000000ffff // 64-bit code segment, not present
.quad 0x00cf9b000000ffff // 32-bit code segment
.quad 0x008f9b000000FFFF // 16-bit code segment
.quad 0x008f93000000FFFF // 16-bit data segment
.quad 0x00cffb000000ffff // 32-bit code segment (user)
.quad 0x00cff3000000ffff // 32/64-bit data segment (user)
.quad 0x00affb000000ffff // 64-bit code segment (user)
.quad 0 // 6 spare selectors
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
tss_descr:
.rept max_cpus
.quad 0x000089000000ffff // 64-bit avail tss
.quad 0 // tss high addr
.endr
gdt64_end:
i = 0
.globl tss
tss:
.rept max_cpus
.long 0
.quad ring0stacktop - i * 4096
.quad 0, 0
.quad 0, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0
i = i + 1
.endr
tss_end:
mb_boot_info: .quad 0
pt_root: .quad ptl4
.section .init
.code32
mb_magic = 0x1BADB002
mb_flags = 0x0
# multiboot header
.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
mb_cmdline = 16
MSR_GS_BASE = 0xc0000101
.macro setup_percpu_area
lea -4096(%esp), %eax
mov $0, %edx
mov $MSR_GS_BASE, %ecx
wrmsr
.endm
.macro setup_segments
mov $MSR_GS_BASE, %ecx
rdmsr
mov $0x10, %bx
mov %bx, %ds
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ss
/* restore MSR_GS_BASE */
wrmsr
.endm
.globl start
start:
mov %ebx, mb_boot_info
mov $stacktop, %esp
setup_percpu_area
call prepare_64
jmpl $8, $start64
switch_to_5level:
/* Disable CR4.PCIDE */
mov %cr4, %eax
btr $17, %eax
mov %eax, %cr4
mov %cr0, %eax
btr $31, %eax
mov %eax, %cr0
mov $ptl5, %eax
mov %eax, pt_root
/* Enable CR4.LA57 */
mov %cr4, %eax
bts $12, %eax
mov %eax, %cr4
mov $0x10, %ax
mov %ax, %ss
call enter_long_mode
jmpl $8, $lvl5
prepare_64:
lgdt gdt64_desc
setup_segments
enter_long_mode:
mov $(1 << 5), %eax // pae
mov %eax, %cr4
mov pt_root, %eax
mov %eax, %cr3
efer = 0xc0000080
mov $efer, %ecx
rdmsr
bts $8, %eax
wrmsr
mov %cr0, %eax
bts $0, %eax
bts $31, %eax
mov %eax, %cr0
ret
smp_stacktop: .long stacktop - 4096
.align 16
gdt32:
.quad 0
.quad 0x00cf9b000000ffff // flat 32-bit code segment
.quad 0x00cf93000000ffff // flat 32-bit data segment
gdt32_end:
.code16
sipi_entry:
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
lgdtl gdt32_descr - sipi_entry
ljmpl $8, $ap_start32
gdt32_descr:
.word gdt32_end - gdt32 - 1
.long gdt32
sipi_end:
.code32
ap_start32:
setup_segments
mov $-4096, %esp
lock/xaddl %esp, smp_stacktop
setup_percpu_area
call prepare_64
ljmpl $8, $ap_start64
.code64
save_id:
movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
movl (%rax), %eax
shrl $24, %eax
lock btsl %eax, online_cpus
retq
ap_start64:
call reset_apic
call load_tss
call enable_apic
call save_id
call enable_x2apic
sti
nop
lock incw cpu_online_count
1: hlt
jmp 1b
start64:
call reset_apic
call load_tss
call mask_pic_interrupts
call enable_apic
call save_id
mov mb_boot_info(%rip), %rbx
mov %rbx, %rdi
call setup_multiboot
call setup_libcflat
mov mb_cmdline(%rbx), %eax
mov %rax, __args(%rip)
call __setup_args
call ap_init
call enable_x2apic
call smp_init
mov __argc(%rip), %edi
lea __argv(%rip), %rsi
lea __environ(%rip), %rdx
call main
mov %eax, %edi
call exit
.globl setup_5level_page_table
setup_5level_page_table:
/* Check if 5-level paging has already enabled */
mov %cr4, %rax
test $0x1000, %eax
jnz lvl5
pushq $32
pushq $switch_to_5level
lretq
lvl5:
retq
idt_descr:
.word end_boot_idt - boot_idt - 1
.quad boot_idt
online_cpus:
.fill (max_cpus + 7) / 8, 1, 0
load_tss:
lidtq idt_descr
mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
mov (%rax), %eax
shr $24, %eax
mov %eax, %ebx
shl $4, %ebx
mov $((tss_end - tss) / max_cpus), %edx
imul %edx
add $tss, %rax
mov %ax, tss_descr+2(%rbx)
shr $16, %rax
mov %al, tss_descr+4(%rbx)
shr $8, %rax
mov %al, tss_descr+7(%rbx)
shr $8, %rax
mov %eax, tss_descr+8(%rbx)
lea tss_descr-gdt64(%rbx), %rax
ltr %ax
ret
ap_init:
cld
lea sipi_entry, %rsi
xor %rdi, %rdi
mov $(sipi_end - sipi_entry), %rcx
rep/movsb
mov $APIC_DEFAULT_PHYS_BASE, %eax
movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
call fwcfg_get_nb_cpus
1: pause
cmpw %ax, cpu_online_count
jne 1b
ret
cpu_online_count: .word 1