protos/limine: Implement base revision 5
diff --git a/bootstrap b/bootstrap
index 704d83fc..9fd1cbe9 100755
--- a/bootstrap
+++ b/bootstrap
@@ -85,7 +85,7 @@ if ! test -f version; then
clone_repo_commit \
https://codeberg.org/Limine/limine-protocol.git \
limine-protocol \
- 42e836e30242c2c14f889fd76c6f9a57b0c18ec2
+ c76af54a01663d89a74c35b725f79d8af77eb811
clone_repo_commit \
https://codeberg.org/PicoEFI/PicoEFI.git \
diff --git a/common/lib/acpi.c b/common/lib/acpi.c
index abb9cccf..32e9c655 100644
--- a/common/lib/acpi.c
+++ b/common/lib/acpi.c
@@ -301,7 +301,7 @@ static void map_single_table(uint64_t addr, uint32_t len) {
uint64_t memmap_type = pmm_check_type(addr);
if (memmap_type != MEMMAP_ACPI_RECLAIMABLE && memmap_type != MEMMAP_ACPI_NVS) {
- memmap_alloc_range(aligned_base, aligned_top - aligned_base, MEMMAP_ACPI_TABLES, 0, true, false, true);
+ memmap_alloc_range(aligned_base, aligned_top - aligned_base, MEMMAP_RESERVED_MAPPED, 0, true, false, true);
}
}
@@ -401,3 +401,75 @@ no_rsdt:;
}
}
}
+
+void smbios_map_tables(void) {
+ void *smbios32_ptr = NULL, *smbios64_ptr = NULL;
+ acpi_get_smbios(&smbios32_ptr, &smbios64_ptr);
+
+ if (smbios32_ptr != NULL) {
+ struct smbios_entry_point_32 *smbios32 = smbios32_ptr;
+ map_single_table((uintptr_t)smbios32, smbios32->length);
+ if (smbios32->table_address != 0) {
+ map_single_table(smbios32->table_address, smbios32->table_length);
+ }
+ }
+
+ if (smbios64_ptr != NULL) {
+ struct smbios_entry_point_64 *smbios64 = smbios64_ptr;
+ map_single_table((uintptr_t)smbios64, smbios64->length);
+ if (smbios64->table_address != 0) {
+ map_single_table(smbios64->table_address, smbios64->table_maximum_size);
+ }
+ }
+}
+
+#if defined (UEFI)
+void efi_map_runtime_entries(void) {
+ size_t entry_count = efi_mmap_size / efi_desc_size;
+
+ for (size_t i = 0; i < entry_count; i++) {
+ EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + i * efi_desc_size;
+
+ if (entry->Type != EfiRuntimeServicesCode
+ && entry->Type != EfiRuntimeServicesData) {
+ continue;
+ }
+
+ uint64_t base = entry->PhysicalStart;
+ uint64_t length;
+ if (__builtin_mul_overflow(entry->NumberOfPages, (uint64_t)4096, &length)) {
+ continue;
+ }
+
+ memmap_alloc_range(base, length, MEMMAP_RESERVED_MAPPED, 0, true, false, true);
+ }
+
+ // Explicitly map the EFI system table and the data it references.
+ // The UEFI spec does not guarantee these reside in EfiRuntimeServicesData,
+ // so we map them separately to ensure they are always accessible via HHDM.
+ map_single_table((uintptr_t)gST, sizeof(*gST));
+
+ if (gST->RuntimeServices != NULL) {
+ map_single_table((uintptr_t)gST->RuntimeServices,
+ sizeof(*gST->RuntimeServices));
+ }
+
+ if (gST->ConfigurationTable != NULL && gST->NumberOfTableEntries > 0) {
+ uint64_t ct_size;
+ if (!__builtin_mul_overflow(gST->NumberOfTableEntries,
+ (uint64_t)sizeof(EFI_CONFIGURATION_TABLE), &ct_size)
+ && ct_size <= UINT32_MAX) {
+ map_single_table((uintptr_t)gST->ConfigurationTable, (uint32_t)ct_size);
+ }
+ }
+
+ if (gST->FirmwareVendor != NULL) {
+ size_t len = 0;
+ while (gST->FirmwareVendor[len] != 0) {
+ len++;
+ }
+ map_single_table((uintptr_t)gST->FirmwareVendor,
+ (len + 1) * sizeof(*gST->FirmwareVendor));
+ }
+}
+#endif
diff --git a/common/lib/acpi.h b/common/lib/acpi.h
index d0e68031..89dd158d 100644
--- a/common/lib/acpi.h
+++ b/common/lib/acpi.h
@@ -138,6 +138,21 @@ struct madt_io_apic {
uint32_t gsib;
} __attribute__((packed));
+struct madt_lapic_nmi {
+ struct madt_header header; // type=4, length=6
+ uint8_t acpi_processor_uid; // 0xff = all processors
+ uint16_t flags; // MPS INTI flags
+ uint8_t lint; // 0 or 1
+} __attribute__((packed));
+
+struct madt_x2apic_nmi {
+ struct madt_header header; // type=0x0a, length=12
+ uint16_t flags; // MPS INTI flags
+ uint32_t acpi_processor_uid; // 0xffffffff = all processors
+ uint8_t lint; // 0 or 1
+ uint8_t reserved[3];
+} __attribute__((packed));
+
struct madt_gicc {
struct madt_header header;
uint8_t reserved1[2];
@@ -181,5 +196,10 @@ void *acpi_get_table(const char *signature, int index);
void acpi_get_smbios(void **smbios32, void **smbios64);
void acpi_map_tables(void);
+void smbios_map_tables(void);
+
+#if defined (UEFI)
+void efi_map_runtime_entries(void);
+#endif
#endif
diff --git a/common/mm/pmm.h b/common/mm/pmm.h
index 27053e2a..e3bc4045 100644
--- a/common/mm/pmm.h
+++ b/common/mm/pmm.h
@@ -20,7 +20,7 @@ struct memmap_entry {
#define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000
#define MEMMAP_KERNEL_AND_MODULES 0x1001
#define MEMMAP_FRAMEBUFFER 0x1002
-#define MEMMAP_ACPI_TABLES 0x1003
+#define MEMMAP_RESERVED_MAPPED 0x1003
#define MEMMAP_EFI_RECLAIMABLE 0x2000
struct meminfo {
diff --git a/common/mm/pmm.s2.c b/common/mm/pmm.s2.c
index d793436c..6cc74cb8 100644
--- a/common/mm/pmm.s2.c
+++ b/common/mm/pmm.s2.c
@@ -69,8 +69,8 @@ static const char *memmap_type(uint32_t type) {
return "Usable RAM";
case MEMMAP_RESERVED:
return "Reserved";
- case MEMMAP_ACPI_TABLES:
- return "ACPI tables";
+ case MEMMAP_RESERVED_MAPPED:
+ return "Reserved (Mapped)";
case MEMMAP_ACPI_RECLAIMABLE:
return "ACPI reclaimable";
case MEMMAP_ACPI_NVS:
@@ -219,10 +219,10 @@ del_mm1:
m[p] = min_e;
}
- // Merge contiguous bootloader-reclaimable, ACPI tables, usable entries
+ // Merge contiguous bootloader-reclaimable, reserved (mapped), usable entries
for (size_t i = 0; i + 1 < count; i++) {
if (m[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
- && m[i].type != MEMMAP_ACPI_TABLES
+ && m[i].type != MEMMAP_RESERVED_MAPPED
&& m[i].type != MEMMAP_USABLE)
continue;
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 0979430c..421c9c23 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -51,7 +51,7 @@ static enum executable_format detect_kernel_format(uint8_t *kernel, size_t kerne
}
}
-#define SUPPORTED_BASE_REVISION 4
+#define SUPPORTED_BASE_REVISION 5
#define MAX_REQUESTS 128
@@ -1028,10 +1028,10 @@ FEAT_START
ext_mem_alloc(sizeof(struct limine_smbios_response));
if (smbios_entry_32) {
- smbios_response->entry_32 = base_revision <= 2 ? reported_addr(smbios_entry_32) : (uintptr_t)smbios_entry_32;
+ smbios_response->entry_32 = (base_revision <= 2 || base_revision >= 5) ? reported_addr(smbios_entry_32) : (uintptr_t)smbios_entry_32;
}
if (smbios_entry_64) {
- smbios_response->entry_64 = base_revision <= 2 ? reported_addr(smbios_entry_64) : (uintptr_t)smbios_entry_64;
+ smbios_response->entry_64 = (base_revision <= 2 || base_revision >= 5) ? reported_addr(smbios_entry_64) : (uintptr_t)smbios_entry_64;
}
smbios_request->response = reported_addr(smbios_response);
@@ -1048,7 +1048,7 @@ FEAT_START
struct limine_efi_system_table_response *est_response =
ext_mem_alloc(sizeof(struct limine_efi_system_table_response));
- est_response->address = base_revision <= 2 ? reported_addr(gST) : (uintptr_t)gST;
+ est_response->address = (base_revision <= 2 || base_revision >= 5) ? reported_addr(gST) : (uintptr_t)gST;
est_request->response = reported_addr(est_response);
FEAT_END
@@ -1475,6 +1475,12 @@ FEAT_END
if (base_revision >= 4) {
acpi_map_tables();
+ if (base_revision >= 5) {
+ smbios_map_tables();
+#if defined (UEFI)
+ efi_map_runtime_entries();
+#endif
+ }
pmm_sanitise_entries(memmap, &memmap_entries, true);
}
@@ -1492,6 +1498,7 @@ FEAT_START
struct limine_mp_info *mp_info;
size_t cpu_count;
#if defined (__x86_64__) || defined (__i386__)
+ smp_configure_apic = base_revision >= 5;
uint32_t bsp_lapic_id;
mp_info = init_smp(&cpu_count, &bsp_lapic_id,
paging_mode,
@@ -1610,8 +1617,8 @@ FEAT_START
case MEMMAP_USABLE:
_memmap[i].type = LIMINE_MEMMAP_USABLE;
break;
- case MEMMAP_ACPI_TABLES:
- _memmap[i].type = LIMINE_MEMMAP_ACPI_TABLES;
+ case MEMMAP_RESERVED_MAPPED:
+ _memmap[i].type = LIMINE_MEMMAP_RESERVED_MAPPED;
break;
case MEMMAP_ACPI_RECLAIMABLE:
_memmap[i].type = LIMINE_MEMMAP_ACPI_RECLAIMABLE;
@@ -1662,7 +1669,11 @@ FEAT_END
iommu_disable_all();
pic_mask_all();
- io_apic_mask_all();
+ io_apic_mask_all(base_revision >= 5);
+
+ if (base_revision >= 5 && lapic_check()) {
+ lapic_configure_bsp();
+ }
irq_flush_type = IRQ_PIC_APIC_FLUSH;
diff --git a/common/sys/lapic.c b/common/sys/lapic.c
index 39c688c3..e79abf51 100644
--- a/common/sys/lapic.c
+++ b/common/sys/lapic.c
@@ -9,6 +9,210 @@
#include <lib/acpi.h>
#include <mm/pmm.h>
+#define LAPIC_REG_LVT_CMCI 0x2f0
+#define LAPIC_REG_LVT_TIMER 0x320
+#define LAPIC_REG_LVT_THERMAL 0x330
+#define LAPIC_REG_LVT_PMC 0x340
+#define LAPIC_REG_LVT_LINT0 0x350
+#define LAPIC_REG_LVT_LINT1 0x360
+#define LAPIC_REG_LVT_ERROR 0x370
+#define LAPIC_REG_SVR 0x0f0
+#define LAPIC_REG_TPR 0x080
+#define LAPIC_REG_VERSION 0x030
+
+static uint32_t pending_lint0 = 0x00010000; // masked
+static uint32_t pending_lint1 = 0x00010000; // masked
+
+static uint32_t lapic_madt_nmi_flags_to_lvt(uint16_t flags) {
+ uint32_t lvt = 0x10400; // masked + NMI delivery mode
+
+ // Polarity: bits 1:0 of flags
+ uint8_t polarity = flags & 0x3;
+ if (polarity == 0x3) {
+ lvt |= (1 << 13); // active low
+ }
+ // 0b00 (conforms) and 0b01 (active high) leave bit 13 clear
+
+ // Trigger mode: bits 3:2 of flags
+ uint8_t trigger = (flags >> 2) & 0x3;
+ if (trigger == 0x3) {
+ lvt |= (1 << 15); // level triggered
+ }
+ // 0b00 (conforms) and 0b01 (edge) leave bit 15 clear
+
+ return lvt;
+}
+
+void lapic_prep_lint(struct madt *madt, uint32_t acpi_uid, bool is_bsp, bool x2apic) {
+ // Set defaults
+ if (is_bsp) {
+ pending_lint0 = 0x00010700; // ExtINT delivery mode, masked
+ } else {
+ pending_lint0 = 0x00010000; // masked
+ }
+ pending_lint1 = 0x00010000; // masked
+
+ // Walk MADT entries looking for NMI entries
+ for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
+ (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
+ madt_ptr += *(madt_ptr + 1)) {
+ if (*(madt_ptr + 1) == 0) {
+ break;
+ }
+ switch (*madt_ptr) {
+ case 4: {
+ // Local APIC NMI
+ if (*(madt_ptr + 1) < sizeof(struct madt_lapic_nmi)) {
+ continue;
+ }
+
+ struct madt_lapic_nmi *nmi = (void *)madt_ptr;
+
+ // Match all processors (0xff) or specific UID
+ if (nmi->acpi_processor_uid != 0xff && nmi->acpi_processor_uid != (uint8_t)acpi_uid) {
+ continue;
+ }
+
+ uint32_t lvt = lapic_madt_nmi_flags_to_lvt(nmi->flags);
+ if (nmi->lint == 0) {
+ pending_lint0 = lvt;
+ } else if (nmi->lint == 1) {
+ pending_lint1 = lvt;
+ }
+ continue;
+ }
+ case 0x0a: {
+ // Local x2APIC NMI
+ if (!x2apic) {
+ continue;
+ }
+ if (*(madt_ptr + 1) < sizeof(struct madt_x2apic_nmi)) {
+ continue;
+ }
+
+ struct madt_x2apic_nmi *nmi = (void *)madt_ptr;
+
+ // Match all processors (0xffffffff) or specific UID
+ if (nmi->acpi_processor_uid != 0xffffffff && nmi->acpi_processor_uid != acpi_uid) {
+ continue;
+ }
+
+ uint32_t lvt = lapic_madt_nmi_flags_to_lvt(nmi->flags);
+ if (nmi->lint == 0) {
+ pending_lint0 = lvt;
+ } else if (nmi->lint == 1) {
+ pending_lint1 = lvt;
+ }
+ continue;
+ }
+ }
+ }
+}
+
+void lapic_configure_handoff_state(void) {
+ bool is_x2 = !!(rdmsr(0x1b) & (1 << 10));
+
+ uint32_t max_lvt;
+ if (is_x2) {
+ max_lvt = (x2apic_read(LAPIC_REG_VERSION) >> 16) & 0xff;
+ } else {
+ max_lvt = (lapic_read(LAPIC_REG_VERSION) >> 16) & 0xff;
+ }
+
+ if (is_x2) {
+ x2apic_write(LAPIC_REG_SVR, 0x1ff);
+ x2apic_write(LAPIC_REG_TPR, 0);
+ if (max_lvt >= 6) {
+ x2apic_write(LAPIC_REG_LVT_CMCI, 0x00010000);
+ }
+ x2apic_write(LAPIC_REG_LVT_TIMER, 0x00010000);
+ if (max_lvt >= 5) {
+ x2apic_write(LAPIC_REG_LVT_THERMAL, 0x00010000);
+ }
+ if (max_lvt >= 4) {
+ x2apic_write(LAPIC_REG_LVT_PMC, 0x00010000);
+ }
+ x2apic_write(LAPIC_REG_LVT_ERROR, 0x00010000);
+ x2apic_write(LAPIC_REG_LVT_LINT0, pending_lint0);
+ x2apic_write(LAPIC_REG_LVT_LINT1, pending_lint1);
+ } else {
+ lapic_write(LAPIC_REG_SVR, 0x1ff);
+ lapic_write(LAPIC_REG_TPR, 0);
+ if (max_lvt >= 6) {
+ lapic_write(LAPIC_REG_LVT_CMCI, 0x00010000);
+ }
+ lapic_write(LAPIC_REG_LVT_TIMER, 0x00010000);
+ if (max_lvt >= 5) {
+ lapic_write(LAPIC_REG_LVT_THERMAL, 0x00010000);
+ }
+ if (max_lvt >= 4) {
+ lapic_write(LAPIC_REG_LVT_PMC, 0x00010000);
+ }
+ lapic_write(LAPIC_REG_LVT_ERROR, 0x00010000);
+ lapic_write(LAPIC_REG_LVT_LINT0, pending_lint0);
+ lapic_write(LAPIC_REG_LVT_LINT1, pending_lint1);
+ }
+}
+
+void lapic_configure_bsp(void) {
+ struct madt *madt = acpi_get_table("APIC", 0);
+ if (madt == NULL) {
+ return;
+ }
+
+ // Detect x2APIC from MSR
+ bool is_x2 = !!(rdmsr(0x1b) & (1 << 10));
+
+ // Find the BSP entry by matching LAPIC ID
+ uint32_t bsp_lapic_id;
+ if (is_x2) {
+ bsp_lapic_id = x2apic_read(LAPIC_REG_ID);
+ } else {
+ bsp_lapic_id = lapic_read(LAPIC_REG_ID) >> 24;
+ }
+
+ uint32_t bsp_acpi_uid = 0;
+
+ for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
+ (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
+ madt_ptr += *(madt_ptr + 1)) {
+ if (*(madt_ptr + 1) == 0) {
+ break;
+ }
+ switch (*madt_ptr) {
+ case 0: {
+ if (*(madt_ptr + 1) < sizeof(struct madt_lapic)) {
+ continue;
+ }
+ struct madt_lapic *lapic = (void *)madt_ptr;
+ if (lapic->lapic_id == bsp_lapic_id) {
+ bsp_acpi_uid = lapic->acpi_processor_uid;
+ goto found;
+ }
+ continue;
+ }
+ case 9: {
+ if (!is_x2) {
+ continue;
+ }
+ if (*(madt_ptr + 1) < sizeof(struct madt_x2apic)) {
+ continue;
+ }
+ struct madt_x2apic *x2lapic = (void *)madt_ptr;
+ if (x2lapic->x2apic_id == bsp_lapic_id) {
+ bsp_acpi_uid = x2lapic->acpi_processor_uid;
+ goto found;
+ }
+ continue;
+ }
+ }
+ }
+
+found:
+ lapic_prep_lint(madt, bsp_acpi_uid, true, is_x2);
+ lapic_configure_handoff_state();
+}
+
struct dmar {
struct sdt header;
uint8_t host_address_width;
@@ -161,7 +365,7 @@ uint32_t io_apic_gsi_count(size_t io_apic) {
return ((io_apic_read(io_apic, 1) & 0xff0000) >> 16) + 1;
}
-void io_apic_mask_all(void) {
+void io_apic_mask_all(bool mask_nmi_and_extint) {
for (size_t i = 0; i < max_io_apics; i++) {
uint32_t gsi_count = io_apic_gsi_count(i);
for (uint32_t j = 0; j < gsi_count; j++) {
@@ -170,6 +374,12 @@ void io_apic_mask_all(void) {
case 0b000: // Fixed
case 0b001: // Lowest Priority
break;
+ case 0b100: // NMI
+ case 0b111: // ExtINT
+ if (!mask_nmi_and_extint) {
+ continue;
+ }
+ break;
default:
continue;
}
diff --git a/common/sys/lapic.h b/common/sys/lapic.h
index 17996752..3565f94f 100644
--- a/common/sys/lapic.h
+++ b/common/sys/lapic.h
@@ -5,6 +5,8 @@
#include <stdint.h>
#include <stdbool.h>
+struct madt;
+
#define LAPIC_REG_ICR0 0x300
#define LAPIC_REG_ICR1 0x310
#define LAPIC_REG_SPURIOUS 0x0f0
@@ -21,10 +23,14 @@ bool x2apic_enable(void);
uint64_t x2apic_read(uint32_t reg);
void x2apic_write(uint32_t reg, uint64_t data);
+void lapic_configure_bsp(void);
+void lapic_prep_lint(struct madt *madt, uint32_t acpi_uid, bool is_bsp, bool x2apic);
+void lapic_configure_handoff_state(void);
+
void init_io_apics(void);
uint32_t io_apic_read(size_t io_apic, uint32_t reg);
void io_apic_write(size_t io_apic, uint32_t reg, uint32_t value);
uint32_t io_apic_gsi_count(size_t io_apic);
-void io_apic_mask_all(void);
+void io_apic_mask_all(bool mask_nmi_and_extint);
#endif
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 6c021b6c..9b123452 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -36,8 +36,11 @@ struct trampoline_passed_info {
uint64_t smp_tpl_bsp_apic_addr_msr;
uint64_t smp_tpl_mtrr_restore;
uint64_t smp_tpl_temp_stack;
+ uint64_t smp_tpl_lapic_setup;
} __attribute__((packed));
+bool smp_configure_apic = false;
+
static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
struct limine_mp_info *info_struct,
int paging_mode, uint32_t pagemap,
@@ -72,6 +75,8 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
passed_info->smp_tpl_bsp_apic_addr_msr = rdmsr(0x1b);
passed_info->smp_tpl_mtrr_restore = (uint64_t)(uintptr_t)mtrr_restore;
passed_info->smp_tpl_temp_stack = (uint64_t)(uintptr_t)temp_stack + 8192;
+ passed_info->smp_tpl_lapic_setup = smp_configure_apic
+ ? (uint64_t)(uintptr_t)lapic_configure_handoff_state : 0;
asm volatile ("" ::: "memory");
@@ -234,6 +239,11 @@ struct limine_mp_info *init_smp(size_t *cpu_count,
printv("smp: [xAPIC] Found candidate AP for bring-up. LAPIC ID: %u\n", lapic->lapic_id);
+ // Set up per-AP LINT values before starting
+ if (smp_configure_apic) {
+ lapic_prep_lint(madt, lapic->acpi_processor_uid, false, x2apic);
+ }
+
// Try to start the AP
if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
paging_mode, (uintptr_t)pagemap.top_level,
@@ -274,6 +284,11 @@ struct limine_mp_info *init_smp(size_t *cpu_count,
printv("smp: [x2APIC] Found candidate AP for bring-up. LAPIC ID: %u\n", x2lapic->x2apic_id);
+ // Set up per-AP LINT values before starting
+ if (smp_configure_apic) {
+ lapic_prep_lint(madt, x2lapic->acpi_processor_uid, false, true);
+ }
+
// Try to start the AP
if (!smp_start_ap(x2lapic->x2apic_id, &gdtr, info_struct,
paging_mode, (uintptr_t)pagemap.top_level,
diff --git a/common/sys/smp.h b/common/sys/smp.h
index de45f08c..7cac37ca 100644
--- a/common/sys/smp.h
+++ b/common/sys/smp.h
@@ -10,6 +10,8 @@
#if defined (__x86_64__) || defined (__i386__)
+extern bool smp_configure_apic;
+
struct limine_mp_info *init_smp(size_t *cpu_count,
uint32_t *_bsp_lapic_id,
int paging_mode,
diff --git a/common/sys/smp_trampoline.asm_x86 b/common/sys/smp_trampoline.asm_x86
index d2b9f3bc..41ac841d 100644
--- a/common/sys/smp_trampoline.asm_x86
+++ b/common/sys/smp_trampoline.asm_x86
@@ -89,6 +89,13 @@ smp_trampoline_start:
%ifdef IA32_TARGET
; Synchronise MTRRs with BSP
call [ebx + (passed_info.mtrr_restore - smp_trampoline_start)]
+
+ ; Configure local APIC handoff state (if pointer is set)
+ mov eax, dword [ebx + (passed_info.lapic_setup - smp_trampoline_start)]
+ test eax, eax
+ jz .skip_lapic_setup32
+ call eax
+ .skip_lapic_setup32:
%endif
lea eax, [ebx + (.mode64 - smp_trampoline_start)]
@@ -138,6 +145,13 @@ parking64:
%ifdef X86_64_TARGET
; Synchronise MTRRs with BSP
call [rbx + (passed_info.mtrr_restore - smp_trampoline_start)]
+
+ ; Configure local APIC handoff state (if pointer is set)
+ mov rax, [rbx + (passed_info.lapic_setup - smp_trampoline_start)]
+ test rax, rax
+ jz .skip_lapic_setup64
+ call rax
+ .skip_lapic_setup64:
%endif
mov edi, dword [rbx + (passed_info.smp_info_struct - smp_trampoline_start)]
@@ -222,6 +236,8 @@ passed_info:
dq 0
.temp_stack:
dq 0
+ .lapic_setup:
+ dq 0
smp_trampoline_end:
diff --git a/test/limine.c b/test/limine.c
index 8254d5a0..b84e7b7e 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -7,7 +7,7 @@
#include <flanterm_backends/fb.h>
__attribute__((section(".limine_requests")))
-static volatile uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(4);
+static volatile uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(5);
static void limine_main(void);
@@ -190,8 +190,8 @@ static char *get_memmap_type(uint64_t type) {
return "Usable";
case LIMINE_MEMMAP_RESERVED:
return "Reserved";
- case LIMINE_MEMMAP_ACPI_TABLES:
- return "ACPI tables";
+ case LIMINE_MEMMAP_RESERVED_MAPPED:
+ return "Reserved (Mapped)";
case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
return "ACPI reclaimable";
case LIMINE_MEMMAP_ACPI_NVS:
