Change return type of cpuid(), add APIC existance check, do not assume BSP APIC ID to be 0
diff --git a/limine.bin b/limine.bin
index 55f23cc1..8d09935d 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/lib/rand.c b/stage2/lib/rand.c
index abfa2597..ed1c51a8 100644
--- a/stage2/lib/rand.c
+++ b/stage2/lib/rand.c
@@ -60,9 +60,9 @@ static void init_rand(void) {
uint32_t eax, ebx, ecx, edx;
// Check for rdseed
- if (!cpuid(0x07, 0, &eax, &ebx, &ecx, &edx) && (ebx & (1 << 18))) {
+ if (cpuid(0x07, 0, &eax, &ebx, &ecx, &edx) && (ebx & (1 << 18))) {
seed *= (seed ^ rdseed(uint32_t));
- } else if (!cpuid(0x01, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 30))) {
+ } else if (cpuid(0x01, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 30))) {
seed *= (seed ^ rdrand(uint32_t));
}
diff --git a/stage2/mm/mtrr.c b/stage2/mm/mtrr.c
index 115a77e6..34efbea4 100644
--- a/stage2/mm/mtrr.c
+++ b/stage2/mm/mtrr.c
@@ -14,7 +14,7 @@ struct mtrr {
static bool mtrr_supported(void) {
uint32_t eax, ebx, ecx, edx;
- if (cpuid(1, 0, &eax, &ebx, &ecx, &edx))
+ if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
return false;
return !!(edx & (1 << 12));
@@ -42,7 +42,7 @@ bool mtrr_set_range(uint64_t base, uint64_t size, uint8_t memory_type) {
uint32_t eax, ebx, ecx, edx;
- if (cpuid(0x80000008, 0, &eax, &ebx, &ecx, &edx))
+ if (!cpuid(0x80000008, 0, &eax, &ebx, &ecx, &edx))
return false;
uint8_t maxphysaddr = eax & 0xff;
diff --git a/stage2/protos/stivale2.c b/stage2/protos/stivale2.c
index 60bb6d0a..290d6eb1 100644
--- a/stage2/protos/stivale2.c
+++ b/stage2/protos/stivale2.c
@@ -325,17 +325,19 @@ void stivale2_load(char *cmdline) {
smp_info = init_smp(&cpu_count, bits == 64, level5pg && level5pg_requested,
pagemap, smp_hdr_tag->flags & 1);
- struct stivale2_struct_tag_smp *tag =
- conv_mem_alloc(sizeof(struct stivale2_struct_tag_smp)
- + sizeof(struct smp_information) * cpu_count);
- tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
- tag->cpu_count = cpu_count;
- tag->flags |= (smp_hdr_tag->flags & 1) && x2apic_check();
-
- memcpy((void*)tag + sizeof(struct stivale2_struct_tag_smp),
- smp_info, sizeof(struct smp_information) * cpu_count);
-
- append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
+ if (smp_info != NULL) {
+ struct stivale2_struct_tag_smp *tag =
+ conv_mem_alloc(sizeof(struct stivale2_struct_tag_smp)
+ + sizeof(struct smp_information) * cpu_count);
+ tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
+ tag->cpu_count = cpu_count;
+ tag->flags |= (smp_hdr_tag->flags & 1) && x2apic_check();
+
+ memcpy((void*)tag + sizeof(struct stivale2_struct_tag_smp),
+ smp_info, sizeof(struct smp_information) * cpu_count);
+
+ append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
+ }
}
}
diff --git a/stage2/sys/cpu.h b/stage2/sys/cpu.h
index 5b96e49a..45112e26 100644
--- a/stage2/sys/cpu.h
+++ b/stage2/sys/cpu.h
@@ -2,6 +2,7 @@
#define __SYS__CPU_H__
#include <stdint.h>
+#include <stdbool.h>
#define FLAT_PTR(PTR) (*((int(*)[])(PTR)))
@@ -10,7 +11,7 @@
#define DWORD_PTR(PTR) (*((uint32_t *)(PTR)))
#define QWORD_PTR(PTR) (*((uint64_t *)(PTR)))
-static inline int cpuid(uint32_t leaf, uint32_t subleaf,
+static inline bool cpuid(uint32_t leaf, uint32_t subleaf,
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
uint32_t cpuid_max;
asm volatile ("cpuid"
@@ -18,11 +19,11 @@ static inline int cpuid(uint32_t leaf, uint32_t subleaf,
: "a" (leaf & 0x80000000)
: "ebx", "ecx", "edx");
if (leaf > cpuid_max)
- return 1;
+ return false;
asm volatile ("cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "a" (leaf), "c" (subleaf));
- return 0;
+ return true;
}
static inline void outb(uint16_t port, uint8_t value) {
diff --git a/stage2/sys/lapic.c b/stage2/sys/lapic.c
index 66636efb..bb16cdf8 100644
--- a/stage2/sys/lapic.c
+++ b/stage2/sys/lapic.c
@@ -14,6 +14,17 @@ struct dmar {
symbol remapping_structures;
} __attribute__((packed));
+bool lapic_check(void) {
+ uint32_t eax, ebx, ecx, edx;
+ if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
+ return false;
+
+ if (!(ecx & (1 << 9)))
+ return false;
+
+ return true;
+}
+
uint32_t lapic_read(uint32_t reg) {
size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
return mmind(lapic_mmio_base + reg);
@@ -26,7 +37,8 @@ void lapic_write(uint32_t reg, uint32_t data) {
bool x2apic_check(void) {
uint32_t eax, ebx, ecx, edx;
- cpuid(1, 0, &eax, &ebx, &ecx, &edx);
+ if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
+ return false;
if (!(ecx & (1 << 21)))
return false;
diff --git a/stage2/sys/lapic.h b/stage2/sys/lapic.h
index e211fee5..caacd392 100644
--- a/stage2/sys/lapic.h
+++ b/stage2/sys/lapic.h
@@ -9,8 +9,10 @@
#define LAPIC_REG_SPURIOUS 0x0f0
#define LAPIC_REG_EOI 0x0b0
+bool lapic_check(void);
uint32_t lapic_read(uint32_t reg);
void lapic_write(uint32_t reg, uint32_t data);
+
bool x2apic_check(void);
bool x2apic_enable(void);
uint64_t x2apic_read(uint32_t reg);
diff --git a/stage2/sys/smp.c b/stage2/sys/smp.c
index 673724ac..f2f4a53e 100644
--- a/stage2/sys/smp.c
+++ b/stage2/sys/smp.c
@@ -100,6 +100,9 @@ struct smp_information *init_smp(size_t *cpu_count,
bool lv5,
pagemap_t pagemap,
bool x2apic) {
+ if (!lapic_check())
+ return NULL;
+
// Search for MADT table
struct madt *madt = acpi_get_table("APIC", 0);
@@ -109,10 +112,28 @@ struct smp_information *init_smp(size_t *cpu_count,
struct gdtr gdtr;
asm volatile ("sgdt %0" :: "m"(gdtr) : "memory");
- *cpu_count = 0;
+ uint32_t eax, ebx, ecx, edx;
+
+ if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
+ return NULL;
+
+ uint8_t bsp_lapic_id = ebx >> 24;
x2apic = x2apic && x2apic_enable();
+ uint32_t bsp_x2apic_id;
+ if (x2apic) {
+ // The Intel manual recommends checking if leaf 0x1f exists first, and
+ // using that in place of 0xb if that's the case
+ if (!cpuid(0x1f, 0, &eax, &ebx, &ecx, &edx))
+ if (!cpuid(0xb, 0, &eax, &ebx, &ecx, &edx))
+ return NULL;
+
+ bsp_x2apic_id = edx;
+ }
+
+ *cpu_count = 0;
+
// Count the MAX of startable APs and allocate accordingly
size_t max_cpus = 0;
@@ -168,7 +189,7 @@ struct smp_information *init_smp(size_t *cpu_count,
info_struct->lapic_id = lapic->lapic_id;
// Do not try to restart the BSP
- if (lapic->lapic_id == 0) {
+ if (lapic->lapic_id == bsp_lapic_id) {
(*cpu_count)++;
continue;
}
@@ -205,7 +226,7 @@ struct smp_information *init_smp(size_t *cpu_count,
info_struct->lapic_id = x2apic->x2apic_id;
// Do not try to restart the BSP
- if (x2apic->x2apic_id == 0) {
+ if (x2apic->x2apic_id == bsp_x2apic_id) {
(*cpu_count)++;
continue;
}
