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