vmotherboard/chipset/
line_sets.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use chipset_device::ChipsetDevice;
5use chipset_device_resources::LineSetId;
6use closeable_mutex::CloseableMutex;
7use inspect::InspectMut;
8use state_unit::SpawnedUnit;
9use state_unit::StateUnit;
10use state_unit::StateUnits;
11use state_unit::UnitHandle;
12use std::collections::HashMap;
13use std::sync::Arc;
14use vmcore::line_interrupt::LineSet;
15use vmcore::line_interrupt::LineSetTarget;
16use vmcore::vm_task::VmTaskDriverSource;
17
18pub struct LineSets {
19    map: HashMap<LineSetId, (Arc<LineSet>, usize)>,
20    pub units: Vec<SpawnedUnit<()>>,
21}
22
23impl LineSets {
24    pub fn new() -> Self {
25        Self {
26            map: HashMap::new(),
27            units: Vec::new(),
28        }
29    }
30
31    pub fn line_set(
32        &mut self,
33        driver: &VmTaskDriverSource,
34        units: &StateUnits,
35        id: LineSetId,
36    ) -> (&LineSet, &UnitHandle) {
37        let (line_set, index) = self.map.entry(id.clone()).or_insert_with(|| {
38            let set = Arc::new(LineSet::new());
39            let unit = units
40                .add(format!("lines/{}", id.name()))
41                .spawn(driver.simple(), {
42                    let set = set.clone();
43                    async move |mut recv| {
44                        while let Ok(req) = recv.recv().await {
45                            req.apply(&mut LineSetUnit(&set)).await;
46                        }
47                    }
48                })
49                .unwrap();
50            let index = self.units.len();
51            self.units.push(unit);
52            (set, index)
53        });
54        (line_set, self.units[*index].handle())
55    }
56}
57
58#[derive(InspectMut)]
59#[inspect(transparent)]
60struct LineSetUnit<'a>(&'a LineSet);
61
62impl StateUnit for LineSetUnit<'_> {
63    async fn start(&mut self) {}
64
65    async fn stop(&mut self) {}
66
67    async fn reset(&mut self) -> anyhow::Result<()> {
68        Ok(())
69    }
70
71    async fn save(
72        &mut self,
73    ) -> Result<Option<vmcore::save_restore::SavedStateBlob>, vmcore::save_restore::SaveError> {
74        Ok(None)
75    }
76
77    async fn restore(
78        &mut self,
79        _: vmcore::save_restore::SavedStateBlob,
80    ) -> Result<(), vmcore::save_restore::RestoreError> {
81        Err(vmcore::save_restore::RestoreError::SavedStateNotSupported)
82    }
83}
84
85pub struct LineSetTargetDevice<T> {
86    device: Arc<CloseableMutex<T>>,
87}
88
89impl<T: ChipsetDevice> LineSetTargetDevice<T> {
90    pub fn new(device: Arc<CloseableMutex<T>>) -> Self {
91        Self { device }
92    }
93}
94
95impl<T: ChipsetDevice> LineSetTarget for LineSetTargetDevice<T> {
96    fn set_irq(&self, vector: u32, high: bool) {
97        self.device
98            .lock()
99            .supports_line_interrupt_target()
100            .unwrap()
101            .set_irq(vector, high);
102    }
103}