feat: GICv2 and timer

fix: TimerReset in GIC.c now uses kTimerFrequency
This commit is contained in:
karina
2026-04-29 08:46:13 +04:00
parent 270aae56b4
commit 7fcb50587e
10 changed files with 181 additions and 5 deletions
+9
View File
@@ -77,6 +77,15 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
bootMap->UART.base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
bootMap->UART.size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
}
else if (StringStartsWith(currentNode, "intc")) {
UInt32* cells = (UInt32*)structs;
bootMap->GIC.GICD.base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
bootMap->GIC.GICD.size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
bootMap->GIC.GICC.base = Merge32To64(BytesSwap32(cells[5]), BytesSwap32(cells[4]));
bootMap->GIC.GICC.size = Merge32To64(BytesSwap32(cells[7]), BytesSwap32(cells[6]));
}
}
structs += propertyLength;
+5 -2
View File
@@ -1,8 +1,11 @@
#include <Arch/Exceptions.h>
#include <Arch/CPU.h>
#include <Arch/GIC.h>
#include <IO/Serial.h>
#include <OS/Panic.h>
void ExceptionsHandler(ExceptionsContext* frame, [[maybe_unused]]ExceptionsType type) {
void ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) {
if (type == ExceptionsIRQEl1h || type == ExceptionsIRQEl064) return GICDispatch(type);
OSPanicException(frame);
}
}
+65
View File
@@ -0,0 +1,65 @@
#include <Arch/GIC.h>
#include <Arch/Exceptions.h>
#include <Arch/Timer.h>
#include <OS/Log.h>
static volatile UInt32* GICD = nullptr;
static volatile UInt32* GICC = nullptr;
void GICInitialize(Pointer gicdVirtBase, Pointer giccVirtBase) {
GICD = (volatile UInt32*)gicdVirtBase;
GICC = (volatile UInt32*)giccVirtBase;
GICD[kGICDCTLR / 4] = 0; // disable Distributor (gicd)
UInt32 typer = GICD[kGICDTYPER / 4]; // how many interrupts are supported
UInt32 maxIRQS = 32 * ((typer & 0x1F) + 1); // total number of interrupts
OSLog("GIC: maxIRQS: %d\n", maxIRQS);
for (UInt32 i = 0; i < maxIRQS / 32; i++) {
GICD[kGICDICENABLER / 4 + i] = 0xFFFFFFFF; // clear enable
GICD[kGICDICPENDR / 4 + i] = 0xFFFFFFFF; // clear pending
}
for (UInt32 i = 0; i < maxIRQS / 4; i++) {
GICD[kGICDIPRIORITYR / 4 + i] = 0xA0A0A0A0; // set priority 0xA0 for all interrupts
}
for (UInt32 i = 8; i < maxIRQS / 4; i++) {
GICD[kGICDITARGETSR / 4 + i] = 0x01010101; // set interrupts id >= 32 for CPU 0
}
GICD[kGICDCTLR / 4] = 1; // enable Distributor (gicd)
GICC[kGICCCTLR / 4] = 0; // disable cpu interface
GICC[kGICCPMR / 4] = 0xFF; // set lowest priority (accept all interrupts)
GICC[kGICCCTLR / 4] = 1; // enable CPU interface (gicc)
OSLog("GICv2 initialized.\n");
}
void GICEnableInterrupt(UInt32 irqID) {
UInt32 regOffset = irqID / 32;
UInt32 bitMask = 1 << (irqID % 32);
GICD[kGICDISENABLER / 4 + regOffset] = bitMask;
}
UInt32 GICCReadIAR(void) {
return GICC[kGICCIAR / 4];
}
void GICCWriteEOIR(UInt32 irqID) {
GICC[kGICCEOIR / 4] = irqID;
}
void GICDispatch(ExceptionsType type) {
if (type != ExceptionsIRQEl1h && type != ExceptionsIRQEl064) return;
UInt32 irqID = GICCReadIAR() & 0x3FF;
if (irqID == 1023) return; // spurious interrupt
if (irqID == 30) {
TimerReset(kTimerFrequency);
}
GICCWriteEOIR(irqID);
}
+14
View File
@@ -0,0 +1,14 @@
#include <Arch/Timer.h>
#include <Arch/GIC.h>
void TimerInitialize() {
GICEnableInterrupt(kTimerIRQ);
TimerReset(kTimerFrequency);
}
void TimerReset(UInt64 interval) {
UInt64 frequency;
__asm__ volatile ("mrs %0, cntfrq_el0" : "=r"(frequency));
__asm__ volatile ("msr cntp_tval_el0, %0" :: "r"(frequency /interval));
__asm__ volatile ("msr cntp_ctl_el0, %0" :: "r" (1));
}