feat: GICv2 and timer
fix: TimerReset in GIC.c now uses kTimerFrequency
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
Reference in New Issue
Block a user