* better
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / pure64.boot0 / src / init_smp.asm
blob2b65f9e016818f66406cc560b6086439dcbcf45c
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
5 ; INIT SMP
6 ; =============================================================================
8 ;MP_debugmsg: db 'MP_CODE!', 0
11 smp_setup:
12 sti ; Enable the timer
13 mov al, '3' ; Start of MP init
14 mov [0x000B809C], al
15 mov al, '0'
16 mov [0x000B809E], al
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)
22 searchingforACPI:
23 lodsq ; Load a quad word from RSI and store in RAX, then increment RSI by 8
24 cmp rax, rbx
25 je foundACPI
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
28 jmp searchingforACPI
30 mov al, '3' ; ACPI tables detected
31 mov [0x000B809C], al
32 mov al, '2'
33 mov [0x000B809E], al
35 foundACPI:
36 jmp init_smp_acpi
38 makempgonow:
39 mov al, '3' ; ACPI tables parsed
40 mov [0x000B809C], al
41 mov al, '6'
42 mov [0x000B809E], al
44 ; Step 2: Enable Local APIC on BSP
45 mov rsi, [os_LocalAPICAddress]
46 cmp rsi, 0x00000000
47 je noMP ; Skip MP init if we didn't get a valid LAPIC address
48 add rsi, 0xf0 ; Offset to Spurious Interrupt Register
49 mov rdi, rsi
50 lodsd
51 or eax, 0000000100000000b
52 stosd
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
59 xor eax, eax
60 xor ecx, ecx
61 xor edx, edx
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
68 xor eax, eax
70 nextcore:
71 cmp rsi, 0x0000000000005900
72 je done
73 lodsb
74 cmp al, 1 ; Is it enabled?
75 jne skipcore
77 ; push rax ; Debug - display APIC ID
78 ; mov al, cl
79 ; add al, 48
80 ; call os_print_char
81 ; pop rax
83 cmp cl, dl ; Is it the BSP?
84 je skipcore
86 ; Broadcast 'INIT' IPI to APIC ID in AL
87 mov al, cl
88 shl eax, 24
89 mov rdi, [os_LocalAPICAddress]
90 add rdi, 0x310
91 stosd
92 mov eax, 0x00004500
93 mov rdi, [os_LocalAPICAddress]
94 add rdi, 0x300
95 stosd
96 push rsi
97 verifyinit:
98 mov rsi, [os_LocalAPICAddress]
99 add rsi, 0x300
100 lodsd
101 bt eax, 12 ; Verify that the command completed
102 jc verifyinit
103 pop rsi
105 mov rax, [os_Counter]
106 add rax, 10
107 wait1:
108 mov rbx, [os_Counter]
109 cmp rax, rbx
110 jg wait1
112 ; Broadcast 'Startup' IPI to destination using vector 0x08 to specify entry-point is at the memory-address 0x00008000
113 mov al, cl
114 shl eax, 24
115 mov rdi, [os_LocalAPICAddress]
116 add rdi, 0x310
117 stosd
118 mov eax, 0x00004608 ; Vector 0x08
119 mov rdi, [os_LocalAPICAddress]
120 add rdi, 0x300
121 stosd
122 push rsi
123 verifystartup1:
124 mov rsi, [os_LocalAPICAddress]
125 add rsi, 0x300
126 lodsd
127 bt eax, 12 ; Verify that the command completed
128 jc verifystartup1
129 pop rsi
131 mov rax, [os_Counter]
132 add rax, 2
133 wait2:
134 mov rbx, [os_Counter]
135 cmp rax, rbx
136 jg wait2
138 skipcore:
139 inc cl
140 jmp nextcore
142 done:
144 mov al, '3'
145 mov [0x000B809C], al
146 mov al, '8'
147 mov [0x000B809E], al
149 ; Let things settle (Give the AP's some time to finish)
150 mov rax, [os_Counter]
151 add rax, 10
152 wait3:
153 mov rbx, [os_Counter]
154 cmp rax, rbx
155 jg wait3
157 ; Step 4: Prepare the IOAPIC
158 ; To be coded...
160 ; Step 5: Finish up
162 noMP:
163 lock
164 inc word [cpu_activated] ; BSP adds one here
166 xor eax, eax
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
174 stosb
176 mov al, '3'
177 mov [0x000B809C], al
178 mov al, 'A'
179 mov [0x000B809E], al
181 ; Calculate speed of CPU (At this point the timer is firing at 1000Hz)
182 xchg bx, bx
183 cpuid
184 xor edx, edx
185 xor eax, eax
186 mov rcx, [os_Counter]
187 add rcx, 10
188 rdtsc
189 push rax
190 speedtest:
191 mov rbx, [os_Counter]
192 cmp rbx, rcx
193 jl speedtest
194 rdtsc
195 pop rdx
196 sub rax, rdx
197 xor edx, edx
198 mov rcx, 10000
199 div rcx
200 mov [cpu_speed], ax
202 mov al, '3'
203 mov [0x000B809C], al
204 mov al, 'C'
205 mov [0x000B809E], al
207 cli ; Disable the timer
209 ; Set PIT Channel 0 to fire at 100Hz (Divisor = 1193180 / hz)
210 mov al, 0x36 ; Set Timer
211 out 0x43, al
212 mov al, 0x9B ; We want 100MHz so 0x2E9B
213 out 0x40, al
214 mov al, 0x2E
215 out 0x40, al
217 ; Disable all IRQs
218 in al, 0x21
219 mov al, 11111111b
220 out 0x21, al
221 in al, 0xA1
222 mov al, 11111111b
223 out 0xA1, al
228 %include "init_smp_acpi.asm"
231 ; =============================================================================
232 ; EOF