:: commit b6d170367a7304417b80487a2131e0dd91a32c52

mintsuki <mintsuki@protonmail.com> — 2020-10-12 19:20

parents: 8f552e4402

Extend x2APIC check as per VT-d specification

diff --git a/limine.bin b/limine.bin
index fb18ec6b..39bbf983 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/sys/lapic.c b/stage2/sys/lapic.c
new file mode 100644
index 00000000..44f379fa
--- /dev/null
+++ b/stage2/sys/lapic.c
@@ -0,0 +1,65 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/lapic.h>
+#include <sys/cpu.h>
+#include <lib/blib.h>
+#include <lib/acpi.h>
+
+struct dmar {
+    struct sdt;
+    uint8_t host_address_width;
+    uint8_t flags;
+    uint8_t reserved[10];
+    symbol  remapping_structures;
+} __attribute__((packed));
+
+uint32_t lapic_read(uint32_t reg) {
+    size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
+    return mmind((void *)(lapic_mmio_base + reg));
+}
+
+void lapic_write(uint32_t reg, uint32_t data) {
+    size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
+    mmoutd((void *)(lapic_mmio_base + reg), data);
+}
+
+bool x2apic_check(void) {
+    uint32_t eax, ebx, ecx, edx;
+    cpuid(1, 0, &eax, &ebx, &ecx, &edx);
+
+    if (!(ecx & (1 << 21)))
+        return false;
+
+    // According to the Intel VT-d spec, we're required
+    // to check if bit 0 and 1 of the flags field of the
+    // DMAR ACPI table are set, and if they are, we should
+    // not report x2APIC capabilities.
+    struct dmar *dmar = acpi_get_table("DMAR", 0);
+    if (!dmar)
+        return true;
+
+    if ((dmar->flags & (1 << 0)) && (dmar->flags & (1 << 1)))
+        return false;
+
+    return true;
+}
+
+bool x2apic_enable(void) {
+    if (!x2apic_check())
+        return false;
+
+    uint64_t ia32_apic_base = rdmsr(0x1b);
+    ia32_apic_base |= (1 << 10);
+    wrmsr(0x1b, ia32_apic_base);
+
+    return true;
+}
+
+uint64_t x2apic_read(uint32_t reg) {
+    return rdmsr(0x800 + (reg >> 4));
+}
+
+void x2apic_write(uint32_t reg, uint64_t data) {
+    wrmsr(0x800 + (reg >> 4), data);
+}
diff --git a/stage2/sys/lapic.h b/stage2/sys/lapic.h
index 1c30436a..e211fee5 100644
--- a/stage2/sys/lapic.h
+++ b/stage2/sys/lapic.h
@@ -2,53 +2,18 @@
 #define __SYS__APIC_H__
 
 #include <stdint.h>
-#include <stddef.h>
 #include <stdbool.h>
-#include <sys/cpu.h>
-#include <lib/blib.h>
 
 #define LAPIC_REG_ICR0     0x300
 #define LAPIC_REG_ICR1     0x310
 #define LAPIC_REG_SPURIOUS 0x0f0
 #define LAPIC_REG_EOI      0x0b0
 
-static inline uint32_t lapic_read(uint32_t reg) {
-    size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
-    return mmind((void *)(lapic_mmio_base + reg));
-}
-
-static inline void lapic_write(uint32_t reg, uint32_t data) {
-    size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
-    mmoutd((void *)(lapic_mmio_base + reg), data);
-}
-
-static inline bool x2apic_check(void) {
-    uint32_t eax, ebx, ecx, edx;
-    cpuid(1, 0, &eax, &ebx, &ecx, &edx);
-
-    if (!(ecx & (1 << 21)))
-        return false;
-
-    return true;
-}
-
-static inline bool x2apic_enable(void) {
-    if (!x2apic_check())
-        return false;
-
-    uint64_t ia32_apic_base = rdmsr(0x1b);
-    ia32_apic_base |= (1 << 10);
-    wrmsr(0x1b, ia32_apic_base);
-
-    return true;
-}
-
-static inline uint64_t x2apic_read(uint32_t reg) {
-    return rdmsr(0x800 + (reg >> 4));
-}
-
-static inline void x2apic_write(uint32_t reg, uint64_t data) {
-    wrmsr(0x800 + (reg >> 4), data);
-}
+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);
+void x2apic_write(uint32_t reg, uint64_t data);
 
 #endif
tab: 248 wrap: offon