1
0
Fork 0
mirror of https://gitlab.com/bztsrc/bootboot.git synced 2023-02-13 20:54:32 -05:00

Alternative SMP init

This commit is contained in:
bzt 2020-09-17 22:36:06 +02:00
parent d475acef85
commit 93b561b388
14 changed files with 191 additions and 26 deletions

View file

@ -5,7 +5,7 @@ Előre lefordított binárisok mellékelve, egyből használhatók.
1. *x86_64-efi* a preferált indítási mód x86_64-en.
Szabvány GNU eszköztár plusz néhány fájl a gnuefi-ből (mellékelve).
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.efi) (95k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.rom) (96k)
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.efi) (100k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.rom) (100k)
2. *x86_64-bios* BIOS, Multiboot (GRUB), El Torito (CDROM), bővítő ROM és Linux boot kompatíbilis, RÉGI betöltő.
Ha újra akarod fordítani, szükséged lesz a fasm-ra (nincs mellékelve).

View file

@ -5,7 +5,7 @@ I provide pre-compiled images ready for use.
1. *x86_64-efi* the preferred way of booting on x86_64 architecture.
Standard GNU toolchain and a few files from gnuefi (included).
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.efi) (95k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.rom) (96k)
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.efi) (100k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/dist/bootboot.rom) (100k)
2. *x86_64-bios* BIOS, Multiboot (GRUB), El Torito (CDROM), Expansion ROM and Linux boot compatible, OBSOLETE loader.
If you want to recompile this, you'll need fasm (not included).

BIN
dist/bootboot.efi vendored

Binary file not shown.

BIN
dist/bootboot.rom vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
extern unsigned char binary_boot_bin[512];
extern unsigned char binary_bootboot_bin[11776];
extern unsigned char binary_bootboot_efi[96946];
extern unsigned char binary_bootboot_efi[100386];
extern unsigned char binary_bootboot_img[34672];
extern unsigned char binary_LICENCE_broadcom[1594];
extern unsigned char binary_bootcode_bin[52480];

View file

@ -1088,7 +1088,7 @@ gzerr: panic("Unable to uncompress");
for(r = *((uint32_t*)(data + 4)), ptr = data + 44, i = 0; ptr < data + r &&
i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); ptr += ptr[1]) {
switch(ptr[0]) {
case 0: lapic_ids[i++] = ptr[2]; break; // found Processor Local APIC
case 0: lapic_ids[(int)ptr[2]] = i++; break; // found Processor Local APIC
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
}
}

View file

@ -129,28 +129,20 @@ bit64:
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
xorq %rbx, %rbx
// find our lapic id
movl $1, %eax
cpuid
shrl $24, %ebx
movl %ebx, %edx
// get array index for it
xorq %rbx, %rbx
xorq %rsi, %rsi
movl $lapic_ids, %esi
movw 0x200C, %cx // bootboot.numcores
1: lodsw
cmpw %dx, %ax
je 1f
incw %bx
decw %cx
jnz 1b
xorw %bx, %bx
1: shlq $10, %rbx // 1k stack for each core
shrl $23, %ebx
andb $0xfe, %bl // ebx = lapic id * 2
addl $lapic_ids, %ebx
xorq %rax, %rax
movw (%rbx), %ax // ax = word[lapic_ids + lapic id * 2]
1: shlq $10, %rax // 1k stack for each core
// set stack and call _start() in sys/core
xorq %rsp, %rsp // sp = core_num * -1024
subq %rbx, %rsp
subq %rax, %rsp
movl $entrypoint, %esi // GAS does not allow "jmp qword[entrypoint]"
lodsq
jmp *%rax

View file

@ -10,7 +10,7 @@ LDFLAGS += -shared -Bsymbolic -L. $(GNUEFI_CRT_OBJS)
TARGET = bootboot.efi
all: tinflate.o $(TARGET)
all: tinflate.o smp.o $(TARGET)
%.efi: %.so
@echo " src x86_64-efi (UEFI)"
@ -19,10 +19,10 @@ all: tinflate.o $(TARGET)
@gcc $(GNUEFI_INCLUDES) -Wall -fshort-wchar efirom.c -o efirom $(LIBS)
@./efirom $(TARGET) ../dist/bootboot.rom || true
@mv $(TARGET) ../dist/$(TARGET)
@rm tinflate.o efirom
@rm tinflate.o smp.o efirom
%.so: %.o
@ld $(LDFLAGS) tinflate.o $^ -o $@ -lefi -lgnuefi -T $(GNUEFI_LDS)
@ld $(LDFLAGS) tinflate.o smp.o $^ -o $@ -lefi -lgnuefi -T $(GNUEFI_LDS)
%.o: %.c
@gcc $(GNUEFI_INCLUDES) $(CFLAGS) -c $< -o $@
@ -31,5 +31,5 @@ all: tinflate.o $(TARGET)
@gcc $(GNUEFI_INCLUDES) $(CFLAGS) -c $< -o $@
clean:
@rm bootboot.o $(TARGET) ../dist/$(TARGET) ../dist/bootboot.rom *.so *.efi efirom tinflate.o 2>/dev/null || true
@rm bootboot.o $(TARGET) ../dist/$(TARGET) ../dist/bootboot.rom *.so *.efi efirom tinflate.o smp.o 2>/dev/null || true

View file

@ -30,6 +30,7 @@
#define BBDEBUG 1
//#define GOP_DEBUG BBDEBUG
#define USE_MP_SERVICES 0 /* without fallback to ACPI parser and APIC INIT + SIPI */
#if BBDEBUG
#define DBG(fmt, ...) do{Print(fmt,__VA_ARGS__); }while(0);
@ -156,6 +157,7 @@ typedef struct {
struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
struct EFI_FILE_PROTOCOL;
#if USE_MP_SERVICES
#ifndef EFI_MP_SERVICES_PROTOCOL_GUID
#define EFI_MP_SERVICES_PROTOCOL_GUID \
{ 0x3fdda605, 0xa76e, 0x4f46, {0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08} }
@ -218,6 +220,10 @@ struct _EFI_MP_SERVICES_PROTOCOL {
EFI_MP_SERVICES_DUMMY WhoAmI;
};
#endif
#else
extern void ap_trampoline();
UINT16 lapic_ids[1024];
#endif
typedef
EFI_STATUS
@ -1292,8 +1298,20 @@ LoadCore()
*/
VOID EFIAPI bootboot_startcore(IN VOID* buf)
{
#if USE_MP_SERVICES
// we have a scalar number, not a pointer, so cast it
UINTN core_num = (UINTN)buf;
#else
(void)buf;
UINT16 core_num;
__asm__ __volatile__ (
"movl $1, %%eax;"
"cpuid;"
"shrl $24, %%ebx;"
"mov %%bx,%0"
: "=b"(core_num) : : );
core_num = lapic_ids[core_num];
#endif
// spinlock until BSP finishes
do { __asm__ __volatile__ ("pause"); } while(!bsp_done);
@ -1321,7 +1339,7 @@ VOID EFIAPI bootboot_startcore(IN VOID* buf)
// pass control over
"pushq %0;"
"retq"
: : "a"(entrypoint), "r"(core_num*1024) : "memory" );
: : "a"(entrypoint), "r"((UINTN)core_num*1024) : "memory" );
}
/**
@ -1342,11 +1360,13 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
EFI_PARTITION_TABLE_HEADER *gptHdr;
EFI_PARTITION_ENTRY *gptEnt;
EFI_INPUT_KEY key;
#if USE_MP_SERVICES
EFI_EVENT Event;
EFI_GUID mpspGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
EFI_MP_SERVICES_PROTOCOL *mp;
UINT8 pibuffer[100];
EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer;
#endif
UINTN bsp_num=0, i, j=0, x,y, handle_size=0,memory_map_size=0, map_key=0, desc_size=0;
UINT32 desc_version=0;
UINT64 lba_s=0,lba_e=0,sysptr;
@ -1696,6 +1716,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
*kne='\n';
// Symmetric Multi Processing support
#if USE_MP_SERVICES
status = uefi_call_wrapper(BS->LocateProtocol, 3, &mpspGuid, NULL, (void**)&mp);
if(!EFI_ERROR(status)) {
// override default values in bootboot struct
@ -1722,6 +1743,55 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
}
}
}
#else
UINT8 *ptr = (UINT8*)bootboot->arch.x86_64.acpi_ptr, *pe, *data;
UINT64 r, lapic_addr=0, ap_code = 0x8000;
ZeroMem(lapic_ids, sizeof(lapic_ids));
if(ptr && (ptr[0]=='X' || ptr[0]=='R') && ptr[1]=='S' && ptr[2]=='D' && ptr[3]=='T') {
pe = ptr; ptr += 36;
// iterate on ACPI table pointers
for(r = *((uint32_t*)(pe + 4)); ptr < pe + r; ptr += pe[0] == 'X' ? 8 : 4) {
data = (uint8_t*)(uintptr_t)(pe[0] == 'X' ? *((uint64_t*)ptr) : *((uint32_t*)ptr));
if(!CompareMem(data, "APIC", 4)) {
// found MADT, iterate on its variable length entries
lapic_addr = (uint64_t)(*((uint32_t*)(data+0x24)));
for(r = *((uint32_t*)(data + 4)), ptr = data + 44, i = 0; ptr < data + r &&
i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); ptr += ptr[1]) {
switch(ptr[0]) {
case 0: lapic_ids[(INTN)ptr[2]] = i++; break; // found Processor Local APIC
case 5: lapic_addr = *((uint64_t*)(ptr+4)); break; // found 64 bit Local APIC Address
}
}
if(i) {
bootboot->numcores = i;
bsp_num = lapic_ids[bootboot->bspid];
}
break;
}
}
// Allocate page at fixed address for AP trampoline code
status = uefi_call_wrapper(BS->AllocatePages, 4, 2, 1, 1, (EFI_PHYSICAL_ADDRESS*)&ap_code);
if(EFI_ERROR(status)) ap_code = 0;
}
if(bootboot->numcores > 1 && lapic_addr && ap_code) {
DBG(L" * SMP numcores %d\n", bootboot->numcores);
CopyMem((uint8_t*)0x8000, &ap_trampoline, 256);
// save UEFI's 64 bit system registers for the trampoline code
__asm__ __volatile__ (
"movq %%cr3, %%rax; movq %%rax, 0x80C0;"
"movl %%cs, %%eax; movl %%eax, 0x80C8;"
"movl %%ds, %%eax; movl %%eax, 0x80CC;"
"sgdt 0x80D0" : : : );
// send Broadcast INIT IPI
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500;
uefi_call_wrapper(BS->Stall, 1, 10);
// send Broadcast STARTUP IPI
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // start at 0800:0000h
uefi_call_wrapper(BS->Stall, 1, 1);
// send second SIPI
*((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608;
}
#endif
// query size of memory map
status = uefi_call_wrapper(BS->GetMemoryMap, 5,

103
x86_64-efi/smp.S Normal file
View file

@ -0,0 +1,103 @@
/*
* x86_64-efi/smp.S
*
* Copyright (C) 2017 - 2020 bzt (bztsrc@gitlab)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This file is part of the BOOTBOOT Protocol package.
* @brief SMP initialization code.
*
*/
.globl ap_trampoline
.extern bootboot_startcode
/*****************************************************************************
* things to do on the APs *
*****************************************************************************/
.align 128
.code16
/* this code will be relocated to 0x8000 - 0x8100 */
ap_trampoline:
cli
cld
ljmp $0, $0x8040
.align 16
// prot mode GDT
_L8010_GDT_table:
.long 0, 0
.long 0x0000FFFF, 0x00CF9A00 // flat code
.long 0x0000FFFF, 0x008F9200 // flat data
.long 0x00000068, 0x00CF8900 // tss, not used but required by VB's vt-x
_L8030_GDT_value:
.word _L8030_GDT_value - _L8010_GDT_table - 1
.long 0x8010
.long 0, 0
.align 64
_L8040:
xorw %ax, %ax
movw %ax, %ds
lgdtl 0x8030
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
ljmp $8, $0x8060
.align 32
.code32
_L8060:
movw $16, %ax
movw %ax, %ds
movl $0x368, %eax // Set PAE, MCE, PGE; OSFXSR, OSXMMEXCPT (enable SSE)
movl %eax, %cr4
movl 0x80C0, %eax // let's hope it's in the first 4G...
movl %eax, %cr3
movl $0x0C0000080, %ecx // EFR MSR
rdmsr
orl $0x100, %eax // enable long mode
wrmsr
movl $0x0C0000011, %eax // clear EM, MP (enable SSE) and WP
movl %eax, %cr0
lgdtl 0x80D0
movl 0x80C8, %eax
push %eax
push $0x80A0
retf
.align 32
.code64
_L80A0:
movl 0x80CC, %eax // load long mode segments
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
jmp bootboot_startcode
.align 32
_L80C0_cr3_value:
.long 0, 0
_L80C8_cs_value:
.long 0
_L80CC_ds_value:
.long 0
_L80D0_gdt_value:
.long 0, 0, 0, 0
ap_trampoline_end: