1#![forbid(unsafe_code)]
7#![expect(missing_docs)]
8
9use async_trait::async_trait;
10use inspect::Inspect;
11use std::future::Future;
12use std::sync::Arc;
13use thiserror::Error;
14
15#[derive(Debug, Copy, Clone, PartialEq, Eq, Inspect)]
17pub struct MsiAddressData {
18 #[inspect(hex)]
20 pub address: u64,
21 #[inspect(hex)]
23 pub data: u32,
24}
25
26pub struct VpciInterruptParameters<'a> {
27 pub vector: u32,
28 pub multicast: bool,
29 pub target_processors: &'a [u32],
30}
31
32pub trait MapVpciInterrupt: Send + Sync {
38 fn register_interrupt(
39 &self,
40 vector_count: u32,
41 params: &VpciInterruptParameters<'_>,
42 ) -> impl Future<Output = Result<MsiAddressData, RegisterInterruptError>> + Send;
43
44 fn unregister_interrupt(&self, address: u64, data: u32) -> impl Future<Output = ()> + Send;
45}
46
47#[async_trait]
48trait DynMapVpciInterrupt: Send + Sync {
49 async fn register_interrupt(
50 &self,
51 vector_count: u32,
52 params: &VpciInterruptParameters<'_>,
53 ) -> Result<MsiAddressData, RegisterInterruptError>;
54
55 async fn unregister_interrupt(&self, address: u64, data: u32);
56}
57
58#[async_trait]
59impl<T: MapVpciInterrupt> DynMapVpciInterrupt for T {
60 async fn register_interrupt(
61 &self,
62 vector_count: u32,
63 params: &VpciInterruptParameters<'_>,
64 ) -> Result<MsiAddressData, RegisterInterruptError> {
65 self.register_interrupt(vector_count, params).await
66 }
67
68 async fn unregister_interrupt(&self, address: u64, data: u32) {
69 self.unregister_interrupt(address, data).await
70 }
71}
72
73#[derive(Clone)]
75pub struct VpciInterruptMapper(Arc<dyn DynMapVpciInterrupt>);
76
77impl VpciInterruptMapper {
78 pub fn new<T: 'static + MapVpciInterrupt>(mapper: Arc<T>) -> Self {
80 Self(mapper)
81 }
82}
83
84impl MapVpciInterrupt for VpciInterruptMapper {
85 async fn register_interrupt(
86 &self,
87 vector_count: u32,
88 params: &VpciInterruptParameters<'_>,
89 ) -> Result<MsiAddressData, RegisterInterruptError> {
90 self.0.register_interrupt(vector_count, params).await
91 }
92
93 async fn unregister_interrupt(&self, address: u64, data: u32) {
94 self.0.unregister_interrupt(address, data).await
95 }
96}
97
98#[derive(Debug, Error)]
99#[error("failed to register an interrupt")]
100pub struct RegisterInterruptError(#[source] Box<dyn std::error::Error + Send + Sync>);
101
102impl RegisterInterruptError {
103 pub fn new(err: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> Self {
104 Self(err.into())
105 }
106}