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
b2353ad388
commit
90f4e071b5
8 changed files with 89 additions and 44 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
|
@ -2120,7 +2120,11 @@ if BBDEBUG eq 1
|
||||||
call real_printfunc
|
call real_printfunc
|
||||||
mov si, gpt_ptr
|
mov si, gpt_ptr
|
||||||
call real_printfunc
|
call real_printfunc
|
||||||
mov si, crlf
|
cmp byte [bad_madt], 0
|
||||||
|
jz @f
|
||||||
|
mov si, dbg_madt
|
||||||
|
call real_printfunc
|
||||||
|
@@: mov si, crlf
|
||||||
call real_printfunc
|
call real_printfunc
|
||||||
real_protmode
|
real_protmode
|
||||||
end if
|
end if
|
||||||
|
@ -2502,8 +2506,8 @@ end if
|
||||||
or eax, 004607h ; start at 0700:0000h
|
or eax, 004607h ; start at 0700:0000h
|
||||||
mov dword [esi + 300h], eax
|
mov dword [esi + 300h], eax
|
||||||
|
|
||||||
; wait 200 microsec
|
; wait 10 millisec
|
||||||
prot_sleep 1
|
prot_sleep 50
|
||||||
|
|
||||||
; do we need a second SIPI?
|
; do we need a second SIPI?
|
||||||
cmp word [ap_done], 0
|
cmp word [ap_done], 0
|
||||||
|
@ -2524,8 +2528,8 @@ end if
|
||||||
or eax, 004607h
|
or eax, 004607h
|
||||||
mov dword [esi + 300h], eax
|
mov dword [esi + 300h], eax
|
||||||
|
|
||||||
; wait 200 microsec
|
; wait 10 millisec
|
||||||
prot_sleep 1
|
prot_sleep 50
|
||||||
jmp .nextcore
|
jmp .nextcore
|
||||||
.nosmp:
|
.nosmp:
|
||||||
;Enter long mode
|
;Enter long mode
|
||||||
|
@ -2970,6 +2974,7 @@ dbg_scan db " * Autodetecting kernel",10,13,0
|
||||||
dbg_elf db " * Parsing ELF64",10,13,0
|
dbg_elf db " * Parsing ELF64",10,13,0
|
||||||
dbg_pe db " * Parsing PE32+",10,13,0
|
dbg_pe db " * Parsing PE32+",10,13,0
|
||||||
dbg_smp db " * SMP numcores ",0
|
dbg_smp db " * SMP numcores ",0
|
||||||
|
dbg_madt db " (bad MADT)",0
|
||||||
dbg_vesa db " * Screen VESA VBE",10,13,0
|
dbg_vesa db " * Screen VESA VBE",10,13,0
|
||||||
end if
|
end if
|
||||||
backup: db " * Backup initrd",10,13,0
|
backup: db " * Backup initrd",10,13,0
|
||||||
|
|
|
@ -761,7 +761,7 @@ void MapPage(uint64_t virt, uint64_t phys)
|
||||||
*/
|
*/
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
unsigned int ret=0, i, dsk;
|
unsigned int ret=0, i, dsk, bad_madt=0;
|
||||||
uint8_t *pe, *ptr;
|
uint8_t *pe, *ptr;
|
||||||
uint32_t np, sp, r;
|
uint32_t np, sp, r;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
@ -1133,6 +1133,7 @@ gzerr: panic("Unable to uncompress");
|
||||||
case 0: // found Processor Local APIC
|
case 0: // found Processor Local APIC
|
||||||
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(int)ptr[3]] == 0xFFFF)
|
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(int)ptr[3]] == 0xFFFF)
|
||||||
lapic_ids[(int)ptr[3]] = i++;
|
lapic_ids[(int)ptr[3]] = i++;
|
||||||
|
else bad_madt++;
|
||||||
break;
|
break;
|
||||||
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
||||||
}
|
}
|
||||||
|
@ -1150,7 +1151,7 @@ gzerr: panic("Unable to uncompress");
|
||||||
: : :);
|
: : :);
|
||||||
|
|
||||||
if(!nosmp && bootboot->numcores > 1 && lapic_addr) {
|
if(!nosmp && bootboot->numcores > 1 && lapic_addr) {
|
||||||
DBG(" * SMP numcores %d\n", bootboot->numcores);
|
DBG(" * SMP numcores %d%s\n", bootboot->numcores, bad_madt ? " (bad MADT)" : "");
|
||||||
memcpy((uint8_t*)0x1000, (void*)&ap_trampoline, 128);
|
memcpy((uint8_t*)0x1000, (void*)&ap_trampoline, 128);
|
||||||
|
|
||||||
// enable Local APIC
|
// enable Local APIC
|
||||||
|
@ -1161,24 +1162,40 @@ gzerr: panic("Unable to uncompress");
|
||||||
// make sure we use the correct Local APIC ID for the BSP
|
// make sure we use the correct Local APIC ID for the BSP
|
||||||
bootboot->bspid = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x20)) >> 24;
|
bootboot->bspid = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x20)) >> 24;
|
||||||
|
|
||||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
#if 0
|
||||||
for(i = 0; i < 255; i++) {
|
// use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled)
|
||||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
if(!bad_madt) {
|
||||||
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0; // clear APIC errors
|
// send Broadcast INIT IPI
|
||||||
r = *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280));
|
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4500;
|
||||||
send_ipi(i, 0xfff00000, 0x00C500); // trigger INIT IPI
|
mdelay(10); // wait 10 msec
|
||||||
udelay(200);
|
// send Broadcast STARTUP IPI
|
||||||
send_ipi(i, 0xfff00000, 0x008500); // deassert INIT IPI
|
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601;// start at 0100:0000h
|
||||||
}
|
udelay(200); // wait 10 msec
|
||||||
mdelay(10); // wait 10 msec
|
// send second SIPI
|
||||||
for(i = 0; i < 255; i++) {
|
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601;
|
||||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
udelay(200); // wait 10 msec
|
||||||
*((uint8_t*)0x1011) = 0;
|
} else
|
||||||
send_ipi(i, 0xfff0f800, 0x004601); // trigger SIPI, start at 0100:0000h
|
#endif
|
||||||
udelay(200); // wait 200 usec
|
{
|
||||||
if(!*((uint8_t*)0x1011)) {
|
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
||||||
send_ipi(i, 0xfff0f800, 0x004601);
|
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);
|
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;
|
||||||
|
*((volatile uint8_t*)0x1011) = 0;
|
||||||
|
send_ipi(i, 0xfff0f800, 0x004601); // trigger SIPI, start at 0100:0000h
|
||||||
|
for(r = 250; !*((volatile uint8_t*)0x1011) && r > 0; r--) udelay(200);// wait for AP with 50 msec timeout
|
||||||
|
if(!*((volatile uint8_t*)0x1011)) {
|
||||||
|
send_ipi(i, 0xfff0f800, 0x004601);
|
||||||
|
mdelay(50);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1459,6 +1459,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer;
|
EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer;
|
||||||
#else
|
#else
|
||||||
UINT64 ncycles = 0, currtime, endtime;
|
UINT64 ncycles = 0, currtime, endtime;
|
||||||
|
UINTN bad_madt=0;
|
||||||
#endif
|
#endif
|
||||||
EFI_GUID SerIoGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
|
EFI_GUID SerIoGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
|
||||||
EFI_SERIAL_IO_PROTOCOL *ser = NULL;
|
EFI_SERIAL_IO_PROTOCOL *ser = NULL;
|
||||||
|
@ -1937,6 +1938,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
|
||||||
case 0: // found Processor Local APIC
|
case 0: // found Processor Local APIC
|
||||||
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(INTN)ptr[3]] == 0xFFFF)
|
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(INTN)ptr[3]] == 0xFFFF)
|
||||||
lapic_ids[(INTN)ptr[3]] = i++;
|
lapic_ids[(INTN)ptr[3]] = i++;
|
||||||
|
else bad_madt++;
|
||||||
break;
|
break;
|
||||||
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
|
||||||
}
|
}
|
||||||
|
@ -1946,7 +1948,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
|
||||||
if(bsp_num == 0xFFFF) bsp_num = 0;
|
if(bsp_num == 0xFFFF) bsp_num = 0;
|
||||||
else {
|
else {
|
||||||
bootboot->numcores = i;
|
bootboot->numcores = i;
|
||||||
DBG(L" * SMP numcores %d\n", bootboot->numcores);
|
DBG(L" * SMP numcores %d%s\n", bootboot->numcores, bad_madt ? L" (bad MADT)" : L"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2082,6 +2084,7 @@ get_memory_map:
|
||||||
// blue (or red) dot on the top left corner (sort of status report)
|
// blue (or red) dot on the top left corner (sort of status report)
|
||||||
*((volatile uint64_t*)(bootboot->fb_ptr)) =
|
*((volatile uint64_t*)(bootboot->fb_ptr)) =
|
||||||
*((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x000000FF000000FFUL;
|
*((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x000000FF000000FFUL;
|
||||||
|
__asm__ __volatile__ ("invlpg (%0)" : : "a"(bootboot->fb_ptr) : "memory"); // memory barrier and flush screen
|
||||||
|
|
||||||
//inform firmware that we're about to leave it's realm
|
//inform firmware that we're about to leave it's realm
|
||||||
status = uefi_call_wrapper(BS->ExitBootServices, 2, image, map_key);
|
status = uefi_call_wrapper(BS->ExitBootServices, 2, image, map_key);
|
||||||
|
@ -2101,7 +2104,7 @@ get_memory_map:
|
||||||
// green dot on the top left corner (do not allow gcc to rearrange this!!!)
|
// green dot on the top left corner (do not allow gcc to rearrange this!!!)
|
||||||
*((volatile uint64_t*)(bootboot->fb_ptr)) =
|
*((volatile uint64_t*)(bootboot->fb_ptr)) =
|
||||||
*((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x0000FF000000FF00UL;
|
*((volatile uint64_t*)(bootboot->fb_ptr + bootboot->fb_scanline)) = 0x0000FF000000FF00UL;
|
||||||
__asm__ __volatile__ ("pause" : : : "memory"); // memory barrier
|
__asm__ __volatile__ ("invlpg (%0)" : : "a"(bootboot->fb_ptr) : "memory"); // memory barrier and flush screen
|
||||||
|
|
||||||
// start APs
|
// start APs
|
||||||
if(bootboot->numcores > 1 && apmemfree) {
|
if(bootboot->numcores > 1 && apmemfree) {
|
||||||
|
@ -2123,24 +2126,40 @@ get_memory_map:
|
||||||
// make sure we use the correct Local APIC ID for the BSP
|
// make sure we use the correct Local APIC ID for the BSP
|
||||||
bootboot->bspid = *((volatile uint32_t*)(lapic_addr + 0x20)) >> 24;
|
bootboot->bspid = *((volatile uint32_t*)(lapic_addr + 0x20)) >> 24;
|
||||||
|
|
||||||
// supports up to 255 cores (lapicid 255 is bcast address), requires x2APIC to have more
|
#if 0
|
||||||
for(i = 0; i < 255; i++) {
|
// use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled)
|
||||||
if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
|
if(!bad_madt) {
|
||||||
*((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors
|
// send Broadcast INIT IPI
|
||||||
a = *((volatile uint32_t*)(lapic_addr + 0x280));
|
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500;
|
||||||
send_ipi(i, 0xfff00000, 0x00C500); // trigger INIT IPI
|
sleep(50); // wait 10 msec
|
||||||
sleep(1);
|
// send Broadcast STARTUP IPI
|
||||||
send_ipi(i, 0xfff00000, 0x008500); // deassert INIT IPI
|
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // start at 0800:0000h
|
||||||
}
|
|
||||||
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
|
sleep(1); // wait 200 usec
|
||||||
if(!ap_done) {
|
// send second SIPI
|
||||||
send_ipi(i, 0xfff0f800, 0x004608);
|
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608;
|
||||||
|
sleep(1); // wait 200 usec
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// 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);
|
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
|
||||||
|
for(a = 250; !ap_done && a > 0; a--) sleep(1); // wait for AP with 50 msec timeout
|
||||||
|
if(!ap_done) {
|
||||||
|
send_ipi(i, 0xfff0f800, 0x004608);
|
||||||
|
sleep(250);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,10 @@ _L80A0:
|
||||||
// some linkers (GNU ld) generates bad relocation record for this
|
// some linkers (GNU ld) generates bad relocation record for this
|
||||||
// jmp bootboot_startcode
|
// jmp bootboot_startcode
|
||||||
movq 0x80D8, %rax
|
movq 0x80D8, %rax
|
||||||
|
// in theory this could cause trouble, but it does not since all cores are executing the same
|
||||||
|
// code at this point, so it doesn't matter if one core is overwriting the same stack with the
|
||||||
|
// stack frame, because all are saving exactly the same stack frame to the same position
|
||||||
|
movl $0x8800, %esp
|
||||||
jmp *%rax
|
jmp *%rax
|
||||||
.align 32
|
.align 32
|
||||||
_L80C0_cr3_value:
|
_L80C0_cr3_value:
|
||||||
|
|
Loading…
Reference in a new issue