mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
357 lines
7.5 KiB
C++
357 lines
7.5 KiB
C++
/*
|
|
This file is part of Fennix Kernel.
|
|
|
|
Fennix Kernel is free software: you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of
|
|
the License, or (at your option) any later version.
|
|
|
|
Fennix Kernel is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __FENNIX_KERNEL_APIC_H__
|
|
#define __FENNIX_KERNEL_APIC_H__
|
|
|
|
#include <types.h>
|
|
|
|
#include <ints.hpp>
|
|
#include <cpu.hpp>
|
|
|
|
namespace APIC
|
|
{
|
|
enum APICRegisters
|
|
{
|
|
// 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)
|
|
};
|
|
|
|
enum IOAPICRegisters
|
|
{
|
|
GetIOAPICVersion = 0x1
|
|
};
|
|
|
|
enum IOAPICFlags
|
|
{
|
|
ActiveHighLow = 2,
|
|
EdgeLevel = 8
|
|
};
|
|
|
|
enum APICDeliveryMode
|
|
{
|
|
Fixed = 0b000,
|
|
LowestPriority = 0b001, /* Reserved */
|
|
SMI = 0b010,
|
|
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
|
|
NMI = 0b100,
|
|
INIT = 0b101,
|
|
Startup = 0b110,
|
|
ExtINT = 0b111 /* Reserved */
|
|
};
|
|
|
|
enum APICDestinationMode
|
|
{
|
|
Physical = 0b0,
|
|
Logical = 0b1
|
|
};
|
|
|
|
enum APICDeliveryStatus
|
|
{
|
|
Idle = 0b0,
|
|
SendPending = 0b1
|
|
};
|
|
|
|
enum APICLevel
|
|
{
|
|
DeAssert = 0b0,
|
|
Assert = 0b1
|
|
};
|
|
|
|
enum APICTriggerMode
|
|
{
|
|
Edge = 0b0,
|
|
Level = 0b1
|
|
};
|
|
|
|
enum APICDestinationShorthand
|
|
{
|
|
NoShorthand = 0b00,
|
|
Self = 0b01,
|
|
AllIncludingSelf = 0b10,
|
|
AllExcludingSelf = 0b11
|
|
};
|
|
|
|
enum LVTTimerDivide
|
|
{
|
|
DivideBy2 = 0b000,
|
|
DivideBy4 = 0b001,
|
|
DivideBy8 = 0b010,
|
|
DivideBy16 = 0b011,
|
|
DivideBy32 = 0b100,
|
|
DivideBy64 = 0b101,
|
|
DivideBy128 = 0b110,
|
|
DivideBy1 = 0b111
|
|
};
|
|
|
|
enum LVTTimerMask
|
|
{
|
|
Unmasked = 0b0,
|
|
Masked = 0b1
|
|
};
|
|
|
|
enum LVTTimerMode
|
|
{
|
|
OneShot = 0b00,
|
|
Periodic = 0b01,
|
|
TSCDeadline = 0b10
|
|
};
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
/** @brief Interrupt Vector */
|
|
uint64_t Vector : 8;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved0 : 4;
|
|
/**
|
|
* @brief Delivery Status
|
|
*
|
|
* 0: Idle
|
|
* 1: Send Pending
|
|
*/
|
|
uint64_t DeliveryStatus : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved1 : 3;
|
|
/**
|
|
* @brief Mask
|
|
*
|
|
* 0: Not masked
|
|
* 1: Masked
|
|
*/
|
|
uint64_t Mask : 1;
|
|
/** @brief Timer Mode
|
|
*
|
|
* 0: One-shot
|
|
* 1: Periodic
|
|
* 2: TSC-Deadline
|
|
*/
|
|
uint64_t TimerMode : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved2 : 14;
|
|
};
|
|
uint64_t raw;
|
|
} __packed LVTTimer;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
/** @brief Spurious Vector */
|
|
uint64_t Vector : 8;
|
|
/** @brief Enable or disable APIC software */
|
|
uint64_t Software : 1;
|
|
/** @brief Focus Processor Checking */
|
|
uint64_t FocusProcessorChecking : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved : 2;
|
|
/** @brief Disable EOI Broadcast */
|
|
uint64_t DisableEOIBroadcast : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved1 : 19;
|
|
};
|
|
uint64_t raw;
|
|
} __packed Spurious;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
/** @brief Interrupt Vector */
|
|
uint64_t Vector : 8;
|
|
/** @brief Delivery Mode */
|
|
uint64_t DeliveryMode : 3;
|
|
/** @brief Destination Mode
|
|
*
|
|
* 0: Physical
|
|
* 1: Logical
|
|
*/
|
|
uint64_t DestinationMode : 1;
|
|
/** @brief Delivery Status
|
|
*
|
|
* @note Reserved when in x2APIC mode
|
|
*/
|
|
uint64_t DeliveryStatus : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved0 : 1;
|
|
/** @brief Level
|
|
*
|
|
* 0: Deassert
|
|
* 1: Assert
|
|
*/
|
|
uint64_t Level : 1;
|
|
/** @brief Trigger Mode
|
|
*
|
|
* 0: Edge
|
|
* 1: Level
|
|
*/
|
|
uint64_t TriggerMode : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved1 : 2;
|
|
/** @brief Destination Shorthand
|
|
*
|
|
* 0: No shorthand
|
|
* 1: Self
|
|
* 2: All including self
|
|
* 3: All excluding self
|
|
*/
|
|
uint64_t DestinationShorthand : 2;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved2 : 12;
|
|
};
|
|
uint64_t raw;
|
|
} __packed InterruptCommandRegisterLow;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
/** @brief Reserved */
|
|
uint64_t Reserved0 : 24;
|
|
/** @brief Destination */
|
|
uint64_t Destination : 8;
|
|
};
|
|
uint64_t raw;
|
|
} __packed InterruptCommandRegisterHigh;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
/** @brief Interrupt Vector */
|
|
uint64_t Vector : 8;
|
|
/** @brief Delivery Mode */
|
|
uint64_t DeliveryMode : 3;
|
|
/** @brief Destination Mode
|
|
*
|
|
* 0: Physical
|
|
* 1: Logical
|
|
*/
|
|
uint64_t DestinationMode : 1;
|
|
/** @brief Delivery Status */
|
|
uint64_t DeliveryStatus : 1;
|
|
/** @brief Interrupt Input Pin Polarity
|
|
*
|
|
* 0: Active High
|
|
* 1: Active Low
|
|
*/
|
|
uint64_t Polarity : 1;
|
|
/** @brief Remote IRR */
|
|
uint64_t RemoteIRR : 1;
|
|
/** @brief Trigger Mode
|
|
*
|
|
* 0: Edge
|
|
* 1: Level
|
|
*/
|
|
uint64_t TriggerMode : 1;
|
|
/** @brief Mask */
|
|
uint64_t Mask : 1;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved0 : 15;
|
|
/** @brief Reserved */
|
|
uint64_t Reserved1 : 24;
|
|
/** @brief Destination */
|
|
uint64_t DestinationID : 8;
|
|
};
|
|
struct
|
|
{
|
|
uint64_t Low;
|
|
uint64_t High;
|
|
} split;
|
|
uint64_t raw;
|
|
} __packed IOAPICRedirectEntry;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint64_t Version : 8;
|
|
uint64_t Reserved : 8;
|
|
uint64_t MaximumRedirectionEntry : 8;
|
|
uint64_t Reserved2 : 8;
|
|
};
|
|
uint64_t raw;
|
|
} __packed IOAPICVersion;
|
|
|
|
class APIC
|
|
{
|
|
private:
|
|
bool x2APICSupported = false;
|
|
uint64_t APICBaseAddress = 0;
|
|
|
|
public:
|
|
decltype(x2APICSupported) &x2APIC = x2APICSupported;
|
|
|
|
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);
|
|
uint32_t IORead(uint64_t Base, uint32_t Register);
|
|
void EOI();
|
|
void RedirectIRQs(int CPU = 0);
|
|
void WaitForIPI();
|
|
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
|
|
void SendInitIPI(uint8_t CPU);
|
|
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
|
|
uint32_t IOGetMaxRedirect(uint32_t APICID);
|
|
void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
|
|
void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
|
|
APIC(int Core);
|
|
~APIC();
|
|
};
|
|
|
|
class Timer : public Interrupts::Handler
|
|
{
|
|
private:
|
|
APIC *lapic;
|
|
uint64_t Ticks = 0;
|
|
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
|
|
|
public:
|
|
uint64_t GetTicks() { return Ticks; }
|
|
void OneShot(uint32_t Vector, uint64_t Miliseconds);
|
|
Timer(APIC *apic);
|
|
~Timer();
|
|
};
|
|
}
|
|
|
|
#endif // !__FENNIX_KERNEL_APIC_H__
|