Alioth Code Coverage

vm.rs0.00%

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::cmp;
16use std::collections::HashMap;
17use std::io::ErrorKind;
18use std::os::fd::{AsFd, BorrowedFd};
19use std::ptr::null_mut;
20use std::sync::Arc;
21use std::thread::JoinHandle;
22
23use parking_lot::Mutex;
24use snafu::ResultExt;
25
26use crate::arch::reg::MpidrEl1;
27use crate::hv::hvf::vcpu::{HvfVcpu, VcpuHandle};
28use crate::hv::hvf::{OsObject, check_ret};
29use crate::hv::{
30 GicV2, GicV2m, GicV3, IoeventFd, IoeventFdRegistry, IrqFd, IrqSender, Its, MemMapOption,
31 MsiSender, Result, Vm, VmMemory, error,
32};
33use crate::sys::hvf::{
34 HvMemoryFlag, hv_gic_config_create, hv_gic_config_set_distributor_base,
35 hv_gic_config_set_msi_interrupt_range, hv_gic_config_set_msi_region_base,
36 hv_gic_config_set_redistributor_base, hv_gic_create, hv_gic_get_spi_interrupt_range,
37 hv_gic_send_msi, hv_gic_set_spi, hv_vcpus_exit, hv_vm_create, hv_vm_destroy, hv_vm_map,
38 hv_vm_unmap,
39};
40
41#[derive(Debug)]
42pub struct HvfMemory;
43
44impl VmMemory for HvfMemory {
45 fn deregister_encrypted_range(&self, _range: &[u8]) -> Result<()> {
46 Err(ErrorKind::Unsupported.into()).context(error::MemEncrypt)
47 }
48
49 fn mem_map(&self, gpa: u64, size: u64, hva: usize, option: MemMapOption) -> Result<()> {
50 if option.log_dirty {
51 return error::Capability { cap: "log dirty" }.fail();
52 }
53 let mut flags = HvMemoryFlag::empty();
54 if option.read {
55 flags |= HvMemoryFlag::READ;
56 }
57 if option.write {
58 flags |= HvMemoryFlag::WRITE;
59 }
60 if option.exec {
61 flags |= HvMemoryFlag::EXEC;
62 }
63 let ret = unsafe { hv_vm_map(hva as *const u8, gpa, size as usize, flags) };
64 check_ret(ret).context(error::GuestMap { hva, gpa, size })
65 }
66
67 fn register_encrypted_range(&self, _range: &[u8]) -> Result<()> {
68 Err(ErrorKind::Unsupported.into()).context(error::MemEncrypt)
69 }
70
71 fn unmap(&self, gpa: u64, size: u64) -> Result<()> {
72 let ret = unsafe { hv_vm_unmap(gpa, size as usize) };
73 check_ret(ret).context(error::GuestUnmap { gpa, size })?;
74 Ok(())
75 }
76
77 fn mark_private_memory(&self, _gpa: u64, _size: u64, _private: bool) -> Result<()> {
78 Err(ErrorKind::Unsupported.into()).context(error::MemEncrypt)
79 }
80
81 fn reset(&self) -> Result<()> {
82 Ok(())
83 }
84}
85
86#[derive(Debug)]
87pub struct HvfIrqSender {
88 spi: u32,
89}
90
91impl IrqSender for HvfIrqSender {
92 fn send(&self) -> Result<()> {
93 let ret = unsafe { hv_gic_set_spi(self.spi, true) };
94 check_ret(ret).context(error::SendInterrupt)
95 }
96}
97
98#[derive(Debug)]
99pub struct HvfIrqFd {}
100impl AsFd for HvfIrqFd {
101 fn as_fd(&self) -> BorrowedFd<'_> {
102 unimplemented!()
103 }
104}
105impl IrqFd for HvfIrqFd {
106 fn get_addr_hi(&self) -> u32 {
107 unimplemented!()
108 }
109
110 fn get_addr_lo(&self) -> u32 {
111 unimplemented!()
112 }
113
114 fn get_data(&self) -> u32 {
115 unimplemented!()
116 }
117
118 fn get_masked(&self) -> bool {
119 unimplemented!()
120 }
121
122 fn set_addr_hi(&self, _val: u32) -> Result<()> {
123 unimplemented!()
124 }
125
126 fn set_addr_lo(&self, _val: u32) -> Result<()> {
127 unimplemented!()
128 }
129
130 fn set_data(&self, _val: u32) -> Result<()> {
131 unimplemented!()
132 }
133
134 fn set_masked(&self, _val: bool) -> Result<bool> {
135 unimplemented!()
136 }
137}
138
139#[derive(Debug)]
140pub struct HvfMsiSender;
141
142impl MsiSender for HvfMsiSender {
143 type IrqFd = HvfIrqFd;
144
145 fn create_irqfd(&self) -> Result<Self::IrqFd> {
146 unimplemented!()
147 }
148
149 fn send(&self, addr: u64, data: u32) -> Result<()> {
150 let ret = unsafe { hv_gic_send_msi(addr, data) };
151 check_ret(ret).context(error::SendInterrupt)
152 }
153}
154
155#[derive(Debug)]
156pub struct HvfIoeventFd {}
157
158impl IoeventFd for HvfIoeventFd {}
159
160impl AsFd for HvfIoeventFd {
161 fn as_fd(&self) -> BorrowedFd<'_> {
162 unreachable!()
163 }
164}
165
166#[derive(Debug)]
167pub struct HvfIoeventFdRegistry;
168
169impl IoeventFdRegistry for HvfIoeventFdRegistry {
170 type IoeventFd = HvfIoeventFd;
171
172 fn create(&self) -> Result<Self::IoeventFd> {
173 Err(ErrorKind::Unsupported.into()).context(error::IoeventFd)
174 }
175
176 fn deregister(&self, _fd: &Self::IoeventFd) -> Result<()> {
177 unreachable!()
178 }
179
180 fn register(
181 &self,
182 _fd: &Self::IoeventFd,
183 _gpa: u64,
184 _len: u8,
185 _data: Option<u64>,
186 ) -> Result<()> {
187 unreachable!()
188 }
189}
190
191#[derive(Debug)]
192pub struct HvfGicV2;
193
194impl GicV2 for HvfGicV2 {
195 fn init(&self) -> Result<()> {
196 unreachable!()
197 }
198
199 fn get_dist_reg(&self, _cpu_index: u32, _offset: u16) -> Result<u32> {
200 unreachable!()
201 }
202
203 fn set_dist_reg(&self, _cpu_index: u32, _offset: u16, _val: u32) -> Result<()> {
204 unreachable!()
205 }
206
207 fn get_cpu_reg(&self, _cpu_index: u32, _offset: u16) -> Result<u32> {
208 unreachable!()
209 }
210
211 fn set_cpu_reg(&self, _cpu_index: u32, _offset: u16, _val: u32) -> Result<()> {
212 unreachable!()
213 }
214
215 fn get_num_irqs(&self) -> Result<u32> {
216 unreachable!()
217 }
218
219 fn set_num_irqs(&self, _val: u32) -> Result<()> {
220 unreachable!()
221 }
222}
223
224#[derive(Debug)]
225pub struct HvfGicV3;
226
227impl GicV3 for HvfGicV3 {
228 fn init(&self) -> Result<()> {
229 Ok(())
230 }
231}
232
233#[derive(Debug)]
234pub struct HvfGicV2m;
235
236impl GicV2m for HvfGicV2m {
237 fn init(&self) -> Result<()> {
238 Ok(())
239 }
240}
241
242#[derive(Debug)]
243pub struct HvfIts;
244
245impl Its for HvfIts {
246 fn init(&self) -> Result<()> {
247 unreachable!()
248 }
249}
250
251#[derive(Debug)]
252pub enum VcpuEvent {
253 PowerOn { pc: u64, context: u64 },
254 Interrupt,
255}
256
257#[derive(Debug)]
258pub struct HvfVm {
259 gic_config: Mutex<(OsObject, bool)>,
260 pub vcpus: Arc<Mutex<HashMap<MpidrEl1, Arc<VcpuHandle>>>>,
261}
262
263impl HvfVm {
264 pub fn new() -> Result<Self> {
265 let ret = unsafe { hv_vm_create(null_mut()) };
266 check_ret(ret).context(error::CreateVm)?;
267 Ok(HvfVm {
268 gic_config: Mutex::new((OsObject { addr: 0 }, false)),
269 vcpus: Arc::new(Mutex::new(HashMap::new())),
270 })
271 }
272}
273
274impl Drop for HvfVm {
275 fn drop(&mut self) {
276 let ret = unsafe { hv_vm_destroy() };
277 if let Err(e) = check_ret(ret) {
278 log::error!("hv_vm_destroy: {e:?}");
279 }
280 }
281}
282
283impl Vm for HvfVm {
284 type GicV2 = HvfGicV2;
285 type GicV2m = HvfGicV2m;
286 type GicV3 = HvfGicV3;
287 type IoeventFdRegistry = HvfIoeventFdRegistry;
288 type IrqSender = HvfIrqSender;
289 type Its = HvfIts;
290 type Memory = HvfMemory;
291 type MsiSender = HvfMsiSender;
292 type Vcpu = HvfVcpu;
293
294 fn create_ioeventfd_registry(&self) -> Result<Self::IoeventFdRegistry> {
295 Ok(HvfIoeventFdRegistry)
296 }
297
298 fn create_msi_sender(&self, _devid: u32) -> Result<Self::MsiSender> {
299 Ok(HvfMsiSender)
300 }
301
302 fn create_vcpu(&self, index: u16, identity: u64) -> Result<Self::Vcpu> {
303 let (config, created) = &mut *self.gic_config.lock();
304 if config.addr != 0 && !*created {
305 let ret = unsafe { hv_gic_create(config.addr as *mut _) };
306 check_ret(ret).context(error::CreateDevice)?;
307 *created = true;
308 }
309
310 HvfVcpu::new(self, index, identity)
311 }
312
313 fn create_vm_memory(&mut self) -> Result<Self::Memory> {
314 Ok(HvfMemory)
315 }
316
317 fn stop_vcpu<T>(&self, identity: u64, _handle: &JoinHandle<T>) -> Result<()> {
318 let mpidr = MpidrEl1(identity);
319
320 let vcpus = self.vcpus.lock();
321 let Some(vcpu) = vcpus.get(&mpidr) else {
322 return Err(ErrorKind::NotFound.into()).context(error::StopVcpu);
323 };
324
325 vcpu.sender.send(VcpuEvent::Interrupt)?;
326 let ret = unsafe { hv_vcpus_exit(&vcpu.vcpu_id, 1) };
327 check_ret(ret).context(error::StopVcpu)
328 }
329
330 fn create_gic_v2(
331 &self,
332 _distributor_base: u64,
333 _cpu_interface_base: u64,
334 ) -> Result<Self::GicV2> {
335 Err(ErrorKind::Unsupported.into()).context(error::CreateDevice)
336 }
337
338 fn create_irq_sender(&self, pin: u8) -> Result<Self::IrqSender> {
339 let mut spi_base = 0;
340 let mut count = 0;
341 let ret = unsafe { hv_gic_get_spi_interrupt_range(&mut spi_base, &mut count) };
342 check_ret(ret).context(error::CreateDevice)?;
343 Ok(HvfIrqSender {
344 spi: spi_base + pin as u32,
345 })
346 }
347
348 fn create_gic_v3(
349 &self,
350 distributor_base: u64,
351 redistributor_base: u64,
352 _redistributor_count: u16,
353 ) -> Result<Self::GicV3> {
354 let (config, _) = &mut *self.gic_config.lock();
355 if config.addr == 0 {
356 *config = OsObject {
357 addr: unsafe { hv_gic_config_create() } as usize,
358 };
359 }
360 let ptr = config.addr as *mut _;
361 let ret = unsafe { hv_gic_config_set_distributor_base(ptr, distributor_base) };
362 check_ret(ret).context(error::CreateDevice)?;
363 let ret = unsafe { hv_gic_config_set_redistributor_base(ptr, redistributor_base) };
364 check_ret(ret).context(error::CreateDevice)?;
365
366 Ok(HvfGicV3)
367 }
368
369 fn create_gic_v2m(&self, base: u64) -> Result<Self::GicV2m> {
370 let (config, _) = &mut *self.gic_config.lock();
371 if config.addr == 0 {
372 *config = OsObject {
373 addr: unsafe { hv_gic_config_create() } as usize,
374 };
375 }
376
377 let ptr = config.addr as *mut _;
378 let ret = unsafe { hv_gic_config_set_msi_region_base(ptr, base) };
379 check_ret(ret).context(error::CreateDevice)?;
380
381 let mut spi_base = 0;
382 let mut count = 0;
383 let ret = unsafe { hv_gic_get_spi_interrupt_range(&mut spi_base, &mut count) };
384 check_ret(ret).context(error::CreateDevice)?;
385 let count = cmp::min(count, 987);
386 let ret = unsafe { hv_gic_config_set_msi_interrupt_range(ptr, spi_base + 32, count - 32) };
387 check_ret(ret).context(error::CreateDevice)?;
388
389 Ok(HvfGicV2m)
390 }
391
392 fn create_its(&self, _base: u64) -> Result<Self::Its> {
393 Err(ErrorKind::Unsupported.into()).context(error::CreateDevice)
394 }
395}
396