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-03-17 08:09:27 +01:00
parent b2353ad388
commit 90f4e071b5
8 changed files with 89 additions and 44 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

@ -2120,7 +2120,11 @@ if BBDEBUG eq 1
call real_printfunc
mov si, gpt_ptr
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
real_protmode
end if
@ -2502,8 +2506,8 @@ end if
or eax, 004607h ; start at 0700:0000h
mov dword [esi + 300h], eax
; wait 200 microsec
prot_sleep 1
; wait 10 millisec
prot_sleep 50
; do we need a second SIPI?
cmp word [ap_done], 0
@ -2524,8 +2528,8 @@ end if
or eax, 004607h
mov dword [esi + 300h], eax
; wait 200 microsec
prot_sleep 1
; wait 10 millisec
prot_sleep 50
jmp .nextcore
.nosmp:
;Enter long mode
@ -2970,6 +2974,7 @@ 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_madt db " (bad MADT)",0
dbg_vesa db " * Screen VESA VBE",10,13,0
end if
backup: db " * Backup initrd",10,13,0

View file

@ -761,7 +761,7 @@ void MapPage(uint64_t virt, uint64_t phys)
*/
int main(void)
{
unsigned int ret=0, i, dsk;
unsigned int ret=0, i, dsk, bad_madt=0;
uint8_t *pe, *ptr;
uint32_t np, sp, r;
unsigned char *data;
@ -1133,6 +1133,7 @@ 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 bad_madt++;
break;
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) {
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);
// enable Local APIC
@ -1161,24 +1162,40 @@ gzerr: panic("Unable to uncompress");
// make sure we use the correct Local APIC ID for the BSP
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
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);
#if 0
// use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled)
if(!bad_madt) {
// send Broadcast INIT IPI
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4500;
mdelay(10); // wait 10 msec
// send Broadcast STARTUP IPI
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601;// start at 0100:0000h
udelay(200); // wait 10 msec
// send second SIPI
*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601;
udelay(200); // wait 10 msec
} 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*)((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;
*((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 {

View file

@ -1459,6 +1459,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer;
#else
UINT64 ncycles = 0, currtime, endtime;
UINTN bad_madt=0;
#endif
EFI_GUID SerIoGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
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
if((ptr[4] & 1) && ptr[3] != 0xFF && lapic_ids[(INTN)ptr[3]] == 0xFFFF)
lapic_ids[(INTN)ptr[3]] = i++;
else bad_madt++;
break;
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;
else {
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;
@ -2082,6 +2084,7 @@ get_memory_map:
// 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 + 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
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!!!)
*((volatile uint64_t*)(bootboot->fb_ptr)) =
*((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
if(bootboot->numcores > 1 && apmemfree) {
@ -2123,24 +2126,40 @@ get_memory_map:
// make sure we use the correct Local APIC ID for the BSP
bootboot->bspid = *((volatile uint32_t*)(lapic_addr + 0x20)) >> 24;
// 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
#if 0
// use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled)
if(!bad_madt) {
// send Broadcast INIT IPI
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500;
sleep(50); // wait 10 msec
// send Broadcast STARTUP IPI
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // start at 0800:0000h
sleep(1); // wait 200 usec
if(!ap_done) {
send_ipi(i, 0xfff0f800, 0x004608);
// send second SIPI
*((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);
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);
}
}
}
}

View file

@ -92,6 +92,10 @@ _L80A0:
// some linkers (GNU ld) generates bad relocation record for this
// jmp bootboot_startcode
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
.align 32
_L80C0_cr3_value: