diff --git a/inc/kernel/system/core.hpp b/inc/kernel/system/core.hpp index 323cfcb..d60d175 100644 --- a/inc/kernel/system/core.hpp +++ b/inc/kernel/system/core.hpp @@ -41,9 +41,9 @@ class Core { size_t StackAddress = 0; uint8_t StackData[Constants::Core::STACK_SIZE] = { 0 }; - IDT CoreIDT; - GDT CoreGDT; - TSS64 CoreTSS; + IDT CoreIDT = { 0, 0 }; + GDT CoreGDT = { 0, 0 }; + TSS64 CoreTSS = { }; void LoadExtraRegisters(uint8_t* Data); void SaveExtraRegisters(uint8_t* Data); @@ -58,12 +58,12 @@ class Core { static Core* GetCore(int ID) { return Processors[ID]; } + static void PreInit(); static void Init(); private: static Core* Processors[]; void Bootstrap(); - void SetupData(size_t ID); }; diff --git a/src/drivers/devices/io/apic.cpp b/src/drivers/devices/io/apic.cpp index 4ded48d..48bb755 100644 --- a/src/drivers/devices/io/apic.cpp +++ b/src/drivers/devices/io/apic.cpp @@ -2,6 +2,8 @@ #include #include #include +#include "kernel/system/core.hpp" +#include "kernel/chroma.h" /************************ *** Team Kitty, 2021 *** @@ -51,7 +53,7 @@ void APIC::Enable() { } void APIC::SendEOI() { - WriteRegister(Registers::EOI, 0); + *((volatile uint32_t*) 0xfee000B0) = 0; } bool APIC::IsReady() { @@ -63,11 +65,14 @@ void APIC::Init() { SerialPrintf("[ ACPI] Enabling APICs...\r\n"); + SerialPrintf("[ ACPI] Memory Mapping APICs..\r\n"); + for (int i = 0; i < 3; i++) { + MapVirtualPage(&KernelAddressSpace, (size_t) Address + i * PAGE_SIZE, (size_t) Address + i * PAGE_SIZE, 3); + } + Address = (void*) ACPI::MADT::instance->LocalAPICBase; SerialPrintf("[ MADT] The APIC of this core is at 0x%p\r\n", (size_t) Address); - // TODO: Check whether the identity mapping covers this address - if (Address == nullptr) { SerialPrintf("[ ACPI] Unable to locate APICs.\r\n"); for (;;) { } @@ -77,10 +82,6 @@ void APIC::Init() { WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10)); Enable(); - // Disable PIC1 and 2 - WritePort(0x21, 0xFF, 1); - WritePort(0xA1, 0xFF, 1); - SerialPrintf("[ ACPI] Enabling Global APIC..\r\n"); IOAPICs = ACPI::MADT::instance->GetIOApicEntries(); SerialPrintf("[ ACPI] Enabling Interrupt Source Overrides..\r\n"); @@ -111,8 +112,8 @@ void APIC::InitializeCore(int Core, size_t EntryPoint) { WriteRegister(Registers::ICR1, 0x600 | ((uint32_t) (EntryPoint / PAGE_SIZE))); } -void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int Core, int Status) { - UNUSED(Core); +void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CoreID, int Status) { + size_t temp = Vector; int64_t target = -1; @@ -124,7 +125,7 @@ void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int Core, i } if (target == -1) { - SerialPrintf("[APIC] No ISO found when setting up redirect."); + SerialPrintf("[ APIC] No ISO found when setting up redirect.\r\n"); return; } @@ -137,6 +138,24 @@ void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int Core, i if (!Status) temp |= (1 << 16); - // TODO + temp |= (((size_t) Core::GetCore(CoreID)->LocalAPIC) << 56); + uint32_t IORegister = (GSI - IOAPICs[target]->GSI) * 2 + 0x10; + SerialPrintf("[ APIC] Setting interrupt %u, redirect %u, on LAPIC %u(%u) of core %u, address 0x%p, register 0x%p, data 0x%p\r\n", GSI, Vector, Core::GetCore(CoreID)->LocalAPIC, target, CoreID, IOAPICs[target]->Address, IORegister, temp); + + WriteIO(IOAPICs[target]->Address, IORegister, (uint32_t) temp); + WriteIO(IOAPICs[target]->Address, IORegister + 1, (uint32_t)(temp >> 32)); +} + +void APIC::Set(int CPU, uint8_t IRQ, int Enabled) { + for(size_t i = 0; ISOs[i] != 0; i++) { + // We need to make sure we take into account the overrides, so check whether any IRQ is overriden + if (ISOs[i]->IRQ == IRQ) { + SetInternal(ISOs[i]->IRQ + 0x20, ISOs[i]->Interrupt, ISOs[i]->Flags, CPU, Enabled); + return; + } + } + + // If there are no overrides, we can just remap it upwards + SetInternal(IRQ + 0x20, IRQ, 0, CPU, Enabled); } \ No newline at end of file diff --git a/src/drivers/devices/io/ps2_keyboard.cpp b/src/drivers/devices/io/ps2_keyboard.cpp index fd11b2a..01d84eb 100644 --- a/src/drivers/devices/io/ps2_keyboard.cpp +++ b/src/drivers/devices/io/ps2_keyboard.cpp @@ -1,5 +1,6 @@ #include #include +#include "driver/io/apic.h" /************************ *** Team Kitty, 2022 *** @@ -154,6 +155,7 @@ void PS2Keyboard::InterruptHandler() { SerialPrintf("[ KEY] %c pressed.\r\n", keys[scancode]); state = ReadPort(0x64, 1); + setState(keystate, scancode); KeyboardData data { keys[scancode], (char) scancode, (bool) keystate }; buffer.emplace_back(data); } diff --git a/src/kernel.cpp b/src/kernel.cpp index afc5dfe..e31965c 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -77,12 +77,15 @@ extern "C" int Main(void) { SetForegroundColor(0x00FFFFFF); + Device::APIC::driver = new Device::APIC(); Device::PS2Keyboard::driver = new Device::PS2Keyboard(); ACPI::RSDP::instance->Init(0); ACPI::MADT::instance->Init(); + Core::PreInit(); + Device::APIC::driver->Init(); Device::PS2Keyboard::driver->Init(); diff --git a/src/system/acpi/MADT.cpp b/src/system/acpi/MADT.cpp index 402327b..aee525c 100644 --- a/src/system/acpi/MADT.cpp +++ b/src/system/acpi/MADT.cpp @@ -40,6 +40,7 @@ MADT::IOAPICEntry** MADT::GetIOApicEntries() { if (table->Type == MADT::Type::IOAPIC) { MADT::IOAPICEntry* io_apic = reinterpret_cast(table); + MapVirtualPage(&KernelAddressSpace, io_apic->Address, io_apic->Address, 3); entries[count] = (MADT::IOAPICEntry*) ((size_t) io_apic); count++; } diff --git a/src/system/core.cpp b/src/system/core.cpp index 4f4c80c..00c974b 100644 --- a/src/system/core.cpp +++ b/src/system/core.cpp @@ -45,7 +45,14 @@ Core::Core(size_t APIC, size_t ID) { Ready = false; } +void Core::PreInit() { + for (size_t i = 0; i < Constants::Core::MAX_CORES; i++) { + Processors[i] = new Core(); + } +} + void Core::Init() { + using namespace ACPI; Ready = false; @@ -78,7 +85,6 @@ void Core::Init() { } SerialPrintf("[ CORE] Found %d core(s).\r\n", Cores); - if (Cores > 1) SerialPrintf("[ CORE] Bringing up other cores.\r\n"); @@ -87,6 +93,7 @@ void Core::Init() { if (Device::APIC::driver->GetCurrentCore() != LAPICs[i]->Core) { SerialPrintf("[ CORE] Enabling core %d.\r\n", i); + delete Processors[i]; Core* c = new Core(LAPICs[i]->APIC, LAPICs[i]->Core); Processors[i] = c; } @@ -97,11 +104,6 @@ void Core::Bootstrap() { // TODO } -void Core::SetupData(size_t Core) { - UNUSED(Core); -} - - void Core::StackTrace(size_t Cycles) { StackFrame* stack; diff --git a/src/system/cpu.cpp b/src/system/cpu.cpp index c118df6..eae4ee6 100644 --- a/src/system/cpu.cpp +++ b/src/system/cpu.cpp @@ -1,5 +1,6 @@ #include #include +#include "driver/io/apic.h" /************************ *** Team Kitty, 2020 *** @@ -71,6 +72,9 @@ void PrepareCPU() { //SetupExtensions(); InitInterrupts(); + + /* In either case, we tell the Master PIC it's been read to receive any IRQ. */ + WritePort(0x20, 0x20, 1); } void SetupInitialGDT() { diff --git a/src/system/interrupts.cpp b/src/system/interrupts.cpp index 1b2db70..c52131b 100644 --- a/src/system/interrupts.cpp +++ b/src/system/interrupts.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "driver/io/apic.h" /************************ *** Team Kitty, 2020 *** @@ -122,19 +123,15 @@ void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { safely tell whether we've actually got something for this IRQ. */ handler = IRQHandlers[Interrupt]; if (handler.numHandlers > 0) { - SerialPrintf("[ IRQ] IRQ %d raised!\r\n", Interrupt); + //SerialPrintf("[ IRQ] IRQ %d raised!\r\n", Interrupt); // Call the handlers for (size_t i = 0; i < handler.numHandlers; i++) handler.handlers[i](Frame); } - /* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */ - if (Interrupt > 7) - WritePort(0xA0, 0x20, 1); - - /* In either case, we tell the Master PIC it's been read to receive any IRQ. */ - WritePort(0x20, 0x20, 1); + Device::APIC::driver->SendEOI(); } + #define PIC1 0x20 /* IO base address for master PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */ #define PIC1_COMMAND PIC1 @@ -154,28 +151,10 @@ void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ #define ICW4_SFNM 0x10 /* Special fully nested (not) */ -void ClearIRQ(size_t idx) { - uint16_t port; - uint8_t value; - - if(idx < 8) { - port = PIC1_DATA; - } else { - port = PIC2_DATA; - idx -= 8; - } - value = ReadPort(port, 1) & ~(1 << idx); - WritePort(port, value, 1); -} - /* However, in order to actually be able to receive IRQs, we need to remap the PICs. */ void RemapIRQControllers() { /* 0x20 is the Master PIC, 0xA0 is the Slave PIC. */ - unsigned char a1, a2; - - a1 = ReadPort(PIC1_DATA, 1); // save masks - a2 = ReadPort(PIC2_DATA, 1); WritePort(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4, 1); // starts the initialization sequence (in cascade mode) WritePort(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4, 1); @@ -187,17 +166,17 @@ void RemapIRQControllers() { WritePort(PIC1_DATA, ICW4_8086, 1); WritePort(PIC2_DATA, ICW4_8086, 1); - WritePort(PIC1_DATA, a1, 1); // restore saved masks. - WritePort(PIC2_DATA, a2, 1); + WritePort(PIC1_DATA, 0xFF, 1); // restore saved masks. + WritePort(PIC2_DATA, 0xFF, 1); - ClearIRQ(1); - ClearIRQ(2); } /* In order to actually handle the IRQs, though, we need to tell the kernel *where* the handlers are. */ /* A simple wrapper that adds a function pointer to the IRQ array. */ size_t InstallIRQ(int IRQ, IRQHandler Handler) { if (IRQ <= 32) { + Device::APIC::driver->Set(Core::GetCurrent()->ID, IRQ, 1); + IRQHandlerData* target = &IRQHandlers[IRQ]; if (target->numHandlers < 7) { target->handlers[target->numHandlers] = Handler; @@ -429,7 +408,6 @@ __attribute__((interrupt)) void IRQ0Handler(INTERRUPT_FRAME* Frame) { } __attribute__((interrupt)) void IRQ1Handler(INTERRUPT_FRAME* Frame) { - SerialPrintf("IRQ1\r\n"); IRQ_Common(Frame, 1); // Keyboard handler }