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