From 0a2d520b1537c720d4c8f6e8fc42aa9d351800bc Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 23 Apr 2024 20:26:11 +0300 Subject: [PATCH] Kernel: Handle CLINT interrupts separately from normal interrupts Since CLINT interrupts are wired directly into the hart, instead of going through an interrupt controller (the PLIC), trying to handle them through the normal numbered-interrupt mechanism will just complicate it for no reason. Instead we now handle them directly in the trap handler. --- Kernel/Arch/riscv64/Interrupts.cpp | 13 ++++++------ Kernel/Arch/riscv64/Timer.cpp | 32 +++++++++++++----------------- Kernel/Arch/riscv64/Timer.h | 18 +++++++++++++---- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/Kernel/Arch/riscv64/Interrupts.cpp b/Kernel/Arch/riscv64/Interrupts.cpp index eab69888f21..4a26e988e72 100644 --- a/Kernel/Arch/riscv64/Interrupts.cpp +++ b/Kernel/Arch/riscv64/Interrupts.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -52,13 +53,11 @@ extern "C" void trap_handler(TrapFrame& trap_frame) Processor::current().enter_trap(trap_frame, true); - auto interrupt_number = to_underlying(scause) & ~RISCV64::CSR::SCAUSE_INTERRUPT_MASK; - - auto* handler = s_interrupt_handlers[interrupt_number]; - VERIFY(handler); - handler->increment_call_count(); - handler->handle_interrupt(*trap_frame.regs); - handler->eoi(); + if (scause == RISCV64::CSR::SCAUSE::SupervisorTimerInterrupt) { + RISCV64::Timer::the().handle_interrupt(*trap_frame.regs); + } else { + TODO_RISCV64(); + } Processor::current().exit_trap(trap_frame); } else { diff --git a/Kernel/Arch/riscv64/Timer.cpp b/Kernel/Arch/riscv64/Timer.cpp index 9ee1a5329a5..812d68d70d5 100644 --- a/Kernel/Arch/riscv64/Timer.cpp +++ b/Kernel/Arch/riscv64/Timer.cpp @@ -5,43 +5,48 @@ */ #include -#include #include #include #include namespace Kernel::RISCV64 { +static Timer* s_the; + Timer::Timer() - : HardwareTimer(to_underlying(CSR::SCAUSE::SupervisorTimerInterrupt) & ~CSR::SCAUSE_INTERRUPT_MASK) { m_frequency = DeviceTree::get().resolve_property("/cpus/timebase-frequency"sv).value().as(); m_interrupt_interval = m_frequency / OPTIMAL_TICKS_PER_SECOND_RATE; set_compare(current_ticks() + m_interrupt_interval); - RISCV64::CSR::set_bits(RISCV64::CSR::Address::SIE, 1 << interrupt_number()); + RISCV64::CSR::set_bits(RISCV64::CSR::Address::SIE, 1 << (to_underlying(CSR::SCAUSE::SupervisorTimerInterrupt) & ~CSR::SCAUSE_INTERRUPT_MASK)); } NonnullLockRefPtr Timer::initialize() { + VERIFY(!s_the); auto timer = adopt_lock_ref(*new Timer); - timer->register_interrupt_handler(); + s_the = timer.ptr(); return timer; } +Timer& Timer::the() +{ + VERIFY(s_the); + return *s_the; +} + u64 Timer::current_ticks() { return RISCV64::CSR::read(RISCV64::CSR::Address::TIME); } -bool Timer::handle_interrupt(RegisterState const& regs) +void Timer::handle_interrupt(RegisterState const& regs) { - auto result = HardwareTimer::handle_interrupt(regs); - + if (m_callback) + m_callback(regs); set_compare(current_ticks() + m_interrupt_interval); - - return result; } u64 Timer::update_time(u64& seconds_since_boot, u32& ticks_this_second, bool query_only) @@ -77,12 +82,3 @@ void Timer::set_compare(u64 compare) } } - -namespace Kernel { - -bool HardwareTimer::eoi() -{ - return true; -} - -} diff --git a/Kernel/Arch/riscv64/Timer.h b/Kernel/Arch/riscv64/Timer.h index baabe22be63..6fe1ccf6596 100644 --- a/Kernel/Arch/riscv64/Timer.h +++ b/Kernel/Arch/riscv64/Timer.h @@ -13,12 +13,14 @@ namespace Kernel::RISCV64 { -class Timer final : public HardwareTimer { +class Timer final : public HardwareTimerBase { public: static NonnullLockRefPtr initialize(); + static Timer& the(); virtual HardwareTimerType timer_type() const override { return HardwareTimerType::RISCVTimer; } virtual StringView model() const override { return "RISC-V Timer"sv; } + virtual size_t ticks_per_second() const override { return m_frequency; } virtual bool is_periodic() const override { TODO_RISCV64(); } virtual bool is_periodic_capable() const override { TODO_RISCV64(); } @@ -31,8 +33,17 @@ public: virtual bool is_capable_of_frequency(size_t) const override { TODO_RISCV64(); } virtual size_t calculate_nearest_possible_frequency(size_t) const override { TODO_RISCV64(); } + virtual void will_be_destroyed() override { } + virtual Function set_callback(Function callback) override + { + auto previous_callback = move(m_callback); + m_callback = move(callback); + return previous_callback; + } + // FIXME: Share code with HPET::update_time u64 update_time(u64& seconds_since_boot, u32& ticks_this_second, bool query_only); + void handle_interrupt(RegisterState const&); private: Timer(); @@ -40,9 +51,8 @@ private: static u64 current_ticks(); static void set_compare(u64 compare); - //^ GenericInterruptHandler - virtual bool handle_interrupt(RegisterState const&) override; - + Function m_callback; + u64 m_frequency { 0 }; u32 m_interrupt_interval { 0 }; u64 m_main_counter_last_read { 0 };