mirror of
https://gitlab.com/bztsrc/bootboot.git
synced 2023-02-13 20:54:32 -05:00
More SMP stuff
This commit is contained in:
parent
e0dc1c152d
commit
b556210529
7 changed files with 311 additions and 284 deletions
BIN
dist/bootboot.bin
vendored
BIN
dist/bootboot.bin
vendored
Binary file not shown.
BIN
dist/bootboot.efi
vendored
BIN
dist/bootboot.efi
vendored
Binary file not shown.
BIN
dist/bootboot.rom
vendored
BIN
dist/bootboot.rom
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -102,6 +102,12 @@ macro prot_readsector
|
|||
call near prot_readsectorfunc
|
||||
}
|
||||
|
||||
macro prot_sleep delay
|
||||
{
|
||||
mov ecx, delay
|
||||
call near prot_sleepfunc
|
||||
}
|
||||
|
||||
macro DBG msg
|
||||
{
|
||||
if BBDEBUG eq 1
|
||||
|
@ -359,12 +365,15 @@ realmode_start:
|
|||
cmp ax, 0600h
|
||||
jb .cpuerror
|
||||
;look for minimum feature flags
|
||||
;so we have PAE?
|
||||
;do we have PAE?
|
||||
bt edx, 6
|
||||
jnc .cpuerror
|
||||
;what about MSR?
|
||||
bt edx, 5
|
||||
jnc .cpuerror
|
||||
;do we have RDTSC instruction?
|
||||
bt edx, 4
|
||||
jnc .cpuerror
|
||||
;and can we use long mode (LME)?
|
||||
mov eax, 80000000h
|
||||
mov ebp, eax
|
||||
|
@ -491,6 +500,21 @@ a20wait2: in al, 64h
|
|||
jz a20wait2
|
||||
ret
|
||||
a20ok:
|
||||
; calibrate RDTSC
|
||||
rdtsc
|
||||
mov dword [ncycles], eax
|
||||
mov dword [ncycles+4], edx
|
||||
; wait 200 usec
|
||||
xor cx, cx
|
||||
mov dx, 200
|
||||
mov ah, 086h
|
||||
int 15h
|
||||
rdtsc
|
||||
sub eax, dword [ncycles]
|
||||
sbb edx, dword [ncycles+4]
|
||||
mov dword [ncycles], eax
|
||||
mov dword [ncycles+4], edx
|
||||
|
||||
; wait for a key press for half a sec, if pressed use backup initrd
|
||||
mov word [origcount], 0
|
||||
sti
|
||||
|
@ -834,7 +858,7 @@ ap_start: xor ax, ax
|
|||
mov eax, dword [esi]
|
||||
or ah, 1h
|
||||
mov dword [esi], eax
|
||||
inc byte [ap_done]
|
||||
lock inc byte [ap_done]
|
||||
; spinlock until BSP finishes
|
||||
@@: pause
|
||||
cmp byte [bsp_done], 0
|
||||
|
@ -1074,6 +1098,26 @@ prot_oct2bin:
|
|||
pop ebx
|
||||
ret
|
||||
|
||||
; IN: ecx delay time in 200 usec units
|
||||
prot_sleepfunc:
|
||||
push edx
|
||||
rdtsc
|
||||
mov dword [gpt_ptr], eax
|
||||
mov dword [gpt_ptr+4], edx
|
||||
mov eax, dword [ncycles]
|
||||
mov edx, dword [ncycles+4]
|
||||
mul ecx
|
||||
add dword [gpt_ptr], eax
|
||||
adc dword [gpt_ptr+4], edx
|
||||
@@: pause
|
||||
rdtsc
|
||||
cmp dword [gpt_ptr+4], edx
|
||||
jl @b
|
||||
cmp dword [gpt_ptr], eax
|
||||
jl @b
|
||||
pop edx
|
||||
ret
|
||||
|
||||
; IN: al, character to send
|
||||
uart_send: mov ah, al
|
||||
mov dx, word [400h] ;3fdh
|
||||
|
@ -1971,38 +2015,35 @@ end if
|
|||
mov edi, lapic_ids
|
||||
.nextmadtentry:
|
||||
cmp word [numcores], 256
|
||||
jae .dosmp
|
||||
jae .acpidone
|
||||
cmp byte [ebx], 0 ; madt_entry.type: is it a Local APIC Processor?
|
||||
jne @f
|
||||
mov al, byte [ebx+4] ; madt_entry.lapicproc.flag & ENABLED
|
||||
and al, 1
|
||||
jz .madterr
|
||||
jz @f
|
||||
xor ax, ax
|
||||
mov al, byte [ebx+3] ; madt_entry.lapicproc.lapicid
|
||||
cmp al, 0FFh
|
||||
je .madterr
|
||||
je @f
|
||||
stosw ; ACPI table holds 1 byte id, but internally we have 2 bytes
|
||||
inc word [numcores]
|
||||
jmp @f
|
||||
.madterr: mov byte [boguscore], 1
|
||||
@@: xor eax, eax
|
||||
mov al, byte [ebx+1] ; madt_entry.size
|
||||
or al, al
|
||||
jz .dosmp
|
||||
jz .acpidone
|
||||
add ebx, eax
|
||||
cmp ecx, eax
|
||||
jl .acpidone
|
||||
sub ecx, eax
|
||||
cmp ecx, 0
|
||||
jg .nextmadtentry
|
||||
jmp .dosmp
|
||||
|
||||
jmp .nextmadtentry
|
||||
|
||||
.trymp: ; in lack of ACPI, try legacy MP structures
|
||||
mov esi, dword [bootboot.mp_ptr]
|
||||
or esi, esi
|
||||
jz .nosmp
|
||||
jz .acpidone
|
||||
mov esi, dword [esi+4]
|
||||
cmp dword [esi], 'PCMP'
|
||||
jne .nosmp
|
||||
jne .acpidone
|
||||
mov eax, dword [esi+36] ; pcmp.lapic_address
|
||||
mov dword [lapic_ptr], eax
|
||||
mov cx, word [esi+34] ; pcmp.numentries
|
||||
|
@ -2010,7 +2051,7 @@ end if
|
|||
mov edi, lapic_ids
|
||||
.nextpcmpentry:
|
||||
cmp word [numcores], 256
|
||||
jae .dosmp
|
||||
jae .acpidone
|
||||
cmp byte [esi], 0 ; pcmp_entry.type: is it a Local APIC Processor?
|
||||
jne @f
|
||||
xor ax, ax
|
||||
|
@ -2021,13 +2062,18 @@ end if
|
|||
@@: add esi, 8
|
||||
dec cx
|
||||
jnz .nextpcmpentry
|
||||
|
||||
; send IPI and SIPI
|
||||
.dosmp: cmp word [numcores], 2
|
||||
jb .nosmp
|
||||
.acpidone:
|
||||
; failsafe
|
||||
cmp dword [lapic_ptr], 0
|
||||
jz .nosmp
|
||||
|
||||
jz @f
|
||||
cmp word [numcores], 0
|
||||
jnz .smpok
|
||||
@@: mov word [numcores], 1
|
||||
mov ax, word [bootboot.bspid]
|
||||
mov word [lapic_ids], ax
|
||||
mov dword [lapic_ptr], 0
|
||||
jmp .stks
|
||||
.smpok:
|
||||
if BBDEBUG eq 1
|
||||
xor eax, eax
|
||||
mov dword [gpt_ptr], eax
|
||||
|
@ -2069,196 +2115,11 @@ if BBDEBUG eq 1
|
|||
call real_printfunc
|
||||
mov si, gpt_ptr
|
||||
call real_printfunc
|
||||
cmp byte [boguscore], 0
|
||||
jz @f
|
||||
mov si, dbg_bogus
|
||||
call real_printfunc
|
||||
@@: mov si, crlf
|
||||
mov si, crlf
|
||||
call real_printfunc
|
||||
real_protmode
|
||||
end if
|
||||
|
||||
; relocate AP trampoline
|
||||
mov esi, ap_trampoline
|
||||
mov edi, 7000h
|
||||
mov ecx, (ap_start-ap_trampoline+3)/4
|
||||
repnz movsd
|
||||
|
||||
; enable Local APIC
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 0F0h
|
||||
mov eax, dword [esi]
|
||||
or ah, 1h
|
||||
mov dword [esi], eax
|
||||
|
||||
cmp byte [boguscore], 0
|
||||
jnz .nobcast
|
||||
|
||||
; send Broadcast INIT IPI
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 300h
|
||||
mov eax, 0C4500h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 10 millisec
|
||||
push esi
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 10000
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop esi
|
||||
|
||||
; send Broadcast STARTUP IPI
|
||||
mov eax, 0C4607h ; start at 0700:0000h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
push eax
|
||||
push esi
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 200
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop esi
|
||||
pop eax
|
||||
mov dword [esi], eax ; second SIPI
|
||||
jmp .nosmp
|
||||
|
||||
; send IPIs to specific cores one by one
|
||||
.nobcast: xor edx, edx
|
||||
.nextcore: cmp dx, word [numcores]
|
||||
jae .nosmp
|
||||
xor esi, esi
|
||||
mov esi, edx
|
||||
inc edx
|
||||
shl esi, 1
|
||||
add esi, lapic_ids
|
||||
mov bx, word [esi]
|
||||
cmp bx, word [bootboot.bspid]
|
||||
je .nextcore
|
||||
shl ebx, 24
|
||||
|
||||
; clear APIC error
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 280h
|
||||
mov dword [esi], 0
|
||||
mov eax, dword [esi]
|
||||
|
||||
; select AP
|
||||
add esi, 30h
|
||||
mov dword [esi], ebx
|
||||
; trigger INIT IPI
|
||||
sub esi, 10h
|
||||
mov eax, 004500h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
push esi
|
||||
push edx
|
||||
push ebx
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 200
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop ebx
|
||||
pop edx
|
||||
pop esi
|
||||
|
||||
; select AP
|
||||
add esi, 10h
|
||||
mov dword [esi], ebx
|
||||
; deassert INIT IPI
|
||||
sub esi, 10h
|
||||
mov eax, 008500h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 10 millisec
|
||||
push esi
|
||||
push edx
|
||||
push ebx
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 10000
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop ebx
|
||||
pop edx
|
||||
pop esi
|
||||
|
||||
mov byte [ap_done], 0
|
||||
; select AP
|
||||
add esi, 10h
|
||||
mov dword [esi], ebx
|
||||
; send STARTUP IPI
|
||||
sub esi, 10h
|
||||
mov eax, 004607h ; start at 0700:0000h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
push eax
|
||||
push esi
|
||||
push edx
|
||||
push ebx
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 200
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop ebx
|
||||
pop edx
|
||||
pop esi
|
||||
pop eax
|
||||
|
||||
; do we need a second SIPI?
|
||||
cmp byte [ap_done], 0
|
||||
jnz .nextcore
|
||||
|
||||
; select AP
|
||||
add esi, 10h
|
||||
mov dword [esi], ebx
|
||||
; send STARTUP IPI
|
||||
sub esi, 10h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
push edx
|
||||
prot_realmode
|
||||
xor cx, cx
|
||||
mov dx, 200
|
||||
mov ah, 086h
|
||||
sti
|
||||
int 15h
|
||||
cli
|
||||
real_protmode
|
||||
pop edx
|
||||
jmp .nextcore
|
||||
|
||||
.nosmp: ; failsafe
|
||||
cmp word [numcores], 0
|
||||
jnz @f
|
||||
inc word [numcores]
|
||||
mov ax, word [bootboot.bspid]
|
||||
mov word [lapic_ids], ax
|
||||
mov dword [lapic_ptr], 0
|
||||
@@: ; remove core stacks from memory map
|
||||
.stks: ; remove core stacks from memory map
|
||||
xor eax, eax
|
||||
mov ax, word [numcores]
|
||||
shl eax, 10
|
||||
|
@ -2498,16 +2359,176 @@ end if
|
|||
stosd
|
||||
stosd
|
||||
|
||||
;Enter long mode
|
||||
cli
|
||||
mov al, 0FFh ;disable PIC
|
||||
out 021h, al
|
||||
out 0A1h, al
|
||||
in al, 70h ;disable NMI
|
||||
or al, 80h
|
||||
out 70h, al
|
||||
|
||||
; send IPI and SIPI
|
||||
cmp word [numcores], 2
|
||||
jb .nosmp
|
||||
cmp dword [lapic_ptr], 0
|
||||
jz .nosmp
|
||||
|
||||
; relocate AP trampoline
|
||||
mov esi, ap_trampoline
|
||||
mov edi, 7000h
|
||||
mov ecx, (ap_start-ap_trampoline+3)/4
|
||||
repnz movsd
|
||||
|
||||
; enable Local APIC
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 0D0h ; logical destination
|
||||
mov al, 1
|
||||
shl eax, 24
|
||||
mov dword [esi], eax
|
||||
add esi, 10h ; destination form
|
||||
xor eax, eax
|
||||
sub eax, 1
|
||||
mov dword [esi], eax
|
||||
add esi, 10h
|
||||
mov eax, dword [esi] ; spurious + enable
|
||||
mov ax, 1FFh
|
||||
mov dword [esi], eax
|
||||
sub esi, 70h ; task priority
|
||||
xor eax, eax
|
||||
mov dword [esi], eax
|
||||
|
||||
; make sure we use the correct Local APIC ID for the BSP
|
||||
sub esi, 60h
|
||||
mov eax, dword [esi]
|
||||
shr eax, 24
|
||||
mov word [bootboot.bspid], ax
|
||||
|
||||
; send IPIs to specific cores one by one
|
||||
xor edx, edx
|
||||
.initcore: cmp dx, word [numcores]
|
||||
jae .sipi
|
||||
mov esi, edx
|
||||
inc edx
|
||||
shl esi, 1
|
||||
add esi, lapic_ids
|
||||
mov bx, word [esi]
|
||||
cmp bx, word [bootboot.bspid]
|
||||
je .initcore
|
||||
shl ebx, 24
|
||||
|
||||
; clear APIC error
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 280h
|
||||
mov dword [esi], 0
|
||||
mov eax, dword [esi]
|
||||
add esi, 20h
|
||||
|
||||
; select AP
|
||||
@@: pause
|
||||
mov eax, dword [esi]
|
||||
bt eax, 12
|
||||
jc @b
|
||||
add esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 00ffffffh
|
||||
or eax, ebx
|
||||
mov dword [esi], eax
|
||||
; trigger INIT IPI
|
||||
sub esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 0fff00000h
|
||||
or eax, 00C500h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
prot_sleep 1
|
||||
|
||||
; select AP
|
||||
@@: pause
|
||||
mov eax, dword [esi]
|
||||
bt eax, 12
|
||||
jc @b
|
||||
add esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 00ffffffh
|
||||
or eax, ebx
|
||||
mov dword [esi], eax
|
||||
; deassert INIT IPI
|
||||
sub esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 0fff00000h
|
||||
or eax, 008500h
|
||||
mov dword [esi], eax
|
||||
jmp .initcore
|
||||
.sipi:
|
||||
; wait 10 millisec
|
||||
prot_sleep 50
|
||||
|
||||
xor edx, edx
|
||||
.nextcore: cmp dx, word [numcores]
|
||||
jae .nosmp
|
||||
mov esi, edx
|
||||
inc edx
|
||||
shl esi, 1
|
||||
add esi, lapic_ids
|
||||
mov bx, word [esi]
|
||||
cmp bx, word [bootboot.bspid]
|
||||
je .nextcore
|
||||
shl ebx, 24
|
||||
|
||||
mov byte [ap_done], 0
|
||||
|
||||
; select AP
|
||||
mov esi, dword [lapic_ptr]
|
||||
add esi, 300h
|
||||
@@: pause
|
||||
mov eax, dword [esi]
|
||||
bt eax, 12
|
||||
jc @b
|
||||
add esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 00ffffffh
|
||||
or eax, ebx
|
||||
mov dword [esi], eax
|
||||
; send STARTUP IPI
|
||||
sub esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 0fff0f800h
|
||||
or eax, 004607h ; start at 0700:0000h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
prot_sleep 1
|
||||
|
||||
; do we need a second SIPI?
|
||||
cmp byte [ap_done], 0
|
||||
jnz .nextcore
|
||||
|
||||
; select AP
|
||||
@@: pause
|
||||
mov eax, dword [esi]
|
||||
bt eax, 12
|
||||
jc @b
|
||||
add esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 00ffffffh
|
||||
or eax, ebx
|
||||
mov dword [esi], eax
|
||||
; send STARTUP IPI
|
||||
sub esi, 10h
|
||||
mov eax, dword [esi]
|
||||
and eax, 0fff0f800h
|
||||
or eax, 004607h
|
||||
mov dword [esi], eax
|
||||
|
||||
; wait 200 microsec
|
||||
prot_sleep 1
|
||||
jmp .nextcore
|
||||
.nosmp:
|
||||
|
||||
;Enter long mode
|
||||
cli
|
||||
;release AP spinlock
|
||||
inc byte [bsp_done]
|
||||
lock inc byte [bsp_done]
|
||||
|
||||
;don't use stack below this line
|
||||
longmode_init:
|
||||
|
@ -2533,7 +2554,7 @@ longmode_init:
|
|||
mov ss, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
lock inc word [bootboot.numcores]
|
||||
lock inc word [bootboot.numcores]
|
||||
; find out our lapic id
|
||||
mov eax, dword [lapic_ptr]
|
||||
or eax, eax
|
||||
|
@ -2918,9 +2939,8 @@ hasconfig: db 0
|
|||
iscdrom: db 0
|
||||
nosmp: db 0
|
||||
numcores: dw 0
|
||||
ap_done:
|
||||
boguscore: db 0
|
||||
bsp_done: ;flag to indicate APs can run
|
||||
ap_done: db 0
|
||||
bsp_done: db 0 ;flag to indicate APs can run
|
||||
fattype: db 0
|
||||
bkp: dd ' '
|
||||
if BBDEBUG eq 1
|
||||
|
@ -2939,7 +2959,6 @@ dbg_scan db " * Autodetecting kernel",10,13,0
|
|||
dbg_elf db " * Parsing ELF64",10,13,0
|
||||
dbg_pe db " * Parsing PE32+",10,13,0
|
||||
dbg_smp db " * SMP numcores ",0
|
||||
dbg_bogus db " (bogus ACPI table)",0
|
||||
dbg_vesa db " * Screen VESA VBE",10,13,0
|
||||
end if
|
||||
backup: db " * Backup initrd",10,13,0
|
||||
|
@ -2989,6 +3008,7 @@ core_len: dd ?
|
|||
gpt_ptr: dd ?
|
||||
gpt_num: dd ?
|
||||
gpt_ent: dd ?
|
||||
ncycles: dq ?
|
||||
lapic_ptr: dd ?
|
||||
lapic_ids:
|
||||
tinf_bss_start:
|
||||
|
|
|
@ -76,10 +76,11 @@ extern void bsp64_init(uint64_t apicid);
|
|||
extern void bsp_init();
|
||||
#endif
|
||||
|
||||
#define send_ipi(a,v) do { \
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) = (a << 24); \
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = v; \
|
||||
#define send_ipi(a,m,v) do { \
|
||||
while(*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & (1 << 12)) __asm__ __volatile__ ("pause" : : : "memory"); \
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) = (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) & \
|
||||
0x00ffffff) | (a << 24); \
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & m) | v; \
|
||||
} while(0)
|
||||
|
||||
/*** ELF64 defines and structs ***/
|
||||
|
@ -760,7 +761,7 @@ void MapPage(uint64_t virt, uint64_t phys)
|
|||
*/
|
||||
int main(void)
|
||||
{
|
||||
int ret=0, i, dsk, boguscore = 0, numcores = 0;
|
||||
int ret=0, i, dsk, numcores = 0;
|
||||
uint8_t *pe, *ptr;
|
||||
uint32_t np,sp,r;
|
||||
unsigned char *data;
|
||||
|
@ -1132,8 +1133,6 @@ gzerr: panic("Unable to uncompress");
|
|||
case 0: // found Processor Local APIC
|
||||
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(int)ptr[3]] == 0xFFFF)
|
||||
lapic_ids[(int)ptr[3]] = i++;
|
||||
else
|
||||
boguscore++;
|
||||
break;
|
||||
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
||||
}
|
||||
|
@ -1143,38 +1142,43 @@ gzerr: panic("Unable to uncompress");
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// disable PIC and NMI
|
||||
__asm__ __volatile__ (
|
||||
"movb $0xFF, %%al; outb %%al, $0x21; outb %%al, $0xA1;" // disable PIC
|
||||
"inb $0x70, %%al; orb $0x80, %%al; outb %%al, $0x70;" // disable NMI
|
||||
: : :);
|
||||
|
||||
if(!nosmp && numcores > 1 && lapic_addr) {
|
||||
DBG(" * SMP numcores %d%s\n", numcores, boguscore ? " (bogus ACPI table)" : "");
|
||||
DBG(" * SMP numcores %d\n", numcores);
|
||||
memcpy((uint8_t*)0x1000, &ap_trampoline, 128);
|
||||
|
||||
// enable Local APIC
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x0D0)) = (1 << 24);
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x0E0)) = 0xFFFFFFFF;
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x0F0)) = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x0F0)) | 0x100;
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x080)) = 0;
|
||||
// make sure we use the correct Local APIC ID for the BSP
|
||||
bootboot->bspid = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x20)) >> 24;
|
||||
|
||||
// if there were no bogus core definitions in the ACPI table, we can do a broadcast (simpler, faster)
|
||||
if(!boguscore) {
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4500; // trigger bcast INIT IPI
|
||||
mdelay(10); // wait 10 msec
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601; // trigger bcast SIPI, start at 0100:0000h
|
||||
udelay(200); // wait 200 usec
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601; // trigger second bcast SIPI
|
||||
} else {
|
||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0; // clear APIC errors
|
||||
r = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280));
|
||||
send_ipi(i, 0x004500); // trigger INIT IPI
|
||||
}
|
||||
mdelay(10); // wait 10 msec
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((uint8_t*)0x1011) = 0;
|
||||
send_ipi(i, 0x004601); // trigger SIPI, start at 0100:0000h
|
||||
udelay(200); // wait 200 usec
|
||||
if(!*((uint8_t*)0x1011)) {
|
||||
send_ipi(i, 0x004601);
|
||||
udelay(200);
|
||||
}
|
||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0; // clear APIC errors
|
||||
r = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280));
|
||||
send_ipi(i, 0xfff00000, 0x00C500); // trigger INIT IPI
|
||||
udelay(200);
|
||||
send_ipi(i, 0xfff00000, 0x008500); // deassert INIT IPI
|
||||
}
|
||||
mdelay(10); // wait 10 msec
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((uint8_t*)0x1011) = 0;
|
||||
send_ipi(i, 0xfff0f800, 0x004601); // trigger SIPI, start at 0100:0000h
|
||||
udelay(200); // wait 200 usec
|
||||
if(!*((uint8_t*)0x1011)) {
|
||||
send_ipi(i, 0xfff0f800, 0x004601);
|
||||
udelay(200);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1542,10 +1542,10 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
|||
} else \
|
||||
__asm__ __volatile__ ("1: pause; dec %%ecx; or %%ecx, %%ecx; jnz 1b" : : "c"(n*1000) : "memory"); \
|
||||
} while(0)
|
||||
#define send_ipi(a,v) do { \
|
||||
*((volatile uint32_t*)(lapic_addr + 0x310)) = (a << 24); \
|
||||
*((volatile uint32_t*)(lapic_addr + 0x300)) = v; \
|
||||
#define send_ipi(a,m,v) do { \
|
||||
while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12)) __asm__ __volatile__ ("pause" : : : "memory"); \
|
||||
*((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (a << 24); \
|
||||
*((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & m) | v; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
|
@ -1922,7 +1922,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
|
|||
numcores = 1;
|
||||
#else
|
||||
UINT8 *ptr = (UINT8*)bootboot->arch.x86_64.acpi_ptr, *pe, *data;
|
||||
UINT64 r, boguscore = 0;
|
||||
UINT64 r;
|
||||
for(i = 0; i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); i++) lapic_ids[i] = 0xFFFF;
|
||||
if(!nosmp && ptr && (ptr[0]=='X' || ptr[0]=='R') && ptr[1]=='S' && ptr[2]=='D' && ptr[3]=='T') {
|
||||
pe = ptr; ptr += 36;
|
||||
|
@ -1938,8 +1938,6 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
|
|||
case 0: // found Processor Local APIC
|
||||
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(INTN)ptr[3]] == 0xFFFF)
|
||||
lapic_ids[(INTN)ptr[3]] = i++;
|
||||
else
|
||||
boguscore++;
|
||||
break;
|
||||
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
||||
}
|
||||
|
@ -1949,7 +1947,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
|
|||
if(bsp_num == 0xFFFF) bsp_num = 0;
|
||||
else {
|
||||
numcores = i;
|
||||
DBG(L" * SMP numcores %d%s\n", numcores, boguscore ? L" (bogus ACPI table)" : L"");
|
||||
DBG(L" * SMP numcores %d\n", numcores);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2094,6 +2092,12 @@ get_memory_map:
|
|||
return report(status,L"ExitBootServices");
|
||||
}
|
||||
|
||||
// disable PIC and NMI
|
||||
__asm__ __volatile__ (
|
||||
"movb $0xFF, %%al; outb %%al, $0x21; outb %%al, $0xA1;" // disable PIC
|
||||
"inb $0x70, %%al; orb $0x80, %%al; outb %%al, $0x70;" // disable NMI
|
||||
: : :);
|
||||
|
||||
#if !defined(USE_MP_SERVICES) || !USE_MP_SERVICES
|
||||
// green dot on the top left corner (do not allow gcc to rearrange this!!!)
|
||||
*((volatile uint64_t*)(bootboot->fb_ptr)) =
|
||||
|
@ -2110,36 +2114,34 @@ get_memory_map:
|
|||
"movl %%cs, %%eax; movl %%eax, 0x80CC;"
|
||||
"movl %%ds, %%eax; movl %%eax, 0x80D0;"
|
||||
"movq %%rbx, 0x80D8;"
|
||||
"sgdt 0x80E0;" : : "a"((uint64_t)&ap_trampoline), "b"((uint64_t)&bootboot_startcore) : );
|
||||
"sgdt 0x80E0;" : : "d"((uint64_t)&ap_trampoline), "b"((uint64_t)&bootboot_startcore) : );
|
||||
|
||||
// enable Local APIC
|
||||
*((volatile uint32_t*)(lapic_addr + 0x0F0)) = *((volatile uint32_t*)(lapic_addr + 0x0F0)) | 0x100;
|
||||
*((volatile uint32_t*)(lapic_addr + 0x0D0)) = (1 << 24);
|
||||
*((volatile uint32_t*)(lapic_addr + 0x0E0)) = 0xFFFFFFFF;
|
||||
*((volatile uint32_t*)(lapic_addr + 0x0F0)) = *((volatile uint32_t*)(lapic_addr + 0x0F0)) | 0x1FF;
|
||||
*((volatile uint32_t*)(lapic_addr + 0x080)) = 0;
|
||||
// make sure we use the correct Local APIC ID for the BSP
|
||||
bootboot->bspid = *((volatile uint32_t*)(lapic_addr + 0x20)) >> 24;
|
||||
|
||||
// if there were no bogus core definitions in the ACPI table, we can do a broadcast (simpler, faster)
|
||||
if(!boguscore) {
|
||||
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500; // trigger bcast INIT IPI
|
||||
sleep(50); // wait 10 msec
|
||||
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // trigger bcast SIPI, start at 0800:0000h
|
||||
sleep(1); // wait 200 usec
|
||||
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // trigger second bcast SIPI
|
||||
} else {
|
||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors
|
||||
a = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280));
|
||||
send_ipi(i, 0x004500); // trigger INIT IPI
|
||||
}
|
||||
sleep(50); // wait 10 msec
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
ap_done = 0;
|
||||
send_ipi(i, 0x004608); // trigger SIPI, start at 0800:0000h
|
||||
sleep(1); // wait 200 usec
|
||||
if(!ap_done) {
|
||||
send_ipi(i, 0x004608);
|
||||
sleep(1);
|
||||
}
|
||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
*((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors
|
||||
a = *((volatile uint32_t*)(lapic_addr + 0x280));
|
||||
send_ipi(i, 0xfff00000, 0x00C500); // trigger INIT IPI
|
||||
sleep(1);
|
||||
send_ipi(i, 0xfff00000, 0x008500); // deassert INIT IPI
|
||||
}
|
||||
sleep(50); // wait 10 msec
|
||||
for(i = 0; i < 255; i++) {
|
||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
||||
ap_done = 0;
|
||||
send_ipi(i, 0xfff0f800, 0x004608); // trigger SIPI, start at 0800:0000h
|
||||
sleep(1); // wait 200 usec
|
||||
if(!ap_done) {
|
||||
send_ipi(i, 0xfff0f800, 0x004608);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2156,6 +2158,7 @@ get_memory_map:
|
|||
|
||||
// release AP spinlock
|
||||
bsp_done = 1;
|
||||
__asm__ __volatile__ ("pause" : : : "memory"); // memory barrier
|
||||
bootboot_startcore((VOID*)bsp_num);
|
||||
}
|
||||
return report(status,L"Initrd not found");
|
||||
|
|
Loading…
Reference in a new issue