1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE-BSD-3-Clause file. 4 5 use crate::configuration::{ 6 PciBarRegionType, PciBridgeSubclass, PciClassCode, PciConfiguration, PciHeaderType, 7 }; 8 use crate::device::{DeviceRelocation, Error as PciDeviceError, PciDevice}; 9 use crate::PciBarConfiguration; 10 use byteorder::{ByteOrder, LittleEndian}; 11 use std::any::Any; 12 use std::collections::HashMap; 13 use std::ops::DerefMut; 14 use std::sync::{Arc, Barrier, Mutex}; 15 use vm_device::{Bus, BusDevice}; 16 17 const VENDOR_ID_INTEL: u16 = 0x8086; 18 const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57; 19 const NUM_DEVICE_IDS: usize = 32; 20 21 /// Errors for device manager. 22 #[derive(Debug)] 23 pub enum PciRootError { 24 /// Could not allocate device address space for the device. 25 AllocateDeviceAddrs(PciDeviceError), 26 /// Could not allocate an IRQ number. 27 AllocateIrq, 28 /// Could not add a device to the port io bus. 29 PioInsert(vm_device::BusError), 30 /// Could not add a device to the mmio bus. 31 MmioInsert(vm_device::BusError), 32 /// Could not find an available device slot on the PCI bus. 33 NoPciDeviceSlotAvailable, 34 /// Invalid PCI device identifier provided. 35 InvalidPciDeviceSlot(usize), 36 /// Valid PCI device identifier but already used. 37 AlreadyInUsePciDeviceSlot(usize), 38 } 39 pub type Result<T> = std::result::Result<T, PciRootError>; 40 41 /// Emulates the PCI Root bridge device. 42 pub struct PciRoot { 43 /// Configuration space. 44 config: PciConfiguration, 45 } 46 47 impl PciRoot { 48 /// Create an empty PCI root bridge. 49 pub fn new(config: Option<PciConfiguration>) -> Self { 50 if let Some(config) = config { 51 PciRoot { config } 52 } else { 53 PciRoot { 54 config: PciConfiguration::new( 55 VENDOR_ID_INTEL, 56 DEVICE_ID_INTEL_VIRT_PCIE_HOST, 57 0, 58 PciClassCode::BridgeDevice, 59 &PciBridgeSubclass::HostBridge, 60 None, 61 PciHeaderType::Device, 62 0, 63 0, 64 None, 65 None, 66 ), 67 } 68 } 69 } 70 } 71 72 impl BusDevice for PciRoot {} 73 74 impl PciDevice for PciRoot { 75 fn write_config_register( 76 &mut self, 77 reg_idx: usize, 78 offset: u64, 79 data: &[u8], 80 ) -> Option<Arc<Barrier>> { 81 self.config.write_config_register(reg_idx, offset, data); 82 None 83 } 84 85 fn read_config_register(&mut self, reg_idx: usize) -> u32 { 86 self.config.read_reg(reg_idx) 87 } 88 89 fn as_any(&mut self) -> &mut dyn Any { 90 self 91 } 92 93 fn id(&self) -> Option<String> { 94 None 95 } 96 } 97 98 pub struct PciBus { 99 /// Devices attached to this bus. 100 /// Device 0 is host bridge. 101 devices: HashMap<u32, Arc<Mutex<dyn PciDevice>>>, 102 device_reloc: Arc<dyn DeviceRelocation>, 103 device_ids: Vec<bool>, 104 } 105 106 impl PciBus { 107 pub fn new(pci_root: PciRoot, device_reloc: Arc<dyn DeviceRelocation>) -> Self { 108 let mut devices: HashMap<u32, Arc<Mutex<dyn PciDevice>>> = HashMap::new(); 109 let mut device_ids: Vec<bool> = vec![false; NUM_DEVICE_IDS]; 110 111 devices.insert(0, Arc::new(Mutex::new(pci_root))); 112 device_ids[0] = true; 113 114 PciBus { 115 devices, 116 device_reloc, 117 device_ids, 118 } 119 } 120 121 pub fn register_mapping( 122 &self, 123 dev: Arc<Mutex<dyn BusDevice>>, 124 #[cfg(target_arch = "x86_64")] io_bus: &Bus, 125 mmio_bus: &Bus, 126 bars: Vec<PciBarConfiguration>, 127 ) -> Result<()> { 128 for bar in bars { 129 match bar.region_type() { 130 PciBarRegionType::IoRegion => { 131 #[cfg(target_arch = "x86_64")] 132 io_bus 133 .insert(dev.clone(), bar.addr(), bar.size()) 134 .map_err(PciRootError::PioInsert)?; 135 #[cfg(target_arch = "aarch64")] 136 error!("I/O region is not supported"); 137 } 138 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { 139 mmio_bus 140 .insert(dev.clone(), bar.addr(), bar.size()) 141 .map_err(PciRootError::MmioInsert)?; 142 } 143 } 144 } 145 Ok(()) 146 } 147 148 pub fn add_device(&mut self, device_id: u32, device: Arc<Mutex<dyn PciDevice>>) -> Result<()> { 149 self.devices.insert(device_id, device); 150 Ok(()) 151 } 152 153 pub fn remove_by_device(&mut self, device: &Arc<Mutex<dyn PciDevice>>) -> Result<()> { 154 self.devices.retain(|_, dev| !Arc::ptr_eq(dev, device)); 155 Ok(()) 156 } 157 158 pub fn next_device_id(&mut self) -> Result<u32> { 159 for (idx, device_id) in self.device_ids.iter_mut().enumerate() { 160 if !(*device_id) { 161 *device_id = true; 162 return Ok(idx as u32); 163 } 164 } 165 166 Err(PciRootError::NoPciDeviceSlotAvailable) 167 } 168 169 pub fn get_device_id(&mut self, id: usize) -> Result<()> { 170 if id < NUM_DEVICE_IDS { 171 if !self.device_ids[id] { 172 self.device_ids[id] = true; 173 Ok(()) 174 } else { 175 Err(PciRootError::AlreadyInUsePciDeviceSlot(id)) 176 } 177 } else { 178 Err(PciRootError::InvalidPciDeviceSlot(id)) 179 } 180 } 181 182 pub fn put_device_id(&mut self, id: usize) -> Result<()> { 183 if id < NUM_DEVICE_IDS { 184 self.device_ids[id] = false; 185 Ok(()) 186 } else { 187 Err(PciRootError::InvalidPciDeviceSlot(id)) 188 } 189 } 190 } 191 192 pub struct PciConfigIo { 193 /// Config space register. 194 config_address: u32, 195 pci_bus: Arc<Mutex<PciBus>>, 196 } 197 198 impl PciConfigIo { 199 pub fn new(pci_bus: Arc<Mutex<PciBus>>) -> Self { 200 PciConfigIo { 201 config_address: 0, 202 pci_bus, 203 } 204 } 205 206 pub fn config_space_read(&self) -> u32 { 207 let enabled = (self.config_address & 0x8000_0000) != 0; 208 if !enabled { 209 return 0xffff_ffff; 210 } 211 212 let (bus, device, function, register) = 213 parse_io_config_address(self.config_address & !0x8000_0000); 214 215 // Only support one bus. 216 if bus != 0 { 217 return 0xffff_ffff; 218 } 219 220 // Don't support multi-function devices. 221 if function > 0 { 222 return 0xffff_ffff; 223 } 224 225 self.pci_bus 226 .as_ref() 227 .lock() 228 .unwrap() 229 .devices 230 .get(&(device as u32)) 231 .map_or(0xffff_ffff, |d| { 232 d.lock().unwrap().read_config_register(register) 233 }) 234 } 235 236 pub fn config_space_write(&mut self, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 237 if offset as usize + data.len() > 4 { 238 return None; 239 } 240 241 let enabled = (self.config_address & 0x8000_0000) != 0; 242 if !enabled { 243 return None; 244 } 245 246 let (bus, device, _function, register) = 247 parse_io_config_address(self.config_address & !0x8000_0000); 248 249 // Only support one bus. 250 if bus != 0 { 251 return None; 252 } 253 254 let pci_bus = self.pci_bus.as_ref().lock().unwrap(); 255 if let Some(d) = pci_bus.devices.get(&(device as u32)) { 256 let mut device = d.lock().unwrap(); 257 258 // Find out if one of the device's BAR is being reprogrammed, and 259 // reprogram it if needed. 260 if let Some(params) = device.detect_bar_reprogramming(register, data) { 261 if let Err(e) = pci_bus.device_reloc.move_bar( 262 params.old_base, 263 params.new_base, 264 params.len, 265 device.deref_mut(), 266 params.region_type, 267 ) { 268 error!( 269 "Failed moving device BAR: {}: 0x{:x}->0x{:x}(0x{:x})", 270 e, params.old_base, params.new_base, params.len 271 ); 272 } 273 } 274 275 // Update the register value 276 device.write_config_register(register, offset, data) 277 } else { 278 None 279 } 280 } 281 282 fn set_config_address(&mut self, offset: u64, data: &[u8]) { 283 if offset as usize + data.len() > 4 { 284 return; 285 } 286 let (mask, value): (u32, u32) = match data.len() { 287 1 => ( 288 0x0000_00ff << (offset * 8), 289 u32::from(data[0]) << (offset * 8), 290 ), 291 2 => ( 292 0x0000_ffff << (offset * 16), 293 (u32::from(data[1]) << 8 | u32::from(data[0])) << (offset * 16), 294 ), 295 4 => (0xffff_ffff, LittleEndian::read_u32(data)), 296 _ => return, 297 }; 298 self.config_address = (self.config_address & !mask) | value; 299 } 300 } 301 302 impl BusDevice for PciConfigIo { 303 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 304 // `offset` is relative to 0xcf8 305 let value = match offset { 306 0..=3 => self.config_address, 307 4..=7 => self.config_space_read(), 308 _ => 0xffff_ffff, 309 }; 310 311 // Only allow reads to the register boundary. 312 let start = offset as usize % 4; 313 let end = start + data.len(); 314 if end <= 4 { 315 for i in start..end { 316 data[i - start] = (value >> (i * 8)) as u8; 317 } 318 } else { 319 for d in data { 320 *d = 0xff; 321 } 322 } 323 } 324 325 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 326 // `offset` is relative to 0xcf8 327 match offset { 328 o @ 0..=3 => { 329 self.set_config_address(o, data); 330 None 331 } 332 o @ 4..=7 => self.config_space_write(o - 4, data), 333 _ => None, 334 } 335 } 336 } 337 338 /// Emulates PCI memory-mapped configuration access mechanism. 339 pub struct PciConfigMmio { 340 pci_bus: Arc<Mutex<PciBus>>, 341 } 342 343 impl PciConfigMmio { 344 pub fn new(pci_bus: Arc<Mutex<PciBus>>) -> Self { 345 PciConfigMmio { pci_bus } 346 } 347 348 fn config_space_read(&self, config_address: u32) -> u32 { 349 let (bus, device, _function, register) = parse_mmio_config_address(config_address); 350 351 // Only support one bus. 352 if bus != 0 { 353 return 0xffff_ffff; 354 } 355 356 self.pci_bus 357 .lock() 358 .unwrap() 359 .devices 360 .get(&(device as u32)) 361 .map_or(0xffff_ffff, |d| { 362 d.lock().unwrap().read_config_register(register) 363 }) 364 } 365 366 fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) { 367 if offset as usize + data.len() > 4 { 368 return; 369 } 370 371 let (bus, device, _function, register) = parse_mmio_config_address(config_address); 372 373 // Only support one bus. 374 if bus != 0 { 375 return; 376 } 377 378 let pci_bus = self.pci_bus.lock().unwrap(); 379 if let Some(d) = pci_bus.devices.get(&(device as u32)) { 380 let mut device = d.lock().unwrap(); 381 382 // Find out if one of the device's BAR is being reprogrammed, and 383 // reprogram it if needed. 384 if let Some(params) = device.detect_bar_reprogramming(register, data) { 385 if let Err(e) = pci_bus.device_reloc.move_bar( 386 params.old_base, 387 params.new_base, 388 params.len, 389 device.deref_mut(), 390 params.region_type, 391 ) { 392 error!( 393 "Failed moving device BAR: {}: 0x{:x}->0x{:x}(0x{:x})", 394 e, params.old_base, params.new_base, params.len 395 ); 396 } 397 } 398 399 // Update the register value 400 device.write_config_register(register, offset, data); 401 } 402 } 403 } 404 405 impl BusDevice for PciConfigMmio { 406 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 407 // Only allow reads to the register boundary. 408 let start = offset as usize % 4; 409 let end = start + data.len(); 410 if end > 4 || offset > u64::from(u32::max_value()) { 411 for d in data { 412 *d = 0xff; 413 } 414 return; 415 } 416 417 let value = self.config_space_read(offset as u32); 418 for i in start..end { 419 data[i - start] = (value >> (i * 8)) as u8; 420 } 421 } 422 423 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 424 if offset > u64::from(u32::max_value()) { 425 return None; 426 } 427 self.config_space_write(offset as u32, offset % 4, data); 428 429 None 430 } 431 } 432 433 fn shift_and_mask(value: u32, offset: usize, mask: u32) -> usize { 434 ((value >> offset) & mask) as usize 435 } 436 437 // Parse the MMIO address offset to a (bus, device, function, register) tuple. 438 // See section 7.2.2 PCI Express Enhanced Configuration Access Mechanism (ECAM) 439 // from the Pci Express Base Specification Revision 5.0 Version 1.0. 440 fn parse_mmio_config_address(config_address: u32) -> (usize, usize, usize, usize) { 441 const BUS_NUMBER_OFFSET: usize = 20; 442 const BUS_NUMBER_MASK: u32 = 0x00ff; 443 const DEVICE_NUMBER_OFFSET: usize = 15; 444 const DEVICE_NUMBER_MASK: u32 = 0x1f; 445 const FUNCTION_NUMBER_OFFSET: usize = 12; 446 const FUNCTION_NUMBER_MASK: u32 = 0x07; 447 const REGISTER_NUMBER_OFFSET: usize = 2; 448 const REGISTER_NUMBER_MASK: u32 = 0x3ff; 449 450 ( 451 shift_and_mask(config_address, BUS_NUMBER_OFFSET, BUS_NUMBER_MASK), 452 shift_and_mask(config_address, DEVICE_NUMBER_OFFSET, DEVICE_NUMBER_MASK), 453 shift_and_mask(config_address, FUNCTION_NUMBER_OFFSET, FUNCTION_NUMBER_MASK), 454 shift_and_mask(config_address, REGISTER_NUMBER_OFFSET, REGISTER_NUMBER_MASK), 455 ) 456 } 457 458 // Parse the CONFIG_ADDRESS register to a (bus, device, function, register) tuple. 459 fn parse_io_config_address(config_address: u32) -> (usize, usize, usize, usize) { 460 const BUS_NUMBER_OFFSET: usize = 16; 461 const BUS_NUMBER_MASK: u32 = 0x00ff; 462 const DEVICE_NUMBER_OFFSET: usize = 11; 463 const DEVICE_NUMBER_MASK: u32 = 0x1f; 464 const FUNCTION_NUMBER_OFFSET: usize = 8; 465 const FUNCTION_NUMBER_MASK: u32 = 0x07; 466 const REGISTER_NUMBER_OFFSET: usize = 2; 467 const REGISTER_NUMBER_MASK: u32 = 0x3f; 468 469 ( 470 shift_and_mask(config_address, BUS_NUMBER_OFFSET, BUS_NUMBER_MASK), 471 shift_and_mask(config_address, DEVICE_NUMBER_OFFSET, DEVICE_NUMBER_MASK), 472 shift_and_mask(config_address, FUNCTION_NUMBER_OFFSET, FUNCTION_NUMBER_MASK), 473 shift_and_mask(config_address, REGISTER_NUMBER_OFFSET, REGISTER_NUMBER_MASK), 474 ) 475 } 476