Extend x2APIC check as per VT-d specification
This commit is contained in:
parent
c778e72af8
commit
513d0a2279
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
65
stage2/sys/lapic.c
Normal file
65
stage2/sys/lapic.c
Normal file
@ -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);
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user