1 // Copyright 2022 Arm Limited (or its affiliates). All rights reserved. 2 3 mod dist_regs; 4 mod icc_regs; 5 mod redist_regs; 6 7 use crate::arch::aarch64::gic::{Error, Result, Vgic}; 8 use crate::kvm::kvm_bindings; 9 use crate::{CpuState, Device, Vm}; 10 use dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr}; 11 use icc_regs::{get_icc_regs, set_icc_regs}; 12 use redist_regs::{construct_gicr_typers, get_redist_regs, set_redist_regs}; 13 use serde::{Deserialize, Serialize}; 14 use std::any::Any; 15 use std::convert::TryInto; 16 use std::sync::Arc; 17 18 const GITS_CTLR: u32 = 0x0000; 19 const GITS_IIDR: u32 = 0x0004; 20 const GITS_CBASER: u32 = 0x0080; 21 const GITS_CWRITER: u32 = 0x0088; 22 const GITS_CREADR: u32 = 0x0090; 23 const GITS_BASER: u32 = 0x0100; 24 25 /// Access an ITS device attribute. 26 /// 27 /// This is a helper function to get/set the ITS device attribute depending 28 /// the bool parameter `set` provided. 29 pub fn gicv3_its_attr_access( 30 its_device: &Arc<dyn Device>, 31 group: u32, 32 attr: u32, 33 val: &u64, 34 set: bool, 35 ) -> Result<()> { 36 let mut gicv3_its_attr = kvm_bindings::kvm_device_attr { 37 group, 38 attr: attr as u64, 39 addr: val as *const u64 as u64, 40 flags: 0, 41 }; 42 if set { 43 its_device 44 .set_device_attr(&gicv3_its_attr) 45 .map_err(Error::SetDeviceAttribute) 46 } else { 47 its_device 48 .get_device_attr(&mut gicv3_its_attr) 49 .map_err(Error::GetDeviceAttribute) 50 } 51 } 52 53 /// Function that saves/restores ITS tables into guest RAM. 54 /// 55 /// The tables get flushed to guest RAM whenever the VM gets stopped. 56 pub fn gicv3_its_tables_access(its_device: &Arc<dyn Device>, save: bool) -> Result<()> { 57 let attr = if save { 58 u64::from(kvm_bindings::KVM_DEV_ARM_ITS_SAVE_TABLES) 59 } else { 60 u64::from(kvm_bindings::KVM_DEV_ARM_ITS_RESTORE_TABLES) 61 }; 62 63 let init_gic_attr = kvm_bindings::kvm_device_attr { 64 group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL, 65 attr, 66 addr: 0, 67 flags: 0, 68 }; 69 its_device 70 .set_device_attr(&init_gic_attr) 71 .map_err(Error::SetDeviceAttribute) 72 } 73 74 pub struct KvmGicV3Its { 75 /// The hypervisor agnostic device for the GicV3 76 device: Arc<dyn Device>, 77 78 /// The hypervisor agnostic device for the Its device 79 its_device: Option<Arc<dyn Device>>, 80 81 /// Vector holding values of GICR_TYPER for each vCPU 82 gicr_typers: Vec<u64>, 83 84 /// GIC distributor address 85 dist_addr: u64, 86 87 /// GIC distributor size 88 dist_size: u64, 89 90 /// GIC distributors address 91 redists_addr: u64, 92 93 /// GIC distributors size 94 redists_size: u64, 95 96 /// GIC MSI address 97 msi_addr: u64, 98 99 /// GIC MSI size 100 msi_size: u64, 101 102 /// Number of CPUs handled by the device 103 vcpu_count: u64, 104 } 105 106 #[derive(Clone, Default, Serialize, Deserialize)] 107 pub struct Gicv3ItsState { 108 dist: Vec<u32>, 109 rdist: Vec<u32>, 110 icc: Vec<u32>, 111 // special register that enables interrupts and affinity routing 112 gicd_ctlr: u32, 113 its_ctlr: u64, 114 its_iidr: u64, 115 its_cbaser: u64, 116 its_cwriter: u64, 117 its_creadr: u64, 118 its_baser: [u64; 8], 119 } 120 121 impl KvmGicV3Its { 122 /// Device trees specific constants 123 pub const ARCH_GIC_V3_MAINT_IRQ: u32 = 9; 124 125 /// Returns the GIC version of the device 126 fn version() -> u32 { 127 kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3 128 } 129 130 fn device(&self) -> &Arc<dyn Device> { 131 &self.device 132 } 133 134 fn its_device(&self) -> Option<&Arc<dyn Device>> { 135 self.its_device.as_ref() 136 } 137 138 /// Setup the device-specific attributes 139 fn init_device_attributes(&mut self, vm: &dyn Vm, nr_irqs: u32) -> Result<()> { 140 // GicV3 part attributes 141 /* Setting up the distributor attribute. 142 We are placing the GIC below 1GB so we need to substract the size of the distributor. 143 */ 144 Self::set_device_attribute( 145 self.device(), 146 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR, 147 u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST), 148 &self.dist_addr as *const u64 as u64, 149 0, 150 )?; 151 152 /* Setting up the redistributors' attribute. 153 We are calculating here the start of the redistributors address. We have one per CPU. 154 */ 155 Self::set_device_attribute( 156 self.device(), 157 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR, 158 u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST), 159 &self.redists_addr as *const u64 as u64, 160 0, 161 )?; 162 163 // ITS part attributes 164 let mut its_device = kvm_bindings::kvm_create_device { 165 type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_ITS, 166 fd: 0, 167 flags: 0, 168 }; 169 170 let its_fd = vm 171 .create_device(&mut its_device) 172 .map_err(Error::CreateGic)?; 173 174 Self::set_device_attribute( 175 &its_fd, 176 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR, 177 u64::from(kvm_bindings::KVM_VGIC_ITS_ADDR_TYPE), 178 &self.msi_addr as *const u64 as u64, 179 0, 180 )?; 181 182 Self::set_device_attribute( 183 &its_fd, 184 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL, 185 u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT), 186 0, 187 0, 188 )?; 189 190 self.set_its_device(Some(its_fd)); 191 192 /* We need to tell the kernel how many irqs to support with this vgic. 193 * See the `layout` module for details. 194 */ 195 let nr_irqs_ptr = &nr_irqs as *const u32; 196 Self::set_device_attribute( 197 self.device(), 198 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 199 0, 200 nr_irqs_ptr as u64, 201 0, 202 )?; 203 204 /* Finalize the GIC. 205 * See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211. 206 */ 207 Self::set_device_attribute( 208 self.device(), 209 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL, 210 u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT), 211 0, 212 0, 213 ) 214 } 215 216 /// Create a KVM Vgic device 217 fn create_device(vm: &dyn Vm) -> Result<Arc<dyn Device>> { 218 let mut gic_device = kvm_bindings::kvm_create_device { 219 type_: Self::version(), 220 fd: 0, 221 flags: 0, 222 }; 223 224 vm.create_device(&mut gic_device).map_err(Error::CreateGic) 225 } 226 227 /// Set a GIC device attribute 228 fn set_device_attribute( 229 device: &Arc<dyn Device>, 230 group: u32, 231 attr: u64, 232 addr: u64, 233 flags: u32, 234 ) -> Result<()> { 235 let attr = kvm_bindings::kvm_device_attr { 236 flags, 237 group, 238 attr, 239 addr, 240 }; 241 device 242 .set_device_attr(&attr) 243 .map_err(Error::SetDeviceAttribute) 244 } 245 246 /// Method to initialize the GIC device 247 #[allow(clippy::new_ret_no_self)] 248 pub fn new( 249 vm: &dyn Vm, 250 vcpu_count: u64, 251 dist_addr: u64, 252 dist_size: u64, 253 redist_size: u64, 254 msi_size: u64, 255 nr_irqs: u32, 256 ) -> Result<KvmGicV3Its> { 257 let vgic = Self::create_device(vm)?; 258 let redists_size: u64 = redist_size * vcpu_count; 259 let redists_addr: u64 = dist_addr - redists_size; 260 let msi_addr: u64 = redists_addr - msi_size; 261 262 let mut gic_device = KvmGicV3Its { 263 device: vgic, 264 its_device: None, 265 gicr_typers: vec![0; vcpu_count.try_into().unwrap()], 266 dist_addr, 267 dist_size, 268 redists_addr, 269 redists_size, 270 msi_addr, 271 msi_size, 272 vcpu_count, 273 }; 274 275 gic_device.init_device_attributes(vm, nr_irqs)?; 276 277 Ok(gic_device) 278 } 279 } 280 281 impl Vgic for KvmGicV3Its { 282 fn fdt_compatibility(&self) -> &str { 283 "arm,gic-v3" 284 } 285 286 fn msi_compatible(&self) -> bool { 287 true 288 } 289 290 fn msi_compatibility(&self) -> &str { 291 "arm,gic-v3-its" 292 } 293 294 fn fdt_maint_irq(&self) -> u32 { 295 KvmGicV3Its::ARCH_GIC_V3_MAINT_IRQ 296 } 297 298 fn vcpu_count(&self) -> u64 { 299 self.vcpu_count 300 } 301 302 fn device_properties(&self) -> [u64; 4] { 303 [ 304 self.dist_addr, 305 self.dist_size, 306 self.redists_addr, 307 self.redists_size, 308 ] 309 } 310 311 fn msi_properties(&self) -> [u64; 2] { 312 [self.msi_addr, self.msi_size] 313 } 314 315 fn set_its_device(&mut self, its_device: Option<Arc<dyn Device>>) { 316 self.its_device = its_device; 317 } 318 319 fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]) { 320 let gicr_typers = construct_gicr_typers(vcpu_states); 321 self.gicr_typers = gicr_typers; 322 } 323 324 fn as_any_concrete_mut(&mut self) -> &mut dyn Any { 325 self 326 } 327 328 /// Save the state of GICv3ITS. 329 fn state(&self) -> Result<Gicv3ItsState> { 330 let gicr_typers = self.gicr_typers.clone(); 331 332 let gicd_ctlr = read_ctlr(self.device())?; 333 334 let dist_state = get_dist_regs(self.device())?; 335 336 let rdist_state = get_redist_regs(self.device(), &gicr_typers)?; 337 338 let icc_state = get_icc_regs(self.device(), &gicr_typers)?; 339 340 let its_baser_state: [u64; 8] = [0; 8]; 341 for i in 0..8 { 342 gicv3_its_attr_access( 343 self.its_device().unwrap(), 344 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 345 GITS_BASER + i * 8, 346 &its_baser_state[i as usize], 347 false, 348 )?; 349 } 350 351 let its_ctlr_state: u64 = 0; 352 gicv3_its_attr_access( 353 self.its_device().unwrap(), 354 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 355 GITS_CTLR, 356 &its_ctlr_state, 357 false, 358 )?; 359 360 let its_cbaser_state: u64 = 0; 361 gicv3_its_attr_access( 362 self.its_device().unwrap(), 363 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 364 GITS_CBASER, 365 &its_cbaser_state, 366 false, 367 )?; 368 369 let its_creadr_state: u64 = 0; 370 gicv3_its_attr_access( 371 self.its_device().unwrap(), 372 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 373 GITS_CREADR, 374 &its_creadr_state, 375 false, 376 )?; 377 378 let its_cwriter_state: u64 = 0; 379 gicv3_its_attr_access( 380 self.its_device().unwrap(), 381 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 382 GITS_CWRITER, 383 &its_cwriter_state, 384 false, 385 )?; 386 387 let its_iidr_state: u64 = 0; 388 gicv3_its_attr_access( 389 self.its_device().unwrap(), 390 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 391 GITS_IIDR, 392 &its_iidr_state, 393 false, 394 )?; 395 396 Ok(Gicv3ItsState { 397 dist: dist_state, 398 rdist: rdist_state, 399 icc: icc_state, 400 gicd_ctlr, 401 its_ctlr: its_ctlr_state, 402 its_iidr: its_iidr_state, 403 its_cbaser: its_cbaser_state, 404 its_cwriter: its_cwriter_state, 405 its_creadr: its_creadr_state, 406 its_baser: its_baser_state, 407 }) 408 } 409 410 /// Restore the state of GICv3ITS. 411 fn set_state(&mut self, state: &Gicv3ItsState) -> Result<()> { 412 let gicr_typers = self.gicr_typers.clone(); 413 414 write_ctlr(self.device(), state.gicd_ctlr)?; 415 416 set_dist_regs(self.device(), &state.dist)?; 417 418 set_redist_regs(self.device(), &gicr_typers, &state.rdist)?; 419 420 set_icc_regs(self.device(), &gicr_typers, &state.icc)?; 421 422 //Restore GICv3ITS registers 423 gicv3_its_attr_access( 424 self.its_device().unwrap(), 425 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 426 GITS_IIDR, 427 &state.its_iidr, 428 true, 429 )?; 430 431 gicv3_its_attr_access( 432 self.its_device().unwrap(), 433 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 434 GITS_CBASER, 435 &state.its_cbaser, 436 true, 437 )?; 438 439 gicv3_its_attr_access( 440 self.its_device().unwrap(), 441 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 442 GITS_CREADR, 443 &state.its_creadr, 444 true, 445 )?; 446 447 gicv3_its_attr_access( 448 self.its_device().unwrap(), 449 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 450 GITS_CWRITER, 451 &state.its_cwriter, 452 true, 453 )?; 454 455 for i in 0..8 { 456 gicv3_its_attr_access( 457 self.its_device().unwrap(), 458 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 459 GITS_BASER + i * 8, 460 &state.its_baser[i as usize], 461 true, 462 )?; 463 } 464 465 // Restore ITS tables 466 gicv3_its_tables_access(self.its_device().unwrap(), false)?; 467 468 gicv3_its_attr_access( 469 self.its_device().unwrap(), 470 kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, 471 GITS_CTLR, 472 &state.its_ctlr, 473 true, 474 ) 475 } 476 477 /// Saves GIC internal data tables into RAM, including: 478 /// - RDIST pending tables 479 /// - ITS tables into guest RAM. 480 fn save_data_tables(&self) -> Result<()> { 481 // Flash RDIST pending tables 482 let init_gic_attr = kvm_bindings::kvm_device_attr { 483 group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL, 484 attr: u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES), 485 addr: 0, 486 flags: 0, 487 }; 488 self.device() 489 .set_device_attr(&init_gic_attr) 490 .map_err(Error::SetDeviceAttribute)?; 491 // Flush ITS tables to guest RAM. 492 gicv3_its_tables_access(self.its_device().unwrap(), true) 493 } 494 } 495 496 #[cfg(test)] 497 mod tests { 498 use crate::aarch64::gic::{ 499 get_dist_regs, get_icc_regs, get_redist_regs, set_dist_regs, set_icc_regs, set_redist_regs, 500 }; 501 use crate::kvm::KvmGicV3Its; 502 503 #[test] 504 fn test_create_gic() { 505 let hv = crate::new().unwrap(); 506 let vm = hv.create_vm().unwrap(); 507 508 assert!(KvmGicV3Its::new( 509 &*vm, 510 1, 511 0x0900_0000 - 0x01_0000, 512 0x01_0000, 513 0x02_0000, 514 0x02_0000, 515 256 516 ) 517 .is_ok()); 518 } 519 520 #[test] 521 fn test_get_set_dist_regs() { 522 let hv = crate::new().unwrap(); 523 let vm = hv.create_vm().unwrap(); 524 let _ = vm.create_vcpu(0, None).unwrap(); 525 let gic = KvmGicV3Its::new( 526 &*vm, 527 1, 528 0x0900_0000 - 0x01_0000, 529 0x01_0000, 530 0x02_0000, 531 0x02_0000, 532 256, 533 ) 534 .expect("Cannot create gic"); 535 536 let res = get_dist_regs(gic.device()); 537 assert!(res.is_ok()); 538 let state = res.unwrap(); 539 assert_eq!(state.len(), 568); 540 541 let res = set_dist_regs(gic.device(), &state); 542 assert!(res.is_ok()); 543 } 544 545 #[test] 546 fn test_get_set_redist_regs() { 547 let hv = crate::new().unwrap(); 548 let vm = hv.create_vm().unwrap(); 549 let _ = vm.create_vcpu(0, None).unwrap(); 550 let gic = KvmGicV3Its::new( 551 &*vm, 552 1, 553 0x0900_0000 - 0x01_0000, 554 0x01_0000, 555 0x02_0000, 556 0x02_0000, 557 256, 558 ) 559 .expect("Cannot create gic"); 560 561 let gicr_typer = vec![123]; 562 let res = get_redist_regs(gic.device(), &gicr_typer); 563 assert!(res.is_ok()); 564 let state = res.unwrap(); 565 println!("{}", state.len()); 566 assert!(state.len() == 24); 567 568 assert!(set_redist_regs(gic.device(), &gicr_typer, &state).is_ok()); 569 } 570 571 #[test] 572 fn test_get_set_icc_regs() { 573 let hv = crate::new().unwrap(); 574 let vm = hv.create_vm().unwrap(); 575 let _ = vm.create_vcpu(0, None).unwrap(); 576 let gic = KvmGicV3Its::new( 577 &*vm, 578 1, 579 0x0900_0000 - 0x01_0000, 580 0x01_0000, 581 0x02_0000, 582 0x02_0000, 583 256, 584 ) 585 .expect("Cannot create gic"); 586 587 let gicr_typer = vec![123]; 588 let res = get_icc_regs(gic.device(), &gicr_typer); 589 assert!(res.is_ok()); 590 let state = res.unwrap(); 591 println!("{}", state.len()); 592 assert!(state.len() == 9); 593 594 assert!(set_icc_regs(gic.device(), &gicr_typer, &state).is_ok()); 595 } 596 597 #[test] 598 fn test_save_data_tables() { 599 let hv = crate::new().unwrap(); 600 let vm = hv.create_vm().unwrap(); 601 let _ = vm.create_vcpu(0, None).unwrap(); 602 let gic = vm 603 .create_vgic( 604 1, 605 0x0900_0000 - 0x01_0000, 606 0x01_0000, 607 0x02_0000, 608 0x02_0000, 609 256, 610 ) 611 .expect("Cannot create gic"); 612 613 assert!(gic.lock().unwrap().save_data_tables().is_ok()); 614 } 615 } 616