The Pedigree Project 0.1
PciMessageInterrupts.h
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#ifndef PEDIGREE_PC_PCI_MESSAGE_INTERRUPTS_H
3#define PEDIGREE_PC_PCI_MESSAGE_INTERRUPTS_H
4
5#include <config.h>
6
7#if MULTIPROCESSOR
8
9#include "pedigree/kernel/Spinlock.h"
10#include "pedigree/kernel/machine/IrqHandlerRegistry.h"
11#include "pedigree/kernel/machine/ThreadedIrqDispatcher.h"
12#include "pedigree/kernel/process/Mutex.h"
13#include "pedigree/kernel/processor/InterruptHandler.h"
14
15class Device;
16class HardIrqHandler;
17class IrqHandler;
18class IrqHandlerBase;
19
21class PciMessageInterrupts : private InterruptHandler {
22 public:
23 static constexpr uint8_t FirstVector = 0x40;
24 static constexpr uint8_t VectorCount = 64;
25
26 PciMessageInterrupts();
27
28 bool initialise();
29 bool initialiseThreaded();
30 bool shutdownThreaded();
31 irq_id_t registerThreaded(Device* device, IrqHandler* handler, bool& fallbackSafe);
32 bool registerThreadedVectors(Device* device, IrqHandler* const* handlers, size_t count,
33 irq_id_t* ids, bool& fallbackSafe,
34 const size_t* processors = nullptr);
35 irq_id_t registerHard(Device* device, HardIrqHandler* handler, bool& fallbackSafe);
36 bool unregisterHandler(irq_id_t id, IrqHandlerBase* handler);
37 void enable(irq_id_t id, bool enabled);
38
39 static bool contains(irq_id_t id) {
40 return id >= FirstVector && id < FirstVector + VectorCount;
41 }
42
43 private:
44 enum class Mode : uint8_t { None, Threaded, Hard };
45 struct Line {
46 Device* device = nullptr;
47 IrqHandlerBase* handler = nullptr;
48 Mode mode = Mode::None;
49 size_t cookie = 0;
50 // Exposed vectors keep their destination; late posted messages may remain.
51 size_t processor = 0;
52 bool used = false;
53 bool workerPrepared = false;
54 bool reusable = false;
55 bool spuriousSafe = false;
56 bool enabled = false;
57 bool removing = false;
58 bool deferred = false;
59 bool msix = false;
60 uint8_t msixIndex = 0;
61 uint8_t unhandled = 0;
62 };
63
64 static size_t advanceCookie(Line& line) {
65 if (!++line.cookie) {
66 ++line.cookie;
67 }
68 return line.cookie;
69 }
70
71 irq_id_t registerHandler(Device* device, IrqHandlerBase* handler, Mode mode, bool& fallbackSafe);
72 bool disableSource(Device* device, bool msix, uint8_t msixIndex);
73 void quarantine(uint8_t slot, size_t expectedCookie = 0);
74 void interrupt(size_t interruptNumber, InterruptState& state) override;
75 static void dispatchThreaded(void* context, uint8_t slot, size_t cookie);
76
77 Mutex m_RegistrationLock;
78 Spinlock m_Lock;
79 IrqHandlerRegistry m_Handlers;
80 ThreadedIrqDispatcher m_Dispatcher;
81 Line m_Lines[VectorCount];
82 uint8_t m_DestinationApicId;
83 bool m_Initialised;
84 bool m_ShuttingDown;
85};
86
87#endif
88
89#endif
Abstract base class for interrupt-handlers.
Definition Mutex.h:56