hypervisor: mshv: splice GVA page offset into translated GPA

On Intel MSHV the memory-intercept guest_physical_address and the
MSHV_VP_TRANSLATE_GVA ioctl both return a page-aligned GPA, while
guest_virtual_address is byte-exact. Returning the cached/translated
GPA unchanged made byte-sized MMIO land at BAR offset 0: virtio
device_status writes (BAR+0x14) hit device_feature_select, so
VIRTIO_F_VERSION_1 was never acked and virtio_blk/net/rng probes
failed with -EINVAL, leaving the guest unable to mount rootfs.

Splice gva & 0xfff into the returned GPA on both the intercept fast
path and the translate_gva fallback, and relax the cached-GVA match
to page granularity so it still hits for other byte offsets in the
same page.

This issue is reproducible on Intel machine, launching
Cloud-Hypervisor on nested scenario, using the Linux Dom0
image as the guest image to turn on nested hypervisor
into the guest.

Assisted-by: Claude:Opus-4.7
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam
2026-07-08 02:36:49 +00:00
committed by Bo Chen
parent 5b53f4202d
commit 30c0fdaff1

View File

@@ -25,10 +25,16 @@ impl MshvEmulatorContext<'_> {
// Do the actual gva -> gpa translation
#[expect(non_upper_case_globals)]
fn translate(&self, gva: u64, flags: u32) -> Result<u64, PlatformError> {
// MSHV can return a page-aligned GPA; splice gva's page offset
// in so byte-sized MMIO (e.g. virtio device_status) is precise.
let page_offset_mask = (HV_HYP_PAGE_SIZE as u64) - 1;
let page_offset = gva & page_offset_mask;
let page_base = !page_offset_mask;
if let Some((cached_gva, cached_gpa)) = self.mapping
&& cached_gva == gva
&& (cached_gva & page_base) == (gva & page_base)
{
return Ok(cached_gpa);
return Ok((cached_gpa & page_base) | page_offset);
}
let (gpa, result_code) = self
@@ -37,7 +43,9 @@ impl MshvEmulatorContext<'_> {
.map_err(|e| PlatformError::TranslateVirtualAddress(anyhow!(e)))?;
match result_code {
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => Ok(gpa),
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => {
Ok((gpa & page_base) | page_offset)
}
_ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))),
}
}