summaryrefslogtreecommitdiff
path: root/kernel/irq.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /kernel/irq.cc
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz
lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'kernel/irq.cc')
-rw-r--r--kernel/irq.cc106
1 files changed, 106 insertions, 0 deletions
diff --git a/kernel/irq.cc b/kernel/irq.cc
new file mode 100644
index 0000000..4de468a
--- /dev/null
+++ b/kernel/irq.cc
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+/*
+ * IRQ Manager Implementation
+ *
+ * Lock-free dispatch path for interrupt context safety.
+ * Registration/unregistration is protected by atomic publish.
+ *
+ * Reference: docs/specs/trap.md §3.3
+ */
+
+#include <lume/console.h>
+#include <lume/errno.h>
+#include <lume/irq.h>
+
+/* Global singleton */
+IrqManager g_irq_manager;
+
+void IrqManager::init() {
+ for (uint32 i = 0; i < kMaxIrqs; i++) {
+ entries_[i].handler_ptr.store(0, __ATOMIC_RELAXED);
+ entries_[i].arg = nullptr;
+ }
+}
+
+int IrqManager::register_handler(uint32 irq, IrqHandler handler, void *arg) {
+ if (irq >= kMaxIrqs)
+ return -EINVAL;
+
+ if (!handler)
+ return -EINVAL;
+
+ /* Check if already registered (CAS from 0 to handler) */
+ uint64 expected = 0;
+ uint64 desired = reinterpret_cast<uint64>(handler);
+
+ /* Set arg first (before publishing handler) so dispatch sees valid arg */
+ entries_[irq].arg = arg;
+
+ if (!entries_[irq].handler_ptr.compare_exchange(expected, desired,
+ __ATOMIC_ACQ_REL)) {
+ /* Already registered by someone else */
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+void IrqManager::unregister_handler(uint32 irq) {
+ if (irq >= kMaxIrqs)
+ return;
+
+ /* Clear handler with release semantics */
+ entries_[irq].handler_ptr.store(0, __ATOMIC_RELEASE);
+ entries_[irq].arg = nullptr;
+}
+
+void IrqManager::dispatch(uint32 irq) {
+ if (irq >= kMaxIrqs)
+ return;
+
+ /* Load handler with acquire semantics — pairs with register's release */
+ uint64 h = entries_[irq].handler_ptr.load(__ATOMIC_ACQUIRE);
+ if (h == 0) {
+ /* Spurious or unregistered IRQ — silently ignore */
+ return;
+ }
+
+ auto handler = reinterpret_cast<IrqHandler>(h);
+ handler(irq, entries_[irq].arg);
+}
+
+bool IrqManager::has_handler(uint32 irq) const {
+ if (irq >= kMaxIrqs)
+ return false;
+ return entries_[irq].handler_ptr.load(__ATOMIC_ACQUIRE) != 0;
+}
+
+void IrqManager::set_chip(const IrqChip* chip) {
+ chip_ = chip;
+}
+
+uint32 IrqManager::claim() const {
+ return chip_ ? chip_->claim() : 0;
+}
+
+void IrqManager::complete(uint32 irq) const {
+ if (chip_) chip_->complete(irq);
+}
+
+void IrqManager::init_ap() const {
+ if (chip_ && chip_->init_ap) chip_->init_ap();
+}
+
+void IrqManager::enable(uint32 irq) const {
+ if (chip_ && chip_->enable) chip_->enable(irq);
+}
+
+void IrqManager::disable(uint32 irq) const {
+ if (chip_ && chip_->disable) chip_->disable(irq);
+}
+
+void IrqManager::set_priority(uint32 irq, uint32 priority) const {
+ if (chip_ && chip_->set_priority) chip_->set_priority(irq, priority);
+}