diff --git a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp index c454d1c..551b405 100644 --- a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp +++ b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp @@ -100,15 +100,6 @@ namespace APIC } } - void APIC::OneShot(uint32_t Vector, uint64_t Miliseconds) - { - int apic_timer_ticks = 0; - fixme("APIC::OneShot(%#lx, %#lx)", Vector, Miliseconds); - this->Write(APIC_TDCR, 0x03); - this->Write(APIC_TIMER, (APIC::APIC::APICRegisters::APIC_ONESHOT | Vector)); - this->Write(APIC_TICR, apic_timer_ticks * Miliseconds); - } - uint32_t APIC::IOGetMaxRedirect(uint32_t APICID) { uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion)); @@ -220,20 +211,31 @@ namespace APIC // fixme("APIC IRQ0 INTERRUPT RECEIVED ON CPU %d", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE)); } + void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds) + { + this->lapic->Write(APIC_TDCR, 0x03); + this->lapic->Write(APIC_TIMER, (APIC_ONESHOT | Vector)); + this->lapic->Write(APIC_TICR, (TicksIn10ms / 10) * Miliseconds); + } + 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); + this->lapic = apic; + this->lapic->Write(APIC_TDCR, 0x3); + + int Count = 10000; /* µs */ + int Ticks = 1193180 / (Count / 100); int IOIn = inb(0x61); IOIn = (IOIn & 0xFD) | 1; outb(0x61, IOIn); - outb(0x43, 0b10110010); - outb(0x42, 155); + outb(0x43, 178); + outb(0x42, Ticks & 0xff); inb(0x60); - outb(0x42, 46); + outb(0x42, Ticks >> 8); - apic->Write(APIC::APIC::APIC_TICR, 0xFFFFFFFF); + this->lapic->Write(APIC_TICR, 0xFFFFFFFF); IOIn = inb(0x61); IOIn = (IOIn & 0xFC); @@ -244,7 +246,7 @@ namespace APIC while ((inb(0x61) & 0x20) != 0) ++Loop; - apic->Write(APIC::APIC::APIC_TIMER, 0x10000); + this->lapic->Write(APIC_TIMER, 0x10000); outb(0x43, 0x28); outb(0x40, 0x0); @@ -252,12 +254,12 @@ namespace APIC outb(0x21, 0xFF); outb(0xA1, 0xFF); - uint64_t ticksIn10ms = 0xFFFFFFFF - apic->Read(APIC::APIC::APIC_TCCR); + TicksIn10ms = 0xFFFFFFFF - this->lapic->Read(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); + this->lapic->Write(APIC_TIMER, (long)CPU::x64::IRQ0 | (long)APIC_PERIODIC); + this->lapic->Write(APIC_TDCR, 0x3); + this->lapic->Write(APIC_TICR, TicksIn10ms / 10); + debug("APIC Timer (CPU %d): %d ticks in 10ms", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), TicksIn10ms / 10); } Timer::~Timer() diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index d06684f..f0e981f 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -87,10 +87,10 @@ namespace SMP for (uint16_t i = 0; i < ((ACPI::MADT *)madt)->CPUCores + 1; i++) { debug("Initializing CPU %d", i); - if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) + if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) { - ((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); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500); Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US); @@ -109,8 +109,8 @@ namespace SMP POKE(volatile uint64_t, START_ADDR) = (uintptr_t)&StartCPU; - ((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)); + ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); + ((APIC::APIC *)Interrupts::apic[0])->Write(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 75888e0..4ecb0f5 100644 --- a/Architecture/amd64/cpu/apic.hpp +++ b/Architecture/amd64/cpu/apic.hpp @@ -8,45 +8,44 @@ namespace APIC { + enum APICRegisters + { + APIC_ONESHOT = (0 << 17), // LVT One-Shot Mode (for Timer) + APIC_PERIODIC = (1 << 17), // LVT Periodic Mode (for Timer) + APIC_TSC_DEADLINE = (2 << 17), // LVT Timer/sDeadline (for Timer) + // source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c + APIC_ID = 0x20, // Local APIC ID + APIC_VER = 0x30, // Local APIC Version + APIC_TPR = 0x80, // Task Priority + APIC_APR = 0x90, // Arbitration Priority + APIC_PPR = 0xa0, // Processor Priority + APIC_EOI = 0xb0, // EOI + APIC_RRD = 0xc0, // Remote Read + APIC_LDR = 0xd0, // Logical Destination + APIC_DFR = 0xe0, // Destination Format + APIC_SVR = 0xf0, // Spurious Interrupt Vector + APIC_ISR = 0x100, // In-Service (8 registers) + APIC_TMR = 0x180, // Trigger Mode (8 registers) + APIC_IRR = 0x200, // Interrupt Request (8 registers) + APIC_ESR = 0x280, // Error Status + APIC_ICRLO = 0x300, // Interrupt Command + APIC_ICRHI = 0x310, // Interrupt Command [63:32] + APIC_TIMER = 0x320, // LVT Timer + APIC_THERMAL = 0x330, // LVT Thermal Sensor + APIC_PERF = 0x340, // LVT Performance Counter + APIC_LINT0 = 0x350, // LVT LINT0 + APIC_LINT1 = 0x360, // LVT LINT1 + APIC_ERROR = 0x370, // LVT Error + APIC_TICR = 0x380, // Initial Count (for Timer) + APIC_TCCR = 0x390, // Current Count (for Timer) + APIC_TDCR = 0x3e0, // Divide Configuration (for Timer) + }; class APIC { private: bool x2APICSupported = false; public: - enum APICRegisters - { - APIC_ONESHOT = (0 << 17), // LVT One-Shot Mode (for Timer) - APIC_PERIODIC = (1 << 17), // LVT Periodic Mode (for Timer) - APIC_TSC_DEADLINE = (2 << 17), // LVT Timer/sDeadline (for Timer) - // source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c - APIC_ID = 0x20, // Local APIC ID - APIC_VER = 0x30, // Local APIC Version - APIC_TPR = 0x80, // Task Priority - APIC_APR = 0x90, // Arbitration Priority - APIC_PPR = 0xa0, // Processor Priority - APIC_EOI = 0xb0, // EOI - APIC_RRD = 0xc0, // Remote Read - APIC_LDR = 0xd0, // Logical Destination - APIC_DFR = 0xe0, // Destination Format - APIC_SVR = 0xf0, // Spurious Interrupt Vector - APIC_ISR = 0x100, // In-Service (8 registers) - APIC_TMR = 0x180, // Trigger Mode (8 registers) - APIC_IRR = 0x200, // Interrupt Request (8 registers) - APIC_ESR = 0x280, // Error Status - APIC_ICRLO = 0x300, // Interrupt Command - APIC_ICRHI = 0x310, // Interrupt Command [63:32] - APIC_TIMER = 0x320, // LVT Timer - APIC_THERMAL = 0x330, // LVT Thermal Sensor - APIC_PERF = 0x340, // LVT Performance Counter - APIC_LINT0 = 0x350, // LVT LINT0 - APIC_LINT1 = 0x360, // LVT LINT1 - APIC_ERROR = 0x370, // LVT Error - APIC_TICR = 0x380, // Initial Count (for Timer) - APIC_TCCR = 0x390, // Current Count (for Timer) - APIC_TDCR = 0x3e0, // Divide Configuration (for Timer) - }; - uint32_t Read(uint32_t Register); void Write(uint32_t Register, uint32_t Value); void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value); @@ -54,7 +53,6 @@ namespace APIC void EOI(); void RedirectIRQs(int CPU = 0); void IPI(uint8_t CPU, uint32_t InterruptNumber); - void OneShot(uint32_t Vector, uint64_t Miliseconds); 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); @@ -65,9 +63,13 @@ namespace APIC class Timer : public Interrupts::Handler { private: + APIC *lapic; + uint64_t TicksIn10ms = 0; void OnInterruptReceived(CPU::x64::TrapFrame *Frame); public: + uint64_t GetTicksIn10ms() { return TicksIn10ms; } + void OneShot(uint32_t Vector, uint64_t Miliseconds); Timer(APIC *apic); ~Timer(); }; diff --git a/include/interrupts.hpp b/include/interrupts.hpp index 98fb9ce..d51b634 100644 --- a/include/interrupts.hpp +++ b/include/interrupts.hpp @@ -8,7 +8,8 @@ namespace Interrupts { #if defined(__amd64__) - extern void *apic[MAX_CPU]; + /* APIC::APIC */ extern void *apic[MAX_CPU]; + /* APIC::Timer */ extern void *apicTimer[MAX_CPU]; #elif defined(__i386__) extern void *apic[MAX_CPU]; #elif defined(__aarch64__)