1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4 // 5 // Copyright © 2020, Microsoft Corporation 6 // 7 // Copyright 2018-2019 CrowdStrike, Inc. 8 // 9 // 10 11 use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd}; 12 use std::result; 13 use std::sync::Arc; 14 #[cfg(target_arch = "x86_64")] 15 use vm_memory::Address; 16 use vmm_sys_util::eventfd::EventFd; 17 18 #[cfg(target_arch = "aarch64")] 19 pub use crate::aarch64::{check_required_kvm_extensions, VcpuInit, VcpuKvmState as CpuState}; 20 use crate::cpu; 21 use crate::hypervisor; 22 use crate::vm; 23 // x86_64 dependencies 24 #[cfg(target_arch = "x86_64")] 25 pub mod x86_64; 26 27 #[cfg(target_arch = "x86_64")] 28 use x86_64::{ 29 check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters, KVM_TSS_ADDRESS, 30 }; 31 32 #[cfg(target_arch = "x86_64")] 33 pub use x86_64::{ 34 CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState as CpuState, 35 Xsave, CPUID_FLAG_VALID_INDEX, 36 }; 37 38 #[cfg(target_arch = "x86_64")] 39 use kvm_bindings::{kvm_enable_cap, MsrList, KVM_CAP_SPLIT_IRQCHIP}; 40 41 #[cfg(target_arch = "x86_64")] 42 use crate::arch::x86::NUM_IOAPIC_PINS; 43 44 // aarch64 dependencies 45 #[cfg(target_arch = "aarch64")] 46 pub mod aarch64; 47 48 pub use kvm_bindings; 49 pub use kvm_bindings::{ 50 kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, kvm_irq_routing_entry, 51 kvm_userspace_memory_region, KVM_IRQ_ROUTING_MSI, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID, 52 }; 53 pub use kvm_ioctls; 54 pub use kvm_ioctls::{Cap, Kvm}; 55 56 /// 57 /// Export generically-named wrappers of kvm-bindings for Unix-based platforms 58 /// 59 pub use { 60 kvm_bindings::kvm_clock_data as ClockData, kvm_bindings::kvm_create_device as CreateDevice, 61 kvm_bindings::kvm_irq_routing as IrqRouting, kvm_bindings::kvm_mp_state as MpState, 62 kvm_bindings::kvm_userspace_memory_region as MemoryRegion, 63 kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::DeviceFd, kvm_ioctls::IoEventAddress, 64 kvm_ioctls::VcpuExit, 65 }; 66 67 /// Wrapper over KVM VM ioctls. 68 pub struct KvmVm { 69 fd: Arc<VmFd>, 70 #[cfg(target_arch = "x86_64")] 71 msrs: MsrEntries, 72 } 73 /// 74 /// Implementation of Vm trait for KVM 75 /// Example: 76 /// #[cfg(feature = "kvm")] 77 /// extern crate hypervisor 78 /// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap(); 79 /// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm); 80 /// let vm = hypervisor.create_vm().expect("new VM fd creation failed"); 81 /// vm.set/get().unwrap() 82 /// 83 impl vm::Vm for KvmVm { 84 #[cfg(target_arch = "x86_64")] 85 /// 86 /// Sets the address of the three-page region in the VM's address space. 87 /// 88 fn set_tss_address(&self, offset: usize) -> vm::Result<()> { 89 self.fd 90 .set_tss_address(offset) 91 .map_err(|e| vm::HypervisorVmError::SetTssAddress(e.into())) 92 } 93 /// 94 /// Creates an in-kernel interrupt controller. 95 /// 96 fn create_irq_chip(&self) -> vm::Result<()> { 97 self.fd 98 .create_irq_chip() 99 .map_err(|e| vm::HypervisorVmError::CreateIrq(e.into())) 100 } 101 /// 102 /// Registers an event that will, when signaled, trigger the `gsi` IRQ. 103 /// 104 fn register_irqfd(&self, fd: &EventFd, gsi: u32) -> vm::Result<()> { 105 self.fd 106 .register_irqfd(fd, gsi) 107 .map_err(|e| vm::HypervisorVmError::RegisterIrqFd(e.into())) 108 } 109 /// 110 /// Unregisters an event that will, when signaled, trigger the `gsi` IRQ. 111 /// 112 fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> vm::Result<()> { 113 self.fd 114 .unregister_irqfd(fd, gsi) 115 .map_err(|e| vm::HypervisorVmError::UnregisterIrqFd(e.into())) 116 } 117 /// 118 /// Creates a VcpuFd object from a vcpu RawFd. 119 /// 120 fn create_vcpu(&self, id: u8) -> vm::Result<Arc<dyn cpu::Vcpu>> { 121 let vc = self 122 .fd 123 .create_vcpu(id) 124 .map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?; 125 let vcpu = KvmVcpu { 126 fd: vc, 127 #[cfg(target_arch = "x86_64")] 128 msrs: self.msrs.clone(), 129 }; 130 Ok(Arc::new(vcpu)) 131 } 132 /// 133 /// Registers an event to be signaled whenever a certain address is written to. 134 /// 135 fn register_ioevent( 136 &self, 137 fd: &EventFd, 138 addr: &IoEventAddress, 139 datamatch: Option<vm::DataMatch>, 140 ) -> vm::Result<()> { 141 if let Some(dm) = datamatch { 142 match dm { 143 vm::DataMatch::DataMatch32(kvm_dm32) => self 144 .fd 145 .register_ioevent(fd, addr, kvm_dm32) 146 .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())), 147 vm::DataMatch::DataMatch64(kvm_dm64) => self 148 .fd 149 .register_ioevent(fd, addr, kvm_dm64) 150 .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())), 151 } 152 } else { 153 self.fd 154 .register_ioevent(fd, addr, NoDatamatch) 155 .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())) 156 } 157 } 158 /// 159 /// Unregisters an event from a certain address it has been previously registered to. 160 /// 161 fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> { 162 self.fd 163 .unregister_ioevent(fd, addr, NoDatamatch) 164 .map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into())) 165 } 166 /// 167 /// Sets the GSI routing table entries, overwriting any previously set 168 /// entries, as per the `KVM_SET_GSI_ROUTING` ioctl. 169 /// 170 fn set_gsi_routing(&self, irq_routing: &IrqRouting) -> vm::Result<()> { 171 self.fd 172 .set_gsi_routing(irq_routing) 173 .map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into())) 174 } 175 /// 176 /// Creates a memory region structure that can be used with set_user_memory_region 177 /// 178 fn make_user_memory_region( 179 &self, 180 slot: u32, 181 guest_phys_addr: u64, 182 memory_size: u64, 183 userspace_addr: u64, 184 readonly: bool, 185 ) -> MemoryRegion { 186 MemoryRegion { 187 slot, 188 guest_phys_addr, 189 memory_size, 190 userspace_addr, 191 flags: if readonly { KVM_MEM_READONLY } else { 0 }, 192 } 193 } 194 /// 195 /// Creates/modifies a guest physical memory slot. 196 /// 197 fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { 198 // Safe because guest regions are guaranteed not to overlap. 199 unsafe { 200 self.fd 201 .set_user_memory_region(user_memory_region) 202 .map_err(|e| vm::HypervisorVmError::SetUserMemory(e.into())) 203 } 204 } 205 /// 206 /// Creates an emulated device in the kernel. 207 /// 208 /// See the documentation for `KVM_CREATE_DEVICE`. 209 fn create_device(&self, device: &mut CreateDevice) -> vm::Result<DeviceFd> { 210 self.fd 211 .create_device(device) 212 .map_err(|e| vm::HypervisorVmError::CreateDevice(e.into())) 213 } 214 /// 215 /// Returns the preferred CPU target type which can be emulated by KVM on underlying host. 216 /// 217 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 218 fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> { 219 self.fd 220 .get_preferred_target(kvi) 221 .map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into())) 222 } 223 #[cfg(target_arch = "x86_64")] 224 fn enable_split_irq(&self) -> vm::Result<()> { 225 // Set TSS 226 self.fd 227 .set_tss_address(KVM_TSS_ADDRESS.raw_value() as usize) 228 .map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?; 229 // Create split irqchip 230 // Only the local APIC is emulated in kernel, both PICs and IOAPIC 231 // are not. 232 let mut cap: kvm_enable_cap = Default::default(); 233 cap.cap = KVM_CAP_SPLIT_IRQCHIP; 234 cap.args[0] = NUM_IOAPIC_PINS as u64; 235 self.fd 236 .enable_cap(&cap) 237 .map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?; 238 Ok(()) 239 } 240 /// Retrieve guest clock. 241 #[cfg(target_arch = "x86_64")] 242 fn get_clock(&self) -> vm::Result<ClockData> { 243 self.fd 244 .get_clock() 245 .map_err(|e| vm::HypervisorVmError::GetClock(e.into())) 246 } 247 /// Set guest clock. 248 #[cfg(target_arch = "x86_64")] 249 fn set_clock(&self, data: &ClockData) -> vm::Result<()> { 250 self.fd 251 .set_clock(data) 252 .map_err(|e| vm::HypervisorVmError::SetClock(e.into())) 253 } 254 /// Checks if a particular `Cap` is available. 255 fn check_extension(&self, c: Cap) -> bool { 256 self.fd.check_extension(c) 257 } 258 } 259 /// Wrapper over KVM system ioctls. 260 pub struct KvmHypervisor { 261 kvm: Kvm, 262 } 263 /// Enum for KVM related error 264 #[derive(Debug)] 265 pub enum KvmError { 266 CapabilityMissing(Cap), 267 } 268 pub type KvmResult<T> = result::Result<T, KvmError>; 269 impl KvmHypervisor { 270 /// Create a hypervisor based on Kvm 271 pub fn new() -> hypervisor::Result<KvmHypervisor> { 272 let kvm_obj = Kvm::new().map_err(|e| hypervisor::HypervisorError::VmCreate(e.into()))?; 273 Ok(KvmHypervisor { kvm: kvm_obj }) 274 } 275 } 276 /// Implementation of Hypervisor trait for KVM 277 /// Example: 278 /// #[cfg(feature = "kvm")] 279 /// extern crate hypervisor 280 /// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap(); 281 /// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm); 282 /// let vm = hypervisor.create_vm().expect("new VM fd creation failed"); 283 /// 284 impl hypervisor::Hypervisor for KvmHypervisor { 285 /// Create a KVM vm object and return the object as Vm trait object 286 /// Example 287 /// # extern crate hypervisor; 288 /// # use hypervisor::KvmHypervisor; 289 /// use hypervisor::KvmVm; 290 /// let hypervisor = KvmHypervisor::new().unwrap(); 291 /// let vm = hypervisor.create_vm().unwrap() 292 /// 293 fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> { 294 let fd: VmFd; 295 loop { 296 match self.kvm.create_vm() { 297 Ok(res) => fd = res, 298 Err(e) => { 299 if e.errno() == libc::EINTR { 300 // If the error returned is EINTR, which means the 301 // ioctl has been interrupted, we have to retry as 302 // this can't be considered as a regular error. 303 continue; 304 } else { 305 return Err(hypervisor::HypervisorError::VmCreate(e.into())); 306 } 307 } 308 } 309 break; 310 } 311 312 let vm_fd = Arc::new(fd); 313 314 #[cfg(target_arch = "x86_64")] 315 { 316 let msr_list = self.get_msr_list()?; 317 let num_msrs = msr_list.as_fam_struct_ref().nmsrs as usize; 318 let mut msrs = MsrEntries::new(num_msrs); 319 let indices = msr_list.as_slice(); 320 let msr_entries = msrs.as_mut_slice(); 321 for (pos, index) in indices.iter().enumerate() { 322 msr_entries[pos].index = *index; 323 } 324 325 Ok(Arc::new(KvmVm { fd: vm_fd, msrs })) 326 } 327 328 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 329 { 330 Ok(Arc::new(KvmVm { fd: vm_fd })) 331 } 332 } 333 334 fn check_required_extensions(&self) -> hypervisor::Result<()> { 335 check_required_kvm_extensions(&self.kvm).expect("Missing KVM capabilities"); 336 Ok(()) 337 } 338 339 /// 340 /// Returns the KVM API version. 341 /// 342 fn get_api_version(&self) -> i32 { 343 self.kvm.get_api_version() 344 } 345 /// 346 /// Returns the size of the memory mapping required to use the vcpu's `kvm_run` structure. 347 /// 348 fn get_vcpu_mmap_size(&self) -> hypervisor::Result<usize> { 349 self.kvm 350 .get_vcpu_mmap_size() 351 .map_err(|e| hypervisor::HypervisorError::GetVcpuMmap(e.into())) 352 } 353 /// 354 /// Gets the recommended maximum number of VCPUs per VM. 355 /// 356 fn get_max_vcpus(&self) -> hypervisor::Result<usize> { 357 Ok(self.kvm.get_max_vcpus()) 358 } 359 /// 360 /// Gets the recommended number of VCPUs per VM. 361 /// 362 fn get_nr_vcpus(&self) -> hypervisor::Result<usize> { 363 Ok(self.kvm.get_nr_vcpus()) 364 } 365 #[cfg(target_arch = "x86_64")] 366 /// 367 /// Checks if a particular `Cap` is available. 368 /// 369 fn check_capability(&self, c: Cap) -> bool { 370 self.kvm.check_extension(c) 371 } 372 #[cfg(target_arch = "x86_64")] 373 /// 374 /// X86 specific call to get the system supported CPUID values. 375 /// 376 fn get_cpuid(&self) -> hypervisor::Result<CpuId> { 377 self.kvm 378 .get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES) 379 .map_err(|e| hypervisor::HypervisorError::GetCpuId(e.into())) 380 } 381 #[cfg(target_arch = "x86_64")] 382 /// 383 /// Retrieve the list of MSRs supported by KVM. 384 /// 385 fn get_msr_list(&self) -> hypervisor::Result<MsrList> { 386 self.kvm 387 .get_msr_index_list() 388 .map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into())) 389 } 390 } 391 /// Vcpu struct for KVM 392 pub struct KvmVcpu { 393 fd: VcpuFd, 394 #[cfg(target_arch = "x86_64")] 395 msrs: MsrEntries, 396 } 397 /// Implementation of Vcpu trait for KVM 398 /// Example: 399 /// #[cfg(feature = "kvm")] 400 /// extern crate hypervisor 401 /// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap(); 402 /// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm); 403 /// let vm = hypervisor.create_vm().expect("new VM fd creation failed"); 404 /// let vcpu = vm.create_vcpu(0).unwrap(); 405 /// vcpu.get/set().unwrap() 406 /// 407 impl cpu::Vcpu for KvmVcpu { 408 #[cfg(target_arch = "x86_64")] 409 /// 410 /// Returns the vCPU general purpose registers. 411 /// 412 fn get_regs(&self) -> cpu::Result<StandardRegisters> { 413 self.fd 414 .get_regs() 415 .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into())) 416 } 417 #[cfg(target_arch = "x86_64")] 418 /// 419 /// Sets the vCPU general purpose registers using the `KVM_SET_REGS` ioctl. 420 /// 421 fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> { 422 self.fd 423 .set_regs(regs) 424 .map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into())) 425 } 426 #[cfg(target_arch = "x86_64")] 427 /// 428 /// Returns the vCPU special registers. 429 /// 430 fn get_sregs(&self) -> cpu::Result<SpecialRegisters> { 431 self.fd 432 .get_sregs() 433 .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into())) 434 } 435 #[cfg(target_arch = "x86_64")] 436 /// 437 /// Sets the vCPU special registers using the `KVM_SET_SREGS` ioctl. 438 /// 439 fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> { 440 self.fd 441 .set_sregs(sregs) 442 .map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into())) 443 } 444 #[cfg(target_arch = "x86_64")] 445 /// 446 /// Returns the floating point state (FPU) from the vCPU. 447 /// 448 fn get_fpu(&self) -> cpu::Result<FpuState> { 449 self.fd 450 .get_fpu() 451 .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into())) 452 } 453 #[cfg(target_arch = "x86_64")] 454 /// 455 /// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct. 456 /// 457 fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> { 458 self.fd 459 .set_fpu(fpu) 460 .map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into())) 461 } 462 #[cfg(target_arch = "x86_64")] 463 /// 464 /// X86 specific call to setup the CPUID registers. 465 /// 466 fn set_cpuid2(&self, cpuid: &CpuId) -> cpu::Result<()> { 467 self.fd 468 .set_cpuid2(cpuid) 469 .map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into())) 470 } 471 /// 472 /// X86 specific call to retrieve the CPUID registers. 473 /// 474 #[cfg(target_arch = "x86_64")] 475 fn get_cpuid2(&self, num_entries: usize) -> cpu::Result<CpuId> { 476 self.fd 477 .get_cpuid2(num_entries) 478 .map_err(|e| cpu::HypervisorCpuError::GetCpuid(e.into())) 479 } 480 #[cfg(target_arch = "x86_64")] 481 /// 482 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 483 /// 484 fn get_lapic(&self) -> cpu::Result<LapicState> { 485 self.fd 486 .get_lapic() 487 .map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into())) 488 } 489 #[cfg(target_arch = "x86_64")] 490 /// 491 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 492 /// 493 fn set_lapic(&self, klapic: &LapicState) -> cpu::Result<()> { 494 self.fd 495 .set_lapic(klapic) 496 .map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into())) 497 } 498 #[cfg(target_arch = "x86_64")] 499 /// 500 /// Returns the model-specific registers (MSR) for this vCPU. 501 /// 502 fn get_msrs(&self, msrs: &mut MsrEntries) -> cpu::Result<usize> { 503 self.fd 504 .get_msrs(msrs) 505 .map_err(|e| cpu::HypervisorCpuError::GetMsrEntries(e.into())) 506 } 507 #[cfg(target_arch = "x86_64")] 508 /// 509 /// Setup the model-specific registers (MSR) for this vCPU. 510 /// Returns the number of MSR entries actually written. 511 /// 512 fn set_msrs(&self, msrs: &MsrEntries) -> cpu::Result<usize> { 513 self.fd 514 .set_msrs(msrs) 515 .map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into())) 516 } 517 /// 518 /// Returns the vcpu's current "multiprocessing state". 519 /// 520 fn get_mp_state(&self) -> cpu::Result<MpState> { 521 self.fd 522 .get_mp_state() 523 .map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into())) 524 } 525 /// 526 /// Sets the vcpu's current "multiprocessing state". 527 /// 528 fn set_mp_state(&self, mp_state: MpState) -> cpu::Result<()> { 529 self.fd 530 .set_mp_state(mp_state) 531 .map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into())) 532 } 533 #[cfg(target_arch = "x86_64")] 534 /// 535 /// X86 specific call that returns the vcpu's current "xsave struct". 536 /// 537 fn get_xsave(&self) -> cpu::Result<Xsave> { 538 self.fd 539 .get_xsave() 540 .map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into())) 541 } 542 #[cfg(target_arch = "x86_64")] 543 /// 544 /// X86 specific call that sets the vcpu's current "xsave struct". 545 /// 546 fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> { 547 self.fd 548 .set_xsave(xsave) 549 .map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into())) 550 } 551 #[cfg(target_arch = "x86_64")] 552 /// 553 /// X86 specific call that returns the vcpu's current "xcrs". 554 /// 555 fn get_xcrs(&self) -> cpu::Result<ExtendedControlRegisters> { 556 self.fd 557 .get_xcrs() 558 .map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into())) 559 } 560 #[cfg(target_arch = "x86_64")] 561 /// 562 /// X86 specific call that sets the vcpu's current "xcrs". 563 /// 564 fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> cpu::Result<()> { 565 self.fd 566 .set_xcrs(&xcrs) 567 .map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into())) 568 } 569 /// 570 /// Triggers the running of the current virtual CPU returning an exit reason. 571 /// 572 fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> { 573 match self.fd.run() { 574 Ok(run) => match run { 575 #[cfg(target_arch = "x86_64")] 576 VcpuExit::IoIn(addr, data) => Ok(cpu::VmExit::IoIn(addr, data)), 577 #[cfg(target_arch = "x86_64")] 578 VcpuExit::IoOut(addr, data) => Ok(cpu::VmExit::IoOut(addr, data)), 579 #[cfg(target_arch = "x86_64")] 580 VcpuExit::IoapicEoi(vector) => Ok(cpu::VmExit::IoapicEoi(vector)), 581 #[cfg(target_arch = "x86_64")] 582 VcpuExit::Shutdown | VcpuExit::Hlt => Ok(cpu::VmExit::Reset), 583 584 #[cfg(target_arch = "aarch64")] 585 VcpuExit::SystemEvent(event_type, flags) => { 586 use kvm_bindings::KVM_SYSTEM_EVENT_SHUTDOWN; 587 // On Aarch64, when the VM is shutdown, run() returns 588 // VcpuExit::SystemEvent with reason KVM_SYSTEM_EVENT_SHUTDOWN 589 if event_type == KVM_SYSTEM_EVENT_SHUTDOWN { 590 Ok(cpu::VmExit::Reset) 591 } else { 592 Err(cpu::HypervisorCpuError::RunVcpu(anyhow!( 593 "Unexpected system event with type 0x{:x}, flags 0x{:x}", 594 event_type, 595 flags 596 ))) 597 } 598 } 599 600 VcpuExit::MmioRead(addr, data) => Ok(cpu::VmExit::MmioRead(addr, data)), 601 VcpuExit::MmioWrite(addr, data) => Ok(cpu::VmExit::MmioWrite(addr, data)), 602 603 r => Err(cpu::HypervisorCpuError::RunVcpu(anyhow!( 604 "Unexpected exit reason on vcpu run: {:?}", 605 r 606 ))), 607 }, 608 609 Err(ref e) => match e.errno() { 610 libc::EAGAIN | libc::EINTR => Ok(cpu::VmExit::Ignore), 611 _ => Err(cpu::HypervisorCpuError::RunVcpu(anyhow!( 612 "VCPU error {:?}", 613 e 614 ))), 615 }, 616 } 617 } 618 #[cfg(target_arch = "x86_64")] 619 /// 620 /// Returns currently pending exceptions, interrupts, and NMIs as well as related 621 /// states of the vcpu. 622 /// 623 fn get_vcpu_events(&self) -> cpu::Result<VcpuEvents> { 624 self.fd 625 .get_vcpu_events() 626 .map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into())) 627 } 628 #[cfg(target_arch = "x86_64")] 629 /// 630 /// Sets pending exceptions, interrupts, and NMIs as well as related states 631 /// of the vcpu. 632 /// 633 fn set_vcpu_events(&self, events: &VcpuEvents) -> cpu::Result<()> { 634 self.fd 635 .set_vcpu_events(events) 636 .map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into())) 637 } 638 #[cfg(target_arch = "x86_64")] 639 /// 640 /// Let the guest know that it has been paused, which prevents from 641 /// potential soft lockups when being resumed. 642 /// 643 fn notify_guest_clock_paused(&self) -> cpu::Result<()> { 644 self.fd 645 .kvmclock_ctrl() 646 .map_err(|e| cpu::HypervisorCpuError::NotifyGuestClockPaused(e.into())) 647 } 648 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 649 fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> { 650 self.fd 651 .vcpu_init(kvi) 652 .map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into())) 653 } 654 /// 655 /// Sets the value of one register for this vCPU. 656 /// 657 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 658 fn set_one_reg(&self, reg_id: u64, data: u64) -> cpu::Result<()> { 659 self.fd 660 .set_one_reg(reg_id, data) 661 .map_err(|e| cpu::HypervisorCpuError::SetOneReg(e.into())) 662 } 663 /// 664 /// Gets the value of one register for this vCPU. 665 /// 666 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 667 fn get_one_reg(&self, reg_id: u64) -> cpu::Result<u64> { 668 self.fd 669 .get_one_reg(reg_id) 670 .map_err(|e| cpu::HypervisorCpuError::GetOneReg(e.into())) 671 } 672 #[cfg(target_arch = "x86_64")] 673 /// 674 /// Get the current CPU state 675 /// 676 /// Ordering requirements: 677 /// 678 /// KVM_GET_MP_STATE calls kvm_apic_accept_events(), which might modify 679 /// vCPU/LAPIC state. As such, it must be done before most everything 680 /// else, otherwise we cannot restore everything and expect it to work. 681 /// 682 /// KVM_GET_VCPU_EVENTS/KVM_SET_VCPU_EVENTS is unsafe if other vCPUs are 683 /// still running. 684 /// 685 /// KVM_GET_LAPIC may change state of LAPIC before returning it. 686 /// 687 /// GET_VCPU_EVENTS should probably be last to save. The code looks as 688 /// it might as well be affected by internal state modifications of the 689 /// GET ioctls. 690 /// 691 /// SREGS saves/restores a pending interrupt, similar to what 692 /// VCPU_EVENTS also does. 693 /// 694 /// GET_MSRS requires a pre-populated data structure to do something 695 /// meaningful. For SET_MSRS it will then contain good data. 696 /// 697 /// # Example 698 /// 699 /// ```rust 700 /// # extern crate hypervisor; 701 /// # use hypervisor::KvmHypervisor; 702 /// # use std::sync::Arc; 703 /// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap(); 704 /// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm); 705 /// let vm = hv.create_vm().expect("new VM fd creation failed"); 706 /// vm.enable_split_irq().unwrap(); 707 /// let vcpu = vm.create_vcpu(0).unwrap(); 708 /// let state = vcpu.state().unwrap(); 709 /// ``` 710 fn state(&self) -> cpu::Result<CpuState> { 711 let mp_state = self.get_mp_state()?; 712 let regs = self.get_regs()?; 713 let sregs = self.get_sregs()?; 714 let xsave = self.get_xsave()?; 715 let xcrs = self.get_xcrs()?; 716 let lapic_state = self.get_lapic()?; 717 let fpu = self.get_fpu()?; 718 let mut msrs = self.msrs.clone(); 719 self.get_msrs(&mut msrs)?; 720 let vcpu_events = self.get_vcpu_events()?; 721 722 Ok(CpuState { 723 msrs, 724 vcpu_events, 725 regs, 726 sregs, 727 fpu, 728 lapic_state, 729 xsave, 730 xcrs, 731 mp_state, 732 }) 733 } 734 #[cfg(target_arch = "aarch64")] 735 fn state(&self) -> cpu::Result<CpuState> { 736 unimplemented!(); 737 } 738 #[cfg(target_arch = "x86_64")] 739 /// 740 /// Restore the previously saved CPU state 741 /// 742 /// Ordering requirements: 743 /// 744 /// KVM_GET_VCPU_EVENTS/KVM_SET_VCPU_EVENTS is unsafe if other vCPUs are 745 /// still running. 746 /// 747 /// Some SET ioctls (like set_mp_state) depend on kvm_vcpu_is_bsp(), so 748 /// if we ever change the BSP, we have to do that before restoring anything. 749 /// The same seems to be true for CPUID stuff. 750 /// 751 /// SREGS saves/restores a pending interrupt, similar to what 752 /// VCPU_EVENTS also does. 753 /// 754 /// SET_REGS clears pending exceptions unconditionally, thus, it must be 755 /// done before SET_VCPU_EVENTS, which restores it. 756 /// 757 /// SET_LAPIC must come after SET_SREGS, because the latter restores 758 /// the apic base msr. 759 /// 760 /// SET_LAPIC must come before SET_MSRS, because the TSC deadline MSR 761 /// only restores successfully, when the LAPIC is correctly configured. 762 /// 763 /// Arguments: CpuState 764 /// # Example 765 /// 766 /// ```rust 767 /// # extern crate hypervisor; 768 /// # use hypervisor::KvmHypervisor; 769 /// # use std::sync::Arc; 770 /// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap(); 771 /// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm); 772 /// let vm = hv.create_vm().expect("new VM fd creation failed"); 773 /// vm.enable_split_irq().unwrap(); 774 /// let vcpu = vm.create_vcpu(0).unwrap(); 775 /// let state = vcpu.state().unwrap(); 776 /// vcpu.set_state(&state).unwrap(); 777 /// ``` 778 fn set_state(&self, state: &CpuState) -> cpu::Result<()> { 779 self.set_mp_state(state.mp_state)?; 780 self.set_regs(&state.regs)?; 781 self.set_sregs(&state.sregs)?; 782 self.set_xsave(&state.xsave)?; 783 self.set_xcrs(&state.xcrs)?; 784 self.set_lapic(&state.lapic_state)?; 785 self.set_fpu(&state.fpu)?; 786 self.set_msrs(&state.msrs)?; 787 self.set_vcpu_events(&state.vcpu_events)?; 788 789 Ok(()) 790 } 791 #[allow(unused_variables)] 792 #[cfg(target_arch = "aarch64")] 793 fn set_state(&self, state: &CpuState) -> cpu::Result<()> { 794 Ok(()) 795 } 796 } 797