xref: /cloud-hypervisor/hypervisor/src/lib.rs (revision 960d7022551dda14eae229b030654583ae6db9a5)
18cd80ea3SRuoqing He // Copyright © 2024 Institute of Software, CAS. All rights reserved.
28cd80ea3SRuoqing He //
356a16385SMuminul Islam // Copyright © 2019 Intel Corporation
456a16385SMuminul Islam //
572ae1577SMuminul Islam // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
656a16385SMuminul Islam //
756a16385SMuminul Islam // Copyright © 2020, Microsoft Corporation
856a16385SMuminul Islam //
956a16385SMuminul Islam // Copyright 2018-2019 CrowdStrike, Inc.
1056a16385SMuminul Islam //
11f9b51a41SMuminul Islam //
12f9b51a41SMuminul Islam 
13f9b51a41SMuminul Islam //! A generic abstraction around hypervisor functionality
14f9b51a41SMuminul Islam //!
15f9b51a41SMuminul Islam //! This crate offers a trait abstraction for underlying hypervisors
16f9b51a41SMuminul Islam //!
17f9b51a41SMuminul Islam //! # Platform support
18f9b51a41SMuminul Islam //!
19f9b51a41SMuminul Islam //! - x86_64
20f9b51a41SMuminul Islam //! - arm64
218cd80ea3SRuoqing He //! - riscv64 (experimental)
22f9b51a41SMuminul Islam //!
23f9b51a41SMuminul Islam 
240f1ab38dSSebastien Boeuf #[macro_use]
250f1ab38dSSebastien Boeuf extern crate anyhow;
26fdcc8539SJinank Jain #[allow(unused_imports)]
270f1ab38dSSebastien Boeuf #[macro_use]
280f1ab38dSSebastien Boeuf extern crate log;
29c48d0c1aSMuminul Islam 
308c85dd32SMuminul Islam /// Architecture specific definitions
318c85dd32SMuminul Islam #[macro_use]
328c85dd32SMuminul Islam pub mod arch;
338c85dd32SMuminul Islam 
349ce6c3b7SMuminul Islam #[cfg(feature = "kvm")]
35f9b51a41SMuminul Islam /// KVM implementation module
36f9b51a41SMuminul Islam pub mod kvm;
37f9b51a41SMuminul Islam 
389919dec1SMuminul Islam /// Microsoft Hypervisor implementation module
39*960d7022SJinank Jain #[cfg(feature = "mshv")]
409919dec1SMuminul Islam pub mod mshv;
419919dec1SMuminul Islam 
42442ac905SPhilipp Schuster /// Hypervisor related module
43288cea91SRob Bradford mod hypervisor;
44683210d6SMuminul Islam 
45f5afc288SMuminul Islam /// Vm related module
46d3f66f87SRob Bradford mod vm;
47f5afc288SMuminul Islam 
48f9b51a41SMuminul Islam /// CPU related module
49f9b51a41SMuminul Islam mod cpu;
50f9b51a41SMuminul Islam 
51e7288888SMichael Zhao /// Device related module
52e7288888SMichael Zhao mod device;
53e7288888SMichael Zhao 
5488a9f799SRob Bradford use std::sync::Arc;
5588a9f799SRob Bradford 
568f3bd4d9SJinank Jain use concat_idents::concat_idents;
577df80220SAnatol Belski #[cfg(target_arch = "x86_64")]
587df80220SAnatol Belski pub use cpu::CpuVendor;
59a4f484bcSWei Liu pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
60a96a5d78SWei Liu pub use device::HypervisorDeviceError;
61c2862b69SMichael Zhao #[cfg(all(feature = "kvm", target_arch = "aarch64"))]
626bb33601SJinank Jain pub use kvm::aarch64;
638cd80ea3SRuoqing He #[cfg(all(feature = "kvm", target_arch = "riscv64"))]
648cd80ea3SRuoqing He pub use kvm::{riscv64, AiaState};
65d3f66f87SRob Bradford pub use vm::{
66d3f66f87SRob Bradford     DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig,
67d3f66f87SRob Bradford     Vm, VmOps,
68d3f66f87SRob Bradford };
69a83bd97eSWei Liu 
7088a9f799SRob Bradford pub use crate::hypervisor::{Hypervisor, HypervisorError};
7188a9f799SRob Bradford 
727d8f7954SMuminul Islam #[derive(Debug, Copy, Clone)]
739fc3379eSWei Liu pub enum HypervisorType {
74a48d7c28SRob Bradford     #[cfg(feature = "kvm")]
759fc3379eSWei Liu     Kvm,
76a48d7c28SRob Bradford     #[cfg(feature = "mshv")]
779fc3379eSWei Liu     Mshv,
789fc3379eSWei Liu }
799fc3379eSWei Liu 
new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError>80a83bd97eSWei Liu pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> {
81a83bd97eSWei Liu     #[cfg(feature = "kvm")]
82bb19c3d2SWei Liu     if kvm::KvmHypervisor::is_available()? {
83bb19c3d2SWei Liu         return kvm::KvmHypervisor::new();
84bb19c3d2SWei Liu     }
85a83bd97eSWei Liu 
8623c46b16SMuminul Islam     #[cfg(feature = "mshv")]
87bb19c3d2SWei Liu     if mshv::MshvHypervisor::is_available()? {
88bb19c3d2SWei Liu         return mshv::MshvHypervisor::new();
89bb19c3d2SWei Liu     }
9023c46b16SMuminul Islam 
91bb19c3d2SWei Liu     Err(HypervisorError::HypervisorCreate(anyhow!(
92bb19c3d2SWei Liu         "no supported hypervisor"
93bb19c3d2SWei Liu     )))
94a83bd97eSWei Liu }
957fad74cbSVineeth Pillai 
967fad74cbSVineeth Pillai // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T>977fad74cbSVineeth Pillai fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
986164aa08SRuoqing He     let rounded_size = size_in_bytes.div_ceil(size_of::<T>());
997fad74cbSVineeth Pillai     let mut v = Vec::with_capacity(rounded_size);
1007fad74cbSVineeth Pillai     v.resize_with(rounded_size, T::default);
1017fad74cbSVineeth Pillai     v
1027fad74cbSVineeth Pillai }
1037fad74cbSVineeth Pillai 
1047fad74cbSVineeth Pillai // The kvm API has many structs that resemble the following `Foo` structure:
1057fad74cbSVineeth Pillai //
1067fad74cbSVineeth Pillai // ```
1077fad74cbSVineeth Pillai // #[repr(C)]
1087fad74cbSVineeth Pillai // struct Foo {
1097fad74cbSVineeth Pillai //    some_data: u32
1107fad74cbSVineeth Pillai //    entries: __IncompleteArrayField<__u32>,
1117fad74cbSVineeth Pillai // }
1127fad74cbSVineeth Pillai // ```
1137fad74cbSVineeth Pillai //
1147fad74cbSVineeth Pillai // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
1157fad74cbSVineeth Pillai // include any space for `entries`. To make the allocation large enough while still being aligned
1167fad74cbSVineeth Pillai // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
1177fad74cbSVineeth Pillai // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
1187fad74cbSVineeth Pillai // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
1197fad74cbSVineeth Pillai use std::mem::size_of;
vec_with_array_field<T: Default, F>(count: usize) -> Vec<T>1207fad74cbSVineeth Pillai pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {
1217fad74cbSVineeth Pillai     let element_space = count * size_of::<F>();
1227fad74cbSVineeth Pillai     let vec_size_bytes = size_of::<T>() + element_space;
1237fad74cbSVineeth Pillai     vec_with_size_in_bytes(vec_size_bytes)
1247fad74cbSVineeth Pillai }
125fabc940bSWei Liu 
126fabc940bSWei Liu ///
127fabc940bSWei Liu /// User memory region structure
128fabc940bSWei Liu ///
129fabc940bSWei Liu #[derive(Debug, Default, Eq, PartialEq)]
130fabc940bSWei Liu pub struct UserMemoryRegion {
131fabc940bSWei Liu     pub slot: u32,
132fabc940bSWei Liu     pub guest_phys_addr: u64,
133fabc940bSWei Liu     pub memory_size: u64,
134fabc940bSWei Liu     pub userspace_addr: u64,
135fabc940bSWei Liu     pub flags: u32,
136fabc940bSWei Liu }
137fabc940bSWei Liu 
138fabc940bSWei Liu ///
139fabc940bSWei Liu /// Flags for user memory region
140fabc940bSWei Liu ///
141fabc940bSWei Liu pub const USER_MEMORY_REGION_READ: u32 = 1;
142fabc940bSWei Liu pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1;
143fabc940bSWei Liu pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2;
144fabc940bSWei Liu pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3;
145321d6f47SJinank Jain pub const USER_MEMORY_REGION_ADJUSTABLE: u32 = 1 << 4;
1469810ed44SWei Liu 
1479810ed44SWei Liu #[derive(Debug)]
1489810ed44SWei Liu pub enum MpState {
1499810ed44SWei Liu     #[cfg(feature = "kvm")]
1509810ed44SWei Liu     Kvm(kvm_bindings::kvm_mp_state),
151*960d7022SJinank Jain     #[cfg(feature = "mshv")]
1527bf0cc1eSPhilipp Schuster     Mshv, /* MSHV does not support MpState yet */
1539810ed44SWei Liu }
154f9f0a60dSWei Liu 
155f9f0a60dSWei Liu #[derive(Debug, Clone, Copy)]
156f9f0a60dSWei Liu pub enum IoEventAddress {
157f9f0a60dSWei Liu     Pio(u64),
158f9f0a60dSWei Liu     Mmio(u64),
159f9f0a60dSWei Liu }
16072d552e5SWei Liu 
16172d552e5SWei Liu #[derive(Clone, serde::Serialize, serde::Deserialize)]
1627b99bd94SWei Liu #[allow(clippy::large_enum_variant)]
16372d552e5SWei Liu pub enum CpuState {
16472d552e5SWei Liu     #[cfg(feature = "kvm")]
16572d552e5SWei Liu     Kvm(kvm::VcpuKvmState),
166f5a2f847SJinank Jain     #[cfg(feature = "mshv")]
16772d552e5SWei Liu     Mshv(mshv::VcpuMshvState),
16872d552e5SWei Liu }
1694201bf40SWei Liu 
1704201bf40SWei Liu #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
1714201bf40SWei Liu #[cfg(target_arch = "x86_64")]
1724201bf40SWei Liu pub enum ClockData {
1734201bf40SWei Liu     #[cfg(feature = "kvm")]
1744201bf40SWei Liu     Kvm(kvm_bindings::kvm_clock_data),
1754201bf40SWei Liu     #[cfg(feature = "mshv")]
1764847f5c4SMuminul Islam     Mshv(mshv::MshvClockData),
1774201bf40SWei Liu }
1784201bf40SWei Liu 
1794201bf40SWei Liu #[cfg(target_arch = "x86_64")]
1804201bf40SWei Liu impl ClockData {
reset_flags(&mut self)1814201bf40SWei Liu     pub fn reset_flags(&mut self) {
1824201bf40SWei Liu         match self {
1834201bf40SWei Liu             #[cfg(feature = "kvm")]
1844201bf40SWei Liu             ClockData::Kvm(s) => s.flags = 0,
1854201bf40SWei Liu             #[allow(unreachable_patterns)]
1864201bf40SWei Liu             _ => {}
1874201bf40SWei Liu         }
1884201bf40SWei Liu     }
1894201bf40SWei Liu }
190d20f647bSWei Liu 
191d20f647bSWei Liu #[derive(Copy, Clone)]
192d20f647bSWei Liu pub enum IrqRoutingEntry {
193d20f647bSWei Liu     #[cfg(feature = "kvm")]
194d20f647bSWei Liu     Kvm(kvm_bindings::kvm_irq_routing_entry),
195d20f647bSWei Liu     #[cfg(feature = "mshv")]
1969f08aa6dSNuno Das Neves     Mshv(mshv_bindings::mshv_user_irq_entry),
197d20f647bSWei Liu }
198feb0a360SJinank Jain 
1995b929cb2SJinank Jain #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
2005b929cb2SJinank Jain pub enum VcpuInit {
2015b929cb2SJinank Jain     #[cfg(all(feature = "kvm", target_arch = "aarch64"))]
2025b929cb2SJinank Jain     Kvm(kvm_bindings::kvm_vcpu_init),
2038c796e6dSJinank Jain     #[cfg(all(feature = "mshv", target_arch = "aarch64"))]
2048c796e6dSJinank Jain     Mshv(mshv_bindings::MshvVcpuInit),
2055b929cb2SJinank Jain }
2065b929cb2SJinank Jain 
207ee0b0d43SJinank Jain #[derive(Debug, Clone, PartialEq)]
208ee0b0d43SJinank Jain pub enum RegList {
209ee0b0d43SJinank Jain     #[cfg(all(feature = "kvm", any(target_arch = "aarch64", target_arch = "riscv64")))]
210ee0b0d43SJinank Jain     Kvm(kvm_bindings::RegList),
211630f5c1fSJinank Jain     #[cfg(all(feature = "mshv", target_arch = "aarch64"))]
212630f5c1fSJinank Jain     Mshv(mshv_bindings::MshvRegList),
213ee0b0d43SJinank Jain }
214ee0b0d43SJinank Jain 
21506148234SJinank Jain pub enum Register {
21606148234SJinank Jain     #[cfg(feature = "kvm")]
21706148234SJinank Jain     Kvm(kvm_bindings::kvm_one_reg),
21806148234SJinank Jain }
21906148234SJinank Jain 
2207da8ae9cSJinank Jain #[allow(clippy::large_enum_variant)]
221feb0a360SJinank Jain #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
222feb0a360SJinank Jain pub enum StandardRegisters {
2238cd80ea3SRuoqing He     #[cfg(all(feature = "kvm", not(target_arch = "riscv64")))]
224feb0a360SJinank Jain     Kvm(kvm_bindings::kvm_regs),
2258cd80ea3SRuoqing He     #[cfg(all(feature = "kvm", target_arch = "riscv64"))]
2268cd80ea3SRuoqing He     Kvm(kvm_bindings::kvm_riscv_core),
2277da8ae9cSJinank Jain     #[cfg(any(feature = "mshv", feature = "mshv_emulator"))]
228feb0a360SJinank Jain     Mshv(mshv_bindings::StandardRegisters),
229feb0a360SJinank Jain }
2308f3bd4d9SJinank Jain 
2318f3bd4d9SJinank Jain macro_rules! set_x86_64_reg {
2328f3bd4d9SJinank Jain     ($reg_name:ident) => {
2338f3bd4d9SJinank Jain         concat_idents!(method_name = "set_", $reg_name {
2348f3bd4d9SJinank Jain             #[cfg(target_arch = "x86_64")]
2358f3bd4d9SJinank Jain             impl StandardRegisters {
2368f3bd4d9SJinank Jain                 pub fn method_name(&mut self, val: u64) {
2378f3bd4d9SJinank Jain                     match self {
2388f3bd4d9SJinank Jain                         #[cfg(feature = "kvm")]
2398f3bd4d9SJinank Jain                         StandardRegisters::Kvm(s) => s.$reg_name = val,
240fe24a7a2SWei Liu                         #[cfg(any(feature = "mshv", feature = "mshv_emulator"))]
2418f3bd4d9SJinank Jain                         StandardRegisters::Mshv(s) => s.$reg_name = val,
2428f3bd4d9SJinank Jain                     }
2438f3bd4d9SJinank Jain                 }
2448f3bd4d9SJinank Jain             }
2458f3bd4d9SJinank Jain         });
2468f3bd4d9SJinank Jain     }
2478f3bd4d9SJinank Jain }
2488f3bd4d9SJinank Jain 
2498f3bd4d9SJinank Jain macro_rules! get_x86_64_reg {
2508f3bd4d9SJinank Jain     ($reg_name:ident) => {
2518f3bd4d9SJinank Jain         concat_idents!(method_name = "get_", $reg_name {
2528f3bd4d9SJinank Jain             #[cfg(target_arch = "x86_64")]
2538f3bd4d9SJinank Jain             impl StandardRegisters {
2548f3bd4d9SJinank Jain                 pub fn method_name(&self) -> u64 {
2558f3bd4d9SJinank Jain                     match self {
2568f3bd4d9SJinank Jain                         #[cfg(feature = "kvm")]
2578f3bd4d9SJinank Jain                         StandardRegisters::Kvm(s) => s.$reg_name,
258fe24a7a2SWei Liu                         #[cfg(any(feature = "mshv", feature = "mshv_emulator"))]
2598f3bd4d9SJinank Jain                         StandardRegisters::Mshv(s) => s.$reg_name,
2608f3bd4d9SJinank Jain                     }
2618f3bd4d9SJinank Jain                 }
2628f3bd4d9SJinank Jain             }
2638f3bd4d9SJinank Jain         });
2648f3bd4d9SJinank Jain     }
2658f3bd4d9SJinank Jain }
2668f3bd4d9SJinank Jain 
2678f3bd4d9SJinank Jain set_x86_64_reg!(rax);
2688f3bd4d9SJinank Jain set_x86_64_reg!(rbx);
2698f3bd4d9SJinank Jain set_x86_64_reg!(rcx);
2708f3bd4d9SJinank Jain set_x86_64_reg!(rdx);
2718f3bd4d9SJinank Jain set_x86_64_reg!(rsi);
2728f3bd4d9SJinank Jain set_x86_64_reg!(rdi);
2738f3bd4d9SJinank Jain set_x86_64_reg!(rsp);
2748f3bd4d9SJinank Jain set_x86_64_reg!(rbp);
2758f3bd4d9SJinank Jain set_x86_64_reg!(r8);
2768f3bd4d9SJinank Jain set_x86_64_reg!(r9);
2778f3bd4d9SJinank Jain set_x86_64_reg!(r10);
2788f3bd4d9SJinank Jain set_x86_64_reg!(r11);
2798f3bd4d9SJinank Jain set_x86_64_reg!(r12);
2808f3bd4d9SJinank Jain set_x86_64_reg!(r13);
2818f3bd4d9SJinank Jain set_x86_64_reg!(r14);
2828f3bd4d9SJinank Jain set_x86_64_reg!(r15);
2838f3bd4d9SJinank Jain set_x86_64_reg!(rip);
2848f3bd4d9SJinank Jain set_x86_64_reg!(rflags);
2858f3bd4d9SJinank Jain 
2868f3bd4d9SJinank Jain get_x86_64_reg!(rax);
2878f3bd4d9SJinank Jain get_x86_64_reg!(rbx);
2888f3bd4d9SJinank Jain get_x86_64_reg!(rcx);
2898f3bd4d9SJinank Jain get_x86_64_reg!(rdx);
2908f3bd4d9SJinank Jain get_x86_64_reg!(rsi);
2918f3bd4d9SJinank Jain get_x86_64_reg!(rdi);
2928f3bd4d9SJinank Jain get_x86_64_reg!(rsp);
2938f3bd4d9SJinank Jain get_x86_64_reg!(rbp);
2948f3bd4d9SJinank Jain get_x86_64_reg!(r8);
2958f3bd4d9SJinank Jain get_x86_64_reg!(r9);
2968f3bd4d9SJinank Jain get_x86_64_reg!(r10);
2978f3bd4d9SJinank Jain get_x86_64_reg!(r11);
2988f3bd4d9SJinank Jain get_x86_64_reg!(r12);
2998f3bd4d9SJinank Jain get_x86_64_reg!(r13);
3008f3bd4d9SJinank Jain get_x86_64_reg!(r14);
3018f3bd4d9SJinank Jain get_x86_64_reg!(r15);
3028f3bd4d9SJinank Jain get_x86_64_reg!(rip);
3038f3bd4d9SJinank Jain get_x86_64_reg!(rflags);
304a987c3d0SJinank Jain 
305a987c3d0SJinank Jain macro_rules! set_aarch64_reg {
306a987c3d0SJinank Jain     ($reg_name:ident, $type:ty) => {
307a987c3d0SJinank Jain         concat_idents!(method_name = "set_", $reg_name {
308a987c3d0SJinank Jain             #[cfg(target_arch = "aarch64")]
309a987c3d0SJinank Jain             impl StandardRegisters {
310a987c3d0SJinank Jain                 pub fn method_name(&mut self, val: $type) {
311a987c3d0SJinank Jain                     match self {
312a987c3d0SJinank Jain                         #[cfg(feature = "kvm")]
313a987c3d0SJinank Jain                         StandardRegisters::Kvm(s) => s.regs.$reg_name = val,
3147da8ae9cSJinank Jain                         #[cfg(feature = "mshv")]
3157da8ae9cSJinank Jain                         StandardRegisters::Mshv(s) => s.$reg_name = val,
316a987c3d0SJinank Jain                     }
317a987c3d0SJinank Jain                 }
318a987c3d0SJinank Jain             }
319a987c3d0SJinank Jain         });
320a987c3d0SJinank Jain     }
321a987c3d0SJinank Jain }
322a987c3d0SJinank Jain 
323a987c3d0SJinank Jain macro_rules! get_aarch64_reg {
324a987c3d0SJinank Jain     ($reg_name:ident, $type:ty) => {
325a987c3d0SJinank Jain         concat_idents!(method_name = "get_", $reg_name {
326a987c3d0SJinank Jain             #[cfg(target_arch = "aarch64")]
327a987c3d0SJinank Jain             impl StandardRegisters {
328a987c3d0SJinank Jain                 pub fn method_name(&self) -> $type {
329a987c3d0SJinank Jain                     match self {
330a987c3d0SJinank Jain                         #[cfg(feature = "kvm")]
331a987c3d0SJinank Jain                         StandardRegisters::Kvm(s) => s.regs.$reg_name,
3327da8ae9cSJinank Jain                         #[cfg(feature = "mshv")]
3337da8ae9cSJinank Jain                         StandardRegisters::Mshv(s) => s.$reg_name,
334a987c3d0SJinank Jain                     }
335a987c3d0SJinank Jain                 }
336a987c3d0SJinank Jain             }
337a987c3d0SJinank Jain         });
338a987c3d0SJinank Jain     }
339a987c3d0SJinank Jain }
340a987c3d0SJinank Jain 
341a987c3d0SJinank Jain set_aarch64_reg!(regs, [u64; 31usize]);
342a987c3d0SJinank Jain set_aarch64_reg!(sp, u64);
343a987c3d0SJinank Jain set_aarch64_reg!(pc, u64);
344a987c3d0SJinank Jain set_aarch64_reg!(pstate, u64);
345a987c3d0SJinank Jain 
346a987c3d0SJinank Jain get_aarch64_reg!(regs, [u64; 31usize]);
347a987c3d0SJinank Jain get_aarch64_reg!(sp, u64);
348a987c3d0SJinank Jain get_aarch64_reg!(pc, u64);
349a987c3d0SJinank Jain get_aarch64_reg!(pstate, u64);
3508cd80ea3SRuoqing He 
3518cd80ea3SRuoqing He macro_rules! set_riscv64_reg {
3528cd80ea3SRuoqing He     (mode) => {
3538cd80ea3SRuoqing He         #[cfg(target_arch = "riscv64")]
3548cd80ea3SRuoqing He         impl StandardRegisters {
3558cd80ea3SRuoqing He             pub fn set_mode(&mut self, val: u64) {
3568cd80ea3SRuoqing He                 match self {
3578cd80ea3SRuoqing He                     #[cfg(feature = "kvm")]
3588cd80ea3SRuoqing He                     StandardRegisters::Kvm(s) => s.mode = val,
3598cd80ea3SRuoqing He                 }
3608cd80ea3SRuoqing He             }
3618cd80ea3SRuoqing He         }
3628cd80ea3SRuoqing He     };
3638cd80ea3SRuoqing He     ($reg_name:ident) => {
3648cd80ea3SRuoqing He         concat_idents!(method_name = "set_", $reg_name {
3658cd80ea3SRuoqing He             #[cfg(target_arch = "riscv64")]
3668cd80ea3SRuoqing He             impl StandardRegisters {
3678cd80ea3SRuoqing He                 pub fn method_name(&mut self, val: u64) {
3688cd80ea3SRuoqing He                     match self {
3698cd80ea3SRuoqing He                         #[cfg(feature = "kvm")]
3708cd80ea3SRuoqing He                         StandardRegisters::Kvm(s) => s.regs.$reg_name = val,
3718cd80ea3SRuoqing He                     }
3728cd80ea3SRuoqing He                 }
3738cd80ea3SRuoqing He             }
3748cd80ea3SRuoqing He         });
3758cd80ea3SRuoqing He     }
3768cd80ea3SRuoqing He }
3778cd80ea3SRuoqing He 
3788cd80ea3SRuoqing He macro_rules! get_riscv64_reg {
3798cd80ea3SRuoqing He     (mode) => {
3808cd80ea3SRuoqing He         #[cfg(target_arch = "riscv64")]
3818cd80ea3SRuoqing He         impl StandardRegisters {
3828cd80ea3SRuoqing He             pub fn get_mode(&self) -> u64 {
3838cd80ea3SRuoqing He                 match self {
3848cd80ea3SRuoqing He                     #[cfg(feature = "kvm")]
3858cd80ea3SRuoqing He                     StandardRegisters::Kvm(s) => s.mode,
3868cd80ea3SRuoqing He                 }
3878cd80ea3SRuoqing He             }
3888cd80ea3SRuoqing He         }
3898cd80ea3SRuoqing He     };
3908cd80ea3SRuoqing He     ($reg_name:ident) => {
3918cd80ea3SRuoqing He         concat_idents!(method_name = "get_", $reg_name {
3928cd80ea3SRuoqing He             #[cfg(target_arch = "riscv64")]
3938cd80ea3SRuoqing He             impl StandardRegisters {
3948cd80ea3SRuoqing He                 pub fn method_name(&self) -> u64 {
3958cd80ea3SRuoqing He                     match self {
3968cd80ea3SRuoqing He                         #[cfg(feature = "kvm")]
3978cd80ea3SRuoqing He                         StandardRegisters::Kvm(s) => s.regs.$reg_name,
3988cd80ea3SRuoqing He                     }
3998cd80ea3SRuoqing He                 }
4008cd80ea3SRuoqing He             }
4018cd80ea3SRuoqing He         });
4028cd80ea3SRuoqing He     }
4038cd80ea3SRuoqing He }
4048cd80ea3SRuoqing He 
4058cd80ea3SRuoqing He set_riscv64_reg!(pc);
4068cd80ea3SRuoqing He set_riscv64_reg!(ra);
4078cd80ea3SRuoqing He set_riscv64_reg!(sp);
4088cd80ea3SRuoqing He set_riscv64_reg!(gp);
4098cd80ea3SRuoqing He set_riscv64_reg!(tp);
4108cd80ea3SRuoqing He set_riscv64_reg!(t0);
4118cd80ea3SRuoqing He set_riscv64_reg!(t1);
4128cd80ea3SRuoqing He set_riscv64_reg!(t2);
4138cd80ea3SRuoqing He set_riscv64_reg!(s0);
4148cd80ea3SRuoqing He set_riscv64_reg!(s1);
4158cd80ea3SRuoqing He set_riscv64_reg!(a0);
4168cd80ea3SRuoqing He set_riscv64_reg!(a1);
4178cd80ea3SRuoqing He set_riscv64_reg!(a2);
4188cd80ea3SRuoqing He set_riscv64_reg!(a3);
4198cd80ea3SRuoqing He set_riscv64_reg!(a4);
4208cd80ea3SRuoqing He set_riscv64_reg!(a5);
4218cd80ea3SRuoqing He set_riscv64_reg!(a6);
4228cd80ea3SRuoqing He set_riscv64_reg!(a7);
4238cd80ea3SRuoqing He set_riscv64_reg!(s2);
4248cd80ea3SRuoqing He set_riscv64_reg!(s3);
4258cd80ea3SRuoqing He set_riscv64_reg!(s4);
4268cd80ea3SRuoqing He set_riscv64_reg!(s5);
4278cd80ea3SRuoqing He set_riscv64_reg!(s6);
4288cd80ea3SRuoqing He set_riscv64_reg!(s7);
4298cd80ea3SRuoqing He set_riscv64_reg!(s8);
4308cd80ea3SRuoqing He set_riscv64_reg!(s9);
4318cd80ea3SRuoqing He set_riscv64_reg!(s10);
4328cd80ea3SRuoqing He set_riscv64_reg!(s11);
4338cd80ea3SRuoqing He set_riscv64_reg!(t3);
4348cd80ea3SRuoqing He set_riscv64_reg!(t4);
4358cd80ea3SRuoqing He set_riscv64_reg!(t5);
4368cd80ea3SRuoqing He set_riscv64_reg!(t6);
4378cd80ea3SRuoqing He set_riscv64_reg!(mode);
4388cd80ea3SRuoqing He 
4398cd80ea3SRuoqing He get_riscv64_reg!(pc);
4408cd80ea3SRuoqing He get_riscv64_reg!(ra);
4418cd80ea3SRuoqing He get_riscv64_reg!(sp);
4428cd80ea3SRuoqing He get_riscv64_reg!(gp);
4438cd80ea3SRuoqing He get_riscv64_reg!(tp);
4448cd80ea3SRuoqing He get_riscv64_reg!(t0);
4458cd80ea3SRuoqing He get_riscv64_reg!(t1);
4468cd80ea3SRuoqing He get_riscv64_reg!(t2);
4478cd80ea3SRuoqing He get_riscv64_reg!(s0);
4488cd80ea3SRuoqing He get_riscv64_reg!(s1);
4498cd80ea3SRuoqing He get_riscv64_reg!(a0);
4508cd80ea3SRuoqing He get_riscv64_reg!(a1);
4518cd80ea3SRuoqing He get_riscv64_reg!(a2);
4528cd80ea3SRuoqing He get_riscv64_reg!(a3);
4538cd80ea3SRuoqing He get_riscv64_reg!(a4);
4548cd80ea3SRuoqing He get_riscv64_reg!(a5);
4558cd80ea3SRuoqing He get_riscv64_reg!(a6);
4568cd80ea3SRuoqing He get_riscv64_reg!(a7);
4578cd80ea3SRuoqing He get_riscv64_reg!(s2);
4588cd80ea3SRuoqing He get_riscv64_reg!(s3);
4598cd80ea3SRuoqing He get_riscv64_reg!(s4);
4608cd80ea3SRuoqing He get_riscv64_reg!(s5);
4618cd80ea3SRuoqing He get_riscv64_reg!(s6);
4628cd80ea3SRuoqing He get_riscv64_reg!(s7);
4638cd80ea3SRuoqing He get_riscv64_reg!(s8);
4648cd80ea3SRuoqing He get_riscv64_reg!(s9);
4658cd80ea3SRuoqing He get_riscv64_reg!(s10);
4668cd80ea3SRuoqing He get_riscv64_reg!(s11);
4678cd80ea3SRuoqing He get_riscv64_reg!(t3);
4688cd80ea3SRuoqing He get_riscv64_reg!(t4);
4698cd80ea3SRuoqing He get_riscv64_reg!(t5);
4708cd80ea3SRuoqing He get_riscv64_reg!(t6);
4718cd80ea3SRuoqing He get_riscv64_reg!(mode);
472