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::btree_map::Entry as BTreeMapEntry; 6 use std::collections::BTreeMap; 7 use std::convert::TryInto; 8 use std::ops::Bound::Included; 9 use std::ops::DerefMut; 10 use std::sync::Arc; 11 use std::sync::Weak; 12 13 use anyhow::Context; 14 use base::error; 15 use base::MemoryMapping; 16 use base::MemoryMappingBuilder; 17 use base::Protection; 18 use base::RawDescriptor; 19 use base::SendTube; 20 use base::SharedMemory; 21 use base::VmEventType; 22 use hypervisor::MemCacheType; 23 use hypervisor::Vm; 24 use resources::SystemAllocator; 25 use serde::Deserialize; 26 use serde::Serialize; 27 use snapshot::AnySnapshot; 28 use sync::Mutex; 29 use vm_memory::GuestAddress; 30 31 use crate::pci::pci_configuration::PciBarConfiguration; 32 use crate::pci::pci_configuration::PciBridgeSubclass; 33 use crate::pci::pci_configuration::PciClassCode; 34 use crate::pci::pci_configuration::PciConfiguration; 35 use crate::pci::pci_configuration::PciHeaderType; 36 use crate::pci::pci_configuration::HEADER_TYPE_MULTIFUNCTION_MASK; 37 use crate::pci::pci_configuration::HEADER_TYPE_REG; 38 use crate::pci::pci_configuration::HEADER_TYPE_REG_OFFSET; 39 use crate::pci::pci_device::Error; 40 use crate::pci::pci_device::PciBus; 41 use crate::pci::pci_device::PciDevice; 42 use crate::pci::PciAddress; 43 use crate::pci::PciBarIndex; 44 use crate::pci::PciId; 45 use crate::pci::PCI_VENDOR_ID_INTEL; 46 use crate::Bus; 47 use crate::BusAccessInfo; 48 use crate::BusDevice; 49 use crate::BusType; 50 use crate::DeviceId; 51 use crate::Suspendable; 52 53 // A PciDevice that holds the root hub's configuration. 54 struct PciRootConfiguration { 55 config: PciConfiguration, 56 } 57 58 impl PciDevice for PciRootConfiguration { debug_label(&self) -> String59 fn debug_label(&self) -> String { 60 "pci root device".to_owned() 61 } allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error>62 fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error> { 63 // PCI root fixed address. 64 Ok(PciAddress { 65 bus: 0, 66 dev: 0, 67 func: 0, 68 }) 69 } keep_rds(&self) -> Vec<RawDescriptor>70 fn keep_rds(&self) -> Vec<RawDescriptor> { 71 Vec::new() 72 } read_config_register(&self, reg_idx: usize) -> u3273 fn read_config_register(&self, reg_idx: usize) -> u32 { 74 self.config.read_reg(reg_idx) 75 } 76 write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])77 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) { 78 self.config.write_reg(reg_idx, offset, data); 79 } 80 setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool, Error>81 fn setup_pci_config_mapping( 82 &mut self, 83 shmem: &SharedMemory, 84 base: usize, 85 len: usize, 86 ) -> Result<bool, Error> { 87 self.config 88 .setup_mapping(shmem, base, len) 89 .map(|_| true) 90 .map_err(Error::MmioSetup) 91 } 92 read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])93 fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {} 94 write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])95 fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {} 96 get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>97 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> { 98 self.config.get_bar_configuration(bar_num) 99 } 100 } 101 102 impl Suspendable for PciRootConfiguration { 103 // no thread to sleep, no change required. sleep(&mut self) -> anyhow::Result<()>104 fn sleep(&mut self) -> anyhow::Result<()> { 105 Ok(()) 106 } 107 wake(&mut self) -> anyhow::Result<()>108 fn wake(&mut self) -> anyhow::Result<()> { 109 Ok(()) 110 } 111 snapshot(&mut self) -> anyhow::Result<AnySnapshot>112 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> { 113 self.config 114 .snapshot() 115 .with_context(|| format!("failed to serialize {}", PciDevice::debug_label(self))) 116 } 117 restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>118 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { 119 self.config 120 .restore(data) 121 .context("failed to deserialize PciRootConfiguration") 122 } 123 } 124 125 // Command send to pci root worker thread to add/remove device from pci root 126 pub enum PciRootCommand { 127 Add(PciAddress, Arc<Mutex<dyn BusDevice>>), 128 AddBridge(Arc<Mutex<PciBus>>), 129 Remove(PciAddress), 130 Kill, 131 } 132 133 #[derive(Serialize)] 134 struct PciRootMmioState { 135 /// Contains pages mapped read-only into the guest's MMIO space corresponding to 136 /// the PCI configuration space. Keys are the offset in number of pages from the 137 /// start of MMIO space. If a particular value is None, then at least one 138 /// attached device on that page does not support read-only mapped MMIO. 139 #[serde(skip_serializing)] 140 mappings: BTreeMap<u32, Option<(SharedMemory, MemoryMapping)>>, 141 /// Base address of the PCI configuration space's MMIO region. 142 base: GuestAddress, 143 /// Number of bits in the address space of a particular function's MMIO space. 144 register_bit_num: usize, 145 } 146 147 /// Emulates the PCI Root bridge. 148 #[allow(dead_code)] // TODO(b/174705596): remove once mmio_bus and io_bus are used 149 pub struct PciRoot { 150 /// Memory (MMIO) bus. 151 mmio_bus: Weak<Bus>, 152 /// IO bus (x86 only - for non-x86 platforms, this is just an empty Bus). 153 io_bus: Weak<Bus>, 154 /// Root pci bus (bus 0) 155 root_bus: Arc<Mutex<PciBus>>, 156 /// Bus configuration for the root device. 157 root_configuration: PciRootConfiguration, 158 /// Devices attached to this bridge. 159 devices: BTreeMap<PciAddress, Arc<Mutex<dyn BusDevice>>>, 160 /// pcie enhanced configuration access mmio base 161 pcie_cfg_mmio: Option<u64>, 162 pci_mmio_state: PciRootMmioState, 163 } 164 165 const PCI_DEVICE_ID_INTEL_82441: u16 = 0x1237; 166 const PCIE_XBAR_BASE_ADDR: usize = 24; 167 168 /// Used to serialize relevant information to PciRoot 169 #[derive(Serialize, Deserialize)] 170 struct PciRootSerializable { 171 root_configuration: AnySnapshot, 172 pcie_cfg_mmio: Option<u64>, 173 } 174 175 impl PciRoot { 176 /// Create an empty PCI root bus. new( vm: &mut impl Vm, mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> anyhow::Result<Self>177 pub fn new( 178 vm: &mut impl Vm, 179 mmio_bus: Weak<Bus>, 180 mmio_base: GuestAddress, 181 mmio_register_bit_num: usize, 182 io_bus: Weak<Bus>, 183 root_bus: Arc<Mutex<PciBus>>, 184 ) -> anyhow::Result<Self> { 185 // mmio_mappings's implementation assumes each device's mmio registers 186 // can fit on a single page. Always true given existing specs. 187 assert!(base::pagesize() >= (1 << mmio_register_bit_num)); 188 let mut root = 189 Self::create_for_test(mmio_bus, mmio_base, mmio_register_bit_num, io_bus, root_bus); 190 root.pci_mmio_state 191 .setup_mapping( 192 &PciAddress::new(0, 0, 0, 0).unwrap(), 193 &mut root.root_configuration, 194 vm, 195 ) 196 .context("failed to set up root configuration mapping")?; 197 Ok(root) 198 } 199 create_for_test( mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> Self200 fn create_for_test( 201 mmio_bus: Weak<Bus>, 202 mmio_base: GuestAddress, 203 mmio_register_bit_num: usize, 204 io_bus: Weak<Bus>, 205 root_bus: Arc<Mutex<PciBus>>, 206 ) -> Self { 207 PciRoot { 208 mmio_bus, 209 io_bus, 210 root_bus, 211 root_configuration: PciRootConfiguration { 212 config: PciConfiguration::new( 213 PCI_VENDOR_ID_INTEL, 214 PCI_DEVICE_ID_INTEL_82441, 215 PciClassCode::BridgeDevice, 216 &PciBridgeSubclass::HostBridge, 217 None, 218 PciHeaderType::Device, 219 0, 220 0, 221 0, 222 ), 223 }, 224 devices: BTreeMap::new(), 225 pcie_cfg_mmio: None, 226 pci_mmio_state: PciRootMmioState { 227 mappings: BTreeMap::new(), 228 base: mmio_base, 229 register_bit_num: mmio_register_bit_num, 230 }, 231 } 232 } 233 234 /// Get the root pci bus get_root_bus(&self) -> Arc<Mutex<PciBus>>235 pub fn get_root_bus(&self) -> Arc<Mutex<PciBus>> { 236 self.root_bus.clone() 237 } 238 239 /// Get the ACPI path to a PCI device acpi_path(&self, address: &PciAddress) -> Option<String>240 pub fn acpi_path(&self, address: &PciAddress) -> Option<String> { 241 if let Some(device) = self.devices.get(address) { 242 let path = self.root_bus.lock().path_to(address.bus); 243 if path.is_empty() { 244 None 245 } else { 246 Some(format!( 247 "_SB_.{}.{}", 248 path.iter() 249 .map(|x| format!("PC{:02X}", x)) 250 .collect::<Vec<String>>() 251 .join("."), 252 match device.lock().is_bridge() { 253 Some(bus_no) => format!("PC{:02X}", bus_no), 254 None => format!("PE{:02X}", address.devfn()), 255 } 256 )) 257 } 258 } else { 259 None 260 } 261 } 262 263 /// enable pcie enhanced configuration access and set base mmio enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64)264 pub fn enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64) { 265 self.pcie_cfg_mmio = Some(pcie_cfg_mmio); 266 // Update the config space registers that depend on pcie_cfg_mmio. 267 self.root_configuration.config.set_reg( 268 PCIE_XBAR_BASE_ADDR, 269 self.pcie_cfg_mmio.unwrap() as u32 | 0x1, 270 0xffff_ffff, 271 ); 272 self.root_configuration.config.set_reg( 273 PCIE_XBAR_BASE_ADDR + 1, 274 (self.pcie_cfg_mmio.unwrap() >> 32) as u32, 275 0xffff_ffff, 276 ); 277 } 278 279 /// Add a `device` to this root PCI bus. add_device<T>( &mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>, mapper: &mut T, ) -> Result<(), Error> where T: PciMmioMapper,280 pub fn add_device<T>( 281 &mut self, 282 address: PciAddress, 283 device: Arc<Mutex<dyn BusDevice>>, 284 mapper: &mut T, 285 ) -> Result<(), Error> 286 where 287 T: PciMmioMapper, 288 { 289 // Ignore attempt to replace PCI Root host bridge. 290 if !address.is_root() { 291 self.pci_mmio_state 292 .setup_mapping(&address, device.lock().deref_mut(), mapper) 293 .map_err(Error::MmioSetup)?; 294 self.devices.insert(address, device); 295 self.sync_multifunction_bit_to_mmio_mappings(&address, true); 296 } 297 298 self.root_bus.lock().add_child_device(address) 299 } 300 sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool)301 fn sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool) { 302 let num_mfd = self.num_multifunction_device(address); 303 let target_range = if (num_mfd == 1 && on_add) || (num_mfd == 0 && !on_add) { 304 // If we added the first mfd or removed the last mfd, update all functions' bits 305 0..8 306 } else if on_add && num_mfd > 0 { 307 // If we added a new function, set its bit if necessary 308 address.func..(address.func + 1) 309 } else { 310 return; 311 }; 312 for i in target_range { 313 self.pci_mmio_state.set_mfd_bit( 314 &PciAddress { 315 func: i, 316 ..*address 317 }, 318 num_mfd > 0, 319 ); 320 } 321 } 322 add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error>323 pub fn add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error> { 324 self.root_bus.lock().add_child_bus(bridge_bus) 325 } 326 remove_device(&mut self, address: PciAddress)327 pub fn remove_device(&mut self, address: PciAddress) { 328 if let Some(d) = self.devices.remove(&address) { 329 for (range, bus_type) in d.lock().get_ranges() { 330 let bus_ptr = if bus_type == BusType::Mmio { 331 match self.mmio_bus.upgrade() { 332 Some(m) => m, 333 None => continue, 334 } 335 } else { 336 match self.io_bus.upgrade() { 337 Some(i) => i, 338 None => continue, 339 } 340 }; 341 let _ = bus_ptr.remove(range.base, range.len); 342 } 343 // Remove the pci bus if this device is a pci bridge. 344 if let Some(bus_no) = d.lock().is_bridge() { 345 let _ = self.root_bus.lock().remove_child_bus(bus_no); 346 } 347 d.lock().destroy_device(); 348 let _ = self.root_bus.lock().remove_child_device(address); 349 } 350 self.sync_multifunction_bit_to_mmio_mappings(&address, false); 351 } 352 config_space_read(&self, address: PciAddress, register: usize) -> u32353 pub fn config_space_read(&self, address: PciAddress, register: usize) -> u32 { 354 if address.is_root() { 355 if register == PCIE_XBAR_BASE_ADDR && self.pcie_cfg_mmio.is_some() { 356 let pcie_mmio = self.pcie_cfg_mmio.unwrap() as u32; 357 pcie_mmio | 0x1 358 } else if register == (PCIE_XBAR_BASE_ADDR + 1) && self.pcie_cfg_mmio.is_some() { 359 (self.pcie_cfg_mmio.unwrap() >> 32) as u32 360 } else { 361 self.root_configuration.config_register_read(register) 362 } 363 } else { 364 let mut data = self 365 .devices 366 .get(&address) 367 .map_or(0xffff_ffff, |d| d.lock().config_register_read(register)); 368 369 if register == HEADER_TYPE_REG { 370 // Set multifunction bit in header type if there are devices at non-zero functions 371 // in this slot. 372 if self.num_multifunction_device(&address) != 0 { 373 data |= (HEADER_TYPE_MULTIFUNCTION_MASK as u32) << (HEADER_TYPE_REG_OFFSET * 8); 374 } 375 } 376 377 data 378 } 379 } 380 config_space_write( &mut self, address: PciAddress, register: usize, offset: u64, data: &[u8], )381 pub fn config_space_write( 382 &mut self, 383 address: PciAddress, 384 register: usize, 385 offset: u64, 386 data: &[u8], 387 ) { 388 if offset as usize + data.len() > 4 { 389 return; 390 } 391 if address.is_root() { 392 self.root_configuration 393 .config_register_write(register, offset, data); 394 } else if let Some(d) = self.devices.get(&address) { 395 let res = d.lock().config_register_write(register, offset, data); 396 397 if !res.mmio_add.is_empty() || !res.mmio_remove.is_empty() { 398 let mmio_bus = match self.mmio_bus.upgrade() { 399 Some(m) => m, 400 None => return, 401 }; 402 for range in &res.mmio_remove { 403 let _ = mmio_bus.remove(range.base, range.len); 404 } 405 for range in &res.mmio_add { 406 let _ = mmio_bus.insert(d.clone(), range.base, range.len); 407 } 408 } 409 410 if !res.io_add.is_empty() || !res.io_remove.is_empty() { 411 let io_bus = match self.io_bus.upgrade() { 412 Some(i) => i, 413 None => return, 414 }; 415 for range in &res.io_remove { 416 let _ = io_bus.remove(range.base, range.len); 417 } 418 for range in &res.io_add { 419 let _ = io_bus.insert(d.clone(), range.base, range.len); 420 } 421 } 422 423 for remove_pci_device in res.removed_pci_devices.iter() { 424 self.remove_device(*remove_pci_device); 425 } 426 } 427 } 428 virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32429 pub fn virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32 { 430 if address.is_root() { 431 0u32 432 } else { 433 self.devices 434 .get(&address) 435 .map_or(0u32, |d| d.lock().virtual_config_register_read(register)) 436 } 437 } 438 virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32)439 pub fn virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32) { 440 if !address.is_root() { 441 if let Some(d) = self.devices.get(&address) { 442 d.lock().virtual_config_register_write(register, value); 443 } 444 } 445 } 446 snapshot(&mut self) -> anyhow::Result<AnySnapshot>447 pub fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> { 448 AnySnapshot::to_any(PciRootSerializable { 449 root_configuration: self 450 .root_configuration 451 .snapshot() 452 .context("failed to serialize PciRoot.root_configuration")?, 453 pcie_cfg_mmio: self.pcie_cfg_mmio, 454 }) 455 .context("failed to serialize PciRoot") 456 } 457 restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>458 pub fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { 459 let deser: PciRootSerializable = 460 AnySnapshot::from_any(data).context("failed to deserialize PciRoot")?; 461 self.root_configuration.restore(deser.root_configuration)?; 462 self.pcie_cfg_mmio = deser.pcie_cfg_mmio; 463 Ok(()) 464 } 465 num_multifunction_device(&self, address: &PciAddress) -> usize466 fn num_multifunction_device(&self, address: &PciAddress) -> usize { 467 self.devices 468 .range(( 469 Included(&PciAddress { 470 func: 1, 471 ..*address 472 }), 473 Included(&PciAddress { 474 func: 7, 475 ..*address 476 }), 477 )) 478 .count() 479 } 480 } 481 482 impl PciRootMmioState { setup_mapping<T>( &mut self, address: &PciAddress, device: &mut dyn BusDevice, mapper: &mut T, ) -> anyhow::Result<()> where T: PciMmioMapper,483 fn setup_mapping<T>( 484 &mut self, 485 address: &PciAddress, 486 device: &mut dyn BusDevice, 487 mapper: &mut T, 488 ) -> anyhow::Result<()> 489 where 490 T: PciMmioMapper, 491 { 492 // ANDROID(b/316956218): pKVM doesn't support readonly memslots, so return early from this 493 // function to opt-out of the optimizations that require readonly memslots. This will also 494 // affect aarch64 cuttlefish unforunately. Once we have a way to detect pKVM at runtime, we 495 // should move this check upstream. 496 if cfg!(target_arch = "aarch64") { 497 return Ok(()); 498 } 499 500 // The PCI spec requires that config writes are non-posted. This requires 501 // uncached mappings in the guest. 32-bit ARM does not support flushing to 502 // PoC from userspace. The cache maintance story for riscv is unclear, so 503 // that is also not implemmented. 504 if cfg!(not(any(target_arch = "x86_64", target_arch = "aarch64"))) { 505 return Ok(()); 506 } 507 508 // The optional optimizations below require the hypervisor to support read-only memory 509 // regions. 510 if !mapper.supports_readonly_mapping() { 511 return Ok(()); 512 } 513 514 let pagesize = base::pagesize(); 515 let offset = address.to_config_address(0, self.register_bit_num); 516 let mmio_mapping_num = offset / pagesize as u32; 517 let (shmem, new_entry) = match self.mappings.entry(mmio_mapping_num) { 518 BTreeMapEntry::Vacant(e) => { 519 let shmem = SharedMemory::new( 520 format!("{:04x}_pci_cfg_mapping", mmio_mapping_num), 521 pagesize as u64, 522 ) 523 .context("failed to create shmem")?; 524 let mapping = MemoryMappingBuilder::new(pagesize) 525 .from_shared_memory(&shmem) 526 .protection(Protection::read_write()) 527 .build() 528 .context("failed to map shmem")?; 529 let (shmem, _) = e.insert(Some((shmem, mapping))).as_ref().unwrap(); 530 (shmem, true) 531 } 532 BTreeMapEntry::Occupied(e) => { 533 let Some((shmem, _)) = e.into_mut() else { 534 // Another device sharing the page didn't support mapped mmio. Oh 535 // well, we'll just have to fall back to vm-exit handling. 536 return Ok(()); 537 }; 538 (&*shmem, false) 539 } 540 }; 541 542 if device.init_pci_config_mapping( 543 shmem, 544 offset as usize % pagesize, 545 1 << self.register_bit_num, 546 ) { 547 if new_entry { 548 let mmio_address = self 549 .base 550 .unchecked_add(mmio_mapping_num as u64 * pagesize as u64); 551 match mapper.add_mapping(mmio_address, shmem) { 552 // We never unmap the mapping, so we don't need the id 553 Ok(_) => (), 554 // If this fails, mmio handling via vm-exit will work fine. Devices 555 // will be doing some pointless work keeping the unused mapping up 556 // to date, but addressing that isn't worth the implementation cost. 557 Err(e) => error!("Failed to map mmio page; {:?}", e), 558 } 559 } 560 } else { 561 self.mappings.insert(mmio_mapping_num, None); 562 } 563 Ok(()) 564 } 565 set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool)566 fn set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool) { 567 let pagesize = base::pagesize(); 568 let offset = address.to_config_address(0, self.register_bit_num); 569 let mapping_num = offset / pagesize as u32; 570 if let Some(Some((_, mapping))) = self.mappings.get_mut(&mapping_num) { 571 let mapping_base = offset as usize % pagesize; 572 let reg_offset = mapping_base + (HEADER_TYPE_REG * 4) + HEADER_TYPE_REG_OFFSET; 573 574 let mut val = mapping.read_obj::<u8>(reg_offset).expect("memcpy failed"); 575 val = if is_mfd { 576 val | HEADER_TYPE_MULTIFUNCTION_MASK 577 } else { 578 val & !HEADER_TYPE_MULTIFUNCTION_MASK 579 }; 580 mapping 581 .write_obj_volatile(val, reg_offset) 582 .expect("memcpy failed"); 583 if let Err(err) = mapping.flush_region(reg_offset, 4) { 584 error!("failed to flush write to mfd bit: {}", err); 585 } 586 } 587 } 588 } 589 590 pub trait PciMmioMapper { supports_readonly_mapping(&self) -> bool591 fn supports_readonly_mapping(&self) -> bool; add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>592 fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>; 593 } 594 595 impl<T: Vm> PciMmioMapper for T { supports_readonly_mapping(&self) -> bool596 fn supports_readonly_mapping(&self) -> bool { 597 self.check_capability(hypervisor::VmCap::ReadOnlyMemoryRegion) 598 } 599 add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>600 fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32> { 601 let mapping = MemoryMappingBuilder::new(base::pagesize()) 602 .from_shared_memory(shmem) 603 .protection(Protection::read()) 604 .build() 605 .context("failed to map shmem")?; 606 self.add_memory_region( 607 addr, 608 Box::new(mapping), 609 true, 610 false, 611 MemCacheType::CacheCoherent, 612 ) 613 .context("failed to create vm mapping") 614 } 615 } 616 617 /// Emulates PCI configuration access mechanism #1 (I/O ports 0xcf8 and 0xcfc). 618 pub struct PciConfigIo { 619 /// PCI root bridge. 620 pci_root: Arc<Mutex<PciRoot>>, 621 /// Current address to read/write from (0xcf8 register, litte endian). 622 config_address: u32, 623 /// Whether or not to actually function. 624 break_linux_pci_config_io: bool, 625 /// Tube to signal that the guest requested reset via writing to 0xcf9 register. 626 reset_evt_wrtube: SendTube, 627 } 628 629 #[derive(Serialize, Deserialize)] 630 struct PciConfigIoSerializable { 631 pci_root: AnySnapshot, 632 config_address: u32, 633 } 634 635 impl PciConfigIo { 636 const REGISTER_BITS_NUM: usize = 8; 637 new( pci_root: Arc<Mutex<PciRoot>>, break_linux_pci_config_io: bool, reset_evt_wrtube: SendTube, ) -> Self638 pub fn new( 639 pci_root: Arc<Mutex<PciRoot>>, 640 break_linux_pci_config_io: bool, 641 reset_evt_wrtube: SendTube, 642 ) -> Self { 643 PciConfigIo { 644 pci_root, 645 config_address: 0, 646 break_linux_pci_config_io, 647 reset_evt_wrtube, 648 } 649 } 650 config_space_read(&self) -> u32651 fn config_space_read(&self) -> u32 { 652 let enabled = (self.config_address & 0x8000_0000) != 0; 653 if !enabled { 654 return 0xffff_ffff; 655 } 656 657 let (address, register) = 658 PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM); 659 self.pci_root.lock().config_space_read(address, register) 660 } 661 config_space_write(&mut self, offset: u64, data: &[u8])662 fn config_space_write(&mut self, offset: u64, data: &[u8]) { 663 let enabled = (self.config_address & 0x8000_0000) != 0; 664 if !enabled { 665 return; 666 } 667 668 let (address, register) = 669 PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM); 670 self.pci_root 671 .lock() 672 .config_space_write(address, register, offset, data) 673 } 674 set_config_address(&mut self, offset: u64, data: &[u8])675 fn set_config_address(&mut self, offset: u64, data: &[u8]) { 676 if offset as usize + data.len() > 4 { 677 return; 678 } 679 let (mask, value): (u32, u32) = match data.len() { 680 1 => ( 681 0x0000_00ff << (offset * 8), 682 (data[0] as u32) << (offset * 8), 683 ), 684 2 => ( 685 0x0000_ffff << (offset * 8), 686 u32::from(u16::from_le_bytes(data.try_into().unwrap())) << (offset * 8), 687 ), 688 4 => (0xffff_ffff, u32::from_le_bytes(data.try_into().unwrap())), 689 _ => return, 690 }; 691 self.config_address = (self.config_address & !mask) | value; 692 } 693 } 694 695 const PCI_RESET_CPU_BIT: u8 = 1 << 2; 696 697 impl BusDevice for PciConfigIo { debug_label(&self) -> String698 fn debug_label(&self) -> String { 699 "pci config io-port".to_string() 700 } 701 device_id(&self) -> DeviceId702 fn device_id(&self) -> DeviceId { 703 PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into() 704 } 705 read(&mut self, info: BusAccessInfo, data: &mut [u8])706 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 707 if self.break_linux_pci_config_io { 708 for d in data { 709 *d = 0xff; 710 } 711 return; 712 } 713 // `offset` is relative to 0xcf8 714 let value = match info.offset { 715 0..=3 => self.config_address, 716 4..=7 => self.config_space_read(), 717 _ => 0xffff_ffff, 718 }; 719 720 // Only allow reads to the register boundary. 721 let start = info.offset as usize % 4; 722 let end = start + data.len(); 723 if end <= 4 { 724 for i in start..end { 725 data[i - start] = (value >> (i * 8)) as u8; 726 } 727 } else { 728 for d in data { 729 *d = 0xff; 730 } 731 } 732 } 733 write(&mut self, info: BusAccessInfo, data: &[u8])734 fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 735 // `offset` is relative to 0xcf8 736 match info.offset { 737 _o @ 1 if data.len() == 1 && data[0] & PCI_RESET_CPU_BIT != 0 => { 738 if let Err(e) = self 739 .reset_evt_wrtube 740 .send::<VmEventType>(&VmEventType::Reset) 741 { 742 error!("failed to trigger PCI 0xcf9 reset event: {}", e); 743 } 744 } 745 o @ 0..=3 => self.set_config_address(o, data), 746 o @ 4..=7 => self.config_space_write(o - 4, data), 747 _ => (), 748 }; 749 } 750 } 751 752 impl Suspendable for PciConfigIo { 753 // no thread to sleep, no change required. sleep(&mut self) -> anyhow::Result<()>754 fn sleep(&mut self) -> anyhow::Result<()> { 755 Ok(()) 756 } 757 wake(&mut self) -> anyhow::Result<()>758 fn wake(&mut self) -> anyhow::Result<()> { 759 Ok(()) 760 } 761 snapshot(&mut self) -> anyhow::Result<AnySnapshot>762 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> { 763 AnySnapshot::to_any(PciConfigIoSerializable { 764 pci_root: self 765 .pci_root 766 .lock() 767 .snapshot() 768 .context("failed to snapshot root")?, 769 config_address: self.config_address, 770 }) 771 .with_context(|| format!("failed to serialize {}", self.debug_label())) 772 } 773 restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>774 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { 775 let mut root = self.pci_root.lock(); 776 let deser: PciConfigIoSerializable = AnySnapshot::from_any(data) 777 .context(format!("failed to deserialize {}", self.debug_label()))?; 778 root.restore(deser.pci_root)?; 779 self.config_address = deser.config_address; 780 Ok(()) 781 } 782 } 783 784 /// Emulates PCI memory-mapped configuration access mechanism. 785 pub struct PciConfigMmio { 786 /// PCI root bridge. 787 pci_root: Arc<Mutex<PciRoot>>, 788 /// Register bit number in config address. 789 register_bit_num: usize, 790 } 791 792 #[derive(Serialize, Deserialize)] 793 struct PciConfigMmioSerializable { 794 pci_root: AnySnapshot, 795 register_bit_num: usize, 796 } 797 798 impl PciConfigMmio { new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self799 pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self { 800 PciConfigMmio { 801 pci_root, 802 register_bit_num, 803 } 804 } 805 config_space_read(&self, config_address: u32) -> u32806 fn config_space_read(&self, config_address: u32) -> u32 { 807 let (address, register) = 808 PciAddress::from_config_address(config_address, self.register_bit_num); 809 self.pci_root.lock().config_space_read(address, register) 810 } 811 config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8])812 fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) { 813 let (address, register) = 814 PciAddress::from_config_address(config_address, self.register_bit_num); 815 self.pci_root 816 .lock() 817 .config_space_write(address, register, offset, data) 818 } 819 } 820 821 impl BusDevice for PciConfigMmio { debug_label(&self) -> String822 fn debug_label(&self) -> String { 823 "pci config mmio".to_owned() 824 } 825 device_id(&self) -> DeviceId826 fn device_id(&self) -> DeviceId { 827 PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into() 828 } 829 read(&mut self, info: BusAccessInfo, data: &mut [u8])830 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 831 // Only allow reads to the register boundary. 832 let start = info.offset as usize % 4; 833 let end = start + data.len(); 834 if end > 4 || info.offset > u32::MAX as u64 { 835 for d in data { 836 *d = 0xff; 837 } 838 return; 839 } 840 841 let value = self.config_space_read(info.offset as u32); 842 for i in start..end { 843 data[i - start] = (value >> (i * 8)) as u8; 844 } 845 } 846 write(&mut self, info: BusAccessInfo, data: &[u8])847 fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 848 if info.offset > u32::MAX as u64 { 849 return; 850 } 851 self.config_space_write(info.offset as u32, info.offset % 4, data) 852 } 853 } 854 855 impl Suspendable for PciConfigMmio { 856 // no thread to sleep, no change required. sleep(&mut self) -> anyhow::Result<()>857 fn sleep(&mut self) -> anyhow::Result<()> { 858 Ok(()) 859 } 860 wake(&mut self) -> anyhow::Result<()>861 fn wake(&mut self) -> anyhow::Result<()> { 862 Ok(()) 863 } 864 snapshot(&mut self) -> anyhow::Result<AnySnapshot>865 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> { 866 AnySnapshot::to_any(PciConfigMmioSerializable { 867 pci_root: self 868 .pci_root 869 .lock() 870 .snapshot() 871 .context("failed to snapshot root")?, 872 register_bit_num: self.register_bit_num, 873 }) 874 .with_context(|| format!("failed to serialize {}", self.debug_label())) 875 } 876 restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>877 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { 878 let mut root = self.pci_root.lock(); 879 let deser: PciConfigMmioSerializable = AnySnapshot::from_any(data) 880 .context(format!("failed to deserialize {}", self.debug_label()))?; 881 root.restore(deser.pci_root)?; 882 self.register_bit_num = deser.register_bit_num; 883 Ok(()) 884 } 885 } 886 887 /// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in 888 /// total) for each PCI device. The guest can use these registers to exchange device-specific 889 /// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these 890 /// register's emulation. The second 4KB is mapped into guest directly as shared memory, so 891 /// when guest access this 4KB, vm exit doesn't happen. 892 /// All these virtual registers from all PCI devices locate in a contiguous memory region. 893 /// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT. 894 /// Bit 12 is used to select the first trapped page or the second directly mapped page 895 /// The offset of each register is calculated in the same way as PCIe ECAM; 896 /// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) | 897 /// (register_index << 2) 898 pub struct PciVirtualConfigMmio { 899 /// PCI root bridge. 900 pci_root: Arc<Mutex<PciRoot>>, 901 /// Register bit number in config address. 902 register_bit_num: usize, 903 } 904 905 #[derive(Serialize, Deserialize)] 906 struct PciVirtualConfigMmioSerializable { 907 pci_root: AnySnapshot, 908 register_bit_num: usize, 909 } 910 911 impl PciVirtualConfigMmio { new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self912 pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self { 913 PciVirtualConfigMmio { 914 pci_root, 915 register_bit_num, 916 } 917 } 918 } 919 920 impl BusDevice for PciVirtualConfigMmio { debug_label(&self) -> String921 fn debug_label(&self) -> String { 922 "pci virtual config mmio".to_owned() 923 } 924 device_id(&self) -> DeviceId925 fn device_id(&self) -> DeviceId { 926 PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into() 927 } 928 read(&mut self, info: BusAccessInfo, data: &mut [u8])929 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 930 let value = if info.offset % 4 != 0 || data.len() != 4 { 931 error!( 932 "{} unexpected read at offset = {}, len = {}", 933 self.debug_label(), 934 info.offset, 935 data.len() 936 ); 937 0u32 938 } else { 939 let (address, register) = 940 PciAddress::from_config_address(info.offset as u32, self.register_bit_num); 941 self.pci_root 942 .lock() 943 .virtual_config_space_read(address, register) 944 }; 945 data[0..4].copy_from_slice(&value.to_le_bytes()[..]); 946 } 947 write(&mut self, info: BusAccessInfo, data: &[u8])948 fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 949 if info.offset % 4 != 0 || data.len() != 4 { 950 error!( 951 "{} unexpected write at offset = {}, len = {}", 952 self.debug_label(), 953 info.offset, 954 data.len() 955 ); 956 return; 957 } 958 // Unwrap is safe as we verified length above 959 let value = u32::from_le_bytes(data.try_into().unwrap()); 960 let (address, register) = 961 PciAddress::from_config_address(info.offset as u32, self.register_bit_num); 962 self.pci_root 963 .lock() 964 .virtual_config_space_write(address, register, value) 965 } 966 } 967 968 impl Suspendable for PciVirtualConfigMmio { 969 // no thread to sleep, no change required. sleep(&mut self) -> anyhow::Result<()>970 fn sleep(&mut self) -> anyhow::Result<()> { 971 Ok(()) 972 } 973 wake(&mut self) -> anyhow::Result<()>974 fn wake(&mut self) -> anyhow::Result<()> { 975 Ok(()) 976 } 977 snapshot(&mut self) -> anyhow::Result<AnySnapshot>978 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> { 979 AnySnapshot::to_any(PciVirtualConfigMmioSerializable { 980 pci_root: self 981 .pci_root 982 .lock() 983 .snapshot() 984 .context("failed to snapshot root")?, 985 register_bit_num: self.register_bit_num, 986 }) 987 .with_context(|| format!("failed to serialize {}", self.debug_label())) 988 } 989 restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>990 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { 991 let mut root = self.pci_root.lock(); 992 let deser: PciVirtualConfigMmioSerializable = AnySnapshot::from_any(data) 993 .context(format!("failed to deserialize {}", self.debug_label()))?; 994 root.restore(deser.pci_root)?; 995 self.register_bit_num = deser.register_bit_num; 996 997 Ok(()) 998 } 999 } 1000 1001 #[cfg(test)] 1002 mod tests { 1003 use base::Tube; 1004 1005 use super::*; 1006 use crate::suspendable_tests; 1007 create_pci_root() -> Arc<Mutex<PciRoot>>1008 fn create_pci_root() -> Arc<Mutex<PciRoot>> { 1009 let io_bus = Arc::new(Bus::new(BusType::Io)); 1010 let mmio_bus = Arc::new(Bus::new(BusType::Mmio)); 1011 let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false))); 1012 1013 Arc::new(Mutex::new(PciRoot::create_for_test( 1014 Arc::downgrade(&mmio_bus), 1015 GuestAddress(0), 1016 0, 1017 Arc::downgrade(&io_bus), 1018 root_bus, 1019 ))) 1020 } 1021 create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo1022 fn create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo { 1023 let (reset_evt_wrtube, _) = Tube::directional_pair().unwrap(); 1024 PciConfigIo::new(pci_root, false, reset_evt_wrtube) 1025 } 1026 modify_pci_io_config(pci_config: &mut PciConfigIo)1027 fn modify_pci_io_config(pci_config: &mut PciConfigIo) { 1028 pci_config.config_address += 1; 1029 } create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio1030 fn create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio { 1031 PciConfigMmio::new(pci_root, 0) 1032 } 1033 modify_pci_mmio_config(pci_config: &mut PciConfigMmio)1034 fn modify_pci_mmio_config(pci_config: &mut PciConfigMmio) { 1035 pci_config.register_bit_num += 1; 1036 } 1037 create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio1038 fn create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio { 1039 PciVirtualConfigMmio::new(pci_root, 0) 1040 } 1041 modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio)1042 fn modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio) { 1043 pci_config.register_bit_num += 1; 1044 } 1045 1046 suspendable_tests!( 1047 pci_io_config, 1048 create_pci_io_config(create_pci_root()), 1049 modify_pci_io_config 1050 ); 1051 suspendable_tests!( 1052 pcie_mmio_config, 1053 create_pci_mmio_config(create_pci_root()), 1054 modify_pci_mmio_config 1055 ); 1056 suspendable_tests!( 1057 pci_virtual_config_mmio, 1058 create_pci_virtual_config_mmio(create_pci_root()), 1059 modify_pci_virtual_config_mmio 1060 ); 1061 1062 #[test] pci_set_config_address_word()1063 fn pci_set_config_address_word() { 1064 let mut pci_io_config = create_pci_io_config(create_pci_root()); 1065 1066 // Set the full 32-bit config_address to a known value (0x11223344). 1067 pci_io_config.write( 1068 BusAccessInfo { 1069 offset: 0, 1070 address: 0xCF8, 1071 id: 0, 1072 }, 1073 &[0x44, 0x33, 0x22, 0x11], 1074 ); 1075 1076 // Overwrite the high 16 bits of config_address with 0x55AA (test for b/274366589). 1077 pci_io_config.write( 1078 BusAccessInfo { 1079 offset: 2, 1080 address: 0xCFA, 1081 id: 0, 1082 }, 1083 &[0xAA, 0x55], 1084 ); 1085 1086 // Verify config_address has the expected value (0x55AA3344). 1087 let mut config_address = [0u8; 4]; 1088 pci_io_config.read( 1089 BusAccessInfo { 1090 offset: 0, 1091 address: 0xCF8, 1092 id: 0, 1093 }, 1094 &mut config_address, 1095 ); 1096 assert_eq!(config_address, [0x44, 0x33, 0xAA, 0x55]); 1097 } 1098 } 1099