1 ; =============================================================================
2 ; Pure64 -- a 64-bit OS loader written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2011 Return Infinity -- see LICENSE.TXT
6 ; =============================================================================
8 ;MP_debugmsg: db 'MP_CODE!', 0
12 sti ; Enable the timer
13 mov al, '3' ; Start of MP init
18 ; Step 1: Get APIC Information via ACPI
19 smp_check_for_acpi: ; Look for the Root System Description Pointer Structure
20 mov rsi
, 0x00000000000E0000 ; We want to start looking here
21 mov rbx
, 'RSD PTR ' ; This in the Signature for the ACPI Structure Table (0x2052545020445352)
23 lodsq
; Load a quad word from RSI and store in RAX, then increment RSI by 8
26 cmp rsi
, 0x00000000000FFFFF ; Keep looking until we get here
27 jge noMP
; We can't find ACPI either.. bail out and default to single cpu mode
30 mov al, '3' ; ACPI tables detected
39 mov al, '3' ; ACPI tables parsed
44 ; Step 2: Enable Local APIC on BSP
45 mov rsi
, [os_LocalAPICAddress
]
47 je noMP
; Skip MP init if we didn't get a valid LAPIC address
48 add rsi
, 0xf0 ; Offset to Spurious Interrupt Register
51 or eax, 0000000100000000b
54 ; Check if we want the AP's to be enabled.. if not then skip to end
55 ; cmp byte [cfg_smpinit], 1 ; Check if SMP should be enabled
56 ; jne noMP ; If not then skip SMP init
58 ; Step 3: Start the AP's one by one
62 mov rsi
, [os_LocalAPICAddress
]
63 add rsi
, 0x20 ; Add the offset for the APIC ID location
64 lodsd ; APIC ID is stored in bits 31:24
65 shr rax
, 24 ; AL now holds the BSP CPU's APIC ID
66 mov dl, al ; Store BSP APIC ID in DL
67 mov rsi
, 0x0000000000005800
71 cmp rsi
, 0x0000000000005900
74 cmp al, 1 ; Is it enabled?
77 ; push rax ; Debug - display APIC ID
83 cmp cl, dl ; Is it the BSP?
86 ; Broadcast 'INIT' IPI to APIC ID in AL
89 mov rdi
, [os_LocalAPICAddress
]
93 mov rdi
, [os_LocalAPICAddress
]
98 mov rsi
, [os_LocalAPICAddress
]
101 bt eax, 12 ; Verify that the command completed
105 mov rax
, [os_Counter
]
108 mov rbx
, [os_Counter
]
112 ; Broadcast 'Startup' IPI to destination using vector 0x08 to specify entry-point is at the memory-address 0x00008000
115 mov rdi
, [os_LocalAPICAddress
]
118 mov eax, 0x00004608 ; Vector 0x08
119 mov rdi
, [os_LocalAPICAddress
]
124 mov rsi
, [os_LocalAPICAddress
]
127 bt eax, 12 ; Verify that the command completed
131 mov rax
, [os_Counter
]
134 mov rbx
, [os_Counter
]
149 ; Let things settle (Give the AP's some time to finish)
150 mov rax
, [os_Counter
]
153 mov rbx
, [os_Counter
]
157 ; Step 4: Prepare the IOAPIC
164 inc word [cpu_activated
] ; BSP adds one here
167 mov rsi
, [os_LocalAPICAddress
]
168 add rsi
, 0x20 ; Add the offset for the APIC ID location
169 lodsd ; APIC ID is stored in bits 31:24
170 shr rax
, 24 ; AL now holds the CPU's APIC ID (0 - 255)
171 mov rdi
, 0x00005700 ; The location where the cpu values are stored
172 add rdi
, rax
; RDI points to infomap CPU area + APIC ID. ex F701 would be APIC ID 1
173 mov al, 3 ; This is the BSP so bits 0 and 1 are set
181 ; Calculate speed of CPU (At this point the timer is firing at 1000Hz)
186 mov rcx
, [os_Counter
]
191 mov rbx
, [os_Counter
]
207 cli ; Disable the timer
209 ; Set PIT Channel 0 to fire at 100Hz (Divisor = 1193180 / hz)
210 mov al, 0x36 ; Set Timer
212 mov al, 0x9B ; We want 100MHz so 0x2E9B
228 %include "init_smp_acpi.asm"
231 ; =============================================================================