Fix dodgy APIC implementation
This commit is contained in:
parent
e09f1790a0
commit
73f6c0dade
|
@ -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);
|
||||
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include <kernel/system/acpi/madt.h>
|
||||
#include <kernel/system/io.h>
|
||||
#include <kernel/system/memory.h>
|
||||
#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);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include <driver/io/ps2_keyboard.h>
|
||||
#include <kernel/chroma.h>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ MADT::IOAPICEntry** MADT::GetIOApicEntries() {
|
|||
|
||||
if (table->Type == MADT::Type::IOAPIC) {
|
||||
MADT::IOAPICEntry* io_apic = reinterpret_cast<MADT::IOAPICEntry*>(table);
|
||||
MapVirtualPage(&KernelAddressSpace, io_apic->Address, io_apic->Address, 3);
|
||||
entries[count] = (MADT::IOAPICEntry*) ((size_t) io_apic);
|
||||
count++;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <kernel/chroma.h>
|
||||
#include <kernel/system/interrupts.h>
|
||||
#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() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <kernel/video/draw.h>
|
||||
#include <kernel/system/interrupts.h>
|
||||
#include <stdbool.h>
|
||||
#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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user