mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-29 15:57:59 +00:00
APIC should be fixed
This commit is contained in:
parent
94dfeb7fd5
commit
e0d4e38b99
@ -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 APIC::IOGetMaxRedirect(uint32_t APICID)
|
||||||
{
|
{
|
||||||
uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
|
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));
|
// 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)
|
Timer::Timer(APIC *apic) : Interrupts::Handler(CPU::x64::IRQ0)
|
||||||
{
|
{
|
||||||
trace("Initializing APIC timer on CPU %d", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE));
|
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);
|
int IOIn = inb(0x61);
|
||||||
IOIn = (IOIn & 0xFD) | 1;
|
IOIn = (IOIn & 0xFD) | 1;
|
||||||
outb(0x61, IOIn);
|
outb(0x61, IOIn);
|
||||||
outb(0x43, 0b10110010);
|
outb(0x43, 178);
|
||||||
outb(0x42, 155);
|
outb(0x42, Ticks & 0xff);
|
||||||
inb(0x60);
|
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 = inb(0x61);
|
||||||
IOIn = (IOIn & 0xFC);
|
IOIn = (IOIn & 0xFC);
|
||||||
@ -244,7 +246,7 @@ namespace APIC
|
|||||||
while ((inb(0x61) & 0x20) != 0)
|
while ((inb(0x61) & 0x20) != 0)
|
||||||
++Loop;
|
++Loop;
|
||||||
|
|
||||||
apic->Write(APIC::APIC::APIC_TIMER, 0x10000);
|
this->lapic->Write(APIC_TIMER, 0x10000);
|
||||||
|
|
||||||
outb(0x43, 0x28);
|
outb(0x43, 0x28);
|
||||||
outb(0x40, 0x0);
|
outb(0x40, 0x0);
|
||||||
@ -252,12 +254,12 @@ namespace APIC
|
|||||||
outb(0x21, 0xFF);
|
outb(0x21, 0xFF);
|
||||||
outb(0xA1, 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);
|
this->lapic->Write(APIC_TIMER, (long)CPU::x64::IRQ0 | (long)APIC_PERIODIC);
|
||||||
apic->Write(APIC::APIC::APIC_TDCR, 0x3);
|
this->lapic->Write(APIC_TDCR, 0x3);
|
||||||
apic->Write(APIC::APIC::APIC_TICR, ticksIn10ms);
|
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);
|
debug("APIC Timer (CPU %d): %d ticks in 10ms", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), TicksIn10ms / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::~Timer()
|
Timer::~Timer()
|
||||||
|
@ -87,10 +87,10 @@ namespace SMP
|
|||||||
for (uint16_t i = 0; i < ((ACPI::MADT *)madt)->CPUCores + 1; i++)
|
for (uint16_t i = 0; i < ((ACPI::MADT *)madt)->CPUCores + 1; i++)
|
||||||
{
|
{
|
||||||
debug("Initializing CPU %d", 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_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_ICRLO, 0x500);
|
||||||
|
|
||||||
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US);
|
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;
|
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_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_ICRLO, 0x600 | ((uint32_t)TRAMPOLINE_START / PAGE_SIZE));
|
||||||
|
|
||||||
while (!CPUEnabled)
|
while (!CPUEnabled)
|
||||||
;
|
;
|
||||||
|
@ -8,45 +8,44 @@
|
|||||||
|
|
||||||
namespace APIC
|
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
|
class APIC
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool x2APICSupported = false;
|
bool x2APICSupported = false;
|
||||||
|
|
||||||
public:
|
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);
|
uint32_t Read(uint32_t Register);
|
||||||
void Write(uint32_t Register, uint32_t Value);
|
void Write(uint32_t Register, uint32_t Value);
|
||||||
void IOWrite(uint64_t Base, 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 EOI();
|
||||||
void RedirectIRQs(int CPU = 0);
|
void RedirectIRQs(int CPU = 0);
|
||||||
void IPI(uint8_t CPU, uint32_t InterruptNumber);
|
void IPI(uint8_t CPU, uint32_t InterruptNumber);
|
||||||
void OneShot(uint32_t Vector, uint64_t Miliseconds);
|
|
||||||
uint32_t IOGetMaxRedirect(uint32_t APICID);
|
uint32_t IOGetMaxRedirect(uint32_t APICID);
|
||||||
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
|
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
|
||||||
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
|
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
|
||||||
@ -65,9 +63,13 @@ namespace APIC
|
|||||||
class Timer : public Interrupts::Handler
|
class Timer : public Interrupts::Handler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
APIC *lapic;
|
||||||
|
uint64_t TicksIn10ms = 0;
|
||||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
uint64_t GetTicksIn10ms() { return TicksIn10ms; }
|
||||||
|
void OneShot(uint32_t Vector, uint64_t Miliseconds);
|
||||||
Timer(APIC *apic);
|
Timer(APIC *apic);
|
||||||
~Timer();
|
~Timer();
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
namespace Interrupts
|
namespace Interrupts
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#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__)
|
#elif defined(__i386__)
|
||||||
extern void *apic[MAX_CPU];
|
extern void *apic[MAX_CPU];
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user