mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-28 21:26:22 +00:00
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.
This commit is contained in:
parent
002bba4a97
commit
0a2d520b15
Notes:
sideshowbarker
2024-07-17 02:29:45 +09:00
Author: https://github.com/IdanHo
Commit: 0a2d520b15
Pull-request: https://github.com/SerenityOS/serenity/pull/24117
Reviewed-by: https://github.com/ADKaster
Reviewed-by: https://github.com/spholz
3 changed files with 34 additions and 29 deletions
|
@ -13,6 +13,7 @@
|
|||
#include <Kernel/Arch/PageFault.h>
|
||||
#include <Kernel/Arch/TrapFrame.h>
|
||||
#include <Kernel/Arch/riscv64/InterruptManagement.h>
|
||||
#include <Kernel/Arch/riscv64/Timer.h>
|
||||
#include <Kernel/Interrupts/GenericInterruptHandler.h>
|
||||
#include <Kernel/Interrupts/SharedIRQHandler.h>
|
||||
#include <Kernel/Interrupts/UnhandledInterruptHandler.h>
|
||||
|
@ -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 {
|
||||
|
|
|
@ -5,43 +5,48 @@
|
|||
*/
|
||||
|
||||
#include <AK/Format.h>
|
||||
#include <AK/NeverDestroyed.h>
|
||||
#include <Kernel/Arch/riscv64/CPU.h>
|
||||
#include <Kernel/Arch/riscv64/SBI.h>
|
||||
#include <Kernel/Arch/riscv64/Timer.h>
|
||||
|
||||
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<u32>();
|
||||
|
||||
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> 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<GenericInterruptHandler>::eoi()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
|
||||
namespace Kernel::RISCV64 {
|
||||
|
||||
class Timer final : public HardwareTimer<GenericInterruptHandler> {
|
||||
class Timer final : public HardwareTimerBase {
|
||||
public:
|
||||
static NonnullLockRefPtr<Timer> 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<void(RegisterState const&)> set_callback(Function<void(RegisterState const&)> 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<void(RegisterState const&)> m_callback;
|
||||
u64 m_frequency { 0 };
|
||||
u32 m_interrupt_interval { 0 };
|
||||
|
||||
u64 m_main_counter_last_read { 0 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue