• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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::convert::TryInto;
7 use std::ops::Bound::Included;
8 use std::sync::Arc;
9 use std::sync::Weak;
10 
11 use anyhow::Context;
12 use base::custom_serde::serialize_arc_mutex;
13 use base::error;
14 use base::RawDescriptor;
15 use base::SendTube;
16 use base::VmEventType;
17 use resources::SystemAllocator;
18 use serde::Deserialize;
19 use serde::Serialize;
20 use sync::Mutex;
21 
22 use crate::pci::pci_configuration::PciBarConfiguration;
23 use crate::pci::pci_configuration::PciBridgeSubclass;
24 use crate::pci::pci_configuration::PciClassCode;
25 use crate::pci::pci_configuration::PciConfiguration;
26 use crate::pci::pci_configuration::PciHeaderType;
27 use crate::pci::pci_configuration::HEADER_TYPE_MULTIFUNCTION_MASK;
28 use crate::pci::pci_configuration::HEADER_TYPE_REG;
29 use crate::pci::pci_device::Error;
30 use crate::pci::pci_device::PciBus;
31 use crate::pci::pci_device::PciDevice;
32 use crate::pci::PciAddress;
33 use crate::pci::PciId;
34 use crate::pci::PCI_VENDOR_ID_INTEL;
35 use crate::Bus;
36 use crate::BusAccessInfo;
37 use crate::BusDevice;
38 use crate::BusType;
39 use crate::DeviceId;
40 use crate::Suspendable;
41 
42 // A PciDevice that holds the root hub's configuration.
43 #[derive(Serialize)]
44 struct PciRootConfiguration {
45     config: PciConfiguration,
46 }
47 
48 impl PciDevice for PciRootConfiguration {
debug_label(&self) -> String49     fn debug_label(&self) -> String {
50         "pci root device".to_owned()
51     }
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error>52     fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error> {
53         // PCI root fixed address.
54         Ok(PciAddress {
55             bus: 0,
56             dev: 0,
57             func: 0,
58         })
59     }
keep_rds(&self) -> Vec<RawDescriptor>60     fn keep_rds(&self) -> Vec<RawDescriptor> {
61         Vec::new()
62     }
read_config_register(&self, reg_idx: usize) -> u3263     fn read_config_register(&self, reg_idx: usize) -> u32 {
64         self.config.read_reg(reg_idx)
65     }
66 
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])67     fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
68         self.config.write_reg(reg_idx, offset, data)
69     }
70 
read_bar(&mut self, _addr: u64, _data: &mut [u8])71     fn read_bar(&mut self, _addr: u64, _data: &mut [u8]) {}
72 
write_bar(&mut self, _addr: u64, _data: &[u8])73     fn write_bar(&mut self, _addr: u64, _data: &[u8]) {}
74 
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>75     fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
76         self.config.get_bar_configuration(bar_num)
77     }
78 }
79 
80 impl Suspendable for PciRootConfiguration {
81     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>82     fn sleep(&mut self) -> anyhow::Result<()> {
83         Ok(())
84     }
85 
wake(&mut self) -> anyhow::Result<()>86     fn wake(&mut self) -> anyhow::Result<()> {
87         Ok(())
88     }
89 
snapshot(&self) -> anyhow::Result<serde_json::Value>90     fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
91         serde_json::to_value(self)
92             .with_context(|| format!("failed to serialize {}", PciDevice::debug_label(self)))
93     }
94 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>95     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
96         #[derive(Deserialize)]
97         struct PciRootConfigurationSerializable {
98             config: serde_json::Value,
99         }
100 
101         let deser: PciRootConfigurationSerializable =
102             serde_json::from_value(data).context("failed to deserialize PciRootConfiguration")?;
103         self.config.restore(deser.config)?;
104         Ok(())
105     }
106 }
107 
108 // Command send to pci root worker thread to add/remove device from pci root
109 pub enum PciRootCommand {
110     Add(PciAddress, Arc<Mutex<dyn BusDevice>>),
111     AddBridge(Arc<Mutex<PciBus>>),
112     Remove(PciAddress),
113     Kill,
114 }
115 
116 /// Emulates the PCI Root bridge.
117 #[allow(dead_code)] // TODO(b/174705596): remove once mmio_bus and io_bus are used
118 #[derive(Serialize)]
119 pub struct PciRoot {
120     /// Memory (MMIO) bus.
121     #[serde(skip_serializing)]
122     mmio_bus: Weak<Bus>,
123     /// IO bus (x86 only - for non-x86 platforms, this is just an empty Bus).
124     #[serde(skip_serializing)]
125     io_bus: Weak<Bus>,
126     /// Root pci bus (bus 0)
127     #[serde(skip_serializing)]
128     root_bus: Arc<Mutex<PciBus>>,
129     /// Bus configuration for the root device.
130     root_configuration: PciRootConfiguration,
131     /// Devices attached to this bridge.
132     #[serde(skip_serializing)]
133     devices: BTreeMap<PciAddress, Arc<Mutex<dyn BusDevice>>>,
134     /// pcie enhanced configuration access mmio base
135     pcie_cfg_mmio: Option<u64>,
136 }
137 
138 const PCI_DEVICE_ID_INTEL_82441: u16 = 0x1237;
139 const PCIE_XBAR_BASE_ADDR: usize = 24;
140 
141 /// Used to serialize relevant information to PciRoot
142 #[derive(Deserialize)]
143 struct PciRootSerializable {
144     root_configuration: serde_json::Value,
145     pcie_cfg_mmio: Option<u64>,
146 }
147 
148 impl PciRoot {
149     /// Create an empty PCI root bus.
new(mmio_bus: Weak<Bus>, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>) -> Self150     pub fn new(mmio_bus: Weak<Bus>, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>) -> Self {
151         PciRoot {
152             mmio_bus,
153             io_bus,
154             root_bus,
155             root_configuration: PciRootConfiguration {
156                 config: PciConfiguration::new(
157                     PCI_VENDOR_ID_INTEL,
158                     PCI_DEVICE_ID_INTEL_82441,
159                     PciClassCode::BridgeDevice,
160                     &PciBridgeSubclass::HostBridge,
161                     None,
162                     PciHeaderType::Device,
163                     0,
164                     0,
165                     0,
166                 ),
167             },
168             devices: BTreeMap::new(),
169             pcie_cfg_mmio: None,
170         }
171     }
172 
173     /// Get the root pci bus
get_root_bus(&self) -> Arc<Mutex<PciBus>>174     pub fn get_root_bus(&self) -> Arc<Mutex<PciBus>> {
175         self.root_bus.clone()
176     }
177 
178     /// Get the ACPI path to a PCI device
acpi_path(&self, address: &PciAddress) -> Option<String>179     pub fn acpi_path(&self, address: &PciAddress) -> Option<String> {
180         if let Some(device) = self.devices.get(address) {
181             let path = self.root_bus.lock().path_to(address.bus);
182             if path.is_empty() {
183                 None
184             } else {
185                 Some(format!(
186                     "_SB_.{}.{}",
187                     path.iter()
188                         .map(|x| format!("PC{:02X}", x))
189                         .collect::<Vec<String>>()
190                         .join("."),
191                     match device.lock().is_bridge() {
192                         Some(bus_no) => format!("PC{:02X}", bus_no),
193                         None => format!("PE{:02X}", address.devfn()),
194                     }
195                 ))
196             }
197         } else {
198             None
199         }
200     }
201 
202     /// enable pcie enhanced configuration access and set base mmio
enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64)203     pub fn enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64) {
204         self.pcie_cfg_mmio = Some(pcie_cfg_mmio);
205     }
206 
207     /// Add a `device` to this root PCI bus.
add_device(&mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>)208     pub fn add_device(&mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>) {
209         // Ignore attempt to replace PCI Root host bridge.
210         if !address.is_root() {
211             self.devices.insert(address, device);
212         }
213 
214         if let Err(e) = self.root_bus.lock().add_child_device(address) {
215             error!("add device error: {}", e);
216         }
217     }
218 
add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>)219     pub fn add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) {
220         if let Err(e) = self.root_bus.lock().add_child_bus(bridge_bus) {
221             error!("add bridge error: {}", e);
222         }
223     }
224 
remove_device(&mut self, address: PciAddress)225     pub fn remove_device(&mut self, address: PciAddress) {
226         if let Some(d) = self.devices.remove(&address) {
227             for (range, bus_type) in d.lock().get_ranges() {
228                 let bus_ptr = if bus_type == BusType::Mmio {
229                     match self.mmio_bus.upgrade() {
230                         Some(m) => m,
231                         None => continue,
232                     }
233                 } else {
234                     match self.io_bus.upgrade() {
235                         Some(i) => i,
236                         None => continue,
237                     }
238                 };
239                 let _ = bus_ptr.remove(range.base, range.len);
240             }
241             // Remove the pci bus if this device is a pci bridge.
242             if let Some(bus_no) = d.lock().is_bridge() {
243                 let _ = self.root_bus.lock().remove_child_bus(bus_no);
244             }
245             d.lock().destroy_device();
246             let _ = self.root_bus.lock().remove_child_device(address);
247         }
248     }
249 
config_space_read(&self, address: PciAddress, register: usize) -> u32250     pub fn config_space_read(&self, address: PciAddress, register: usize) -> u32 {
251         if address.is_root() {
252             if register == PCIE_XBAR_BASE_ADDR && self.pcie_cfg_mmio.is_some() {
253                 let pcie_mmio = self.pcie_cfg_mmio.unwrap() as u32;
254                 pcie_mmio | 0x1
255             } else if register == (PCIE_XBAR_BASE_ADDR + 1) && self.pcie_cfg_mmio.is_some() {
256                 (self.pcie_cfg_mmio.unwrap() >> 32) as u32
257             } else {
258                 self.root_configuration.config_register_read(register)
259             }
260         } else {
261             let mut data = self
262                 .devices
263                 .get(&address)
264                 .map_or(0xffff_ffff, |d| d.lock().config_register_read(register));
265 
266             if register == HEADER_TYPE_REG {
267                 // Set multifunction bit in header type if there are devices at non-zero functions
268                 // in this slot.
269                 if self
270                     .devices
271                     .range((
272                         Included(&PciAddress {
273                             bus: address.bus,
274                             dev: address.dev,
275                             func: 1,
276                         }),
277                         Included(&PciAddress {
278                             bus: address.bus,
279                             dev: address.dev,
280                             func: 7,
281                         }),
282                     ))
283                     .next()
284                     .is_some()
285                 {
286                     data |= HEADER_TYPE_MULTIFUNCTION_MASK;
287                 }
288             }
289 
290             data
291         }
292     }
293 
config_space_write( &mut self, address: PciAddress, register: usize, offset: u64, data: &[u8], )294     pub fn config_space_write(
295         &mut self,
296         address: PciAddress,
297         register: usize,
298         offset: u64,
299         data: &[u8],
300     ) {
301         if offset as usize + data.len() > 4 {
302             return;
303         }
304         if address.is_root() {
305             self.root_configuration
306                 .config_register_write(register, offset, data);
307         } else if let Some(d) = self.devices.get(&address) {
308             let res = d.lock().config_register_write(register, offset, data);
309 
310             if !res.mmio_add.is_empty() || !res.mmio_remove.is_empty() {
311                 let mmio_bus = match self.mmio_bus.upgrade() {
312                     Some(m) => m,
313                     None => return,
314                 };
315                 for range in &res.mmio_remove {
316                     let _ = mmio_bus.remove(range.base, range.len);
317                 }
318                 for range in &res.mmio_add {
319                     let _ = mmio_bus.insert(d.clone(), range.base, range.len);
320                 }
321             }
322 
323             if !res.io_add.is_empty() || !res.io_remove.is_empty() {
324                 let io_bus = match self.io_bus.upgrade() {
325                     Some(i) => i,
326                     None => return,
327                 };
328                 for range in &res.io_remove {
329                     let _ = io_bus.remove(range.base, range.len);
330                 }
331                 for range in &res.io_add {
332                     let _ = io_bus.insert(d.clone(), range.base, range.len);
333                 }
334             }
335 
336             for remove_pci_device in res.removed_pci_devices.iter() {
337                 self.remove_device(*remove_pci_device);
338             }
339         }
340     }
341 
virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32342     pub fn virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32 {
343         if address.is_root() {
344             0u32
345         } else {
346             self.devices
347                 .get(&address)
348                 .map_or(0u32, |d| d.lock().virtual_config_register_read(register))
349         }
350     }
351 
virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32)352     pub fn virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32) {
353         if !address.is_root() {
354             if let Some(d) = self.devices.get(&address) {
355                 d.lock().virtual_config_register_write(register, value);
356             }
357         }
358     }
359 
snapshot(&self) -> anyhow::Result<serde_json::Value>360     pub fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
361         serde_json::to_value(self).context("failed to serialize PciRoot")
362     }
363 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>364     pub fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
365         let deser: PciRootSerializable =
366             serde_json::from_value(data).context("failed to deserialize PciRoot")?;
367         self.root_configuration.restore(deser.root_configuration)?;
368         self.pcie_cfg_mmio = deser.pcie_cfg_mmio;
369         Ok(())
370     }
371 }
372 
373 /// Emulates PCI configuration access mechanism #1 (I/O ports 0xcf8 and 0xcfc).
374 #[derive(Serialize)]
375 pub struct PciConfigIo {
376     /// PCI root bridge.
377     #[serde(serialize_with = "serialize_arc_mutex")]
378     pci_root: Arc<Mutex<PciRoot>>,
379     /// Current address to read/write from (0xcf8 register, litte endian).
380     config_address: u32,
381     /// Tube to signal that the guest requested reset via writing to 0xcf9 register.
382     #[serde(skip_serializing)]
383     reset_evt_wrtube: SendTube,
384 }
385 
386 #[derive(Deserialize)]
387 struct PciConfigIoSerializable {
388     pci_root: serde_json::Value,
389     config_address: u32,
390 }
391 
392 impl PciConfigIo {
393     const REGISTER_BITS_NUM: usize = 8;
394 
new(pci_root: Arc<Mutex<PciRoot>>, reset_evt_wrtube: SendTube) -> Self395     pub fn new(pci_root: Arc<Mutex<PciRoot>>, reset_evt_wrtube: SendTube) -> Self {
396         PciConfigIo {
397             pci_root,
398             config_address: 0,
399             reset_evt_wrtube,
400         }
401     }
402 
config_space_read(&self) -> u32403     fn config_space_read(&self) -> u32 {
404         let enabled = (self.config_address & 0x8000_0000) != 0;
405         if !enabled {
406             return 0xffff_ffff;
407         }
408 
409         let (address, register) =
410             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
411         self.pci_root.lock().config_space_read(address, register)
412     }
413 
config_space_write(&mut self, offset: u64, data: &[u8])414     fn config_space_write(&mut self, offset: u64, data: &[u8]) {
415         let enabled = (self.config_address & 0x8000_0000) != 0;
416         if !enabled {
417             return;
418         }
419 
420         let (address, register) =
421             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
422         self.pci_root
423             .lock()
424             .config_space_write(address, register, offset, data)
425     }
426 
set_config_address(&mut self, offset: u64, data: &[u8])427     fn set_config_address(&mut self, offset: u64, data: &[u8]) {
428         if offset as usize + data.len() > 4 {
429             return;
430         }
431         let (mask, value): (u32, u32) = match data.len() {
432             1 => (
433                 0x0000_00ff << (offset * 8),
434                 (data[0] as u32) << (offset * 8),
435             ),
436             2 => (
437                 0x0000_ffff << (offset * 8),
438                 u32::from(u16::from_le_bytes(data.try_into().unwrap())) << (offset * 8),
439             ),
440             4 => (0xffff_ffff, u32::from_le_bytes(data.try_into().unwrap())),
441             _ => return,
442         };
443         self.config_address = (self.config_address & !mask) | value;
444     }
445 }
446 
447 const PCI_RESET_CPU_BIT: u8 = 1 << 2;
448 
449 impl BusDevice for PciConfigIo {
debug_label(&self) -> String450     fn debug_label(&self) -> String {
451         format!("pci config io-port 0x{:03x}", self.config_address)
452     }
453 
device_id(&self) -> DeviceId454     fn device_id(&self) -> DeviceId {
455         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
456     }
457 
read(&mut self, info: BusAccessInfo, data: &mut [u8])458     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
459         // `offset` is relative to 0xcf8
460         let value = match info.offset {
461             0..=3 => self.config_address,
462             4..=7 => self.config_space_read(),
463             _ => 0xffff_ffff,
464         };
465 
466         // Only allow reads to the register boundary.
467         let start = info.offset as usize % 4;
468         let end = start + data.len();
469         if end <= 4 {
470             for i in start..end {
471                 data[i - start] = (value >> (i * 8)) as u8;
472             }
473         } else {
474             for d in data {
475                 *d = 0xff;
476             }
477         }
478     }
479 
write(&mut self, info: BusAccessInfo, data: &[u8])480     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
481         // `offset` is relative to 0xcf8
482         match info.offset {
483             _o @ 1 if data.len() == 1 && data[0] & PCI_RESET_CPU_BIT != 0 => {
484                 if let Err(e) = self
485                     .reset_evt_wrtube
486                     .send::<VmEventType>(&VmEventType::Reset)
487                 {
488                     error!("failed to trigger PCI 0xcf9 reset event: {}", e);
489                 }
490             }
491             o @ 0..=3 => self.set_config_address(o, data),
492             o @ 4..=7 => self.config_space_write(o - 4, data),
493             _ => (),
494         };
495     }
496 }
497 
498 impl Suspendable for PciConfigIo {
499     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>500     fn sleep(&mut self) -> anyhow::Result<()> {
501         Ok(())
502     }
503 
wake(&mut self) -> anyhow::Result<()>504     fn wake(&mut self) -> anyhow::Result<()> {
505         Ok(())
506     }
507 
snapshot(&self) -> anyhow::Result<serde_json::Value>508     fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
509         serde_json::to_value(self)
510             .with_context(|| format!("failed to serialize {}", self.debug_label()))
511     }
512 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>513     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
514         let mut root = self.pci_root.lock();
515         let deser: PciConfigIoSerializable = serde_json::from_value(data)
516             .context(format!("failed to deserialize {}", self.debug_label()))?;
517         root.restore(deser.pci_root)?;
518         self.config_address = deser.config_address;
519         Ok(())
520     }
521 }
522 
523 /// Emulates PCI memory-mapped configuration access mechanism.
524 #[derive(Serialize)]
525 pub struct PciConfigMmio {
526     /// PCI root bridge.
527     #[serde(serialize_with = "serialize_arc_mutex")]
528     pci_root: Arc<Mutex<PciRoot>>,
529     /// Register bit number in config address.
530     register_bit_num: usize,
531 }
532 
533 #[derive(Deserialize)]
534 struct PciConfigMmioSerializable {
535     pci_root: serde_json::Value,
536     register_bit_num: usize,
537 }
538 
539 impl PciConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self540     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
541         PciConfigMmio {
542             pci_root,
543             register_bit_num,
544         }
545     }
546 
config_space_read(&self, config_address: u32) -> u32547     fn config_space_read(&self, config_address: u32) -> u32 {
548         let (address, register) =
549             PciAddress::from_config_address(config_address, self.register_bit_num);
550         self.pci_root.lock().config_space_read(address, register)
551     }
552 
config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8])553     fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) {
554         let (address, register) =
555             PciAddress::from_config_address(config_address, self.register_bit_num);
556         self.pci_root
557             .lock()
558             .config_space_write(address, register, offset, data)
559     }
560 }
561 
562 impl BusDevice for PciConfigMmio {
debug_label(&self) -> String563     fn debug_label(&self) -> String {
564         "pci config mmio".to_owned()
565     }
566 
device_id(&self) -> DeviceId567     fn device_id(&self) -> DeviceId {
568         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
569     }
570 
read(&mut self, info: BusAccessInfo, data: &mut [u8])571     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
572         // Only allow reads to the register boundary.
573         let start = info.offset as usize % 4;
574         let end = start + data.len();
575         if end > 4 || info.offset > u32::max_value() as u64 {
576             for d in data {
577                 *d = 0xff;
578             }
579             return;
580         }
581 
582         let value = self.config_space_read(info.offset as u32);
583         for i in start..end {
584             data[i - start] = (value >> (i * 8)) as u8;
585         }
586     }
587 
write(&mut self, info: BusAccessInfo, data: &[u8])588     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
589         if info.offset > u32::max_value() as u64 {
590             return;
591         }
592         self.config_space_write(info.offset as u32, info.offset % 4, data)
593     }
594 }
595 
596 impl Suspendable for PciConfigMmio {
597     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>598     fn sleep(&mut self) -> anyhow::Result<()> {
599         Ok(())
600     }
601 
wake(&mut self) -> anyhow::Result<()>602     fn wake(&mut self) -> anyhow::Result<()> {
603         Ok(())
604     }
605 
snapshot(&self) -> anyhow::Result<serde_json::Value>606     fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
607         serde_json::to_value(self)
608             .with_context(|| format!("failed to serialize {}", self.debug_label()))
609     }
610 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>611     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
612         let mut root = self.pci_root.lock();
613         let deser: PciConfigMmioSerializable = serde_json::from_value(data)
614             .context(format!("failed to deserialize {}", self.debug_label()))?;
615         root.restore(deser.pci_root)?;
616         self.register_bit_num = deser.register_bit_num;
617         Ok(())
618     }
619 }
620 
621 /// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in
622 /// total) for each PCI device. The guest can use these registers to exchange device-specific
623 /// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these
624 /// register's emulation. The second 4KB is mapped into guest directly as shared memory, so
625 /// when guest access this 4KB, vm exit doesn't happen.
626 /// All these virtual registers from all PCI devices locate in a contiguous memory region.
627 /// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT.
628 /// Bit 12 is used to select the first trapped page or the second directly mapped page
629 /// The offset of each register is calculated in the same way as PCIe ECAM;
630 /// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) |
631 /// (register_index << 2)
632 #[derive(Serialize)]
633 pub struct PciVirtualConfigMmio {
634     /// PCI root bridge.
635     #[serde(serialize_with = "serialize_arc_mutex")]
636     pci_root: Arc<Mutex<PciRoot>>,
637     /// Register bit number in config address.
638     register_bit_num: usize,
639 }
640 
641 #[derive(Deserialize)]
642 struct PciVirtualConfigMmioSerializable {
643     pci_root: serde_json::Value,
644     register_bit_num: usize,
645 }
646 
647 impl PciVirtualConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self648     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
649         PciVirtualConfigMmio {
650             pci_root,
651             register_bit_num,
652         }
653     }
654 }
655 
656 impl BusDevice for PciVirtualConfigMmio {
debug_label(&self) -> String657     fn debug_label(&self) -> String {
658         "pci virtual config mmio".to_owned()
659     }
660 
device_id(&self) -> DeviceId661     fn device_id(&self) -> DeviceId {
662         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
663     }
664 
read(&mut self, info: BusAccessInfo, data: &mut [u8])665     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
666         let value = if info.offset % 4 != 0 || data.len() != 4 {
667             error!(
668                 "{} unexpected read at offset = {}, len = {}",
669                 self.debug_label(),
670                 info.offset,
671                 data.len()
672             );
673             0u32
674         } else {
675             let (address, register) =
676                 PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
677             self.pci_root
678                 .lock()
679                 .virtual_config_space_read(address, register)
680         };
681         data[0..4].copy_from_slice(&value.to_le_bytes()[..]);
682     }
683 
write(&mut self, info: BusAccessInfo, data: &[u8])684     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
685         if info.offset % 4 != 0 || data.len() != 4 {
686             error!(
687                 "{} unexpected write at offset = {}, len = {}",
688                 self.debug_label(),
689                 info.offset,
690                 data.len()
691             );
692             return;
693         }
694         // Unwrap is safe as we verified length above
695         let value = u32::from_le_bytes(data.try_into().unwrap());
696         let (address, register) =
697             PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
698         self.pci_root
699             .lock()
700             .virtual_config_space_write(address, register, value)
701     }
702 }
703 
704 impl Suspendable for PciVirtualConfigMmio {
705     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>706     fn sleep(&mut self) -> anyhow::Result<()> {
707         Ok(())
708     }
709 
wake(&mut self) -> anyhow::Result<()>710     fn wake(&mut self) -> anyhow::Result<()> {
711         Ok(())
712     }
713 
snapshot(&self) -> anyhow::Result<serde_json::Value>714     fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
715         serde_json::to_value(self)
716             .with_context(|| format!("failed to serialize {}", self.debug_label()))
717     }
718 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>719     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
720         let mut root = self.pci_root.lock();
721         let deser: PciVirtualConfigMmioSerializable = serde_json::from_value(data)
722             .context(format!("failed to deserialize {}", self.debug_label()))?;
723         root.restore(deser.pci_root)?;
724         self.register_bit_num = deser.register_bit_num;
725 
726         Ok(())
727     }
728 }
729 
730 #[cfg(test)]
731 mod tests {
732     use base::Tube;
733 
734     use super::*;
735     use crate::suspendable_tests;
736 
create_pci_root() -> Arc<Mutex<PciRoot>>737     fn create_pci_root() -> Arc<Mutex<PciRoot>> {
738         let io_bus = Arc::new(Bus::new());
739         let mmio_bus = Arc::new(Bus::new());
740         let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false)));
741 
742         Arc::new(Mutex::new(PciRoot::new(
743             Arc::downgrade(&mmio_bus),
744             Arc::downgrade(&io_bus),
745             root_bus,
746         )))
747     }
748 
create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo749     fn create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo {
750         let (reset_evt_wrtube, _) = Tube::directional_pair().unwrap();
751         PciConfigIo::new(pci_root, reset_evt_wrtube)
752     }
753 
modify_pci_io_config(pci_config: &mut PciConfigIo)754     fn modify_pci_io_config(pci_config: &mut PciConfigIo) {
755         pci_config.config_address += 1;
756     }
create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio757     fn create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio {
758         PciConfigMmio::new(pci_root, 0)
759     }
760 
modify_pci_mmio_config(pci_config: &mut PciConfigMmio)761     fn modify_pci_mmio_config(pci_config: &mut PciConfigMmio) {
762         pci_config.register_bit_num += 1;
763     }
764 
create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio765     fn create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio {
766         PciVirtualConfigMmio::new(pci_root, 0)
767     }
768 
modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio)769     fn modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio) {
770         pci_config.register_bit_num += 1;
771     }
772 
773     suspendable_tests!(
774         pci_io_config,
775         create_pci_io_config(create_pci_root()),
776         modify_pci_io_config
777     );
778     suspendable_tests!(
779         pcie_mmio_config,
780         create_pci_mmio_config(create_pci_root()),
781         modify_pci_mmio_config
782     );
783     suspendable_tests!(
784         pci_virtual_config_mmio,
785         create_pci_virtual_config_mmio(create_pci_root()),
786         modify_pci_virtual_config_mmio
787     );
788 
789     #[test]
pci_set_config_address_word()790     fn pci_set_config_address_word() {
791         let mut pci_io_config = create_pci_io_config(create_pci_root());
792 
793         // Set the full 32-bit config_address to a known value (0x11223344).
794         pci_io_config.write(
795             BusAccessInfo {
796                 offset: 0,
797                 address: 0xCF8,
798                 id: 0,
799             },
800             &[0x44, 0x33, 0x22, 0x11],
801         );
802 
803         // Overwrite the high 16 bits of config_address with 0x55AA (test for b/274366589).
804         pci_io_config.write(
805             BusAccessInfo {
806                 offset: 2,
807                 address: 0xCFA,
808                 id: 0,
809             },
810             &[0xAA, 0x55],
811         );
812 
813         // Verify config_address has the expected value (0x55AA3344).
814         let mut config_address = [0u8; 4];
815         pci_io_config.read(
816             BusAccessInfo {
817                 offset: 0,
818                 address: 0xCF8,
819                 id: 0,
820             },
821             &mut config_address,
822         );
823         assert_eq!(config_address, [0x44, 0x33, 0xAA, 0x55]);
824     }
825 }
826