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