vmexit.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 crate::hv::kvm::vcpu::KvmVcpu;16
use crate::hv::{Error, VmExit, error};17
#[cfg(target_arch = "x86_64")]18
use crate::sys::kvm::KvmExitIo;19
use crate::sys::kvm::{KvmHypercall, KvmMapGpaRangeFlag, KvmMemoryFaultFlag, KvmSystemEvent};20
21
impl KvmVcpu {22
#[cfg(target_endian = "little")]23
pub(super) fn handle_mmio(&mut self) -> Result<VmExit, Error> {24
let kvm_mmio = unsafe { &self.kvm_run.exit.mmio };25
let data = u64::from_ne_bytes(kvm_mmio.data) & u64::MAX >> (64 - (kvm_mmio.len << 3));26
let exit = VmExit::Mmio {27
addr: kvm_mmio.phys_addr,28
write: if kvm_mmio.is_write > 0 {29
Some(data)30
} else {31
None32
},33
size: kvm_mmio.len as u8,34
};35
Ok(exit)36
}37
38
#[cfg(target_arch = "x86_64")]39
pub(super) fn handle_io(&mut self) -> VmExit {40
let kvm_io = unsafe { self.kvm_run.exit.io };41
let offset = kvm_io.data_offset as usize;42
let count = kvm_io.count as usize;43
let index = self.arch.io_index;44
let write = if kvm_io.direction == KvmExitIo::IN {45
None46
} else {47
let data = match kvm_io.size {48
1 => unsafe { self.kvm_run.data_slice::<u8>(offset, count)[index] as u32 },49
2 => unsafe { self.kvm_run.data_slice::<u16>(offset, count)[index] as u32 },50
4 => unsafe { self.kvm_run.data_slice::<u32>(offset, count)[index] },51
_ => unreachable!("kvm_io.size = {}", kvm_io.size),52
};53
Some(data)54
};55
VmExit::Io {56
port: kvm_io.port,57
write,58
size: kvm_io.size,59
}60
}61
62
pub(super) fn handle_hypercall(&mut self) -> Result<VmExit, Error> {63
let hypercall = unsafe { self.kvm_run.exit.hypercall };64
match hypercall.nr {65
KvmHypercall::MAP_GPA_RANGE => {66
let flag = KvmMapGpaRangeFlag::from_bits_retain(hypercall.args[2]);67
Ok(VmExit::ConvertMemory {68
gpa: hypercall.args[0],69
size: hypercall.args[1] << 12,70
private: flag.contains(KvmMapGpaRangeFlag::ENCRYPTED),71
})72
}73
_ => unimplemented!(),74
}75
}76
77
pub(super) fn handle_system_event(&mut self) -> Result<VmExit, Error> {78
let kvm_system_event = unsafe { &self.kvm_run.exit.system_event };79
match kvm_system_event.type_ {80
KvmSystemEvent::SHUTDOWN => Ok(VmExit::Shutdown),81
KvmSystemEvent::RESET => Ok(VmExit::Reboot),82
_ => error::VmExit {83
msg: format!("{kvm_system_event:#x?}"),84
}85
.fail(),86
}87
}88
89
pub(crate) fn handle_memory_fault(&mut self) -> VmExit {90
let memory_fault = unsafe { &self.kvm_run.exit.memory_fault };91
let private = memory_fault.flags.contains(KvmMemoryFaultFlag::PRIVATE);92
VmExit::ConvertMemory {93
gpa: memory_fault.gpa,94
size: memory_fault.size,95
private,96
}97
}98
}99