:: commit 2ab2c153f5e4e17780d0c69e82937b6acc707276

mintsuki <mintsuki@protonmail.com> — 2020-10-22 13:25

parents: 5bd25ac520

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 c65fe0f9..cdba3a9b 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 7adcba5a..39f1972f 100644
--- a/stage2/protos/stivale2.c
+++ b/stage2/protos/stivale2.c
@@ -317,17 +317,19 @@ void stivale2_load(char *cmdline, int boot_drive) {
         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;
                 }
tab: 248 wrap: offon