xref: /cloud-hypervisor/hypervisor/src/vm.rs (revision cfa758fbb113c77fb65ed41cec48a60efbbd0ca1)
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 #[cfg(target_arch = "aarch64")]
12 use crate::aarch64::VcpuInit;
13 use crate::cpu::Vcpu;
14 #[cfg(target_arch = "x86_64")]
15 use crate::ClockData;
16 use crate::{CreateDevice, DeviceFd, IoEventAddress, IrqRouting, MemoryRegion};
17 use std::sync::Arc;
18 use thiserror::Error;
19 use vmm_sys_util::eventfd::EventFd;
20 
21 ///
22 /// I/O events data matches (32 or 64 bits).
23 ///
24 pub enum DataMatch {
25     DataMatch32(u32),
26     DataMatch64(u64),
27 }
28 
29 impl Into<u64> for DataMatch {
30     fn into(self) -> u64 {
31         match self {
32             DataMatch::DataMatch32(dm) => dm.into(),
33             DataMatch::DataMatch64(dm) => dm,
34         }
35     }
36 }
37 
38 #[derive(Error, Debug)]
39 ///
40 /// Enum for VM error
41 pub enum HypervisorVmError {
42     ///
43     /// Create Vcpu error
44     ///
45     #[error("Failed to create Vcpu: {0}")]
46     CreateVcpu(#[source] anyhow::Error),
47     ///
48     /// TSS address error
49     ///
50     #[error("Failed to set TSS address: {0}")]
51     SetTssAddress(#[source] anyhow::Error),
52     ///
53     /// Create interrupt controller error
54     ///
55     #[error("Failed to create interrupt controller: {0}")]
56     CreateIrq(#[source] anyhow::Error),
57     ///
58     /// Register interrupt event error
59     ///
60     #[error("Failed to register interrupt event: {0}")]
61     RegisterIrqFd(#[source] anyhow::Error),
62     ///
63     /// Un register interrupt event error
64     ///
65     #[error("Failed to unregister interrupt event: {0}")]
66     UnregisterIrqFd(#[source] anyhow::Error),
67     ///
68     /// Register IO event error
69     ///
70     #[error("Failed to register IO event: {0}")]
71     RegisterIoEvent(#[source] anyhow::Error),
72     ///
73     /// Unregister IO event error
74     ///
75     #[error("Failed to unregister IO event: {0}")]
76     UnregisterIoEvent(#[source] anyhow::Error),
77     ///
78     /// Set GSI routing error
79     ///
80     #[error("Failed to set GSI routing: {0}")]
81     SetGsiRouting(#[source] anyhow::Error),
82     ///
83     /// Set user memory error
84     ///
85     #[error("Failed to set user memory: {0}")]
86     SetUserMemory(#[source] anyhow::Error),
87     ///
88     /// Create device error
89     ///
90     #[error("Failed to set GSI routing: {0}")]
91     CreateDevice(#[source] anyhow::Error),
92     ///
93     /// Get preferred target error
94     ///
95     #[error("Failed to get preferred target: {0}")]
96     GetPreferredTarget(#[source] anyhow::Error),
97     ///
98     /// Enable split Irq error
99     ///
100     #[error("Failed to enable split Irq: {0}")]
101     EnableSplitIrq(#[source] anyhow::Error),
102     ///
103     /// Get clock error
104     ///
105     #[error("Failed to get clock: {0}")]
106     GetClock(#[source] anyhow::Error),
107     ///
108     /// Set clock error
109     ///
110     #[error("Failed to set clock: {0}")]
111     SetClock(#[source] anyhow::Error),
112 }
113 ///
114 /// Result type for returning from a function
115 ///
116 pub type Result<T> = std::result::Result<T, HypervisorVmError>;
117 
118 ///
119 /// Trait to represent a Vm
120 ///
121 /// This crate provides a hypervisor-agnostic interfaces for Vm
122 ///
123 pub trait Vm: Send + Sync {
124     #[cfg(target_arch = "x86_64")]
125     /// Sets the address of the three-page region in the VM's address space.
126     fn set_tss_address(&self, offset: usize) -> Result<()>;
127     /// Creates an in-kernel interrupt controller.
128     fn create_irq_chip(&self) -> Result<()>;
129     /// Registers an event that will, when signaled, trigger the `gsi` IRQ.
130     fn register_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>;
131     /// Unregister an event that will, when signaled, trigger the `gsi` IRQ.
132     fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>;
133     /// Creates a new KVM vCPU file descriptor and maps the memory corresponding
134     fn create_vcpu(&self, id: u8) -> Result<Arc<dyn Vcpu>>;
135     /// Registers an event to be signaled whenever a certain address is written to.
136     fn register_ioevent(
137         &self,
138         fd: &EventFd,
139         addr: &IoEventAddress,
140         datamatch: Option<DataMatch>,
141     ) -> Result<()>;
142     /// Unregister an event from a certain address it has been previously registered to.
143     fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>;
144     /// Sets the GSI routing table entries, overwriting any previously set
145     fn set_gsi_routing(&self, irq_routing: &IrqRouting) -> Result<()>;
146     /// Creates a memory region structure that can be used with set_user_memory_region
147     fn make_user_memory_region(
148         &self,
149         slot: u32,
150         guest_phys_addr: u64,
151         memory_size: u64,
152         userspace_addr: u64,
153         readonly: bool,
154     ) -> MemoryRegion;
155     /// Creates/modifies a guest physical memory slot.
156     fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>;
157     /// Creates an emulated device in the kernel.
158     fn create_device(&self, device: &mut CreateDevice) -> Result<DeviceFd>;
159     /// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
160     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
161     fn get_preferred_target(&self, kvi: &mut VcpuInit) -> Result<()>;
162     /// Enable split Irq capability
163     #[cfg(target_arch = "x86_64")]
164     fn enable_split_irq(&self) -> Result<()>;
165     /// Retrieve guest clock.
166     #[cfg(target_arch = "x86_64")]
167     fn get_clock(&self) -> Result<ClockData>;
168     /// Set guest clock.
169     #[cfg(target_arch = "x86_64")]
170     fn set_clock(&self, data: &ClockData) -> Result<()>;
171 }
172