Kernel: Rework interrupt mechanism

All interruptrable classes now inherit from Interruptable which
has methdo handle_irq which is called on a interrupt.
This commit is contained in:
2023-10-05 18:53:45 +03:00
parent 68a913c838
commit 27eb5af6f0
23 changed files with 716 additions and 706 deletions

View File

@@ -4,51 +4,56 @@
#include <kernel/InterruptController.h>
#include <kernel/Memory/Types.h>
class APIC final : public InterruptController
namespace Kernel
{
public:
virtual void eoi(uint8_t) override;
virtual void enable_irq(uint8_t) override;
virtual bool is_in_service(uint8_t) override;
private:
uint32_t read_from_local_apic(ptrdiff_t);
void write_to_local_apic(ptrdiff_t, uint32_t);
private:
~APIC() { ASSERT_NOT_REACHED(); }
static APIC* create();
friend class InterruptController;
private:
struct Processor
class APIC final : public InterruptController
{
enum Flags : uint8_t
public:
virtual void eoi(uint8_t) override;
virtual void enable_irq(uint8_t) override;
virtual bool is_in_service(uint8_t) override;
private:
uint32_t read_from_local_apic(ptrdiff_t);
void write_to_local_apic(ptrdiff_t, uint32_t);
private:
~APIC() { ASSERT_NOT_REACHED(); }
static APIC* create();
friend class InterruptController;
private:
struct Processor
{
Enabled = 1,
OnlineCapable = 2,
enum Flags : uint8_t
{
Enabled = 1,
OnlineCapable = 2,
};
uint8_t processor_id;
uint8_t apic_id;
uint8_t flags;
};
uint8_t processor_id;
uint8_t apic_id;
uint8_t flags;
struct IOAPIC
{
uint8_t id;
Kernel::paddr_t paddr;
Kernel::vaddr_t vaddr;
uint32_t gsi_base;
uint8_t max_redirs;
uint32_t read(uint8_t offset);
void write(uint8_t offset, uint32_t data);
};
private:
BAN::Vector<Processor> m_processors;
Kernel::paddr_t m_local_apic_paddr = 0;
Kernel::vaddr_t m_local_apic_vaddr = 0;
BAN::Vector<IOAPIC> m_io_apics;
uint8_t m_irq_overrides[0x100] {};
};
struct IOAPIC
{
uint8_t id;
Kernel::paddr_t paddr;
Kernel::vaddr_t vaddr;
uint32_t gsi_base;
uint8_t max_redirs;
uint32_t read(uint8_t offset);
void write(uint8_t offset, uint32_t data);
};
private:
BAN::Vector<Processor> m_processors;
Kernel::paddr_t m_local_apic_paddr = 0;
Kernel::vaddr_t m_local_apic_vaddr = 0;
BAN::Vector<IOAPIC> m_io_apics;
uint8_t m_irq_overrides[0x100] {};
};
}

View File

@@ -4,11 +4,10 @@
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
namespace IDT
namespace Kernel::IDT
{
void initialize();
void register_irq_handler(uint8_t irq, void(*f)());
[[noreturn]] void force_triple_fault();
}

View File

@@ -0,0 +1,97 @@
#pragma once
#include <stdint.h>
namespace Kernel::Input::PS2
{
enum IOPort : uint8_t
{
DATA = 0x60,
STATUS = 0x64,
COMMAND = 0x64,
};
enum Status : uint8_t
{
OUTPUT_FULL = (1 << 0),
INPUT_FULL = (1 << 1),
SYSTEM = (1 << 2),
DEVICE_OR_CONTROLLER = (1 << 3),
TIMEOUT_ERROR = (1 << 6),
PARITY_ERROR = (1 << 7),
};
enum Config : uint8_t
{
INTERRUPT_FIRST_PORT = (1 << 0),
INTERRUPT_SECOND_PORT = (1 << 1),
SYSTEM_FLAG = (1 << 2),
ZERO1 = (1 << 3),
CLOCK_FIRST_PORT = (1 << 4),
CLOCK_SECOND_PORT = (1 << 5),
TRANSLATION_FIRST_PORT = (1 << 6),
ZERO2 = (1 << 7),
};
enum Command : uint8_t
{
READ_CONFIG = 0x20,
WRITE_CONFIG = 0x60,
DISABLE_SECOND_PORT = 0xA7,
ENABLE_SECOND_PORT = 0xA8,
TEST_SECOND_PORT = 0xA9,
TEST_CONTROLLER = 0xAA,
TEST_FIRST_PORT = 0xAB,
DISABLE_FIRST_PORT = 0xAD,
ENABLE_FIRST_PORT = 0xAE,
WRITE_TO_SECOND_PORT = 0xD4,
};
enum Response : uint8_t
{
TEST_FIRST_PORT_PASS = 0x00,
TEST_SECOND_PORT_PASS = 0x00,
TEST_CONTROLLER_PASS = 0x55,
SELF_TEST_PASS = 0xAA,
ACK = 0xFA,
};
enum DeviceCommand : uint8_t
{
ENABLE_SCANNING = 0xF4,
DISABLE_SCANNING = 0xF5,
IDENTIFY = 0xF2,
RESET = 0xFF,
};
enum IRQ : uint8_t
{
DEVICE0 = 1,
DEVICE1 = 12,
};
enum KBResponse : uint8_t
{
KEY_ERROR_OR_BUFFER_OVERRUN1 = 0x00,
SELF_TEST_PASSED = 0xAA,
ECHO_RESPONSE = 0xEE,
RESEND = 0xFE,
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
};
enum KBScancode : uint8_t
{
SET_SCANCODE_SET1 = 1,
SET_SCANCODE_SET2 = 2,
SET_SCANCODE_SET3 = 3,
};
enum KBLeds : uint8_t
{
SCROLL_LOCK = (1 << 0),
NUM_LOCK = (1 << 1),
CAPS_LOCK = (1 << 2),
};
}

View File

@@ -1,16 +1,16 @@
#pragma once
#include <kernel/Device/Device.h>
#include <kernel/InterruptController.h>
namespace Kernel::Input
{
class PS2Device : public CharacterDevice
class PS2Device : public CharacterDevice, public Interruptable
{
public:
virtual ~PS2Device() {}
virtual void on_byte(uint8_t) = 0;
public:
PS2Device()
: CharacterDevice(Mode::IRUSR | Mode::IRGRP, 0, 0)
@@ -33,11 +33,8 @@ namespace Kernel::Input
BAN::ErrorOr<void> reset_device(uint8_t);
BAN::ErrorOr<void> set_scanning(uint8_t, bool);
static void device0_irq();
static void device1_irq();
private:
PS2Device* m_devices[2] { nullptr, nullptr };
};
}
}

View File

@@ -29,7 +29,7 @@ namespace Kernel::Input
public:
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
virtual void on_byte(uint8_t) override;
virtual void handle_irq() override;
virtual void update() override;
private:

View File

@@ -5,22 +5,42 @@
#define DISABLE_INTERRUPTS() asm volatile("cli")
#define ENABLE_INTERRUPTS() asm volatile("sti")
class InterruptController
namespace Kernel
{
public:
virtual ~InterruptController() {}
virtual void eoi(uint8_t) = 0;
virtual void enable_irq(uint8_t) = 0;
virtual bool is_in_service(uint8_t) = 0;
class Interruptable
{
public:
Interruptable() = default;
static void initialize(bool force_pic);
static InterruptController& get();
void set_irq(int irq);
void enable_interrupt();
void disable_interrupt();
void enter_acpi_mode();
virtual void handle_irq() = 0;
private:
bool m_using_apic { false };
};
private:
int m_irq { -1 };
};
bool interrupts_enabled();
class InterruptController
{
public:
virtual ~InterruptController() {}
virtual void eoi(uint8_t) = 0;
virtual void enable_irq(uint8_t) = 0;
virtual bool is_in_service(uint8_t) = 0;
static void initialize(bool force_pic);
static InterruptController& get();
void enter_acpi_mode();
private:
bool m_using_apic { false };
};
bool interrupts_enabled();
}

View File

@@ -2,17 +2,22 @@
#include <kernel/InterruptController.h>
class PIC final : public InterruptController
namespace Kernel
{
public:
virtual void eoi(uint8_t) override;
virtual void enable_irq(uint8_t) override;
virtual bool is_in_service(uint8_t) override;
static void remap();
static void mask_all();
class PIC final : public InterruptController
{
public:
virtual void eoi(uint8_t) override;
virtual void enable_irq(uint8_t) override;
virtual bool is_in_service(uint8_t) override;
private:
static PIC* create();
friend class InterruptController;
};
static void remap();
static void mask_all();
private:
static PIC* create();
friend class InterruptController;
};
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <BAN/Errors.h>
#include <kernel/InterruptController.h>
#include <kernel/SpinLock.h>
#include <kernel/Storage/ATAController.h>
@@ -9,7 +10,7 @@ namespace Kernel
class ATADevice;
class ATABus
class ATABus : public Interruptable
{
public:
enum class DeviceType
@@ -27,7 +28,7 @@ namespace Kernel
ATAController& controller() { return m_controller; }
void on_irq();
virtual void handle_irq() override;
private:
ATABus(ATAController& controller, uint16_t base, uint16_t ctrl)

View File

@@ -1,6 +1,8 @@
#pragma once
#include <BAN/CircularQueue.h>
#include <BAN/Errors.h>
#include <kernel/InterruptController.h>
#include <kernel/Terminal/TTY.h>
namespace Kernel
@@ -34,7 +36,7 @@ namespace Kernel
uint32_t m_height { 0 };
};
class SerialTTY final : public TTY
class SerialTTY final : public TTY, public Interruptable
{
public:
static BAN::ErrorOr<BAN::RefPtr<SerialTTY>> create(Serial);
@@ -45,6 +47,8 @@ namespace Kernel
virtual void update() override;
virtual void handle_irq() override;
protected:
virtual BAN::StringView name() const override { return m_name; }
@@ -55,6 +59,7 @@ namespace Kernel
private:
BAN::String m_name;
Serial m_serial;
BAN::CircularQueue<uint8_t, 128> m_input;
public:
virtual dev_t rdev() const override { return m_rdev; }

View File

@@ -1,11 +1,12 @@
#pragma once
#include <kernel/InterruptController.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
{
class HPET final : public Timer
class HPET final : public Timer, public Interruptable
{
public:
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(bool force_pic);
@@ -13,6 +14,8 @@ namespace Kernel
virtual uint64_t ms_since_boot() const override;
virtual timespec time_since_boot() const override;
virtual void handle_irq() override;
private:
HPET() = default;
BAN::ErrorOr<void> initialize(bool force_pic);

View File

@@ -1,14 +1,12 @@
#pragma once
#include <kernel/InterruptController.h>
#include <kernel/Timer/Timer.h>
#include <stdint.h>
#define PIT_IRQ 0
namespace Kernel
{
class PIT final : public Timer
class PIT final : public Timer, public Interruptable
{
public:
static BAN::ErrorOr<BAN::UniqPtr<PIT>> create();
@@ -16,8 +14,13 @@ namespace Kernel
virtual uint64_t ms_since_boot() const override;
virtual timespec time_since_boot() const override;
virtual void handle_irq() override;
private:
void initialize();
private:
volatile uint64_t m_system_time { 0 };
};
}