mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
hypervisor: mshv: Validate GPA mapping with GvaGpaValid flag
The GvaGpaValid flag in the intercept message indicates whether the provided GPA corresponds to the decoded GVA. Without checking this flag, the emulator may incorrectly use a stale GPA mapping when the hypervisor invalidates it. Add a check for the GvaGpaValid flag before using the cached (GVA, GPA) mapping. If the flag is clear, use a sentinel value to force translate() to perform a proper hypercall-based translation instead of using an invalid cached mapping. Signed-off-by: Pedro Barbuda <pbarbuda@microsoft.com> Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
@@ -720,11 +720,28 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
let gva = info.guest_virtual_address;
|
||||
let gpa = info.guest_physical_address;
|
||||
|
||||
debug!("Exit ({msg_type:?}) GVA {gva:x} GPA {gpa:x}");
|
||||
// The GvaGpaValid flag indicates that the GPA in the intercept
|
||||
// message corresponds to the GVA in the message. If that flag
|
||||
// is set, and the GVA in the message matches the GVA in the decoded
|
||||
// instruction, then the emulator can use the GPA provided by
|
||||
// the hypervisor. Otherwise, the emulator must translate the GVA
|
||||
// via a hypercall.
|
||||
// SAFETY: accessing the bitfield union variant.
|
||||
let gva_gpa_valid =
|
||||
unsafe { info.memory_access_info.__bindgen_anon_1.gva_gpa_valid() != 0 };
|
||||
|
||||
debug!(
|
||||
"Exit ({msg_type:?}) GVA {gva:x} GPA {gpa:x} \
|
||||
gva_gpa_valid={gva_gpa_valid}"
|
||||
);
|
||||
|
||||
let mut context = MshvEmulatorContext {
|
||||
vcpu: self,
|
||||
map: (gva, gpa),
|
||||
map: if gva_gpa_valid {
|
||||
(gva, gpa)
|
||||
} else {
|
||||
(u64::MAX, 0)
|
||||
},
|
||||
};
|
||||
|
||||
let old_state = context
|
||||
|
||||
@@ -19,7 +19,12 @@ pub struct MshvEmulatorContext<'a> {
|
||||
}
|
||||
|
||||
impl MshvEmulatorContext<'_> {
|
||||
// Do the actual gva -> gpa translation
|
||||
// Do the actual gva -> gpa translation.
|
||||
//
|
||||
// When the hypervisor sets GvaGpaValid in the intercept message, `map`
|
||||
// caches the (gva, gpa) pair as a fast path that avoids a translate
|
||||
// hypercall. When the flag is clear, `map` is set to a sentinel
|
||||
// (u64::MAX, 0) so this shortcut never fires.
|
||||
#[allow(non_upper_case_globals)]
|
||||
fn translate(&self, gva: u64, flags: u32) -> Result<u64, PlatformError> {
|
||||
if self.map.0 == gva {
|
||||
|
||||
Reference in New Issue
Block a user