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__
|
#define __SYS__APIC_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/cpu.h>
|
|
||||||
#include <lib/blib.h>
|
|
||||||
|
|
||||||
#define LAPIC_REG_ICR0 0x300
|
#define LAPIC_REG_ICR0 0x300
|
||||||
#define LAPIC_REG_ICR1 0x310
|
#define LAPIC_REG_ICR1 0x310
|
||||||
#define LAPIC_REG_SPURIOUS 0x0f0
|
#define LAPIC_REG_SPURIOUS 0x0f0
|
||||||
#define LAPIC_REG_EOI 0x0b0
|
#define LAPIC_REG_EOI 0x0b0
|
||||||
|
|
||||||
static inline uint32_t lapic_read(uint32_t reg) {
|
uint32_t lapic_read(uint32_t reg);
|
||||||
size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
|
void lapic_write(uint32_t reg, uint32_t data);
|
||||||
return mmind((void *)(lapic_mmio_base + reg));
|
bool x2apic_check(void);
|
||||||
}
|
bool x2apic_enable(void);
|
||||||
|
uint64_t x2apic_read(uint32_t reg);
|
||||||
static inline void lapic_write(uint32_t reg, uint32_t data) {
|
void x2apic_write(uint32_t reg, uint64_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user