1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 4 // 5 6 use devices::interrupt_controller::InterruptController; 7 use hypervisor::IrqRoutingEntry; 8 use std::collections::HashMap; 9 use std::io; 10 use std::sync::atomic::{AtomicBool, Ordering}; 11 use std::sync::{Arc, Mutex}; 12 use vm_allocator::SystemAllocator; 13 use vm_device::interrupt::{ 14 InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup, 15 LegacyIrqGroupConfig, MsiIrqGroupConfig, 16 }; 17 use vmm_sys_util::eventfd::EventFd; 18 19 /// Reuse std::io::Result to simplify interoperability among crates. 20 pub type Result<T> = std::io::Result<T>; 21 22 struct InterruptRoute { 23 gsi: u32, 24 irq_fd: EventFd, 25 registered: AtomicBool, 26 } 27 28 impl InterruptRoute { 29 pub fn new(allocator: &mut SystemAllocator) -> Result<Self> { 30 let irq_fd = EventFd::new(libc::EFD_NONBLOCK)?; 31 let gsi = allocator 32 .allocate_gsi() 33 .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed allocating new GSI"))?; 34 35 Ok(InterruptRoute { 36 gsi, 37 irq_fd, 38 registered: AtomicBool::new(false), 39 }) 40 } 41 42 pub fn enable(&self, vm: &Arc<dyn hypervisor::Vm>) -> Result<()> { 43 if !self.registered.load(Ordering::Acquire) { 44 vm.register_irqfd(&self.irq_fd, self.gsi).map_err(|e| { 45 io::Error::new( 46 io::ErrorKind::Other, 47 format!("Failed registering irq_fd: {}", e), 48 ) 49 })?; 50 51 // Update internals to track the irq_fd as "registered". 52 self.registered.store(true, Ordering::Release); 53 } 54 55 Ok(()) 56 } 57 58 pub fn disable(&self, vm: &Arc<dyn hypervisor::Vm>) -> Result<()> { 59 if self.registered.load(Ordering::Acquire) { 60 vm.unregister_irqfd(&self.irq_fd, self.gsi).map_err(|e| { 61 io::Error::new( 62 io::ErrorKind::Other, 63 format!("Failed unregistering irq_fd: {}", e), 64 ) 65 })?; 66 67 // Update internals to track the irq_fd as "unregistered". 68 self.registered.store(false, Ordering::Release); 69 } 70 71 Ok(()) 72 } 73 74 pub fn trigger(&self) -> Result<()> { 75 self.irq_fd.write(1) 76 } 77 78 pub fn notifier(&self) -> Option<EventFd> { 79 Some( 80 self.irq_fd 81 .try_clone() 82 .expect("Failed cloning interrupt's EventFd"), 83 ) 84 } 85 } 86 87 pub struct RoutingEntry<IrqRoutingEntry> { 88 route: IrqRoutingEntry, 89 masked: bool, 90 } 91 92 pub struct MsiInterruptGroup<IrqRoutingEntry> { 93 vm: Arc<dyn hypervisor::Vm>, 94 gsi_msi_routes: Arc<Mutex<HashMap<u32, RoutingEntry<IrqRoutingEntry>>>>, 95 irq_routes: HashMap<InterruptIndex, InterruptRoute>, 96 } 97 98 impl MsiInterruptGroup<IrqRoutingEntry> { 99 fn set_gsi_routes(&self, routes: &HashMap<u32, RoutingEntry<IrqRoutingEntry>>) -> Result<()> { 100 let mut entry_vec: Vec<IrqRoutingEntry> = Vec::new(); 101 for (_, entry) in routes.iter() { 102 if entry.masked { 103 continue; 104 } 105 106 entry_vec.push(entry.route); 107 } 108 109 self.vm.set_gsi_routing(&entry_vec).map_err(|e| { 110 io::Error::new( 111 io::ErrorKind::Other, 112 format!("Failed setting GSI routing: {}", e), 113 ) 114 }) 115 } 116 } 117 118 impl MsiInterruptGroup<IrqRoutingEntry> { 119 fn new( 120 vm: Arc<dyn hypervisor::Vm>, 121 gsi_msi_routes: Arc<Mutex<HashMap<u32, RoutingEntry<IrqRoutingEntry>>>>, 122 irq_routes: HashMap<InterruptIndex, InterruptRoute>, 123 ) -> Self { 124 MsiInterruptGroup { 125 vm, 126 gsi_msi_routes, 127 irq_routes, 128 } 129 } 130 } 131 132 impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> { 133 fn enable(&self) -> Result<()> { 134 for (_, route) in self.irq_routes.iter() { 135 route.enable(&self.vm)?; 136 } 137 138 Ok(()) 139 } 140 141 fn disable(&self) -> Result<()> { 142 for (_, route) in self.irq_routes.iter() { 143 route.disable(&self.vm)?; 144 } 145 146 Ok(()) 147 } 148 149 fn trigger(&self, index: InterruptIndex) -> Result<()> { 150 if let Some(route) = self.irq_routes.get(&index) { 151 return route.trigger(); 152 } 153 154 Err(io::Error::new( 155 io::ErrorKind::Other, 156 format!("trigger: Invalid interrupt index {}", index), 157 )) 158 } 159 160 fn notifier(&self, index: InterruptIndex) -> Option<EventFd> { 161 if let Some(route) = self.irq_routes.get(&index) { 162 return route.notifier(); 163 } 164 165 None 166 } 167 168 fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()> { 169 if let Some(route) = self.irq_routes.get(&index) { 170 let entry = RoutingEntry::<_>::make_entry(&self.vm, route.gsi, &config)?; 171 let mut routes = self.gsi_msi_routes.lock().unwrap(); 172 routes.insert(route.gsi, *entry); 173 return self.set_gsi_routes(&routes); 174 } 175 176 Err(io::Error::new( 177 io::ErrorKind::Other, 178 format!("update: Invalid interrupt index {}", index), 179 )) 180 } 181 182 fn mask(&self, index: InterruptIndex) -> Result<()> { 183 if let Some(route) = self.irq_routes.get(&index) { 184 let mut routes = self.gsi_msi_routes.lock().unwrap(); 185 if let Some(entry) = routes.get_mut(&route.gsi) { 186 entry.masked = true; 187 } else { 188 return Err(io::Error::new( 189 io::ErrorKind::Other, 190 format!("mask: No existing route for interrupt index {}", index), 191 )); 192 } 193 self.set_gsi_routes(&routes)?; 194 return route.disable(&self.vm); 195 } 196 197 Err(io::Error::new( 198 io::ErrorKind::Other, 199 format!("mask: Invalid interrupt index {}", index), 200 )) 201 } 202 203 fn unmask(&self, index: InterruptIndex) -> Result<()> { 204 if let Some(route) = self.irq_routes.get(&index) { 205 let mut routes = self.gsi_msi_routes.lock().unwrap(); 206 if let Some(entry) = routes.get_mut(&route.gsi) { 207 entry.masked = false; 208 } else { 209 return Err(io::Error::new( 210 io::ErrorKind::Other, 211 format!("mask: No existing route for interrupt index {}", index), 212 )); 213 } 214 self.set_gsi_routes(&routes)?; 215 return route.enable(&self.vm); 216 } 217 218 Err(io::Error::new( 219 io::ErrorKind::Other, 220 format!("unmask: Invalid interrupt index {}", index), 221 )) 222 } 223 } 224 225 pub struct LegacyUserspaceInterruptGroup { 226 ioapic: Arc<Mutex<dyn InterruptController>>, 227 irq: u32, 228 } 229 230 impl LegacyUserspaceInterruptGroup { 231 fn new(ioapic: Arc<Mutex<dyn InterruptController>>, irq: u32) -> Self { 232 LegacyUserspaceInterruptGroup { ioapic, irq } 233 } 234 } 235 236 impl InterruptSourceGroup for LegacyUserspaceInterruptGroup { 237 fn trigger(&self, _index: InterruptIndex) -> Result<()> { 238 self.ioapic 239 .lock() 240 .unwrap() 241 .service_irq(self.irq as usize) 242 .map_err(|e| { 243 io::Error::new( 244 io::ErrorKind::Other, 245 format!("failed to inject IRQ #{}: {:?}", self.irq, e), 246 ) 247 }) 248 } 249 250 fn update(&self, _index: InterruptIndex, _config: InterruptSourceConfig) -> Result<()> { 251 Ok(()) 252 } 253 254 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 255 self.ioapic.lock().unwrap().notifier(self.irq as usize) 256 } 257 } 258 259 pub struct LegacyUserspaceInterruptManager { 260 ioapic: Arc<Mutex<dyn InterruptController>>, 261 } 262 263 pub struct MsiInterruptManager<IrqRoutingEntry> { 264 allocator: Arc<Mutex<SystemAllocator>>, 265 vm: Arc<dyn hypervisor::Vm>, 266 gsi_msi_routes: Arc<Mutex<HashMap<u32, RoutingEntry<IrqRoutingEntry>>>>, 267 } 268 269 impl LegacyUserspaceInterruptManager { 270 pub fn new(ioapic: Arc<Mutex<dyn InterruptController>>) -> Self { 271 LegacyUserspaceInterruptManager { ioapic } 272 } 273 } 274 275 impl MsiInterruptManager<IrqRoutingEntry> { 276 pub fn new(allocator: Arc<Mutex<SystemAllocator>>, vm: Arc<dyn hypervisor::Vm>) -> Self { 277 // Create a shared list of GSI that can be shared through all PCI 278 // devices. This way, we can maintain the full list of used GSI, 279 // preventing one device from overriding interrupts setting from 280 // another one. 281 let gsi_msi_routes = Arc::new(Mutex::new(HashMap::new())); 282 283 MsiInterruptManager { 284 allocator, 285 vm, 286 gsi_msi_routes, 287 } 288 } 289 } 290 291 impl InterruptManager for LegacyUserspaceInterruptManager { 292 type GroupConfig = LegacyIrqGroupConfig; 293 294 fn create_group(&self, config: Self::GroupConfig) -> Result<Arc<dyn InterruptSourceGroup>> { 295 Ok(Arc::new(LegacyUserspaceInterruptGroup::new( 296 self.ioapic.clone(), 297 config.irq as u32, 298 ))) 299 } 300 301 fn destroy_group(&self, _group: Arc<dyn InterruptSourceGroup>) -> Result<()> { 302 Ok(()) 303 } 304 } 305 306 impl InterruptManager for MsiInterruptManager<IrqRoutingEntry> { 307 type GroupConfig = MsiIrqGroupConfig; 308 309 fn create_group(&self, config: Self::GroupConfig) -> Result<Arc<dyn InterruptSourceGroup>> { 310 let mut allocator = self.allocator.lock().unwrap(); 311 let mut irq_routes: HashMap<InterruptIndex, InterruptRoute> = 312 HashMap::with_capacity(config.count as usize); 313 for i in config.base..config.base + config.count { 314 irq_routes.insert(i, InterruptRoute::new(&mut allocator)?); 315 } 316 317 Ok(Arc::new(MsiInterruptGroup::new( 318 self.vm.clone(), 319 self.gsi_msi_routes.clone(), 320 irq_routes, 321 ))) 322 } 323 324 fn destroy_group(&self, _group: Arc<dyn InterruptSourceGroup>) -> Result<()> { 325 Ok(()) 326 } 327 } 328 329 #[cfg(feature = "kvm")] 330 pub mod kvm { 331 use super::*; 332 use hypervisor::kvm::KVM_MSI_VALID_DEVID; 333 use hypervisor::kvm::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI}; 334 335 type KvmRoutingEntry = RoutingEntry<kvm_irq_routing_entry>; 336 pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>; 337 338 impl KvmRoutingEntry { 339 pub fn make_entry( 340 vm: &Arc<dyn hypervisor::Vm>, 341 gsi: u32, 342 config: &InterruptSourceConfig, 343 ) -> Result<Box<Self>> { 344 if let InterruptSourceConfig::MsiIrq(cfg) = &config { 345 let mut kvm_route = kvm_irq_routing_entry { 346 gsi, 347 type_: KVM_IRQ_ROUTING_MSI, 348 ..Default::default() 349 }; 350 351 kvm_route.u.msi.address_lo = cfg.low_addr; 352 kvm_route.u.msi.address_hi = cfg.high_addr; 353 kvm_route.u.msi.data = cfg.data; 354 355 if vm.check_extension(hypervisor::Cap::MsiDevid) { 356 kvm_route.flags = KVM_MSI_VALID_DEVID; 357 kvm_route.u.msi.__bindgen_anon_1.devid = cfg.devid; 358 } 359 360 let kvm_entry = KvmRoutingEntry { 361 route: kvm_route, 362 masked: false, 363 }; 364 365 return Ok(Box::new(kvm_entry)); 366 } else if let InterruptSourceConfig::LegacyIrq(cfg) = &config { 367 let mut kvm_route = kvm_irq_routing_entry { 368 gsi, 369 type_: KVM_IRQ_ROUTING_IRQCHIP, 370 ..Default::default() 371 }; 372 kvm_route.u.irqchip.irqchip = cfg.irqchip; 373 kvm_route.u.irqchip.pin = cfg.pin; 374 let kvm_entry = KvmRoutingEntry { 375 route: kvm_route, 376 masked: false, 377 }; 378 379 return Ok(Box::new(kvm_entry)); 380 } 381 382 Err(io::Error::new( 383 io::ErrorKind::Other, 384 "Interrupt config type not supported", 385 )) 386 } 387 } 388 } 389 390 #[cfg(feature = "mshv")] 391 pub mod mshv { 392 use super::*; 393 use hypervisor::mshv::*; 394 395 type MshvRoutingEntry = RoutingEntry<mshv_msi_routing_entry>; 396 pub type MshvMsiInterruptManager = MsiInterruptManager<mshv_msi_routing_entry>; 397 398 impl MshvRoutingEntry { 399 pub fn make_entry( 400 _vm: &Arc<dyn hypervisor::Vm>, 401 gsi: u32, 402 config: &InterruptSourceConfig, 403 ) -> Result<Box<Self>> { 404 if let InterruptSourceConfig::MsiIrq(cfg) = &config { 405 let route = mshv_msi_routing_entry { 406 gsi, 407 address_lo: cfg.low_addr, 408 address_hi: cfg.high_addr, 409 data: cfg.data, 410 }; 411 let entry = MshvRoutingEntry { 412 route, 413 masked: false, 414 }; 415 416 return Ok(Box::new(entry)); 417 } 418 419 Err(io::Error::new( 420 io::ErrorKind::Other, 421 "Interrupt config type not supported", 422 )) 423 } 424 } 425 } 426 427 #[cfg(target_arch = "aarch64")] 428 #[cfg(test)] 429 mod tests { 430 use arch::aarch64::gic::kvm::{create_gic, save_pending_tables}; 431 use arch::aarch64::gic::{ 432 get_dist_regs, get_icc_regs, get_redist_regs, set_dist_regs, set_icc_regs, set_redist_regs, 433 }; 434 435 #[test] 436 fn test_create_gic() { 437 let hv = hypervisor::new().unwrap(); 438 let vm = hv.create_vm().unwrap(); 439 440 assert!(create_gic(&vm, 1).is_ok()); 441 } 442 443 #[test] 444 fn test_get_set_dist_regs() { 445 let hv = hypervisor::new().unwrap(); 446 let vm = hv.create_vm().unwrap(); 447 let _ = vm.create_vcpu(0, None).unwrap(); 448 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 449 450 let res = get_dist_regs(gic.device()); 451 assert!(res.is_ok()); 452 let state = res.unwrap(); 453 assert_eq!(state.len(), 568); 454 455 let res = set_dist_regs(gic.device(), &state); 456 assert!(res.is_ok()); 457 } 458 459 #[test] 460 fn test_get_set_redist_regs() { 461 let hv = hypervisor::new().unwrap(); 462 let vm = hv.create_vm().unwrap(); 463 let _ = vm.create_vcpu(0, None).unwrap(); 464 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 465 466 let gicr_typer = vec![123]; 467 let res = get_redist_regs(gic.device(), &gicr_typer); 468 assert!(res.is_ok()); 469 let state = res.unwrap(); 470 println!("{}", state.len()); 471 assert!(state.len() == 24); 472 473 assert!(set_redist_regs(gic.device(), &gicr_typer, &state).is_ok()); 474 } 475 476 #[test] 477 fn test_get_set_icc_regs() { 478 let hv = hypervisor::new().unwrap(); 479 let vm = hv.create_vm().unwrap(); 480 let _ = vm.create_vcpu(0, None).unwrap(); 481 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 482 483 let gicr_typer = vec![123]; 484 let res = get_icc_regs(gic.device(), &gicr_typer); 485 assert!(res.is_ok()); 486 let state = res.unwrap(); 487 println!("{}", state.len()); 488 assert!(state.len() == 9); 489 490 assert!(set_icc_regs(gic.device(), &gicr_typer, &state).is_ok()); 491 } 492 493 #[test] 494 fn test_save_pending_tables() { 495 let hv = hypervisor::new().unwrap(); 496 let vm = hv.create_vm().unwrap(); 497 let _ = vm.create_vcpu(0, None).unwrap(); 498 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 499 500 assert!(save_pending_tables(gic.device()).is_ok()); 501 } 502 } 503