mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
@@ -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))),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user