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( 295 &self, 296 config: Self::GroupConfig, 297 ) -> Result<Arc<Box<dyn InterruptSourceGroup>>> { 298 Ok(Arc::new(Box::new(LegacyUserspaceInterruptGroup::new( 299 self.ioapic.clone(), 300 config.irq as u32, 301 )))) 302 } 303 304 fn destroy_group(&self, _group: Arc<Box<dyn InterruptSourceGroup>>) -> Result<()> { 305 Ok(()) 306 } 307 } 308 309 impl InterruptManager for MsiInterruptManager<IrqRoutingEntry> { 310 type GroupConfig = MsiIrqGroupConfig; 311 312 fn create_group( 313 &self, 314 config: Self::GroupConfig, 315 ) -> Result<Arc<Box<dyn InterruptSourceGroup>>> { 316 let mut allocator = self.allocator.lock().unwrap(); 317 let mut irq_routes: HashMap<InterruptIndex, InterruptRoute> = 318 HashMap::with_capacity(config.count as usize); 319 for i in config.base..config.base + config.count { 320 irq_routes.insert(i, InterruptRoute::new(&mut allocator)?); 321 } 322 323 Ok(Arc::new(Box::new(MsiInterruptGroup::new( 324 self.vm.clone(), 325 self.gsi_msi_routes.clone(), 326 irq_routes, 327 )))) 328 } 329 330 fn destroy_group(&self, _group: Arc<Box<dyn InterruptSourceGroup>>) -> Result<()> { 331 Ok(()) 332 } 333 } 334 335 #[cfg(feature = "kvm")] 336 pub mod kvm { 337 use super::*; 338 use hypervisor::kvm::KVM_MSI_VALID_DEVID; 339 use hypervisor::kvm::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI}; 340 341 type KvmRoutingEntry = RoutingEntry<kvm_irq_routing_entry>; 342 pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>; 343 344 impl KvmRoutingEntry { 345 pub fn make_entry( 346 vm: &Arc<dyn hypervisor::Vm>, 347 gsi: u32, 348 config: &InterruptSourceConfig, 349 ) -> Result<Box<Self>> { 350 if let InterruptSourceConfig::MsiIrq(cfg) = &config { 351 let mut kvm_route = kvm_irq_routing_entry { 352 gsi, 353 type_: KVM_IRQ_ROUTING_MSI, 354 ..Default::default() 355 }; 356 357 kvm_route.u.msi.address_lo = cfg.low_addr; 358 kvm_route.u.msi.address_hi = cfg.high_addr; 359 kvm_route.u.msi.data = cfg.data; 360 361 if vm.check_extension(hypervisor::Cap::MsiDevid) { 362 kvm_route.flags = KVM_MSI_VALID_DEVID; 363 kvm_route.u.msi.__bindgen_anon_1.devid = cfg.devid; 364 } 365 366 let kvm_entry = KvmRoutingEntry { 367 route: kvm_route, 368 masked: false, 369 }; 370 371 return Ok(Box::new(kvm_entry)); 372 } else if let InterruptSourceConfig::LegacyIrq(cfg) = &config { 373 let mut kvm_route = kvm_irq_routing_entry { 374 gsi, 375 type_: KVM_IRQ_ROUTING_IRQCHIP, 376 ..Default::default() 377 }; 378 kvm_route.u.irqchip.irqchip = cfg.irqchip; 379 kvm_route.u.irqchip.pin = cfg.pin; 380 let kvm_entry = KvmRoutingEntry { 381 route: kvm_route, 382 masked: false, 383 }; 384 385 return Ok(Box::new(kvm_entry)); 386 } 387 388 Err(io::Error::new( 389 io::ErrorKind::Other, 390 "Interrupt config type not supported", 391 )) 392 } 393 } 394 } 395 396 #[cfg(feature = "mshv")] 397 pub mod mshv { 398 use super::*; 399 use hypervisor::mshv::*; 400 401 type MshvRoutingEntry = RoutingEntry<mshv_msi_routing_entry>; 402 pub type MshvMsiInterruptManager = MsiInterruptManager<mshv_msi_routing_entry>; 403 404 impl MshvRoutingEntry { 405 pub fn make_entry( 406 _vm: &Arc<dyn hypervisor::Vm>, 407 gsi: u32, 408 config: &InterruptSourceConfig, 409 ) -> Result<Box<Self>> { 410 if let InterruptSourceConfig::MsiIrq(cfg) = &config { 411 let route = mshv_msi_routing_entry { 412 gsi, 413 address_lo: cfg.low_addr, 414 address_hi: cfg.high_addr, 415 data: cfg.data, 416 }; 417 let entry = MshvRoutingEntry { 418 route, 419 masked: false, 420 }; 421 422 return Ok(Box::new(entry)); 423 } 424 425 Err(io::Error::new( 426 io::ErrorKind::Other, 427 "Interrupt config type not supported", 428 )) 429 } 430 } 431 } 432 433 #[cfg(target_arch = "aarch64")] 434 #[cfg(test)] 435 mod tests { 436 use arch::aarch64::gic::kvm::{create_gic, save_pending_tables}; 437 use arch::aarch64::gic::{ 438 get_dist_regs, get_icc_regs, get_redist_regs, set_dist_regs, set_icc_regs, set_redist_regs, 439 }; 440 441 #[test] 442 fn test_create_gic() { 443 let hv = hypervisor::new().unwrap(); 444 let vm = hv.create_vm().unwrap(); 445 446 assert!(create_gic(&vm, 1).is_ok()); 447 } 448 449 #[test] 450 fn test_get_set_dist_regs() { 451 let hv = hypervisor::new().unwrap(); 452 let vm = hv.create_vm().unwrap(); 453 let _ = vm.create_vcpu(0, None).unwrap(); 454 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 455 456 let res = get_dist_regs(gic.device()); 457 assert!(res.is_ok()); 458 let state = res.unwrap(); 459 assert_eq!(state.len(), 568); 460 461 let res = set_dist_regs(gic.device(), &state); 462 assert!(res.is_ok()); 463 } 464 465 #[test] 466 fn test_get_set_redist_regs() { 467 let hv = hypervisor::new().unwrap(); 468 let vm = hv.create_vm().unwrap(); 469 let _ = vm.create_vcpu(0, None).unwrap(); 470 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 471 472 let gicr_typer = vec![123]; 473 let res = get_redist_regs(gic.device(), &gicr_typer); 474 assert!(res.is_ok()); 475 let state = res.unwrap(); 476 println!("{}", state.len()); 477 assert!(state.len() == 24); 478 479 assert!(set_redist_regs(gic.device(), &gicr_typer, &state).is_ok()); 480 } 481 482 #[test] 483 fn test_get_set_icc_regs() { 484 let hv = hypervisor::new().unwrap(); 485 let vm = hv.create_vm().unwrap(); 486 let _ = vm.create_vcpu(0, None).unwrap(); 487 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 488 489 let gicr_typer = vec![123]; 490 let res = get_icc_regs(gic.device(), &gicr_typer); 491 assert!(res.is_ok()); 492 let state = res.unwrap(); 493 println!("{}", state.len()); 494 assert!(state.len() == 9); 495 496 assert!(set_icc_regs(gic.device(), &gicr_typer, &state).is_ok()); 497 } 498 499 #[test] 500 fn test_save_pending_tables() { 501 let hv = hypervisor::new().unwrap(); 502 let vm = hv.create_vm().unwrap(); 503 let _ = vm.create_vcpu(0, None).unwrap(); 504 let gic = create_gic(&vm, 1).expect("Cannot create gic"); 505 506 assert!(save_pending_tables(gic.device()).is_ok()); 507 } 508 } 509