1 // Copyright © 2024 Institute of Software, CAS. All rights reserved. 2 // 3 // Copyright © 2019 Intel Corporation 4 // 5 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 6 // 7 // Copyright © 2020, Microsoft Corporation 8 // 9 // Copyright 2018-2019 CrowdStrike, Inc. 10 // 11 // 12 13 //! A generic abstraction around hypervisor functionality 14 //! 15 //! This crate offers a trait abstraction for underlying hypervisors 16 //! 17 //! # Platform support 18 //! 19 //! - x86_64 20 //! - arm64 21 //! - riscv64 (experimental) 22 //! 23 24 #[macro_use] 25 extern crate anyhow; 26 #[allow(unused_imports)] 27 #[macro_use] 28 extern crate log; 29 30 /// Architecture specific definitions 31 #[macro_use] 32 pub mod arch; 33 34 #[cfg(feature = "kvm")] 35 /// KVM implementation module 36 pub mod kvm; 37 38 /// Microsoft Hypervisor implementation module 39 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 40 pub mod mshv; 41 42 /// Hypervisor related module 43 mod hypervisor; 44 45 /// Vm related module 46 mod vm; 47 48 /// CPU related module 49 mod cpu; 50 51 /// Device related module 52 mod device; 53 54 use std::sync::Arc; 55 56 use concat_idents::concat_idents; 57 #[cfg(target_arch = "x86_64")] 58 pub use cpu::CpuVendor; 59 pub use cpu::{HypervisorCpuError, Vcpu, VmExit}; 60 pub use device::HypervisorDeviceError; 61 #[cfg(all(feature = "kvm", target_arch = "aarch64"))] 62 pub use kvm::aarch64; 63 #[cfg(all(feature = "kvm", target_arch = "riscv64"))] 64 pub use kvm::{riscv64, AiaState}; 65 pub use vm::{ 66 DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig, 67 Vm, VmOps, 68 }; 69 70 pub use crate::hypervisor::{Hypervisor, HypervisorError}; 71 72 #[derive(Debug, Copy, Clone)] 73 pub enum HypervisorType { 74 #[cfg(feature = "kvm")] 75 Kvm, 76 #[cfg(feature = "mshv")] 77 Mshv, 78 } 79 80 pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> { 81 #[cfg(feature = "kvm")] 82 if kvm::KvmHypervisor::is_available()? { 83 return kvm::KvmHypervisor::new(); 84 } 85 86 #[cfg(feature = "mshv")] 87 if mshv::MshvHypervisor::is_available()? { 88 return mshv::MshvHypervisor::new(); 89 } 90 91 Err(HypervisorError::HypervisorCreate(anyhow!( 92 "no supported hypervisor" 93 ))) 94 } 95 96 // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`. 97 fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { 98 let rounded_size = size_in_bytes.div_ceil(size_of::<T>()); 99 let mut v = Vec::with_capacity(rounded_size); 100 v.resize_with(rounded_size, T::default); 101 v 102 } 103 104 // The kvm API has many structs that resemble the following `Foo` structure: 105 // 106 // ``` 107 // #[repr(C)] 108 // struct Foo { 109 // some_data: u32 110 // entries: __IncompleteArrayField<__u32>, 111 // } 112 // ``` 113 // 114 // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not 115 // include any space for `entries`. To make the allocation large enough while still being aligned 116 // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used 117 // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous 118 // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries. 119 use std::mem::size_of; 120 pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { 121 let element_space = count * size_of::<F>(); 122 let vec_size_bytes = size_of::<T>() + element_space; 123 vec_with_size_in_bytes(vec_size_bytes) 124 } 125 126 /// 127 /// User memory region structure 128 /// 129 #[derive(Debug, Default, Eq, PartialEq)] 130 pub struct UserMemoryRegion { 131 pub slot: u32, 132 pub guest_phys_addr: u64, 133 pub memory_size: u64, 134 pub userspace_addr: u64, 135 pub flags: u32, 136 } 137 138 /// 139 /// Flags for user memory region 140 /// 141 pub const USER_MEMORY_REGION_READ: u32 = 1; 142 pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1; 143 pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2; 144 pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3; 145 pub const USER_MEMORY_REGION_ADJUSTABLE: u32 = 1 << 4; 146 147 #[derive(Debug)] 148 pub enum MpState { 149 #[cfg(feature = "kvm")] 150 Kvm(kvm_bindings::kvm_mp_state), 151 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 152 Mshv, /* MSHV does not support MpState yet */ 153 } 154 155 #[derive(Debug, Clone, Copy)] 156 pub enum IoEventAddress { 157 Pio(u64), 158 Mmio(u64), 159 } 160 161 #[derive(Clone, serde::Serialize, serde::Deserialize)] 162 #[allow(clippy::large_enum_variant)] 163 pub enum CpuState { 164 #[cfg(feature = "kvm")] 165 Kvm(kvm::VcpuKvmState), 166 #[cfg(feature = "mshv")] 167 Mshv(mshv::VcpuMshvState), 168 } 169 170 #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] 171 #[cfg(target_arch = "x86_64")] 172 pub enum ClockData { 173 #[cfg(feature = "kvm")] 174 Kvm(kvm_bindings::kvm_clock_data), 175 #[cfg(feature = "mshv")] 176 Mshv(mshv::MshvClockData), 177 } 178 179 #[cfg(target_arch = "x86_64")] 180 impl ClockData { 181 pub fn reset_flags(&mut self) { 182 match self { 183 #[cfg(feature = "kvm")] 184 ClockData::Kvm(s) => s.flags = 0, 185 #[allow(unreachable_patterns)] 186 _ => {} 187 } 188 } 189 } 190 191 #[derive(Copy, Clone)] 192 pub enum IrqRoutingEntry { 193 #[cfg(feature = "kvm")] 194 Kvm(kvm_bindings::kvm_irq_routing_entry), 195 #[cfg(feature = "mshv")] 196 Mshv(mshv_bindings::mshv_user_irq_entry), 197 } 198 199 #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] 200 pub enum VcpuInit { 201 #[cfg(all(feature = "kvm", target_arch = "aarch64"))] 202 Kvm(kvm_bindings::kvm_vcpu_init), 203 #[cfg(all(feature = "mshv", target_arch = "aarch64"))] 204 Mshv(mshv_bindings::MshvVcpuInit), 205 } 206 207 #[derive(Debug, Clone, PartialEq)] 208 pub enum RegList { 209 #[cfg(all(feature = "kvm", any(target_arch = "aarch64", target_arch = "riscv64")))] 210 Kvm(kvm_bindings::RegList), 211 #[cfg(all(feature = "mshv", target_arch = "aarch64"))] 212 Mshv(mshv_bindings::MshvRegList), 213 } 214 215 pub enum Register { 216 #[cfg(feature = "kvm")] 217 Kvm(kvm_bindings::kvm_one_reg), 218 } 219 220 #[allow(clippy::large_enum_variant)] 221 #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] 222 pub enum StandardRegisters { 223 #[cfg(all(feature = "kvm", not(target_arch = "riscv64")))] 224 Kvm(kvm_bindings::kvm_regs), 225 #[cfg(all(feature = "kvm", target_arch = "riscv64"))] 226 Kvm(kvm_bindings::kvm_riscv_core), 227 #[cfg(any(feature = "mshv", feature = "mshv_emulator"))] 228 Mshv(mshv_bindings::StandardRegisters), 229 } 230 231 macro_rules! set_x86_64_reg { 232 ($reg_name:ident) => { 233 concat_idents!(method_name = "set_", $reg_name { 234 #[cfg(target_arch = "x86_64")] 235 impl StandardRegisters { 236 pub fn method_name(&mut self, val: u64) { 237 match self { 238 #[cfg(feature = "kvm")] 239 StandardRegisters::Kvm(s) => s.$reg_name = val, 240 #[cfg(any(feature = "mshv", feature = "mshv_emulator"))] 241 StandardRegisters::Mshv(s) => s.$reg_name = val, 242 } 243 } 244 } 245 }); 246 } 247 } 248 249 macro_rules! get_x86_64_reg { 250 ($reg_name:ident) => { 251 concat_idents!(method_name = "get_", $reg_name { 252 #[cfg(target_arch = "x86_64")] 253 impl StandardRegisters { 254 pub fn method_name(&self) -> u64 { 255 match self { 256 #[cfg(feature = "kvm")] 257 StandardRegisters::Kvm(s) => s.$reg_name, 258 #[cfg(any(feature = "mshv", feature = "mshv_emulator"))] 259 StandardRegisters::Mshv(s) => s.$reg_name, 260 } 261 } 262 } 263 }); 264 } 265 } 266 267 set_x86_64_reg!(rax); 268 set_x86_64_reg!(rbx); 269 set_x86_64_reg!(rcx); 270 set_x86_64_reg!(rdx); 271 set_x86_64_reg!(rsi); 272 set_x86_64_reg!(rdi); 273 set_x86_64_reg!(rsp); 274 set_x86_64_reg!(rbp); 275 set_x86_64_reg!(r8); 276 set_x86_64_reg!(r9); 277 set_x86_64_reg!(r10); 278 set_x86_64_reg!(r11); 279 set_x86_64_reg!(r12); 280 set_x86_64_reg!(r13); 281 set_x86_64_reg!(r14); 282 set_x86_64_reg!(r15); 283 set_x86_64_reg!(rip); 284 set_x86_64_reg!(rflags); 285 286 get_x86_64_reg!(rax); 287 get_x86_64_reg!(rbx); 288 get_x86_64_reg!(rcx); 289 get_x86_64_reg!(rdx); 290 get_x86_64_reg!(rsi); 291 get_x86_64_reg!(rdi); 292 get_x86_64_reg!(rsp); 293 get_x86_64_reg!(rbp); 294 get_x86_64_reg!(r8); 295 get_x86_64_reg!(r9); 296 get_x86_64_reg!(r10); 297 get_x86_64_reg!(r11); 298 get_x86_64_reg!(r12); 299 get_x86_64_reg!(r13); 300 get_x86_64_reg!(r14); 301 get_x86_64_reg!(r15); 302 get_x86_64_reg!(rip); 303 get_x86_64_reg!(rflags); 304 305 macro_rules! set_aarch64_reg { 306 ($reg_name:ident, $type:ty) => { 307 concat_idents!(method_name = "set_", $reg_name { 308 #[cfg(target_arch = "aarch64")] 309 impl StandardRegisters { 310 pub fn method_name(&mut self, val: $type) { 311 match self { 312 #[cfg(feature = "kvm")] 313 StandardRegisters::Kvm(s) => s.regs.$reg_name = val, 314 #[cfg(feature = "mshv")] 315 StandardRegisters::Mshv(s) => s.$reg_name = val, 316 } 317 } 318 } 319 }); 320 } 321 } 322 323 macro_rules! get_aarch64_reg { 324 ($reg_name:ident, $type:ty) => { 325 concat_idents!(method_name = "get_", $reg_name { 326 #[cfg(target_arch = "aarch64")] 327 impl StandardRegisters { 328 pub fn method_name(&self) -> $type { 329 match self { 330 #[cfg(feature = "kvm")] 331 StandardRegisters::Kvm(s) => s.regs.$reg_name, 332 #[cfg(feature = "mshv")] 333 StandardRegisters::Mshv(s) => s.$reg_name, 334 } 335 } 336 } 337 }); 338 } 339 } 340 341 set_aarch64_reg!(regs, [u64; 31usize]); 342 set_aarch64_reg!(sp, u64); 343 set_aarch64_reg!(pc, u64); 344 set_aarch64_reg!(pstate, u64); 345 346 get_aarch64_reg!(regs, [u64; 31usize]); 347 get_aarch64_reg!(sp, u64); 348 get_aarch64_reg!(pc, u64); 349 get_aarch64_reg!(pstate, u64); 350 351 macro_rules! set_riscv64_reg { 352 (mode) => { 353 #[cfg(target_arch = "riscv64")] 354 impl StandardRegisters { 355 pub fn set_mode(&mut self, val: u64) { 356 match self { 357 #[cfg(feature = "kvm")] 358 StandardRegisters::Kvm(s) => s.mode = val, 359 } 360 } 361 } 362 }; 363 ($reg_name:ident) => { 364 concat_idents!(method_name = "set_", $reg_name { 365 #[cfg(target_arch = "riscv64")] 366 impl StandardRegisters { 367 pub fn method_name(&mut self, val: u64) { 368 match self { 369 #[cfg(feature = "kvm")] 370 StandardRegisters::Kvm(s) => s.regs.$reg_name = val, 371 } 372 } 373 } 374 }); 375 } 376 } 377 378 macro_rules! get_riscv64_reg { 379 (mode) => { 380 #[cfg(target_arch = "riscv64")] 381 impl StandardRegisters { 382 pub fn get_mode(&self) -> u64 { 383 match self { 384 #[cfg(feature = "kvm")] 385 StandardRegisters::Kvm(s) => s.mode, 386 } 387 } 388 } 389 }; 390 ($reg_name:ident) => { 391 concat_idents!(method_name = "get_", $reg_name { 392 #[cfg(target_arch = "riscv64")] 393 impl StandardRegisters { 394 pub fn method_name(&self) -> u64 { 395 match self { 396 #[cfg(feature = "kvm")] 397 StandardRegisters::Kvm(s) => s.regs.$reg_name, 398 } 399 } 400 } 401 }); 402 } 403 } 404 405 set_riscv64_reg!(pc); 406 set_riscv64_reg!(ra); 407 set_riscv64_reg!(sp); 408 set_riscv64_reg!(gp); 409 set_riscv64_reg!(tp); 410 set_riscv64_reg!(t0); 411 set_riscv64_reg!(t1); 412 set_riscv64_reg!(t2); 413 set_riscv64_reg!(s0); 414 set_riscv64_reg!(s1); 415 set_riscv64_reg!(a0); 416 set_riscv64_reg!(a1); 417 set_riscv64_reg!(a2); 418 set_riscv64_reg!(a3); 419 set_riscv64_reg!(a4); 420 set_riscv64_reg!(a5); 421 set_riscv64_reg!(a6); 422 set_riscv64_reg!(a7); 423 set_riscv64_reg!(s2); 424 set_riscv64_reg!(s3); 425 set_riscv64_reg!(s4); 426 set_riscv64_reg!(s5); 427 set_riscv64_reg!(s6); 428 set_riscv64_reg!(s7); 429 set_riscv64_reg!(s8); 430 set_riscv64_reg!(s9); 431 set_riscv64_reg!(s10); 432 set_riscv64_reg!(s11); 433 set_riscv64_reg!(t3); 434 set_riscv64_reg!(t4); 435 set_riscv64_reg!(t5); 436 set_riscv64_reg!(t6); 437 set_riscv64_reg!(mode); 438 439 get_riscv64_reg!(pc); 440 get_riscv64_reg!(ra); 441 get_riscv64_reg!(sp); 442 get_riscv64_reg!(gp); 443 get_riscv64_reg!(tp); 444 get_riscv64_reg!(t0); 445 get_riscv64_reg!(t1); 446 get_riscv64_reg!(t2); 447 get_riscv64_reg!(s0); 448 get_riscv64_reg!(s1); 449 get_riscv64_reg!(a0); 450 get_riscv64_reg!(a1); 451 get_riscv64_reg!(a2); 452 get_riscv64_reg!(a3); 453 get_riscv64_reg!(a4); 454 get_riscv64_reg!(a5); 455 get_riscv64_reg!(a6); 456 get_riscv64_reg!(a7); 457 get_riscv64_reg!(s2); 458 get_riscv64_reg!(s3); 459 get_riscv64_reg!(s4); 460 get_riscv64_reg!(s5); 461 get_riscv64_reg!(s6); 462 get_riscv64_reg!(s7); 463 get_riscv64_reg!(s8); 464 get_riscv64_reg!(s9); 465 get_riscv64_reg!(s10); 466 get_riscv64_reg!(s11); 467 get_riscv64_reg!(t3); 468 get_riscv64_reg!(t4); 469 get_riscv64_reg!(t5); 470 get_riscv64_reg!(t6); 471 get_riscv64_reg!(mode); 472