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(&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 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 io_bus 136 .insert(dev.clone(), bar.addr(), bar.size()) 137 .map_err(PciRootError::PioInsert)?; 138 } 139 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { 140 mmio_bus 141 .insert(dev.clone(), bar.addr(), bar.size()) 142 .map_err(PciRootError::MmioInsert)?; 143 } 144 } 145 } 146 Ok(()) 147 } 148 149 pub fn add_device(&mut self, device_id: u32, device: Arc<Mutex<dyn PciDevice>>) -> Result<()> { 150 self.devices.insert(device_id, device); 151 Ok(()) 152 } 153 154 pub fn remove_by_device(&mut self, device: &Arc<Mutex<dyn PciDevice>>) -> Result<()> { 155 self.devices.retain(|_, dev| !Arc::ptr_eq(dev, device)); 156 Ok(()) 157 } 158 159 pub fn next_device_id(&mut self) -> Result<u32> { 160 for (idx, device_id) in self.device_ids.iter_mut().enumerate() { 161 if !(*device_id) { 162 *device_id = true; 163 return Ok(idx as u32); 164 } 165 } 166 167 Err(PciRootError::NoPciDeviceSlotAvailable) 168 } 169 170 pub fn get_device_id(&mut self, id: usize) -> Result<()> { 171 if id < NUM_DEVICE_IDS { 172 if !self.device_ids[id] { 173 self.device_ids[id] = true; 174 Ok(()) 175 } else { 176 Err(PciRootError::AlreadyInUsePciDeviceSlot(id)) 177 } 178 } else { 179 Err(PciRootError::InvalidPciDeviceSlot(id)) 180 } 181 } 182 183 pub fn put_device_id(&mut self, id: usize) -> Result<()> { 184 if id < NUM_DEVICE_IDS { 185 self.device_ids[id] = false; 186 Ok(()) 187 } else { 188 Err(PciRootError::InvalidPciDeviceSlot(id)) 189 } 190 } 191 } 192 193 pub struct PciConfigIo { 194 /// Config space register. 195 config_address: u32, 196 pci_bus: Arc<Mutex<PciBus>>, 197 } 198 199 impl PciConfigIo { 200 pub fn new(pci_bus: Arc<Mutex<PciBus>>) -> Self { 201 PciConfigIo { 202 config_address: 0, 203 pci_bus, 204 } 205 } 206 207 pub fn config_space_read(&self) -> u32 { 208 let enabled = (self.config_address & 0x8000_0000) != 0; 209 if !enabled { 210 return 0xffff_ffff; 211 } 212 213 let (bus, device, function, register) = 214 parse_io_config_address(self.config_address & !0x8000_0000); 215 216 // Only support one bus. 217 if bus != 0 { 218 return 0xffff_ffff; 219 } 220 221 // Don't support multi-function devices. 222 if function > 0 { 223 return 0xffff_ffff; 224 } 225 226 self.pci_bus 227 .as_ref() 228 .lock() 229 .unwrap() 230 .devices 231 .get(&(device as u32)) 232 .map_or(0xffff_ffff, |d| { 233 d.lock().unwrap().read_config_register(register) 234 }) 235 } 236 237 pub fn config_space_write(&mut self, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 238 if offset as usize + data.len() > 4 { 239 return None; 240 } 241 242 let enabled = (self.config_address & 0x8000_0000) != 0; 243 if !enabled { 244 return None; 245 } 246 247 let (bus, device, _function, register) = 248 parse_io_config_address(self.config_address & !0x8000_0000); 249 250 // Only support one bus. 251 if bus != 0 { 252 return None; 253 } 254 255 let pci_bus = self.pci_bus.as_ref().lock().unwrap(); 256 if let Some(d) = pci_bus.devices.get(&(device as u32)) { 257 let mut device = d.lock().unwrap(); 258 259 // Find out if one of the device's BAR is being reprogrammed, and 260 // reprogram it if needed. 261 if let Some(params) = device.detect_bar_reprogramming(register, data) { 262 if let Err(e) = pci_bus.device_reloc.move_bar( 263 params.old_base, 264 params.new_base, 265 params.len, 266 device.deref_mut(), 267 params.region_type, 268 ) { 269 error!( 270 "Failed moving device BAR: {}: 0x{:x}->0x{:x}(0x{:x})", 271 e, params.old_base, params.new_base, params.len 272 ); 273 } 274 } 275 276 // Update the register value 277 device.write_config_register(register, offset, data) 278 } else { 279 None 280 } 281 } 282 283 fn set_config_address(&mut self, offset: u64, data: &[u8]) { 284 if offset as usize + data.len() > 4 { 285 return; 286 } 287 let (mask, value): (u32, u32) = match data.len() { 288 1 => ( 289 0x0000_00ff << (offset * 8), 290 u32::from(data[0]) << (offset * 8), 291 ), 292 2 => ( 293 0x0000_ffff << (offset * 16), 294 ((u32::from(data[1]) << 8) | u32::from(data[0])) << (offset * 16), 295 ), 296 4 => (0xffff_ffff, LittleEndian::read_u32(data)), 297 _ => return, 298 }; 299 self.config_address = (self.config_address & !mask) | value; 300 } 301 } 302 303 impl BusDevice for PciConfigIo { 304 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 305 // `offset` is relative to 0xcf8 306 let value = match offset { 307 0..=3 => self.config_address, 308 4..=7 => self.config_space_read(), 309 _ => 0xffff_ffff, 310 }; 311 312 // Only allow reads to the register boundary. 313 let start = offset as usize % 4; 314 let end = start + data.len(); 315 if end <= 4 { 316 for i in start..end { 317 data[i - start] = (value >> (i * 8)) as u8; 318 } 319 } else { 320 for d in data { 321 *d = 0xff; 322 } 323 } 324 } 325 326 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 327 // `offset` is relative to 0xcf8 328 match offset { 329 o @ 0..=3 => { 330 self.set_config_address(o, data); 331 None 332 } 333 o @ 4..=7 => self.config_space_write(o - 4, data), 334 _ => None, 335 } 336 } 337 } 338 339 /// Emulates PCI memory-mapped configuration access mechanism. 340 pub struct PciConfigMmio { 341 pci_bus: Arc<Mutex<PciBus>>, 342 } 343 344 impl PciConfigMmio { 345 pub fn new(pci_bus: Arc<Mutex<PciBus>>) -> Self { 346 PciConfigMmio { pci_bus } 347 } 348 349 fn config_space_read(&self, config_address: u32) -> u32 { 350 let (bus, device, _function, register) = parse_mmio_config_address(config_address); 351 352 // Only support one bus. 353 if bus != 0 { 354 return 0xffff_ffff; 355 } 356 357 self.pci_bus 358 .lock() 359 .unwrap() 360 .devices 361 .get(&(device as u32)) 362 .map_or(0xffff_ffff, |d| { 363 d.lock().unwrap().read_config_register(register) 364 }) 365 } 366 367 fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) { 368 if offset as usize + data.len() > 4 { 369 return; 370 } 371 372 let (bus, device, _function, register) = parse_mmio_config_address(config_address); 373 374 // Only support one bus. 375 if bus != 0 { 376 return; 377 } 378 379 let pci_bus = self.pci_bus.lock().unwrap(); 380 if let Some(d) = pci_bus.devices.get(&(device as u32)) { 381 let mut device = d.lock().unwrap(); 382 383 // Find out if one of the device's BAR is being reprogrammed, and 384 // reprogram it if needed. 385 if let Some(params) = device.detect_bar_reprogramming(register, data) { 386 if let Err(e) = pci_bus.device_reloc.move_bar( 387 params.old_base, 388 params.new_base, 389 params.len, 390 device.deref_mut(), 391 params.region_type, 392 ) { 393 error!( 394 "Failed moving device BAR: {}: 0x{:x}->0x{:x}(0x{:x})", 395 e, params.old_base, params.new_base, params.len 396 ); 397 } 398 } 399 400 // Update the register value 401 device.write_config_register(register, offset, data); 402 } 403 } 404 } 405 406 impl BusDevice for PciConfigMmio { 407 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 408 // Only allow reads to the register boundary. 409 let start = offset as usize % 4; 410 let end = start + data.len(); 411 if end > 4 || offset > u64::from(u32::MAX) { 412 for d in data { 413 *d = 0xff; 414 } 415 return; 416 } 417 418 let value = self.config_space_read(offset as u32); 419 for i in start..end { 420 data[i - start] = (value >> (i * 8)) as u8; 421 } 422 } 423 424 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 425 if offset > u64::from(u32::MAX) { 426 return None; 427 } 428 self.config_space_write(offset as u32, offset % 4, data); 429 430 None 431 } 432 } 433 434 fn shift_and_mask(value: u32, offset: usize, mask: u32) -> usize { 435 ((value >> offset) & mask) as usize 436 } 437 438 // Parse the MMIO address offset to a (bus, device, function, register) tuple. 439 // See section 7.2.2 PCI Express Enhanced Configuration Access Mechanism (ECAM) 440 // from the Pci Express Base Specification Revision 5.0 Version 1.0. 441 fn parse_mmio_config_address(config_address: u32) -> (usize, usize, usize, usize) { 442 const BUS_NUMBER_OFFSET: usize = 20; 443 const BUS_NUMBER_MASK: u32 = 0x00ff; 444 const DEVICE_NUMBER_OFFSET: usize = 15; 445 const DEVICE_NUMBER_MASK: u32 = 0x1f; 446 const FUNCTION_NUMBER_OFFSET: usize = 12; 447 const FUNCTION_NUMBER_MASK: u32 = 0x07; 448 const REGISTER_NUMBER_OFFSET: usize = 2; 449 const REGISTER_NUMBER_MASK: u32 = 0x3ff; 450 451 ( 452 shift_and_mask(config_address, BUS_NUMBER_OFFSET, BUS_NUMBER_MASK), 453 shift_and_mask(config_address, DEVICE_NUMBER_OFFSET, DEVICE_NUMBER_MASK), 454 shift_and_mask(config_address, FUNCTION_NUMBER_OFFSET, FUNCTION_NUMBER_MASK), 455 shift_and_mask(config_address, REGISTER_NUMBER_OFFSET, REGISTER_NUMBER_MASK), 456 ) 457 } 458 459 // Parse the CONFIG_ADDRESS register to a (bus, device, function, register) tuple. 460 fn parse_io_config_address(config_address: u32) -> (usize, usize, usize, usize) { 461 const BUS_NUMBER_OFFSET: usize = 16; 462 const BUS_NUMBER_MASK: u32 = 0x00ff; 463 const DEVICE_NUMBER_OFFSET: usize = 11; 464 const DEVICE_NUMBER_MASK: u32 = 0x1f; 465 const FUNCTION_NUMBER_OFFSET: usize = 8; 466 const FUNCTION_NUMBER_MASK: u32 = 0x07; 467 const REGISTER_NUMBER_OFFSET: usize = 2; 468 const REGISTER_NUMBER_MASK: u32 = 0x3f; 469 470 ( 471 shift_and_mask(config_address, BUS_NUMBER_OFFSET, BUS_NUMBER_MASK), 472 shift_and_mask(config_address, DEVICE_NUMBER_OFFSET, DEVICE_NUMBER_MASK), 473 shift_and_mask(config_address, FUNCTION_NUMBER_OFFSET, FUNCTION_NUMBER_MASK), 474 shift_and_mask(config_address, REGISTER_NUMBER_OFFSET, REGISTER_NUMBER_MASK), 475 ) 476 } 477