+; \r
+; Multiprocessing AP Startup Code (Must be within 0x10FFF0)\r
+;\r
+%if USE_MP\r
+[extern gGDT]\r
+[extern gGDTPtr]\r
+[extern gIDTPtr]\r
+[extern gpMP_LocalAPIC]\r
+[extern gaAPIC_to_CPU]\r
+[extern gaCPUs]\r
+[extern giNumInitingCPUs]\r
+lGDTPtr: ; Local GDT Pointer\r
+ dw 2*8-1\r
+ dd gGDT-KERNEL_BASE\r
+\r
+[bits 16]\r
+[global APStartup]\r
+APStartup:\r
+ xchg bx, bx ; MAGIC BREAK!\r
+ mov ax, 0xFFFF\r
+ mov ds, ax\r
+ lgdt [DWORD ds:lGDTPtr-KERNEL_BASE-0xFFFF0]\r
+ mov eax, cr0\r
+ or al, 1\r
+ mov cr0, eax\r
+ jmp 08h:DWORD .ProtectedMode-KERNEL_BASE\r
+[bits 32]\r
+.ProtectedMode:\r
+ ; Start Paging\r
+ mov eax, gaInitPageDir - KERNEL_BASE\r
+ mov cr3, eax\r
+ mov eax, cr0\r
+ or eax, 0x80010000 ; PG and WP\r
+ mov cr0, eax\r
+ ; Jump to higher half\r
+ lea eax, [.higherHalf]\r
+ jmp eax\r
+.higherHalf:\r
+ ; Load True GDT & IDT\r
+ lgdt [gGDTPtr]\r
+ lidt [gIDTPtr]\r
+\r
+ mov eax, [gpMP_LocalAPIC]\r
+ mov DWORD [eax], 0\r
+ xor ecx, ecx\r
+ mov cl, BYTE [eax+0x10]\r
+ ; CL is now local APIC ID\r
+ mov cl, BYTE [gaAPIC_to_CPU+ecx]\r
+ ; CL is now the CPU ID\r
+ mov BYTE [gaCPUs+ecx*8+1], 1\r
+ ; Decrement the remaining CPU count\r
+ dec DWORD [giNumInitingCPUs]\r
+ ; CPU is now marked as initialised\r
+ sti\r
+.hlt:\r
+ hlt\r
+ jmp .hlt\r
+%endif\r
+\r