acpi/platform/
interrupt.rs

1use crate::ManagedSlice;
2use core::alloc::Allocator;
3
4#[derive(Debug, Clone, Copy)]
5pub struct IoApic {
6    pub id: u8,
7    /// The physical address at which to access this I/O APIC.
8    pub address: u32,
9    /// The global system interrupt number where this I/O APIC's inputs start.
10    pub global_system_interrupt_base: u32,
11}
12
13#[derive(Debug, Clone, Copy)]
14pub struct NmiLine {
15    pub processor: NmiProcessor,
16    pub line: LocalInterruptLine,
17}
18
19/// Indicates which local interrupt line will be utilized by an external interrupt. Specifically,
20/// these lines directly correspond to their requisite LVT entries in a processor's APIC.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum LocalInterruptLine {
23    Lint0,
24    Lint1,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum NmiProcessor {
29    All,
30    ProcessorUid(u32),
31}
32
33/// Polarity indicates what signal mode the interrupt line needs to be in to be considered 'active'.
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum Polarity {
36    SameAsBus,
37    ActiveHigh,
38    ActiveLow,
39}
40
41/// Trigger mode of an interrupt, describing how the interrupt is triggered.
42///
43/// When an interrupt is `Edge` triggered, it is triggered exactly once, when the interrupt
44/// signal goes from its opposite polarity to its active polarity.
45///
46/// For `Level` triggered interrupts, a continuous signal is emitted so long as the interrupt
47/// is in its active polarity.
48///
49/// `SameAsBus`-triggered interrupts will utilize the same interrupt triggering as the system bus
50/// they communicate across.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum TriggerMode {
53    SameAsBus,
54    Edge,
55    Level,
56}
57
58/// Describes a difference in the mapping of an ISA interrupt to how it's mapped in other interrupt
59/// models. For example, if a device is connected to ISA IRQ 0 and IOAPIC input 2, an override will
60/// appear mapping source 0 to GSI 2. Currently these will only be created for ISA interrupt
61/// sources.
62#[derive(Debug, Clone, Copy)]
63pub struct InterruptSourceOverride {
64    pub isa_source: u8,
65    pub global_system_interrupt: u32,
66    pub polarity: Polarity,
67    pub trigger_mode: TriggerMode,
68}
69
70/// Describes a Global System Interrupt that should be enabled as non-maskable. Any source that is
71/// non-maskable can not be used by devices.
72#[derive(Debug, Clone, Copy)]
73pub struct NmiSource {
74    pub global_system_interrupt: u32,
75    pub polarity: Polarity,
76    pub trigger_mode: TriggerMode,
77}
78
79#[derive(Debug, Clone)]
80pub struct Apic<'a, A>
81where
82    A: Allocator,
83{
84    pub local_apic_address: u64,
85    pub io_apics: ManagedSlice<'a, IoApic, A>,
86    pub local_apic_nmi_lines: ManagedSlice<'a, NmiLine, A>,
87    pub interrupt_source_overrides: ManagedSlice<'a, InterruptSourceOverride, A>,
88    pub nmi_sources: ManagedSlice<'a, NmiSource, A>,
89
90    /// If this field is set, you must remap and mask all the lines of the legacy PIC, even if
91    /// you choose to use the APIC. It's recommended that you do this even if ACPI does not
92    /// require you to.
93    pub also_has_legacy_pics: bool,
94}
95
96impl<'a, A> Apic<'a, A>
97where
98    A: Allocator,
99{
100    pub(crate) fn new(
101        local_apic_address: u64,
102        io_apics: ManagedSlice<'a, IoApic, A>,
103        local_apic_nmi_lines: ManagedSlice<'a, NmiLine, A>,
104        interrupt_source_overrides: ManagedSlice<'a, InterruptSourceOverride, A>,
105        nmi_sources: ManagedSlice<'a, NmiSource, A>,
106        also_has_legacy_pics: bool,
107    ) -> Self {
108        Self {
109            local_apic_address,
110            io_apics,
111            local_apic_nmi_lines,
112            interrupt_source_overrides,
113            nmi_sources,
114            also_has_legacy_pics,
115        }
116    }
117}
118
119#[derive(Debug, Clone)]
120#[non_exhaustive]
121pub enum InterruptModel<'a, A>
122where
123    A: Allocator,
124{
125    /// This model is only chosen when the MADT does not describe another interrupt model. On `x86_64` platforms,
126    /// this probably means only the legacy i8259 PIC is present.
127    Unknown,
128
129    /// Describes an interrupt controller based around the Advanced Programmable Interrupt Controller (any of APIC,
130    /// XAPIC, or X2APIC). These are likely to be found on x86 and x86_64 systems and are made up of a Local APIC
131    /// for each core and one or more I/O APICs to handle external interrupts.
132    Apic(Apic<'a, A>),
133}