global smp_bootstrap_stackarray global smp_bootstrap_bsp global smp_bootstrap_corecount global final_gdt_descriptor extern smp_kinit extern _pmem_vaddr [bits 16] smp_trampoline: cli in al, 0x92 or al, 2 out 0x92, al xor ax, ax mov ds, ax lgdt [.gdt_descriptor_p] mov eax, cr0 or eax, 0x1 mov cr0, eax ; now in long mode jmp 0x8:smp_protected ;________________________________________________________________________________________ .gdt_start_p: ; we need to start with a null gdt dd 0 dd 0 .gdt_code_p: dw 0xffff dw 0x0000 db 0x00 db 10011010b db 11001111b db 0x0000 .gdt_data_p: dw 0xffff dw 0x0000 db 0x00 db 10010010b db 11001111b db 0x0000 .gdt_end_p: .gdt_descriptor_p: dw .gdt_end_p - .gdt_start_p - 1 dq .gdt_start_p SMP_PROTECTED_CODE_SEGMENT equ .gdt_code_p - .gdt_start_p SMP_PROTECTED_DATA_SEGMENT equ .gdt_data_p - .gdt_start_p ;________________________________________________________________________________________ smp_protected: bits 32 mov ax, SMP_PROTECTED_DATA_SEGMENT mov ds, ax mov ss, ax mov es, ax mov fs, ax mov gs, ax mov eax, 0x10000 mov cr3, eax ;setting up misc features mov eax, cr4 ; PAE, OSFXSR, OSXMMEXCPT or eax, 1 << 5 | 1 << 9 | 1 << 10 mov cr4, eax ;set NX and LME mov eax, 0x80000001 cpuid mov ebx, edx and ebx, 1 << 20 shr ebx, 9 mov ecx, 0xc0000080 rdmsr or eax, 1 << 8 fuckyou: or eax, ebx wrmsr ;enable paging mov eax, cr0 or eax, 1 << 31 | 1 << 0; and ax, ~(1 << 2) mov cr0, eax lgdt [final_gdt_descriptor] jmp SMP_LONG_CODE_SEGMENT:smp_longsetup ;________________________________________________________________________________________ bits 64 final_gdt: .start: ;and now we set up a temporary GDT creating a 1:1 mapping dw 0xffff dw 0 db 0 ;this is the invalid GDT db 0 db 1 db 0 ;now for the code GDT: .code: dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!) dw 0 ; base address 15:00 db 0 ; base address 23:16 db 10011010b db 00100000b db 0 .data: dw 0 dw 0 db 0 db 10010010b db 00100000b db 0 .end: ; later calculates offset in defs below final_gdt_descriptor: dw final_gdt.end - final_gdt.start - 1 .offset: dq final_gdt.start SMP_LONG_CODE_SEGMENT equ final_gdt.code - final_gdt.start SMP_LONG_DATA_SEGMENT equ final_gdt.data - final_gdt.start smp_longsetup: mov eax, 1 cpuid shr ebx, 24 cmp bl, BYTE [smp_bootstrap_bsp] jl .apic_below_bsp sub bl, 1 .apic_below_bsp: mov rax, QWORD [smp_bootstrap_stackarray] mov rsp, QWORD [rax + rbx * 8] mov rax, 0xffff800000000000 ;or QWORD [final_gdt_descriptor.offset], rax ;lgdt [final_gdt_descriptor] .inc_corecounter: mov rax, [smp_bootstrap_corecount] lock inc BYTE [rax] smp_enter_kernel: mov rax, smp_kinit jmp rax align 8 smp_bootstrap_stackarray: dq 0 smp_lock: dq 0 smp_bootstrap_bsp: db 0 smp_bootstrap_corecount: db 0 times 512 - ($ - $$) db 0