vm.rs0.00%
1
// Copyright 2024 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::cmp;16
use std::collections::HashMap;17
use std::io::ErrorKind;18
use std::os::fd::{AsFd, BorrowedFd};19
use std::ptr::null_mut;20
use std::sync::Arc;21
use std::thread::JoinHandle;22
23
use parking_lot::Mutex;24
use snafu::ResultExt;25
26
use crate::arch::reg::MpidrEl1;27
use crate::hv::hvf::vcpu::{HvfVcpu, VcpuHandle};28
use crate::hv::hvf::{OsObject, check_ret};29
use crate::hv::{30
GicV2, GicV2m, GicV3, IoeventFd, IoeventFdRegistry, IrqFd, IrqSender, Its, MemMapOption,31
MsiSender, Result, Vm, VmMemory, error,32
};33
use 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)]42
pub struct HvfMemory;43
44
impl 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)]87
pub struct HvfIrqSender {88
spi: u32,89
}90
91
impl 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)]99
pub struct HvfIrqFd {}100
impl AsFd for HvfIrqFd {101
fn as_fd(&self) -> BorrowedFd<'_> {102
unimplemented!()103
}104
}105
impl 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)]140
pub struct HvfMsiSender;141
142
impl 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)]156
pub struct HvfIoeventFd {}157
158
impl IoeventFd for HvfIoeventFd {}159
160
impl AsFd for HvfIoeventFd {161
fn as_fd(&self) -> BorrowedFd<'_> {162
unreachable!()163
}164
}165
166
#[derive(Debug)]167
pub struct HvfIoeventFdRegistry;168
169
impl 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)]192
pub struct HvfGicV2;193
194
impl 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)]225
pub struct HvfGicV3;226
227
impl GicV3 for HvfGicV3 {228
fn init(&self) -> Result<()> {229
Ok(())230
}231
}232
233
#[derive(Debug)]234
pub struct HvfGicV2m;235
236
impl GicV2m for HvfGicV2m {237
fn init(&self) -> Result<()> {238
Ok(())239
}240
}241
242
#[derive(Debug)]243
pub struct HvfIts;244
245
impl Its for HvfIts {246
fn init(&self) -> Result<()> {247
unreachable!()248
}249
}250
251
#[derive(Debug)]252
pub enum VcpuEvent {253
PowerOn { pc: u64, context: u64 },254
Interrupt,255
}256
257
#[derive(Debug)]258
pub struct HvfVm {259
gic_config: Mutex<(OsObject, bool)>,260
pub vcpus: Arc<Mutex<HashMap<MpidrEl1, Arc<VcpuHandle>>>>,261
}262
263
impl 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
274
impl 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
283
impl 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