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