diff --git a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp index e34ecf8..9b1b5eb 100644 --- a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp +++ b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp @@ -52,22 +52,16 @@ namespace APIC if (Register != APIC_ICRLO && Register != APIC_ICRHI && Register != APIC_ID) - debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0); + debug("APIC::Read(%#lx) [x2=%d]", + Register, x2APICSupported ? 1 : 0); #endif if (x2APICSupported) - { - if (Register != APIC_ICRHI) - return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800)); - else - return s_cst(uint32_t, rdmsr(0x30 + 0x800)); - } - else - { - CPU::MemBar::Barrier(); - uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register)); - CPU::MemBar::Barrier(); - return ret; - } + assert(false); + + CPU::MemBar::Barrier(); + uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register)); + CPU::MemBar::Barrier(); + return ret; } void APIC::Write(uint32_t Register, uint32_t Value) @@ -79,21 +73,15 @@ namespace APIC Register != APIC_TICR && Register != APIC_ICRLO && Register != APIC_ICRHI) - debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0); + debug("APIC::Write(%#lx, %#lx) [x2=%d]", + Register, Value, x2APICSupported ? 1 : 0); #endif if (x2APICSupported) - { - if (Register != APIC_ICRHI) - wrmsr((Register >> 4) + 0x800, Value); - else - wrmsr(MSR_X2APIC_ICR, Value); - } - else - { - CPU::MemBar::Barrier(); - *((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value; - CPU::MemBar::Barrier(); - } + assert(false); + + CPU::MemBar::Barrier(); + *((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value; + CPU::MemBar::Barrier(); } void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value) @@ -117,30 +105,50 @@ namespace APIC return ret; } - void APIC::EOI() { this->Write(APIC_EOI, 0); } + void APIC::EOI() + { + if (this->x2APICSupported) + wrmsr(MSR_X2APIC_EOI, 0); + else + this->Write(APIC_EOI, 0); + } void APIC::WaitForIPI() { - InterruptCommandRegisterLow icr = {.raw = 0}; - do + if (this->x2APICSupported) { - icr.raw = this->Read(APIC_ICRLO); - CPU::Pause(); - } while (icr.DeliveryStatus != Idle); + ErrorStatusRegister esr{}; + esr.raw = uint32_t(rdmsr(MSR_X2APIC_ESR)); + UNUSED(esr); + /* FIXME: Not sure if this is required or + how to implement it. */ + } + else + { + InterruptCommandRegister icr{}; + do + { + icr.split.Low = this->Read(APIC_ICRLO); + CPU::Pause(); + } while (icr.DS != Idle); + } } - void APIC::IPI(int CPU, InterruptCommandRegisterLow icr) + void APIC::ICR(InterruptCommandRegister icr) { SmartCriticalSection(APICLock); if (x2APICSupported) { - wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw)); + assert(icr.MT != LowestPriority); + assert(icr.MT != DeliveryMode); + assert(icr.MT != ExtINT); + wrmsr(MSR_X2APIC_ICR, icr.raw); this->WaitForIPI(); } else { - this->Write(APIC_ICRHI, (CPU << 24)); - this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); + this->Write(APIC_ICRHI, icr.split.High); + this->Write(APIC_ICRLO, icr.split.Low); this->WaitForIPI(); } } @@ -148,21 +156,25 @@ namespace APIC void APIC::SendInitIPI(int CPU) { SmartCriticalSection(APICLock); + InterruptCommandRegister icr{}; + if (x2APICSupported) { - InterruptCommandRegisterLow icr = {.raw = 0}; - icr.DeliveryMode = INIT; - icr.Level = Assert; - wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw)); + icr.x2.MT = INIT; + icr.x2.L = Assert; + icr.x2.DES = uint8_t(CPU); + + wrmsr(MSR_X2APIC_ICR, icr.raw); this->WaitForIPI(); } else { - InterruptCommandRegisterLow icr = {.raw = 0}; - icr.DeliveryMode = INIT; - icr.Level = Assert; - this->Write(APIC_ICRHI, (CPU << 24)); - this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); + icr.MT = INIT; + icr.L = Assert; + icr.DES = uint8_t(CPU); + + this->Write(APIC_ICRHI, icr.split.High); + this->Write(APIC_ICRLO, icr.split.Low); this->WaitForIPI(); } } @@ -170,45 +182,54 @@ namespace APIC void APIC::SendStartupIPI(int CPU, uint64_t StartupAddress) { SmartCriticalSection(APICLock); + InterruptCommandRegister icr{}; + if (x2APICSupported) { - InterruptCommandRegisterLow icr = {.raw = 0}; - icr.Vector = s_cst(uint8_t, StartupAddress >> 12); - icr.DeliveryMode = Startup; - icr.Level = Assert; - wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw)); + icr.x2.VEC = s_cst(uint8_t, StartupAddress >> 12); + icr.x2.MT = Startup; + icr.x2.L = Assert; + icr.x2.DES = uint8_t(CPU); + + wrmsr(MSR_X2APIC_ICR, icr.raw); this->WaitForIPI(); } else { - InterruptCommandRegisterLow icr = {.raw = 0}; - icr.Vector = s_cst(uint8_t, StartupAddress >> 12); - icr.DeliveryMode = Startup; - icr.Level = Assert; - this->Write(APIC_ICRHI, (CPU << 24)); - this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); + icr.VEC = s_cst(uint8_t, StartupAddress >> 12); + icr.MT = Startup; + icr.L = Assert; + icr.DES = uint8_t(CPU); + + this->Write(APIC_ICRHI, icr.split.High); + this->Write(APIC_ICRLO, icr.split.Low); this->WaitForIPI(); } } uint32_t APIC::IOGetMaxRedirect(uint32_t APICID) { - uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion)); - return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry; + ACPI::MADT::MADTIOApic *ioapic = ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]; + uint32_t TableAddress = (this->IORead(ioapic->Address, GetIOAPICVersion)); + IOAPICVersion ver = {.raw = TableAddress}; + return ver.MLE + 1; } - void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status) + void APIC::RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, uint8_t CPU, int Status) { - uint64_t Value = Vector; - int64_t IOAPICTarget = -1; - for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++) - if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase <= GSI) - if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI) + ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT(); + for (size_t i = 0; i < madt->ioapic.size(); i++) + { + if (madt->ioapic[i]->GSIBase <= GSI) + { + if (madt->ioapic[i]->GSIBase + IOGetMaxRedirect(uint32_t(i)) > GSI) { IOAPICTarget = i; break; } + } + } if (IOAPICTarget == -1) { @@ -216,40 +237,46 @@ namespace APIC return; } - // TODO: IOAPICRedirectEntry Entry = {.raw = 0}; + IOAPICRedirectEntry Entry{}; + Entry.VEC = Vector; + Entry.DES = CPU; if (Flags & ActiveHighLow) - Value |= (1 << 13); + Entry.IPP = 1; if (Flags & EdgeLevel) - Value |= (1 << 15); + Entry.TGM = 1; if (!Status) - Value |= (1 << 16); + Entry.M = 1; - Value |= (((uintptr_t)CPU) << 56); - uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->GSIBase) * 2 + 16; - - this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister, (uint32_t)Value); - this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32)); + uint32_t IORegister = (GSI - madt->ioapic[IOAPICTarget]->GSIBase) * 2 + 16; + this->IOWrite(madt->ioapic[IOAPICTarget]->Address, + IORegister, Entry.split.Low); + this->IOWrite(madt->ioapic[IOAPICTarget]->Address, + IORegister + 1, Entry.split.High); } - void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status) + void APIC::RedirectIRQ(uint8_t CPU, uint8_t IRQ, int Status) { - for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++) - if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ) + ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT(); + for (uint64_t i = 0; i < madt->iso.size(); i++) + if (madt->iso[i]->IRQSource == IRQ) { debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d", - i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, CPU); + i, madt->iso[i]->IRQSource, madt->iso[i]->GSI, CPU); - this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource + 0x20, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->Flags, CPU, Status); + this->RawRedirectIRQ(madt->iso[i]->IRQSource + 0x20, + madt->iso[i]->GSI, + madt->iso[i]->Flags, + CPU, Status); return; } debug("Mapping IRQ%d on CPU %d", IRQ, CPU); this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status); } - void APIC::RedirectIRQs(int CPU) + void APIC::RedirectIRQs(uint8_t CPU) { SmartCriticalSection(APICLock); debug("Redirecting IRQs..."); @@ -262,21 +289,22 @@ namespace APIC { SmartCriticalSection(APICLock); APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)}; - uint64_t BaseLow = BaseStruct.ApicBaseLo; - uint64_t BaseHigh = BaseStruct.ApicBaseHi; + uint64_t BaseLow = BaseStruct.ABALow; + uint64_t BaseHigh = BaseStruct.ABAHigh; this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u; trace("APIC Address: %#lx", this->APICBaseAddress); - Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); + Memory::Virtual().Map((void *)this->APICBaseAddress, + (void *)this->APICBaseAddress, + Memory::RW | Memory::PCD); - bool x2APICSupported = false; if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) { CPU::x86::AMD::CPUID0x00000001 cpuid; cpuid.Get(); if (cpuid.ECX.x2APIC) { - // x2APICSupported = cpuid.ECX.x2APIC; - fixme("x2APIC is supported"); + this->x2APICSupported = cpuid.ECX.x2APIC; + debug("x2APIC is supported"); } } else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) @@ -285,39 +313,38 @@ namespace APIC cpuid.Get(); if (cpuid.ECX.x2APIC) { - // x2APICSupported = cpuid.ECX.x2APIC; - fixme("x2APIC is supported"); + this->x2APICSupported = cpuid.ECX.x2APIC; + debug("x2APIC is supported"); } } - if (x2APICSupported) - { - this->x2APICSupported = true; - wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10)); - BaseStruct.EN = 1; - wrmsr(MSR_APIC_BASE, BaseStruct.raw); - } - else - { - BaseStruct.EN = 1; - wrmsr(MSR_APIC_BASE, BaseStruct.raw); - } + BaseStruct.AE = 1; + wrmsr(MSR_APIC_BASE, BaseStruct.raw); - this->Write(APIC_TPR, 0x0); - // this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100 + if (this->x2APICSupported) + { + BaseStruct.EXTD = 1; + wrmsr(MSR_APIC_BASE, BaseStruct.raw); + } if (!this->x2APICSupported) { + this->Write(APIC_TPR, 0x0); this->Write(APIC_DFR, 0xF0000000); this->Write(APIC_LDR, this->Read(APIC_ID)); } + else + { + wrmsr(MSR_X2APIC_TPR, 0x0); + } ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT(); for (size_t i = 0; i < madt->nmi.size(); i++) { - if (madt->nmi[i]->processor != 0xFF && Core != madt->nmi[i]->processor) - return; + if (madt->nmi[i]->processor != 0xFF && + Core != madt->nmi[i]->processor) + break; uint32_t nmi = 0x402; if (madt->nmi[i]->flags & 2) @@ -325,16 +352,34 @@ namespace APIC if (madt->nmi[i]->flags & 8) nmi |= 1 << 15; if (madt->nmi[i]->lint == 0) - this->Write(APIC_LINT0, nmi); + { + if (this->x2APICSupported) + wrmsr(MSR_X2APIC_LVT_LINT0, nmi); + else + this->Write(APIC_LINT0, nmi); + } else if (madt->nmi[i]->lint == 1) - this->Write(APIC_LINT1, nmi); + { + if (this->x2APICSupported) + wrmsr(MSR_X2APIC_LVT_LINT1, nmi); + else + this->Write(APIC_LINT1, nmi); + } } - // Setup the spurrious interrupt vector - Spurious Spurious = {.raw = this->Read(APIC_SVR)}; - Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something? - Spurious.Software = 1; - this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw)); + /* Setup the spurious interrupt vector */ + Spurious svr{}; + if (this->x2APICSupported) + svr.raw = uint32_t(rdmsr(MSR_X2APIC_SIVR)); + else + svr.raw = this->Read(APIC_SVR); + + svr.VEC = IRQ223; + svr.ASE = 1; + if (this->x2APICSupported) + wrmsr(MSR_X2APIC_SIVR, svr.raw); + else + this->Write(APIC_SVR, svr.raw); static int once = 0; if (!once++) @@ -356,45 +401,85 @@ namespace APIC void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds) { SmartCriticalSection(APICLock); - LVTTimer timer = {.raw = 0}; - timer.Vector = s_cst(uint8_t, Vector); - timer.TimerMode = 0; - if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0) - this->lapic->Write(APIC_TDCR, DivideBy128); + LVTTimer timer{}; + timer.VEC = uint8_t(Vector); + timer.TMM = LVTTimerMode::OneShot; + + LVTTimerDivide Divider = DivideBy8; + + if (unlikely(strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)) + Divider = DivideBy128; + + if (this->lapic->x2APIC) + { + wrmsr(MSR_X2APIC_DIV_CONF, Divider); + wrmsr(MSR_X2APIC_INIT_COUNT, uint32_t(Ticks * Miliseconds)); + wrmsr(MSR_X2APIC_LVT_TIMER, uint32_t(timer.raw)); + } else - this->lapic->Write(APIC_TDCR, DivideBy16); - this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds)); - this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw)); + { + this->lapic->Write(APIC_TDCR, Divider); + this->lapic->Write(APIC_TICR, uint32_t(Ticks * Miliseconds)); + this->lapic->Write(APIC_TIMER, uint32_t(timer.raw)); + } } Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */ { SmartCriticalSection(APICLock); this->lapic = apic; - LVTTimerDivide Divider = DivideBy16; + LVTTimerDivide Divider = DivideBy8; - trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID); + trace("Initializing APIC timer on CPU %d", + GetCurrentCPU()->ID); - this->lapic->Write(APIC_TDCR, Divider); - this->lapic->Write(APIC_TICR, 0xFFFFFFFF); + if (this->lapic->x2APIC) + { + wrmsr(MSR_X2APIC_DIV_CONF, Divider); + wrmsr(MSR_X2APIC_INIT_COUNT, 0xFFFFFFFF); + } + else + { + this->lapic->Write(APIC_TDCR, Divider); + this->lapic->Write(APIC_TICR, 0xFFFFFFFF); + } TimeManager->Sleep(1, Time::Units::Milliseconds); // Mask the timer - this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */); - Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR); + if (this->lapic->x2APIC) + { + wrmsr(MSR_X2APIC_LVT_TIMER, 0x10000 /* LVTTimer.Mask flag */); + Ticks = 0xFFFFFFFF - rdmsr(MSR_X2APIC_CUR_COUNT); + } + else + { + this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */); + Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR); + } // Config for IRQ0 timer - LVTTimer timer = {.raw = 0}; - timer.Vector = IRQ0; - timer.Mask = Unmasked; - timer.TimerMode = LVTTimerMode::OneShot; + LVTTimer timer{}; + timer.VEC = IRQ0; + timer.M = Unmasked; + timer.TMM = LVTTimerMode::OneShot; // Initialize APIC timer - this->lapic->Write(APIC_TDCR, Divider); - this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks)); - this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw)); - trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks); + if (this->lapic->x2APIC) + { + wrmsr(MSR_X2APIC_DIV_CONF, Divider); + wrmsr(MSR_X2APIC_INIT_COUNT, Ticks); + wrmsr(MSR_X2APIC_LVT_TIMER, timer.raw); + } + else + { + this->lapic->Write(APIC_TDCR, Divider); + this->lapic->Write(APIC_TICR, uint32_t(Ticks)); + this->lapic->Write(APIC_TIMER, uint32_t(timer.raw)); + } + + trace("%d APIC Timer %d ticks in.", + GetCurrentCPU()->ID, Ticks); KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks); } diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index f730f20..83fd80e 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -53,7 +53,15 @@ SafeFunction CPUData *GetCurrentCPU() if (unlikely(!Interrupts::apic[0])) return &CPUs[0]; /* No APIC means we are on the BSP. */ - int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24; + APIC::APIC *apic = (APIC::APIC *)Interrupts::apic[0]; + int CoreID = 0; + if (CPUEnabled.load(std::memory_order_acquire) == true) + { + if (apic->x2APIC) + CoreID = int(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID)); + else + CoreID = apic->Read(APIC::APIC_ID) >> 24; + } if (unlikely((&CPUs[CoreID])->IsActive != true)) { @@ -94,18 +102,23 @@ namespace SMP int Cores = madt->CPUCores + 1; if (Config.Cores > madt->CPUCores + 1) - KPrint("More cores requested than available. Using %d cores", madt->CPUCores + 1); + KPrint("More cores requested than available. Using %d cores", + madt->CPUCores + 1); else if (Config.Cores != 0) Cores = Config.Cores; CPUCores = Cores; - uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start; + uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - + (uintptr_t)&_trampoline_start; Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW); /* We reserved the TRAMPOLINE_START address inside Physical class. */ - Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW); + Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, + TrampolineLength, Memory::PTFlag::RW); memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength); - debug("Trampoline address: %#lx-%#lx", TRAMPOLINE_START, TRAMPOLINE_START + TrampolineLength); + debug("Trampoline address: %#lx-%#lx", + TRAMPOLINE_START, + TRAMPOLINE_START + TrampolineLength); void *CPUTmpStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); asmv("sgdt [0x580]"); @@ -117,26 +130,39 @@ namespace SMP for (int i = 0; i < Cores; i++) { ACPI::MADT::LocalAPIC *lapic = madt->lapic[i]; + APIC::APIC *apic = (APIC::APIC *)Interrupts::apic[0]; + debug("Initializing CPU %d", lapic->APICId); - if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != lapic->APICId) + uint8_t APIC_ID = 0; + if (apic->x2APIC) + APIC_ID = uint8_t(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID)); + else + APIC_ID = uint8_t(apic->Read(APIC::APIC_ID) >> 24); + + if (APIC_ID != lapic->APICId) { VPOKE(int, CORE) = i; + if (!apic->x2APIC) + { + APIC::InterruptCommandRegister icr{}; + icr.MT = APIC::INIT; + icr.DES = lapic->APICId; + apic->ICR(icr); + } - ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (lapic->APICId << 24)); - ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500); - - ((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(lapic->APICId); - TimeManager->Sleep(5, Time::Units::Milliseconds); - ((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(lapic->APICId, TRAMPOLINE_START); - + apic->SendInitIPI(lapic->APICId); + TimeManager->Sleep(20, Time::Units::Milliseconds); + apic->SendStartupIPI(lapic->APICId, TRAMPOLINE_START); debug("Waiting for CPU %d to load...", lapic->APICId); + uint64_t Timeout = TimeManager->CalculateTarget(2, Time::Units::Seconds); while (CPUEnabled.load(std::memory_order_acquire) == false) { if (TimeManager->GetCounter() > Timeout) { error("CPU %d failed to load!", lapic->APICId); - KPrint("\eFF8C19CPU \e8888FF%d \eFF8C19failed to load!", lapic->APICId); + KPrint("\eFF8C19CPU \e8888FF%d \eFF8C19failed to load!", + lapic->APICId); break; } CPU::Pause(); diff --git a/Architecture/amd64/cpu/apic.hpp b/Architecture/amd64/cpu/apic.hpp index a69b6d9..34aae7f 100644 --- a/Architecture/amd64/cpu/apic.hpp +++ b/Architecture/amd64/cpu/apic.hpp @@ -27,32 +27,66 @@ namespace APIC { enum APICRegisters { - // source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c - APIC_ID = 0x20, // Local APIC ID - APIC_VER = 0x30, // Local APIC Version - APIC_TPR = 0x80, // Task Priority - APIC_APR = 0x90, // Arbitration Priority - APIC_PPR = 0xA0, // Processor Priority - APIC_EOI = 0xB0, // EOI - APIC_RRD = 0xC0, // Remote Read - APIC_LDR = 0xD0, // Logical Destination - APIC_DFR = 0xE0, // Destination Format - APIC_SVR = 0xF0, // Spurious Interrupt Vector - APIC_ISR = 0x100, // In-Service (8 registers) - APIC_TMR = 0x180, // Trigger Mode (8 registers) - APIC_IRR = 0x200, // Interrupt Request (8 registers) - APIC_ESR = 0x280, // Error Status - APIC_ICRLO = 0x300, // Interrupt Command - APIC_ICRHI = 0x310, // Interrupt Command [63:32] - APIC_TIMER = 0x320, // LVT Timer - APIC_THERMAL = 0x330, // LVT Thermal Sensor - APIC_PERF = 0x340, // LVT Performance Counter - APIC_LINT0 = 0x350, // LVT LINT0 - APIC_LINT1 = 0x360, // LVT LINT1 - APIC_ERROR = 0x370, // LVT Error - APIC_TICR = 0x380, // Initial Count (for Timer) - APIC_TCCR = 0x390, // Current Count (for Timer) - APIC_TDCR = 0x3E0, // Divide Configuration (for Timer) + /* APIC ID Register */ + APIC_ID = 0x20, + /* APIC Version Register */ + APIC_VER = 0x30, + /* Task Priority Register (TPR) */ + APIC_TPR = 0x80, + /* Arbitration Priority Register (APR) */ + APIC_APR = 0x90, + /* Processor Priority Register (PPR) */ + APIC_PPR = 0xA0, + /* End of Interrupt Register (EOI) */ + APIC_EOI = 0xB0, + /* Remote Read Register */ + APIC_RRD = 0xC0, + /* Logical Destination Register (LDR) */ + APIC_LDR = 0xD0, + /* Destination Format Register (DFR) */ + APIC_DFR = 0xE0, + /* Spurious Interrupt Vector Register */ + APIC_SVR = 0xF0, + /* In-Service Register (ISR) */ + APIC_ISR = 0x100, + /* Trigger Mode Register (TMR) */ + APIC_TMR = 0x180, + /* Interrupt Request Register (IRR) */ + APIC_IRR = 0x200, + /* Error Status Register (ESR) */ + APIC_ESR = 0x280, + /* Interrupt Command Register Low (bits 31:0) */ + APIC_ICRLO = 0x300, + /* Interrupt Command Register High (bits 63:32) */ + APIC_ICRHI = 0x310, + /* Timer Local Vector Table Entry */ + APIC_TIMER = 0x320, + /* Thermal Local Vector Table Entry */ + APIC_THERMAL = 0x330, + /* Performance Counter Local Vector Table Entry */ + APIC_PERF = 0x340, + /* Local Interrupt 0 Vector Table Entry */ + APIC_LINT0 = 0x350, + /* Local Interrupt 1 Vector Table Entry */ + APIC_LINT1 = 0x360, + /* Error Vector Table Entry */ + APIC_ERROR = 0x370, + /* Timer Initial Count Register */ + APIC_TICR = 0x380, + /* Timer Current Count Register */ + APIC_TCCR = 0x390, + /* Timer Divide Configuration Register */ + APIC_TDCR = 0x3E0, + /* Extended APIC Feature Register */ + APIC_EFR = 0x400, + /* Extended APIC Control Register */ + APIC_ECR = 0x410, + /* Specific End of Interrupt Register (SEOI) */ + APIC_SEOI = 0x420, + /* Interrupt Enable Registers (IER) */ + APIC_IER0 = 0x480, + /* Extended Interrupt [3:0] Local Vector Table Registers */ + APIC_EILVT0 = 0x500, }; enum IOAPICRegisters @@ -66,12 +100,12 @@ namespace APIC EdgeLevel = 8 }; - enum APICDeliveryMode + enum APICMessageType { Fixed = 0b000, LowestPriority = 0b001, /* Reserved */ SMI = 0b010, - APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */ + DeliveryMode = 0b011, /* Reserved */ NMI = 0b100, INIT = 0b101, Startup = 0b110, @@ -139,163 +173,153 @@ namespace APIC { struct { - /** @brief Interrupt Vector */ - uint64_t Vector : 8; - /** @brief Reserved */ + /** Vector */ + uint64_t VEC : 8; + /** Reserved */ uint64_t Reserved0 : 4; - /** - * @brief Delivery Status - * - * 0: Idle - * 1: Send Pending - */ - uint64_t DeliveryStatus : 1; - /** @brief Reserved */ + /** Delivery Status */ + uint64_t DS : 1; + /** Reserved */ uint64_t Reserved1 : 3; - /** - * @brief Mask - * - * 0: Not masked - * 1: Masked - */ - uint64_t Mask : 1; - /** @brief Timer Mode - * - * 0: One-shot - * 1: Periodic - * 2: TSC-Deadline - */ - uint64_t TimerMode : 1; - /** @brief Reserved */ + /** Mask */ + uint64_t M : 1; + /** Timer Mode */ + uint64_t TMM : 1; + /** Reserved */ uint64_t Reserved2 : 14; }; - uint64_t raw; + uint32_t raw; } __packed LVTTimer; typedef union { struct { - /** @brief Spurious Vector */ - uint64_t Vector : 8; - /** @brief Enable or disable APIC software */ - uint64_t Software : 1; - /** @brief Focus Processor Checking */ - uint64_t FocusProcessorChecking : 1; - /** @brief Reserved */ - uint64_t Reserved : 2; - /** @brief Disable EOI Broadcast */ - uint64_t DisableEOIBroadcast : 1; - /** @brief Reserved */ - uint64_t Reserved1 : 19; + /** Vector */ + uint64_t VEC : 8; + /** APIC Software Enable */ + uint64_t ASE : 1; + /** Focus CPU Core Checking */ + uint64_t FCC : 1; + /** Reserved */ + uint64_t Reserved0 : 22; }; - uint64_t raw; + uint32_t raw; } __packed Spurious; typedef union { struct { - /** @brief Interrupt Vector */ - uint64_t Vector : 8; - /** @brief Delivery Mode */ - uint64_t DeliveryMode : 3; - /** @brief Destination Mode - * - * 0: Physical - * 1: Logical - */ - uint64_t DestinationMode : 1; - /** @brief Delivery Status - * - * @note Reserved when in x2APIC mode - */ - uint64_t DeliveryStatus : 1; - /** @brief Reserved */ + /** Vector */ + uint64_t VEC : 8; + /** Message Type */ + uint64_t MT : 3; + /** Destination Mode */ + uint64_t DM : 1; + /** Delivery Status */ + uint64_t DS : 1; + /** Reserved */ uint64_t Reserved0 : 1; - /** @brief Level - * - * 0: Deassert - * 1: Assert - */ - uint64_t Level : 1; - /** @brief Trigger Mode - * - * 0: Edge - * 1: Level - */ - uint64_t TriggerMode : 1; - /** @brief Reserved */ + /** Level */ + uint64_t L : 1; + /** Trigger Mode */ + uint64_t TGM : 1; + /** Remote Read Status */ + uint64_t RSS : 2; + /** Destination Shorthand */ + uint64_t DSH : 2; + /** Reserved */ + uint64_t Reserved2 : 36; + /** Destination */ + uint64_t DES : 8; + }; + struct + { + /** Vector */ + uint64_t VEC : 8; + /** Message Type */ + uint64_t MT : 3; + /** Destination Mode */ + uint64_t DM : 1; + /** Reserved */ + uint64_t Reserved0 : 2; + /** Level */ + uint64_t L : 1; + /** Trigger Mode */ + uint64_t TGM : 1; + /** Reserved */ uint64_t Reserved1 : 2; - /** @brief Destination Shorthand - * - * 0: No shorthand - * 1: Self - * 2: All including self - * 3: All excluding self - */ - uint64_t DestinationShorthand : 2; - /** @brief Reserved */ + /** Destination Shorthand */ + uint64_t DSH : 2; + /** Reserved */ uint64_t Reserved2 : 12; - }; + /** Destination */ + uint64_t DES : 32; + } x2; + struct + { + uint32_t Low; + uint32_t High; + } split; uint64_t raw; - } __packed InterruptCommandRegisterLow; + } __packed InterruptCommandRegister; typedef union { struct { - /** @brief Reserved */ - uint64_t Reserved0 : 24; - /** @brief Destination */ - uint64_t Destination : 8; + /** Reserved */ + uint64_t Reserved0 : 2; + /** Sent Accept Error */ + uint64_t SAE : 1; + /** Receive Accept Error */ + uint64_t RAE : 1; + /** Reserved */ + uint64_t Reserved1 : 1; + /** Sent Illegal Vector */ + uint64_t SIV : 1; + /** Received Illegal Vector */ + uint64_t RIV : 1; + /** Illegal Register Address */ + uint64_t IRA : 1; + /** Reserved */ + uint64_t Reserved2 : 24; }; - uint64_t raw; - } __packed InterruptCommandRegisterHigh; + uint32_t raw; + } ErrorStatusRegister; typedef union { struct { - /** @brief Interrupt Vector */ - uint64_t Vector : 8; - /** @brief Delivery Mode */ - uint64_t DeliveryMode : 3; - /** @brief Destination Mode - * - * 0: Physical - * 1: Logical - */ - uint64_t DestinationMode : 1; - /** @brief Delivery Status */ - uint64_t DeliveryStatus : 1; - /** @brief Interrupt Input Pin Polarity - * - * 0: Active High - * 1: Active Low - */ - uint64_t Polarity : 1; - /** @brief Remote IRR */ - uint64_t RemoteIRR : 1; - /** @brief Trigger Mode - * - * 0: Edge - * 1: Level - */ - uint64_t TriggerMode : 1; - /** @brief Mask */ - uint64_t Mask : 1; - /** @brief Reserved */ + /** Interrupt Vector */ + uint64_t VEC : 8; + /** Delivery Mode */ + uint64_t MT : 3; + /** Destination Mode */ + uint64_t DM : 1; + /** Delivery Status */ + uint64_t DS : 1; + /** Interrupt Input Pin Polarity */ + uint64_t IPP : 1; + /** Remote IRR */ + uint64_t RIR : 1; + /** Trigger Mode */ + uint64_t TGM : 1; + /** Mask */ + uint64_t M : 1; + /** Reserved */ uint64_t Reserved0 : 15; - /** @brief Reserved */ + /** Reserved */ uint64_t Reserved1 : 24; - /** @brief Destination */ - uint64_t DestinationID : 8; + /** Destination */ + uint64_t DES : 8; }; struct { - uint64_t Low; - uint64_t High; + uint32_t Low; + uint32_t High; } split; uint64_t raw; } __packed IOAPICRedirectEntry; @@ -304,12 +328,18 @@ namespace APIC { struct { - uint64_t Version : 8; - uint64_t Reserved : 8; - uint64_t MaximumRedirectionEntry : 8; - uint64_t Reserved2 : 8; + /** Version */ + uint64_t VER : 8; + /** Reserved */ + uint64_t Reserved0 : 8; + /** Max LVT Entries */ + uint64_t MLE : 8; + /** Reserved */ + uint64_t Reserved1 : 7; + /** Extended APIC Register Space Present */ + uint64_t EAS : 1; }; - uint64_t raw; + uint32_t raw; } __packed IOAPICVersion; class APIC @@ -319,19 +349,21 @@ namespace APIC uint64_t APICBaseAddress = 0; public: + decltype(x2APICSupported) &x2APIC = x2APICSupported; + uint32_t Read(uint32_t Register); void Write(uint32_t Register, uint32_t Value); void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value); uint32_t IORead(uint64_t Base, uint32_t Register); void EOI(); - void RedirectIRQs(int CPU = 0); + void RedirectIRQs(uint8_t CPU = 0); void WaitForIPI(); - void IPI(int CPU, InterruptCommandRegisterLow icr); + void ICR(InterruptCommandRegister icr); void SendInitIPI(int CPU); void SendStartupIPI(int CPU, uint64_t StartupAddress); uint32_t IOGetMaxRedirect(uint32_t APICID); - void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); - void RedirectIRQ(int CPU, uint16_t IRQ, int Status); + void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, uint8_t CPU, int Status); + void RedirectIRQ(uint8_t CPU, uint8_t IRQ, int Status); APIC(int Core); ~APIC(); }; diff --git a/Core/CPU.cpp b/Core/CPU.cpp index 99aa71c..12c720a 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -267,12 +267,10 @@ namespace CPU cr4.OSXMMEXCPT = 1; CPUData *CoreData = GetCPU(Core); - CoreData->Data.FPU = (CPU::x64::FXState *)KernelAllocator.RequestPages(TO_PAGES(sizeof(CPU::x64::FXState) + 1)); - memset(CoreData->Data.FPU, 0, FROM_PAGES(TO_PAGES(sizeof(CPU::x64::FXState)))); - CoreData->Data.FPU->mxcsr = 0b0001111110000000; - CoreData->Data.FPU->mxcsrmask = 0b1111111110111111; - CoreData->Data.FPU->fcw = 0b0000001100111111; - CPU::x64::fxrstor(CoreData->Data.FPU); + CoreData->Data.FPU.mxcsr = 0b0001111110000000; + CoreData->Data.FPU.mxcsrmask = 0b1111111110111111; + CoreData->Data.FPU.fcw = 0b0000001100111111; + CPU::x64::fxrstor(&CoreData->Data.FPU); SSEEnableAfter = true; } diff --git a/Core/DifferentiatedSystemDescriptionTable.cpp b/Core/DifferentiatedSystemDescriptionTable.cpp index ab375c3..d285b69 100644 --- a/Core/DifferentiatedSystemDescriptionTable.cpp +++ b/Core/DifferentiatedSystemDescriptionTable.cpp @@ -263,7 +263,7 @@ namespace ACPI } } - ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); + ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, uint8_t(acpi->FADT->SCI_Interrupt), 1); return; } warn("Failed to parse _S5 in ACPI"); diff --git a/Core/InterruptsManager.cpp b/Core/InterruptsManager.cpp index 69258a3..a996ea1 100644 --- a/Core/InterruptsManager.cpp +++ b/Core/InterruptsManager.cpp @@ -110,7 +110,7 @@ namespace Interrupts // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. apic[Core] = new APIC::APIC(Core); if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core. - ((APIC::APIC *)apic[Core])->RedirectIRQs(Core); + ((APIC::APIC *)apic[Core])->RedirectIRQs(uint8_t(Core)); } else { @@ -168,7 +168,8 @@ namespace Interrupts Core = CoreData->ID; /* If this is false, we have a big problem. */ - if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0)) + if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && + Frame->InterruptNumber > CPU::x86::ISR0)) { /* Halt core interrupt */ if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29)) @@ -201,7 +202,8 @@ namespace Interrupts if (likely(apic[Core])) { - ((APIC::APIC *)Interrupts::apic[Core])->EOI(); + APIC::APIC *this_apic = (APIC::APIC *)apic[Core]; + this_apic->EOI(); // TODO: Handle PIC too return; } diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 04f9105..97736be 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -349,7 +349,7 @@ static int sys_fork(SysFrm *Frame) ReturnAddress = Frame->ReturnAddress; ChildStackPointer = Frame->StackPointer; - memcpy(NewThread->FPU, Thread->FPU, sizeof(CPU::x64::FXState)); + memcpy(&NewThread->FPU, &Thread->FPU, sizeof(CPU::x64::FXState)); NewThread->Stack->Fork(Thread->Stack); NewThread->Info = Thread->Info; NewThread->Registers = Thread->Registers; diff --git a/Tasking/Scheduler.cpp b/Tasking/Scheduler.cpp index 167dc90..07a6702 100644 --- a/Tasking/Scheduler.cpp +++ b/Tasking/Scheduler.cpp @@ -525,7 +525,7 @@ namespace Tasking else { CurrentCPU->CurrentThread->Registers = *Frame; - CPU::x64::fxsave(CurrentCPU->CurrentThread->FPU); + CPU::x64::fxsave(&CurrentCPU->CurrentThread->FPU); CurrentCPU->CurrentThread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); @@ -616,7 +616,7 @@ namespace Tasking /* Not sure if this is needed, but it's better to be safe than sorry. */ asmv("movq %cr3, %rax"); asmv("movq %rax, %cr3"); - CPU::x64::fxrstor(CurrentCPU->CurrentThread->FPU); + CPU::x64::fxrstor(&CurrentCPU->CurrentThread->FPU); CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); diff --git a/Tasking/Thread.cpp b/Tasking/Thread.cpp index 080ac82..7000a4e 100644 --- a/Tasking/Thread.cpp +++ b/Tasking/Thread.cpp @@ -458,27 +458,10 @@ namespace Tasking this->Security.ExecutionMode = this->Parent->Security.ExecutionMode; - std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1); - this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs); - memset(this->FPU, 0, sizeof(CPU::x64::FXState)); - // TODO: Is really a good idea to use the FPU in kernel mode? - this->FPU->mxcsr = 0b0001111110000000; - this->FPU->mxcsrmask = 0b1111111110111111; - this->FPU->fcw = 0b0000001100111111; - - // CPU::x64::fxrstor(this->FPU); - // uint16_t FCW = 0b1100111111; - // asmv("fldcw %0" - // : - // : "m"(FCW) - // : "memory"); - // uint32_t MXCSR = 0b1111110000000; - // asmv("ldmxcsr %0" - // : - // : "m"(MXCSR) - // : "memory"); - // CPU::x64::fxsave(this->FPU); + this->FPU.mxcsr = 0b0001111110000000; + this->FPU.mxcsrmask = 0b1111111110111111; + this->FPU.fcw = 0b0000001100111111; #ifdef DEBUG #ifdef a64 diff --git a/include/cpu.hpp b/include/cpu.hpp index c9870d3..48c8eb7 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -534,27 +534,36 @@ namespace CPU { struct { - /** @brief Reserved */ - uint32_t Reserved0 : 8; - /** - * @brief BSP Flag - * @details If the BSP flag is set to 1, the processor is the bootstrap processor. - */ - uint32_t BSP : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 1; - /** @brief Enable x2APIC mode */ - uint32_t EXTD : 1; - /** @brief APIC Global Enable */ - uint32_t EN : 1; + /** Reserved */ + uint64_t Reserved0 : 8; + /** Boot Strap CPU Core */ + uint64_t BSC : 1; + /** Reserved */ + uint64_t Reserved1 : 1; + /** x2APIC Mode Enable */ + uint64_t EXTD : 1; + /** APIC Enable */ + uint64_t AE : 1; /** @brief APIC Base Low Address */ - uint32_t ApicBaseLo : 20; + uint64_t ABALow : 20; /** @brief APIC Base High Address */ - uint32_t ApicBaseHi : 32; + uint64_t ABAHigh : 32; + /** Reserved */ + uint64_t Reserved2 : 12; }; uint64_t raw; } __packed APIC_BASE; + typedef union + { + struct + { + uint64_t Reserved : 24; + uint64_t AID : 8; + }; + uint32_t raw; + } __packed APIC_ID; + typedef union { struct diff --git a/include/smp.hpp b/include/smp.hpp index d346784..d29f221 100644 --- a/include/smp.hpp +++ b/include/smp.hpp @@ -30,43 +30,41 @@ struct CPUArchData { #if defined(a64) - CPU::x64::FXState *FPU; - /* TODO */ + __aligned(16) CPU::x64::FXState FPU{}; #elif defined(a32) - CPU::x32::FXState *FPU; - /* TODO */ + __aligned(16) CPU::x32::FXState FPU{}; #elif defined(aa64) #endif }; struct CPUData { - /** @brief Used by CPU */ - uintptr_t Stack; + /** @brief Used by CPU */ + uintptr_t Stack; - /** @brief CPU ID. */ - int ID; + /** @brief CPU ID. */ + int ID; - /** @brief Local CPU error code. */ - long ErrorCode; + /** @brief Local CPU error code. */ + long ErrorCode; - /** @brief Current running process */ - std::atomic CurrentProcess; + /** @brief Current running process */ + std::atomic CurrentProcess; - /** @brief Current running thread */ - std::atomic CurrentThread; + /** @brief Current running thread */ + std::atomic CurrentThread; - /** @brief Unwind data */ - __cxa_eh_globals EHGlobals; + /** @brief Unwind data */ + __cxa_eh_globals EHGlobals; - /** @brief Architecture-specific data. */ - CPUArchData Data; + /** @brief Architecture-specific data. */ + CPUArchData Data; - /** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */ - int Checksum; + /** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */ + int Checksum; - /** @brief Is CPU online? */ - bool IsActive; + /** @brief Is CPU online? */ + bool IsActive; } __aligned(16); CPUData *GetCurrentCPU(); @@ -74,8 +72,8 @@ CPUData *GetCPU(long ID); namespace SMP { - extern int CPUCores; - void Initialize(void *madt); + extern int CPUCores; + void Initialize(void *madt); } #endif // !__FENNIX_KERNEL_SMP_H__ diff --git a/include/task.hpp b/include/task.hpp index 7990641..7e6afa4 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -198,7 +198,7 @@ namespace Tasking uintptr_t Registers; // TODO #endif uintptr_t IPHistory[128]; - CPU::x64::FXState *FPU; + __aligned(16) CPU::x64::FXState FPU; /* Info & Security info */ struct