1
0
Fork 0
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:
bzt 2021-01-26 01:59:38 +01:00
parent e0dc1c152d
commit b556210529
7 changed files with 311 additions and 284 deletions

BIN
dist/bootboot.bin vendored

Binary file not shown.

BIN
dist/bootboot.efi vendored

Binary file not shown.

BIN
dist/bootboot.rom vendored

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -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:

View file

@ -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 {

View file

@ -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");