From c944f57a3b76dc6420a7e949be1db97ecad8c913 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Oct 2022 04:05:44 +0300 Subject: [PATCH] APIC implementation (not working as expected) --- ...AdvancedConfigurationandPowerInterface.cpp | 11 +- .../DifferentiatedSystemDescriptionTable.cpp | 121 +++++++----------- .../amd64/MultipleAPICDescriptionTable.cpp | 1 + Architecture/amd64/acpi.hpp | 4 - ...dvancedProgrammableInterruptController.cpp | 94 +++++++++++--- .../amd64/cpu/GlobalDescriptorTable.cpp | 5 +- .../amd64/cpu/SymmetricMultiprocessing.cpp | 29 ++--- Architecture/amd64/cpu/apic.hpp | 15 ++- Core/CPU.cpp | 4 +- Core/CrashHandler.cpp | 3 +- Core/Interrupts/IntManager.cpp | 64 ++++++--- Core/Power.cpp | 49 ++++++- Kernel.cpp | 9 +- include/interrupts.hpp | 10 +- include/power.hpp | 6 +- 15 files changed, 272 insertions(+), 153 deletions(-) diff --git a/Architecture/amd64/AdvancedConfigurationandPowerInterface.cpp b/Architecture/amd64/AdvancedConfigurationandPowerInterface.cpp index 3205334..81b3011 100644 --- a/Architecture/amd64/AdvancedConfigurationandPowerInterface.cpp +++ b/Architecture/amd64/AdvancedConfigurationandPowerInterface.cpp @@ -30,7 +30,7 @@ namespace ACPI } } // warn("%s not found!", Signature); - return 0; + return nullptr; } void ACPI::SearchTables(ACPIHeader *Header) @@ -116,9 +116,12 @@ namespace ACPI this->SearchTables(XSDT); - outb(FADT->SMI_CommandPort, FADT->AcpiEnable); - while (!(inw(FADT->PM1aControlBlock) & 1)) - ; + if (FADT) + { + outb(FADT->SMI_CommandPort, FADT->AcpiEnable); + while (!(inw(FADT->PM1aControlBlock) & 1)) + ; + } } ACPI::~ACPI() diff --git a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp index a009a0e..23c51b8 100644 --- a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp +++ b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp @@ -32,11 +32,27 @@ namespace ACPI void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *Frame) { debug("SCI Handle Triggered"); - uint16_t event = this->GetSCIevent(); - debug("SCI Event: %#llx", event); - if (event & ACPI_TIMER) - event &= ~ACPI_TIMER; // Remove the ACPI timer flag. - switch (event) + uint16_t Event = 0; + + { + uint16_t a = 0, b = 0; + if (acpi->FADT->PM1aEventBlock) + { + a = inw(acpi->FADT->PM1aEventBlock); + outw(acpi->FADT->PM1aEventBlock, a); + } + if (acpi->FADT->PM1bEventBlock) + { + b = inw(acpi->FADT->PM1bEventBlock); + outw(acpi->FADT->PM1bEventBlock, b); + } + Event = a | b; + } + + debug("SCI Event: %#llx", Event); + if (Event & ACPI_TIMER) + Event &= ~ACPI_TIMER; // Remove the ACPI timer flag. + switch (Event) { case ACPI_POWER_BUTTON: { @@ -52,7 +68,7 @@ namespace ACPI } default: { - warn("unknown event 0x%04p", event); + warn("unknown event 0x%04p", Event); return; } } @@ -62,13 +78,7 @@ namespace ACPI void DSDT::Shutdown() { trace("Shutting down..."); - if (!ACPIShutdownSupported) - { - outl(0xB004, 0x2000); // for qemu - outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu - outl(0x4004, 0x3400); // virtual box - } - else if (SCI_EN == 1) + if (SCI_EN == 1) { outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP)); if (acpi->FADT->PM1bControlBlock) @@ -77,35 +87,11 @@ namespace ACPI if (PM1b_CNT) outw(PM1b_CNT, SLP_TYPb | SLP_EN); } - CPU::Stop(); } void DSDT::Reboot() { trace("Rebooting..."); - if (!ACPIShutdownSupported) - { - uint8_t val = 0x02; - while (val & 0x02) - val = inb(0x64); - outb(0x64, 0xFE); - - warn("Executing the second attempt to reboot..."); - - // second attempt to reboot - // https://wiki.osdev.org/Reboot - uint8_t temp; - asm volatile("cli"); - do - { - temp = inb(0x64); - if (((temp) & (1 << (0))) != 0) - inb(0x60); - } while (((temp) & (1 << (1))) != 0); - outb(0x64, 0xFE); - - CPU::Stop(); - } switch (acpi->FADT->ResetReg.AddressSpace) { case ACPI_GAS_MMIO: @@ -126,39 +112,6 @@ namespace ACPI */ break; } - CPU::Stop(); - } - - uint16_t DSDT::GetSCIevent() - { - uint16_t a = 0, b = 0; - if (acpi->FADT->PM1aEventBlock) - { - a = inw(acpi->FADT->PM1aEventBlock); - outw(acpi->FADT->PM1aEventBlock, a); - } - if (acpi->FADT->PM1bEventBlock) - { - b = inw(acpi->FADT->PM1bEventBlock); - outw(acpi->FADT->PM1bEventBlock, b); - } - return a | b; - } - - void DSDT::SetSCIevent(uint16_t value) - { - uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2); - uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2); - if (acpi->FADT->PM1aEventBlock) - outw(a, value); - if (acpi->FADT->PM1bEventBlock) - outw(b, value); - } - - void DSDT::RegisterSCIEvents() - { - this->SetSCIevent(ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE); - GetSCIevent(); } DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0) @@ -199,8 +152,32 @@ namespace ACPI SCI_EN = 1; trace("ACPI Shutdown is supported"); ACPIShutdownSupported = true; - this->RegisterSCIEvents(); - ((APIC::APIC *)Interrupts::apic)->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); + + uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE; + { + uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2); + uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2); + debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b); + if (acpi->FADT->PM1aEventBlock) + outw(a, value); + if (acpi->FADT->PM1bEventBlock) + outw(b, value); + } + + { + uint16_t a = 0, b = 0; + if (acpi->FADT->PM1aEventBlock) + { + a = inw(acpi->FADT->PM1aEventBlock); + outw(acpi->FADT->PM1aEventBlock, a); + } + if (acpi->FADT->PM1bEventBlock) + { + b = inw(acpi->FADT->PM1bEventBlock); + outw(acpi->FADT->PM1bEventBlock, b); + } + } + ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); return; } warn("Failed to parse _S5 in ACPI"); diff --git a/Architecture/amd64/MultipleAPICDescriptionTable.cpp b/Architecture/amd64/MultipleAPICDescriptionTable.cpp index 9bb2e5c..b1d4e9f 100644 --- a/Architecture/amd64/MultipleAPICDescriptionTable.cpp +++ b/Architecture/amd64/MultipleAPICDescriptionTable.cpp @@ -9,6 +9,7 @@ namespace ACPI { MADT::MADT(ACPI::MADTHeader *madt) { + trace("Initializing MADT"); CPUCores = 0; LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress; for (uint8_t *ptr = (uint8_t *)(madt->Entries); diff --git a/Architecture/amd64/acpi.hpp b/Architecture/amd64/acpi.hpp index affd209..6a2f25c 100644 --- a/Architecture/amd64/acpi.hpp +++ b/Architecture/amd64/acpi.hpp @@ -273,10 +273,6 @@ namespace ACPI public: bool ACPIShutdownSupported = false; - void RegisterSCIEvents(); - void SetSCIevent(uint16_t value); - uint16_t GetSCIevent(); - void Reboot(); void Shutdown(); diff --git a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp index dd35e51..28f2f16 100644 --- a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp +++ b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp @@ -1,7 +1,9 @@ #include "apic.hpp" +#include #include #include +#include #include "../../../kernel.h" #include "../acpi.hpp" @@ -33,14 +35,7 @@ namespace APIC uint32_t APIC::Read(uint32_t Register) { - // Too repetitive - if (Register != APIC_EOI && - Register != APIC_ID && - Register != APIC_TIMER && - Register != APIC_TDCR && - Register != APIC_TICR && - Register != APIC_TCCR) - debug("APIC::Read(%#lx)", Register); + debug("APIC::Read(%#lx)", Register); if (x2APICSupported) { if (Register != APIC_ICRHI) @@ -54,13 +49,7 @@ namespace APIC void APIC::Write(uint32_t Register, uint32_t Value) { - // Too repetitive - if (Register != APIC_EOI && - Register != APIC_TIMER && - Register != APIC_TDCR && - Register != APIC_TICR && - Register != APIC_TCCR) - debug("APIC::Write(%#lx, %#lx)", Register, Value); + debug("APIC::Write(%#lx, %#lx)", Register, Value); if (x2APICSupported) { if (Register != APIC_ICRHI) @@ -176,7 +165,7 @@ namespace APIC this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status); } - APIC::APIC() + APIC::APIC(int Core) { uint32_t rcx; CPU::x64::cpuid(1, 0, 0, &rcx, 0); @@ -195,9 +184,82 @@ namespace APIC 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) + { + this->Write(APIC_DFR, 0xF0000000); + this->Write(APIC_LDR, this->Read(APIC_ID)); + } + + 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; + + uint32_t nmi = 0x402; + if (madt->nmi[i]->flags & 2) + nmi |= 1 << 13; + if (madt->nmi[i]->flags & 8) + nmi |= 1 << 15; + if (madt->nmi[i]->lint == 0) + this->Write(0x350, nmi); + else if (madt->nmi[i]->lint == 1) + this->Write(0x360, nmi); + } } APIC::~APIC() { } + + void Timer::OnInterruptReceived(CPU::x64::TrapFrame *Frame) + { + fixme("APIC IRQ0 INTERRUPT RECEIVED ON CPU %d", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE)); + } + + Timer::Timer(APIC *apic) : Interrupts::Handler(CPU::x64::IRQ0) + { + trace("Initializing APIC timer on CPU %d", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE)); + apic->Write(APIC::APIC::APIC_TDCR, 0x3); + + int IOIn = inb(0x61); + IOIn = (IOIn & 0xFD) | 1; + outb(0x61, IOIn); + outb(0x43, 0b10110010); + outb(0x42, 155); + inb(0x60); + outb(0x42, 46); + + apic->Write(APIC::APIC::APIC_TICR, 0xFFFFFFFF); + + IOIn = inb(0x61); + IOIn = (IOIn & 0xFC); + outb(0x61, IOIn); + IOIn |= 1; + outb(0x61, IOIn); + uint32_t Loop = 0; + while ((inb(0x61) & 0x20) != 0) + ++Loop; + + apic->Write(APIC::APIC::APIC_TIMER, 0x10000); + + outb(0x43, 0x28); + outb(0x40, 0x0); + + outb(0x21, 0xFF); + outb(0xA1, 0xFF); + + uint64_t ticksIn10ms = 0xFFFFFFFF - apic->Read(APIC::APIC::APIC_TCCR); + + apic->Write(APIC::APIC::APIC_TIMER, (long)CPU::x64::IRQ0 | (long)APIC::APIC::APICRegisters::APIC_PERIODIC); + apic->Write(APIC::APIC::APIC_TDCR, 0x3); + apic->Write(APIC::APIC::APIC_TICR, ticksIn10ms); + debug("APIC Timer (CPU %d): %d ticks in 10ms", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), ticksIn10ms); + } + + Timer::~Timer() + { + } } diff --git a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp index b938012..e99f895 100644 --- a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp @@ -40,10 +40,7 @@ namespace GlobalDescriptorTable "1:\n" "movw $16, %%ax\n" "movw %%ax, %%ds\n" - "movw %%ax, %%es\n" - "movw $0x1b, %%ax\n" - "movw %%ax, %%fs\n" - "movw %%ax, %%gs\n" :: + "movw %%ax, %%es\n" :: : "memory", "rax"); uint64_t Base = (uint64_t)&tss[Core]; diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index a6d922e..0b3fb17 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -23,6 +23,7 @@ enum SMPTrampolineAddress STACK = 0x570, GDT = 0x580, IDT = 0x590, + CORE = 0x600 }; volatile bool CPUEnabled = false; @@ -36,7 +37,7 @@ CPUData *GetCurrentCPU() { uint64_t ret = 0; #if defined(__amd64__) - ret = ((APIC::APIC *)Interrupts::apic)->Read(APIC::APIC::APIC_ID) >> 24; + ret = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); #elif defined(__i386__) #elif defined(__aarch64__) #endif @@ -59,18 +60,14 @@ extern "C" void StartCPU() { CPU::Interrupts(CPU::Disable); CPU::InitializeFeatures(); - - // Enable APIC - CPU::x64::wrmsr(CPU::x64::MSR_APIC_BASE, (CPU::x64::rdmsr(CPU::x64::MSR_APIC_BASE) | 0x800) & ~(1 << 10)); - ((APIC::APIC *)Interrupts::apic)->Write(APIC::APIC::APIC_SVR, ((APIC::APIC *)Interrupts::apic)->Read(APIC::APIC::APIC_SVR) | 0x1FF); - - uint64_t CPU_ID; - // Set CPU_ID variable using APIC - CPU_ID = ((APIC::APIC *)Interrupts::apic)->Read(APIC::APIC::APIC_ID) >> 24; + uintptr_t CoreID = CORE; + CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, (int)*reinterpret_cast(CoreID)); + uint64_t CPU_ID = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); // Initialize GDT and IDT Interrupts::Initialize(CPU_ID); - ((APIC::APIC *)Interrupts::apic)->RedirectIRQs(CPU_ID); + Interrupts::Enable(CPU_ID); + Interrupts::InitializeTimer(CPU_ID); CPU::Interrupts(CPU::Enable); KPrint("CPU %d is online", CPU_ID); @@ -89,10 +86,11 @@ namespace SMP } for (uint8_t i = 0; i < ((ACPI::MADT *)madt)->CPUCores + 1; i++) { - if ((((APIC::APIC *)Interrupts::apic)->Read(APIC::APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) + debug("Initializing CPU %d", i); + if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) { - ((APIC::APIC *)Interrupts::apic)->Write(APIC::APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); - ((APIC::APIC *)Interrupts::apic)->Write(APIC::APIC::APIC_ICRLO, 0x500); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC::APIC_ICRLO, 0x500); Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US); @@ -104,14 +102,15 @@ namespace SMP POKE(volatile uint64_t, PAGE_TABLE) = CPU::x64::readcr3().raw; POKE(volatile uint64_t, STACK) = (uint64_t)KernelAllocator.RequestPage(); + POKE(volatile uint64_t, CORE) = i; asm volatile("sgdt [0x580]\n" "sidt [0x590]\n"); POKE(volatile uint64_t, START_ADDR) = (uintptr_t)&StartCPU; - ((APIC::APIC *)Interrupts::apic)->Write(APIC::APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); - ((APIC::APIC *)Interrupts::apic)->Write(APIC::APIC::APIC_ICRLO, 0x600 | ((uint32_t)TRAMPOLINE_START / PAGE_SIZE)); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC::APIC_ICRLO, 0x600 | ((uint32_t)TRAMPOLINE_START / PAGE_SIZE)); while (!CPUEnabled) ; diff --git a/Architecture/amd64/cpu/apic.hpp b/Architecture/amd64/cpu/apic.hpp index bfa7b34..75888e0 100644 --- a/Architecture/amd64/cpu/apic.hpp +++ b/Architecture/amd64/cpu/apic.hpp @@ -3,6 +3,9 @@ #include +#include +#include + namespace APIC { class APIC @@ -55,9 +58,19 @@ namespace APIC uint32_t IOGetMaxRedirect(uint32_t APICID); void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RedirectIRQ(int CPU, uint8_t IRQ, int Status); - APIC(); + APIC(int Core); ~APIC(); }; + + class Timer : public Interrupts::Handler + { + private: + void OnInterruptReceived(CPU::x64::TrapFrame *Frame); + + public: + Timer(APIC *apic); + ~Timer(); + }; } #endif // !__FENNIX_KERNEL_APIC_H__ diff --git a/Core/CPU.cpp b/Core/CPU.cpp index d8edb7a..d852669 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -208,7 +208,9 @@ namespace CPU void InitializeFeatures() { #if defined(__amd64__) - static int BSP; + static int BSP = 0; + if (!BSP) + CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, 0); CPU::x64::CR0 cr0 = CPU::x64::readcr0(); CPU::x64::CR4 cr4 = CPU::x64::readcr4(); uint32_t rax, rbx, rcx, rdx; diff --git a/Core/CrashHandler.cpp b/Core/CrashHandler.cpp index 0ec28d5..12893d0 100644 --- a/Core/CrashHandler.cpp +++ b/Core/CrashHandler.cpp @@ -341,8 +341,7 @@ namespace CrashHandler CrashEnd: Display->SetBuffer(255); - while (1) - CPU::Stop(); + CPU::Stop(); } } diff --git a/Core/Interrupts/IntManager.cpp b/Core/Interrupts/IntManager.cpp index 6b4456f..174036f 100644 --- a/Core/Interrupts/IntManager.cpp +++ b/Core/Interrupts/IntManager.cpp @@ -2,6 +2,7 @@ #include #include +#include #if defined(__amd64__) #include "../Architecture/amd64/cpu/gdt.hpp" @@ -24,9 +25,10 @@ namespace Interrupts HashMap *RegisteredEvents; #if defined(__amd64__) - /* APIC::APIC */ void *apic = nullptr; + /* APIC::APIC */ void *apic[MAX_CPU]; + /* APIC::Timer */ void *apicTimer[MAX_CPU]; #elif defined(__i386__) - /* APIC::APIC */ void *apic = nullptr; + /* APIC::APIC */ void *apic[MAX_CPU]; #elif defined(__aarch64__) #endif @@ -37,8 +39,8 @@ namespace Interrupts RegisteredEvents = new HashMap; #if defined(__amd64__) - GlobalDescriptorTable::Init(0); - InterruptDescriptorTable::Init(0); + GlobalDescriptorTable::Init(Core); + InterruptDescriptorTable::Init(Core); InitializeSystemCalls(); #elif defined(__i386__) warn("i386 is not supported yet"); @@ -47,13 +49,14 @@ namespace Interrupts #endif } - void Enable() + void Enable(int Core) { #if defined(__amd64__) if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr) { - apic = new APIC::APIC; - ((APIC::APIC *)apic)->RedirectIRQs(0); + // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. + apic[Core] = new APIC::APIC(Core); + ((APIC::APIC *)apic[Core])->RedirectIRQs(Core); } else { @@ -67,10 +70,16 @@ namespace Interrupts #endif } - void InitializeTimer() + void InitializeTimer(int Core) { + // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. #if defined(__amd64__) - + if (apic[Core] != nullptr) + apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]); + else + { + fixme("apic not found"); + } #elif defined(__i386__) warn("i386 is not supported yet"); #elif defined(__aarch64__) @@ -82,16 +91,17 @@ namespace Interrupts { #if defined(__amd64__) CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data; + int Core = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); Handler *handler = (Handler *)RegisteredEvents->Get(Frame->InterruptNumber); if (handler != (Handler *)0xdeadbeef) handler->OnInterruptReceived(Frame); else - error("Unhandled IRQ%d on CPU %d", Frame->InterruptNumber - 32, ((APIC::APIC *)Interrupts::apic)->Read(APIC::APIC::APIC_ID) >> 24); + error("Unhandled IRQ%d on CPU %d.", Frame->InterruptNumber - 32, Core); - if (apic) + if (apic[Core]) { - ((APIC::APIC *)Interrupts::apic)->EOI(); + ((APIC::APIC *)Interrupts::apic[Core])->EOI(); return; } // TODO: PIC @@ -100,21 +110,41 @@ namespace Interrupts #elif defined(__aarch64__) void *Frame = Data; #endif - while (1) - CPU::Stop(); + CPU::Stop(); } Handler::Handler(int InterruptNumber) { - debug("Registering interrupt handler for IRQ%d", InterruptNumber - 32); + if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)0xdeadbeef) + { + warn("IRQ%d is already registered.", InterruptNumber - 32); + return; + } + + debug("Registering interrupt handler for IRQ%d.", InterruptNumber - 32); this->InterruptNumber = InterruptNumber; RegisteredEvents->AddNode(InterruptNumber, (uint64_t)this); } Handler::~Handler() { - debug("Unregistering interrupt handler for IRQ%d", InterruptNumber - 32); + debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32); if (RegisteredEvents->DeleteNode(InterruptNumber) == 0xdeadbeef) - warn("Node %d not found", InterruptNumber); + warn("Node %d not found.", InterruptNumber); + } + +#if defined(__amd64__) + void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame) + { + trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32); +#elif defined(__i386__) + void Handler::OnInterruptReceived(void *Frame); + { + trace("Unhandled interrupt received"); +#elif defined(__aarch64__) + void Handler::OnInterruptReceived(void *Frame); + { + trace("Unhandled interrupt received"); +#endif } } diff --git a/Core/Power.cpp b/Core/Power.cpp index 76e66a6..84c592d 100644 --- a/Core/Power.cpp +++ b/Core/Power.cpp @@ -1,21 +1,62 @@ #include #include -#include "../kernel.h" #include +#include "../kernel.h" + #if defined(__amd64__) +#include + #include "../Architecture/amd64/acpi.hpp" namespace Power { - void Power::Reboot() { ((ACPI::DSDT *)this->dsdt)->Reboot(); } - void Power::Shutdown() { ((ACPI::DSDT *)this->dsdt)->Shutdown(); } + void Power::Reboot() + { + if (((ACPI::ACPI *)this->acpi)->FADT) + if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) + ((ACPI::DSDT *)this->dsdt)->Reboot(); + + uint8_t val = 0x02; + while (val & 0x02) + val = inb(0x64); + outb(0x64, 0xFE); + + warn("Executing the second attempt to reboot..."); + + // second attempt to reboot + // https://wiki.osdev.org/Reboot + uint8_t temp; + asm volatile("cli"); + do + { + temp = inb(0x64); + if (((temp) & (1 << (0))) != 0) + inb(0x60); + } while (((temp) & (1 << (1))) != 0); + outb(0x64, 0xFE); + + CPU::Stop(); + } + + void Power::Shutdown() + { + if (((ACPI::ACPI *)this->acpi)->FADT) + if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) + ((ACPI::DSDT *)this->dsdt)->Shutdown(); + + outl(0xB004, 0x2000); // for qemu + outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu + outl(0x4004, 0x3400); // virtual box + CPU::Stop(); + } Power::Power() { this->acpi = new ACPI::ACPI(bInfo); - this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi); + if (((ACPI::ACPI *)this->acpi)->FADT) + this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi); this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT); trace("Power manager initialized"); } diff --git a/Kernel.cpp b/Kernel.cpp index b253274..a89f08d 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -74,15 +74,14 @@ EXTERNC void Entry(BootInfo *Info) PCI::Descriptors::GetProgIFName(hdr->Class, hdr->Subclass, hdr->ProgIF)); } KPrint("Enabling interrupts"); - Interrupts::Enable(); + Interrupts::Enable(0); + KPrint("Initializing timer"); + Interrupts::InitializeTimer(0); KPrint("Initializing SMP"); SMP::Initialize(PowerManager->GetMADT()); - KPrint("Initializing timer"); - Interrupts::InitializeTimer(); KPrint("\e058C19######## \eE85230END \e058C19########"); CPU::Interrupts(CPU::Enable); - while (1) - CPU::Halt(); + CPU::Stop(); } EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) diff --git a/include/interrupts.hpp b/include/interrupts.hpp index 0aa800f..98fb9ce 100644 --- a/include/interrupts.hpp +++ b/include/interrupts.hpp @@ -3,18 +3,19 @@ #include #include +#include namespace Interrupts { #if defined(__amd64__) - extern void *apic; + extern void *apic[MAX_CPU]; #elif defined(__i386__) - extern void *apic; + extern void *apic[MAX_CPU]; #elif defined(__aarch64__) #endif void Initialize(int Core); - void Enable(); - void InitializeTimer(); + void Enable(int Core); + void InitializeTimer(int Core); class Handler { @@ -36,7 +37,6 @@ namespace Interrupts virtual void OnInterruptReceived(void *Frame); #endif }; - } #endif // !__FENNIX_KERNEL_INTERRUPTS_H__ diff --git a/include/power.hpp b/include/power.hpp index 57ea41e..d3b3e22 100644 --- a/include/power.hpp +++ b/include/power.hpp @@ -16,21 +16,21 @@ namespace Power /** * @brief Get Advanced Configuration and Power Interface. (Available only on x32 and x64) * - * @return void* + * @return void* (ACPI::ACPI *) */ void *GetACPI() { return this->acpi; } /** * @brief Get Differentiated System Description Table. (Available only on x32 and x64) * - * @return void* + * @return void* (ACPI::DSDT *) */ void *GetDSDT() { return this->dsdt; } /** * @brief Get Multiple APIC Description Table. (Available only on x32 and x64) * - * @return void* + * @return void* (ACPI::MADT *) */ void *GetMADT() { return this->madt; }