xref: /cloud-hypervisor/devices/src/interrupt_controller.rs (revision 1b91aa8ef3ba490a12853d41783ed558cf7b7060)
1e8c330e2SRuoqing He // Copyright © 2024 Institute of Software, CAS. All rights reserved.
2b32d3025SMichael Zhao // Copyright 2020, ARM Limited.
3b32d3025SMichael Zhao //
4b32d3025SMichael Zhao // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
5b32d3025SMichael Zhao 
661e57e1cSRuoqing He use std::{io, result};
788a9f799SRob Bradford 
889b429c7SSamrutGadde use thiserror::Error;
93bd47ffdSSebastien Boeuf use vmm_sys_util::eventfd::EventFd;
10b32d3025SMichael Zhao 
1189b429c7SSamrutGadde #[derive(Debug, Error)]
12b32d3025SMichael Zhao pub enum Error {
13b32d3025SMichael Zhao     /// Invalid trigger mode.
1489b429c7SSamrutGadde     #[error("Invalid trigger mode")]
15b32d3025SMichael Zhao     InvalidTriggerMode,
16b32d3025SMichael Zhao     /// Invalid delivery mode.
1789b429c7SSamrutGadde     #[error("Invalid delivery mode")]
18b32d3025SMichael Zhao     InvalidDeliveryMode,
19b32d3025SMichael Zhao     /// Failed creating the interrupt source group.
20*1b91aa8eSPhilipp Schuster     #[error("Failed creating the interrupt source group")]
2193b599e5SPhilipp Schuster     CreateInterruptSourceGroup(#[source] io::Error),
22b32d3025SMichael Zhao     /// Failed triggering the interrupt.
23*1b91aa8eSPhilipp Schuster     #[error("Failed triggering the interrupt")]
2493b599e5SPhilipp Schuster     TriggerInterrupt(#[source] io::Error),
25b32d3025SMichael Zhao     /// Failed masking the interrupt.
26*1b91aa8eSPhilipp Schuster     #[error("Failed masking the interrupt")]
2793b599e5SPhilipp Schuster     MaskInterrupt(#[source] io::Error),
28b32d3025SMichael Zhao     /// Failed unmasking the interrupt.
29*1b91aa8eSPhilipp Schuster     #[error("Failed unmasking the interrupt")]
3093b599e5SPhilipp Schuster     UnmaskInterrupt(#[source] io::Error),
31b32d3025SMichael Zhao     /// Failed updating the interrupt.
32*1b91aa8eSPhilipp Schuster     #[error("Failed updating the interrupt")]
3393b599e5SPhilipp Schuster     UpdateInterrupt(#[source] io::Error),
34b32d3025SMichael Zhao     /// Failed enabling the interrupt.
35*1b91aa8eSPhilipp Schuster     #[error("Failed enabling the interrupt")]
3693b599e5SPhilipp Schuster     EnableInterrupt(#[source] io::Error),
37b173f6f6SMichael Zhao     #[cfg(target_arch = "aarch64")]
38957d3a74SMichael Zhao     /// Failed creating GIC device.
39*1b91aa8eSPhilipp Schuster     #[error("Failed creating GIC device")]
40ab575a54SPhilipp Schuster     CreateGic(#[source] hypervisor::HypervisorVmError),
41b173f6f6SMichael Zhao     #[cfg(target_arch = "aarch64")]
42b173f6f6SMichael Zhao     /// Failed restoring GIC device.
43*1b91aa8eSPhilipp Schuster     #[error("Failed restoring GIC device")]
44ab575a54SPhilipp Schuster     RestoreGic(#[source] hypervisor::arch::aarch64::gic::Error),
45e8c330e2SRuoqing He     #[cfg(target_arch = "riscv64")]
46e8c330e2SRuoqing He     /// Failed creating AIA device.
47*1b91aa8eSPhilipp Schuster     #[error("Failed creating AIA device")]
48ab575a54SPhilipp Schuster     CreateAia(#[source] hypervisor::HypervisorVmError),
49e8c330e2SRuoqing He     #[cfg(target_arch = "riscv64")]
50e8c330e2SRuoqing He     /// Failed restoring AIA device.
51*1b91aa8eSPhilipp Schuster     #[error("Failed restoring AIA device")]
52ab575a54SPhilipp Schuster     RestoreAia(#[source] hypervisor::arch::riscv64::aia::Error),
53b32d3025SMichael Zhao }
54b32d3025SMichael Zhao 
55b32d3025SMichael Zhao type Result<T> = result::Result<T, Error>;
56b32d3025SMichael Zhao 
57b32d3025SMichael Zhao pub struct MsiMessage {
58b32d3025SMichael Zhao     // Message Address Register
59b32d3025SMichael Zhao     //   31-20: Base address. Fixed value (0x0FEE)
60b32d3025SMichael Zhao     //   19-12: Destination ID
61b32d3025SMichael Zhao     //   11-4:  Reserved
62b32d3025SMichael Zhao     //   3:     Redirection Hint indication
63b32d3025SMichael Zhao     //   2:     Destination Mode
64b32d3025SMichael Zhao     //   1-0:   Reserved
65b32d3025SMichael Zhao     pub addr: u32,
66b32d3025SMichael Zhao     // Message Data Register
67b32d3025SMichael Zhao     //   32-16: Reserved
68b32d3025SMichael Zhao     //   15:    Trigger Mode. 0 = Edge, 1 = Level
69b32d3025SMichael Zhao     //   14:    Level. 0 = Deassert, 1 = Assert
70b32d3025SMichael Zhao     //   13-11: Reserved
71b32d3025SMichael Zhao     //   10-8:  Delivery Mode
72b32d3025SMichael Zhao     //   7-0:   Vector
73b32d3025SMichael Zhao     pub data: u32,
74b32d3025SMichael Zhao }
75b32d3025SMichael Zhao 
76b32d3025SMichael Zhao // Introduce trait InterruptController to uniform the interrupt
77b32d3025SMichael Zhao // service provided for devices.
78b32d3025SMichael Zhao // Device manager uses this trait without caring whether it is a
79e8c330e2SRuoqing He // IOAPIC (X86), GIC (Arm) or AIA (RISC-V).
80b32d3025SMichael Zhao pub trait InterruptController: Send {
service_irq(&mut self, irq: usize) -> Result<()>81b32d3025SMichael Zhao     fn service_irq(&mut self, irq: usize) -> Result<()>;
828f1f9d9eSMichael Zhao     #[cfg(target_arch = "x86_64")]
end_of_interrupt(&mut self, vec: u8)83b32d3025SMichael Zhao     fn end_of_interrupt(&mut self, vec: u8);
notifier(&self, irq: usize) -> Option<EventFd>843bd47ffdSSebastien Boeuf     fn notifier(&self, irq: usize) -> Option<EventFd>;
85b32d3025SMichael Zhao }
86