Skip to content

Commit

Permalink
Kernel/Interrupts: Return boolean on whether we handled the interrupt
Browse files Browse the repository at this point in the history
If we are in a shared interrupt handler, the called handlers might
indicate it was not their interrupt, so we should not increment the
call counter of these handlers.
  • Loading branch information
supercomputer7 authored and awesomekling committed Jun 17, 2021
1 parent 7a6d5a7 commit b91df26
Show file tree
Hide file tree
Showing 43 changed files with 125 additions and 71 deletions.
2 changes: 1 addition & 1 deletion Kernel/ACPI/DynamicParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ UNMAP_AFTER_INIT DynamicParser::DynamicParser(PhysicalAddress rsdp)
dmesgln("ACPI: Dynamic Parsing Enabled, Can parse AML");
}

void DynamicParser::handle_irq(const RegisterState&)
bool DynamicParser::handle_irq(const RegisterState&)
{
// FIXME: Implement IRQ handling of ACPI signals!
VERIFY_NOT_REACHED();
Expand Down
2 changes: 1 addition & 1 deletion Kernel/ACPI/DynamicParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class DynamicParser final
private:
void build_namespace();
// ^IRQHandler
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;

OwnPtr<Region> m_acpi_namespace;
};
Expand Down
9 changes: 5 additions & 4 deletions Kernel/Devices/HID/I8042Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,25 +129,26 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices()
m_mouse_device->enable_interrupts();
}

void I8042Controller::irq_process_input_buffer(HIDDevice::Type)
bool I8042Controller::irq_process_input_buffer(HIDDevice::Type)
{
VERIFY(Processor::current().in_irq());

u8 status = IO::in8(I8042_STATUS);
if (!(status & I8042_BUFFER_FULL))
return;
return false;
HIDDevice::Type data_for_device = ((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) ? HIDDevice::Type::Mouse : HIDDevice::Type::Keyboard;
u8 byte = IO::in8(I8042_BUFFER);
if (data_for_device == HIDDevice::Type::Mouse) {
VERIFY(m_mouse_device);
static_cast<PS2MouseDevice&>(*m_mouse_device).irq_handle_byte_read(byte);
return;
return true;
}
if (data_for_device == HIDDevice::Type::Keyboard) {
VERIFY(m_keyboard_device);
static_cast<PS2KeyboardDevice&>(*m_keyboard_device).irq_handle_byte_read(byte);
return;
return true;
}
return false;
}

void I8042Controller::do_drain()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Devices/HID/I8042Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class I8042Controller : public RefCounted<I8042Controller> {
void prepare_for_output();
void prepare_for_input(HIDDevice::Type);

void irq_process_input_buffer(HIDDevice::Type);
bool irq_process_input_buffer(HIDDevice::Type);

RefPtr<MouseDevice> mouse() const;
RefPtr<KeyboardDevice> keyboard() const;
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Devices/HID/PS2KeyboardDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ void PS2KeyboardDevice::irq_handle_byte_read(u8 byte)
}
}

void PS2KeyboardDevice::handle_irq(const RegisterState&)
bool PS2KeyboardDevice::handle_irq(const RegisterState&)
{
// The controller will read the data and call irq_handle_byte_read
// for the appropriate device
m_i8042_controller->irq_process_input_buffer(HIDDevice::Type::Keyboard);
return m_i8042_controller->irq_process_input_buffer(HIDDevice::Type::Keyboard);
}

UNMAP_AFTER_INIT RefPtr<PS2KeyboardDevice> PS2KeyboardDevice::try_to_initialize(const I8042Controller& ps2_controller)
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Devices/HID/PS2KeyboardDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class PS2KeyboardDevice final : public IRQHandler
explicit PS2KeyboardDevice(const I8042Controller&);

// ^IRQHandler
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;

// ^CharacterDevice
virtual const char* class_name() const override { return "KeyboardDevice"; }
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Devices/HID/PS2MouseDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ UNMAP_AFTER_INIT PS2MouseDevice::~PS2MouseDevice()
{
}

void PS2MouseDevice::handle_irq(const RegisterState&)
bool PS2MouseDevice::handle_irq(const RegisterState&)
{
// The controller will read the data and call irq_handle_byte_read
// for the appropriate device
m_i8042_controller->irq_process_input_buffer(instrument_type());
return m_i8042_controller->irq_process_input_buffer(instrument_type());
}

void PS2MouseDevice::irq_handle_byte_read(u8 byte)
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Devices/HID/PS2MouseDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PS2MouseDevice : public IRQHandler
protected:
explicit PS2MouseDevice(const I8042Controller&);
// ^IRQHandler
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;

struct RawPacket {
union {
Expand Down
5 changes: 4 additions & 1 deletion Kernel/Devices/SB16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,10 @@ void SB16::dma_start(uint32_t length)
IO::out8(0xd4, (channel % 4));
}

void SB16::handle_irq(const RegisterState&)
bool SB16::handle_irq(const RegisterState&)
{
// FIXME: Check if the interrupt was actually for us or not... (shared IRQs)

// Stop sound output ready for the next block.
dsp_write(0xd5);

Expand All @@ -215,6 +217,7 @@ void SB16::handle_irq(const RegisterState&)
IO::in8(DSP_R_ACK); // 16 bit interrupt

m_irq_queue.wake_all();
return true;
}

void SB16::wait_for_irq()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Devices/SB16.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SB16 final : public IRQHandler

private:
// ^IRQHandler
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;

// ^CharacterDevice
virtual const char* class_name() const override { return "SB16"; }
Expand Down
5 changes: 3 additions & 2 deletions Kernel/Devices/USB/UHCIController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,13 @@ void UHCIController::spawn_port_proc()
});
}

void UHCIController::handle_irq(const RegisterState&)
bool UHCIController::handle_irq(const RegisterState&)
{
u32 status = read_usbsts();

// Shared IRQ. Not ours!
if (!status)
return;
return false;

if constexpr (UHCI_DEBUG) {
dbgln("UHCI: Interrupt happened!");
Expand All @@ -601,6 +601,7 @@ void UHCIController::handle_irq(const RegisterState&)

// Write back USBSTS to clear bits
write_usbsts(status);
return true;
}

}
2 changes: 1 addition & 1 deletion Kernel/Devices/USB/UHCIController.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class UHCIController final : public PCI::Device {
void write_portsc1(u16 value) { m_io_base.offset(0x10).out(value); }
void write_portsc2(u16 value) { m_io_base.offset(0x12).out(value); }

virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;

void create_structures();
void setup_schedule();
Expand Down
10 changes: 6 additions & 4 deletions Kernel/Interrupts/APIC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class APICIPIInterruptHandler final : public GenericInterruptHandler {
handler->register_interrupt_handler();
}

virtual void handle_interrupt(const RegisterState&) override;
virtual bool handle_interrupt(const RegisterState&) override;

virtual bool eoi() override;

Expand Down Expand Up @@ -101,7 +101,7 @@ class APICErrInterruptHandler final : public GenericInterruptHandler {
handler->register_interrupt_handler();
}

virtual void handle_interrupt(const RegisterState&) override;
virtual bool handle_interrupt(const RegisterState&) override;

virtual bool eoi() override;

Expand Down Expand Up @@ -555,9 +555,10 @@ u32 APIC::get_timer_divisor()
return 16;
}

void APICIPIInterruptHandler::handle_interrupt(const RegisterState&)
bool APICIPIInterruptHandler::handle_interrupt(const RegisterState&)
{
dbgln_if(APIC_SMP_DEBUG, "APIC IPI on CPU #{}", Processor::id());
return true;
}

bool APICIPIInterruptHandler::eoi()
Expand All @@ -567,9 +568,10 @@ bool APICIPIInterruptHandler::eoi()
return true;
}

void APICErrInterruptHandler::handle_interrupt(const RegisterState&)
bool APICErrInterruptHandler::handle_interrupt(const RegisterState&)
{
dbgln("APIC: SMP error on CPU #{}", Processor::id());
return true;
}

bool APICErrInterruptHandler::eoi()
Expand Down
4 changes: 3 additions & 1 deletion Kernel/Interrupts/GenericInterruptHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class GenericInterruptHandler {
{
VERIFY(!m_registered);
}
virtual void handle_interrupt(const RegisterState& regs) = 0;
// Note: this method returns boolean value, to indicate if the handler handled
// the interrupt or not. This is useful for shared handlers mostly.
virtual bool handle_interrupt(const RegisterState& regs) = 0;

void will_be_destroyed();
bool is_registered() const { return m_registered; }
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Interrupts/IRQHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class IRQHandler : public GenericInterruptHandler {
public:
virtual ~IRQHandler();

virtual void handle_interrupt(const RegisterState& regs) { handle_irq(regs); }
virtual void handle_irq(const RegisterState&) = 0;
virtual bool handle_interrupt(const RegisterState& regs) { return handle_irq(regs); }
virtual bool handle_irq(const RegisterState&) = 0;

void enable_irq();
void disable_irq();
Expand Down
11 changes: 7 additions & 4 deletions Kernel/Interrupts/SharedIRQHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,27 @@ SharedIRQHandler::~SharedIRQHandler()
disable_interrupt_vector();
}

void SharedIRQHandler::handle_interrupt(const RegisterState& regs)
bool SharedIRQHandler::handle_interrupt(const RegisterState& regs)
{
VERIFY_INTERRUPTS_DISABLED();

if constexpr (INTERRUPT_DEBUG) {
dbgln("Interrupt @ {}", interrupt_number());
dbgln("Interrupt Handlers registered - {}", m_handlers.size());
}

int i = 0;
bool was_handled = false;
for (auto* handler : m_handlers) {
dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {}", i, interrupt_number());
VERIFY(handler != nullptr);
handler->increment_invoking_counter();
handler->handle_interrupt(regs);
if (handler->handle_interrupt(regs)) {
handler->increment_invoking_counter();
was_handled = true;
}
dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {} - End", i, interrupt_number());
i++;
}
return was_handled;
}

void SharedIRQHandler::enable_interrupt_vector()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Interrupts/SharedIRQHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SharedIRQHandler final : public GenericInterruptHandler {
public:
static void initialize(u8 interrupt_number);
virtual ~SharedIRQHandler();
virtual void handle_interrupt(const RegisterState& regs) override;
virtual bool handle_interrupt(const RegisterState& regs) override;

void register_handler(GenericInterruptHandler&);
void unregister_handler(GenericInterruptHandler&);
Expand Down
11 changes: 7 additions & 4 deletions Kernel/Interrupts/SpuriousInterruptHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,19 @@ SpuriousInterruptHandler::~SpuriousInterruptHandler()
{
}

void SpuriousInterruptHandler::handle_interrupt(const RegisterState& state)
bool SpuriousInterruptHandler::handle_interrupt(const RegisterState& state)
{
// Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ.
if (m_responsible_irq_controller->get_isr() & (1 << interrupt_number())) {
m_real_irq = true; // remember that we had a real IRQ, when EOI later!
m_real_handler->increment_invoking_counter();
m_real_handler->handle_interrupt(state);
return;
if (m_real_handler->handle_interrupt(state)) {
m_real_handler->increment_invoking_counter();
return true;
}
return false;
}
dbgln("Spurious interrupt, vector {}", interrupt_number());
return true;
}

void SpuriousInterruptHandler::enable_interrupt_vector()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Interrupts/SpuriousInterruptHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SpuriousInterruptHandler final : public GenericInterruptHandler {
public:
static void initialize(u8 interrupt_number);
virtual ~SpuriousInterruptHandler();
virtual void handle_interrupt(const RegisterState& regs) override;
virtual bool handle_interrupt(const RegisterState& regs) override;

void register_handler(GenericInterruptHandler&);
void unregister_handler(GenericInterruptHandler&);
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Interrupts/UnhandledInterruptHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ UnhandledInterruptHandler::UnhandledInterruptHandler(u8 interrupt_vector)
{
}

void UnhandledInterruptHandler::handle_interrupt(const RegisterState&)
bool UnhandledInterruptHandler::handle_interrupt(const RegisterState&)
{
PANIC("Interrupt: Unhandled vector {} was invoked for handle_interrupt(RegisterState&).", interrupt_number());
}
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Interrupts/UnhandledInterruptHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class UnhandledInterruptHandler final : public GenericInterruptHandler {
explicit UnhandledInterruptHandler(u8 interrupt_vector);
virtual ~UnhandledInterruptHandler();

virtual void handle_interrupt(const RegisterState&) override;
virtual bool handle_interrupt(const RegisterState&) override;

[[noreturn]] virtual bool eoi() override;

Expand Down
6 changes: 5 additions & 1 deletion Kernel/Net/E1000NetworkAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,15 @@ UNMAP_AFTER_INIT E1000NetworkAdapter::~E1000NetworkAdapter()
{
}

void E1000NetworkAdapter::handle_irq(const RegisterState&)
bool E1000NetworkAdapter::handle_irq(const RegisterState&)
{
u32 status = in32(REG_INTERRUPT_CAUSE_READ);

m_entropy_source.add_random_event(status);

if (status == 0)
return false;

if (status & INTERRUPT_LSC) {
u32 flags = in32(REG_CTRL);
out32(REG_CTRL, flags | ECTRL_SLU);
Expand All @@ -253,6 +256,7 @@ void E1000NetworkAdapter::handle_irq(const RegisterState&)
m_wait_queue.wake_all();

out32(REG_INTERRUPT_CAUSE_READ, 0xffffffff);
return true;
}

UNMAP_AFTER_INIT void E1000NetworkAdapter::detect_eeprom()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Net/E1000NetworkAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class E1000NetworkAdapter : public NetworkAdapter
void setup_link();

E1000NetworkAdapter(PCI::Address, u8 irq);
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;
virtual const char* class_name() const override { return "E1000NetworkAdapter"; }

struct [[gnu::packed]] e1000_rx_desc {
Expand Down
6 changes: 5 additions & 1 deletion Kernel/Net/NE2000NetworkAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,13 @@ UNMAP_AFTER_INIT NE2000NetworkAdapter::~NE2000NetworkAdapter()
{
}

void NE2000NetworkAdapter::handle_irq(const RegisterState&)
bool NE2000NetworkAdapter::handle_irq(const RegisterState&)
{
u8 status = in8(REG_RW_INTERRUPTSTATUS);
dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Got interrupt, status={:#02x}", status);
if (status == 0) {
return false;
}

if (status & BIT_INTERRUPTMASK_PRX) {
dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Interrupt for packet received");
Expand Down Expand Up @@ -223,6 +226,7 @@ void NE2000NetworkAdapter::handle_irq(const RegisterState&)
m_wait_queue.wake_all();

out8(REG_RW_INTERRUPTSTATUS, status);
return true;
}

UNMAP_AFTER_INIT int NE2000NetworkAdapter::ram_test()
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Net/NE2000NetworkAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class NE2000NetworkAdapter final : public NetworkAdapter

private:
NE2000NetworkAdapter(PCI::Address, u8 irq);
virtual void handle_irq(const RegisterState&) override;
virtual bool handle_irq(const RegisterState&) override;
virtual const char* class_name() const override { return "NE2000NetworkAdapter"; }

int ram_test();
Expand Down
Loading

0 comments on commit b91df26

Please sign in to comment.