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