• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::collections::BTreeMap;
6 use std::sync::Arc;
7 
8 use acpi_tables::aml::Aml;
9 use base::syslog;
10 use base::AsRawDescriptors;
11 use base::Tube;
12 use devices::Bus;
13 use devices::BusDevice;
14 use devices::IrqChip;
15 use devices::IrqEventSource;
16 use devices::ProxyDevice;
17 use devices::VfioPlatformDevice;
18 use libc::sched_getcpu;
19 use minijail::Minijail;
20 use resources::AllocOptions;
21 use resources::SystemAllocator;
22 use sync::Mutex;
23 
24 use crate::DeviceRegistrationError;
25 use crate::MsrValueFrom;
26 
27 impl MsrValueFrom {
28     /// Get the physical(host) CPU id from MsrValueFrom type.
get_cpu_id(&self) -> usize29     pub fn get_cpu_id(&self) -> usize {
30         match self {
31             MsrValueFrom::RWFromCPU0 => 0,
32             MsrValueFrom::RWFromRunningCPU => {
33                 // Safe because the host supports this sys call.
34                 (unsafe { sched_getcpu() }) as usize
35             }
36         }
37     }
38 }
39 
40 /// Adds goldfish battery and returns the platform needed resources including
41 /// its AML data and mmio base address
42 ///
43 /// # Arguments
44 ///
45 /// * `amls` - the vector to put the goldfish battery AML
46 /// * `battery_jail` - used when sandbox is enabled
47 /// * `mmio_bus` - bus to add the devices to
48 /// * `irq_chip` - the IrqChip object for registering irq events
49 /// * `irq_num` - assigned interrupt to use
50 /// * `resources` - the SystemAllocator to allocate IO and MMIO for acpi
add_goldfish_battery( amls: &mut Vec<u8>, battery_jail: Option<Minijail>, mmio_bus: &Bus, irq_chip: &mut dyn IrqChip, irq_num: u32, resources: &mut SystemAllocator, #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>, ) -> Result<(Tube, u64), DeviceRegistrationError>51 pub fn add_goldfish_battery(
52     amls: &mut Vec<u8>,
53     battery_jail: Option<Minijail>,
54     mmio_bus: &Bus,
55     irq_chip: &mut dyn IrqChip,
56     irq_num: u32,
57     resources: &mut SystemAllocator,
58     #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>,
59 ) -> Result<(Tube, u64), DeviceRegistrationError> {
60     let alloc = resources.get_anon_alloc();
61     let mmio_base = resources
62         .allocate_mmio(
63             devices::bat::GOLDFISHBAT_MMIO_LEN,
64             alloc,
65             "GoldfishBattery".to_string(),
66             AllocOptions::new().align(devices::bat::GOLDFISHBAT_MMIO_LEN),
67         )
68         .map_err(DeviceRegistrationError::AllocateIoResource)?;
69 
70     let (control_tube, response_tube) =
71         Tube::pair().map_err(DeviceRegistrationError::CreateTube)?;
72 
73     #[cfg(feature = "power-monitor-powerd")]
74     let create_monitor = Some(Box::new(power_monitor::powerd::DBusMonitor::connect)
75         as Box<dyn power_monitor::CreatePowerMonitorFn>);
76 
77     #[cfg(not(feature = "power-monitor-powerd"))]
78     let create_monitor = None;
79 
80     let irq_evt = devices::IrqLevelEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
81 
82     let goldfish_bat = devices::GoldfishBattery::new(
83         mmio_base,
84         irq_num,
85         irq_evt
86             .try_clone()
87             .map_err(DeviceRegistrationError::EventClone)?,
88         response_tube,
89         create_monitor,
90     )
91     .map_err(DeviceRegistrationError::RegisterBattery)?;
92     goldfish_bat.to_aml_bytes(amls);
93 
94     irq_chip
95         .register_level_irq_event(
96             irq_num,
97             &irq_evt,
98             IrqEventSource::from_device(&goldfish_bat),
99         )
100         .map_err(DeviceRegistrationError::RegisterIrqfd)?;
101 
102     match battery_jail {
103         #[cfg(not(windows))]
104         Some(jail) => {
105             let mut keep_rds = goldfish_bat.keep_rds();
106             syslog::push_descriptors(&mut keep_rds);
107             cros_tracing::push_descriptors!(&mut keep_rds);
108             mmio_bus
109                 .insert(
110                     Arc::new(Mutex::new(
111                         ProxyDevice::new(
112                             goldfish_bat,
113                             jail,
114                             keep_rds,
115                             #[cfg(feature = "swap")]
116                             swap_controller,
117                         )
118                         .map_err(DeviceRegistrationError::ProxyDeviceCreation)?,
119                     )),
120                     mmio_base,
121                     devices::bat::GOLDFISHBAT_MMIO_LEN,
122                 )
123                 .map_err(DeviceRegistrationError::MmioInsert)?;
124         }
125         #[cfg(windows)]
126         Some(_) => {}
127         None => {
128             mmio_bus
129                 .insert(
130                     Arc::new(Mutex::new(goldfish_bat)),
131                     mmio_base,
132                     devices::bat::GOLDFISHBAT_MMIO_LEN,
133                 )
134                 .map_err(DeviceRegistrationError::MmioInsert)?;
135         }
136     }
137 
138     Ok((control_tube, mmio_base))
139 }
140 
141 /// Creates a platform device for use by this Vm.
142 #[cfg(unix)]
generate_platform_bus( devices: Vec<(VfioPlatformDevice, Option<Minijail>)>, irq_chip: &mut dyn IrqChip, mmio_bus: &Bus, resources: &mut SystemAllocator, #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>, ) -> Result<(Vec<Arc<Mutex<dyn BusDevice>>>, BTreeMap<u32, String>), DeviceRegistrationError>143 pub fn generate_platform_bus(
144     devices: Vec<(VfioPlatformDevice, Option<Minijail>)>,
145     irq_chip: &mut dyn IrqChip,
146     mmio_bus: &Bus,
147     resources: &mut SystemAllocator,
148     #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>,
149 ) -> Result<(Vec<Arc<Mutex<dyn BusDevice>>>, BTreeMap<u32, String>), DeviceRegistrationError> {
150     let mut platform_devices = Vec::new();
151     let mut pid_labels = BTreeMap::new();
152 
153     // Allocate ranges that may need to be in the Platform MMIO region (MmioType::Platform).
154     for (mut device, jail) in devices.into_iter() {
155         let ranges = device
156             .allocate_regions(resources)
157             .map_err(DeviceRegistrationError::AllocateIoResource)?;
158 
159         let mut keep_rds = device.keep_rds();
160         syslog::push_descriptors(&mut keep_rds);
161         cros_tracing::push_descriptors!(&mut keep_rds);
162 
163         let irqs = device
164             .get_platform_irqs()
165             .map_err(DeviceRegistrationError::AllocateIrqResource)?;
166         for irq in irqs.into_iter() {
167             let irq_num = resources
168                 .allocate_irq()
169                 .ok_or(DeviceRegistrationError::AllocateIrq)?;
170 
171             if device.irq_is_automask(&irq) {
172                 let irq_evt =
173                     devices::IrqLevelEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
174                 irq_chip
175                     .register_level_irq_event(
176                         irq_num,
177                         &irq_evt,
178                         IrqEventSource::from_device(&device),
179                     )
180                     .map_err(DeviceRegistrationError::RegisterIrqfd)?;
181                 device
182                     .assign_level_platform_irq(&irq_evt, irq.index)
183                     .map_err(DeviceRegistrationError::SetupVfioPlatformIrq)?;
184                 keep_rds.extend(irq_evt.as_raw_descriptors());
185             } else {
186                 let irq_evt =
187                     devices::IrqEdgeEvent::new().map_err(DeviceRegistrationError::EventCreate)?;
188                 irq_chip
189                     .register_edge_irq_event(
190                         irq_num,
191                         &irq_evt,
192                         IrqEventSource::from_device(&device),
193                     )
194                     .map_err(DeviceRegistrationError::RegisterIrqfd)?;
195                 device
196                     .assign_edge_platform_irq(&irq_evt, irq.index)
197                     .map_err(DeviceRegistrationError::SetupVfioPlatformIrq)?;
198                 keep_rds.extend(irq_evt.as_raw_descriptors());
199             }
200         }
201 
202         let arced_dev: Arc<Mutex<dyn BusDevice>> = if let Some(jail) = jail {
203             let proxy = ProxyDevice::new(
204                 device,
205                 jail,
206                 keep_rds,
207                 #[cfg(feature = "swap")]
208                 swap_controller,
209             )
210             .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
211             pid_labels.insert(proxy.pid() as u32, proxy.debug_label());
212             Arc::new(Mutex::new(proxy))
213         } else {
214             device.on_sandboxed();
215             Arc::new(Mutex::new(device))
216         };
217         platform_devices.push(arced_dev.clone());
218         for range in &ranges {
219             mmio_bus
220                 .insert(arced_dev.clone(), range.0, range.1)
221                 .map_err(DeviceRegistrationError::MmioInsert)?;
222         }
223     }
224     Ok((platform_devices, pid_labels))
225 }
226