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