Opened 22 months ago
Last modified 21 months ago
#21625 new defect
File corrupted while copying large file and playing video in parallel
Reported by: | Yadong | Owned by: | |
---|---|---|---|
Component: | other | Version: | VirtualBox-7.0.8 |
Keywords: | Cc: | ||
Guest type: | Linux | Host type: | Windows |
Description
Setup:
- VirtualBox version 7.0.8 r156879 (Qt5.15.2) or 6.1.36 r152435
- Host: Windows 11 Pro (22H2, OS Build 22621.1555)
- Guest: Ubuntu 20.04.6 LTS (kernel: 5.15.0-69-generic #76~20.04.1-Ubuntu)
- Host processor: Intel i5-1135G7
- Host graphics: Intel Iris Xe Graphics
Observations:
- In guest OS, while playing videos and copy large files in parallel, the copied file might be corrupt.
Reproduce steps(in Guest OS):
- Create a 1G file, e.g.: head -c 1G < /dev/zero | LANG=C tr "\000" "\377" > t1
- Playing a video(repeat mode)
- In terminal, run 3 backgound processes to copy t1 to t2/t2/t3.
- After all processes done, compare file contents of t1, t2, t3, t4, simply use sha256sum will show the result.
Expected result:
- t1/t2/t3/t4 got same contents
Actual result:
- There are random corrupted bytes in t2 or t3 or t4.
Attachments (1)
Change History (3)
by , 22 months ago
comment:1 by , 22 months ago
comment:2 by , 21 months ago
Hi, Maintainers
I root caused the issue, it is caused by HDA device emulation. https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Devices/Audio/DevHda.cpp#L2354
case HDA_REG_DPLBASE: pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK; Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */ /* Also make sure to handle the DMA position enable bit. */ pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0); #ifndef IN_RING0 LogRel(("HDA: DP base (lower) set: %#RGp\n", pThis->u64DPBase)); LogRel(("HDA: DMA position buffer is %s\n", pThis->fDMAPosition ? "enabled" : "disabled")); #else return VINF_IOM_R3_MMIO_WRITE; /* (Go to ring-3 for release logging.) */ #endif break; case HDA_REG_DPUBASE: pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]); #ifndef IN_RING0 LogRel(("HDA: DP base (upper) set: %#RGp\n", pThis->u64DPBase)); #else return VINF_IOM_R3_MMIO_WRITE; /* (Go to ring-3 for release logging.) */ #endif break;
Currenly in Linux HDA driver, it follows below steps to setup DPBASE address:
- in snd_hdac_bus_init_chip(): write both DPLBASE(DISABLE) and DPUBASE
- in snd_hdac_stream_setup(): wirte only DPLBASE(ENABLE)
So in Step2, the PHDASTATE.u64DPBase will be overwritten with DPLBASE, the u64DPBase address will be incorrect if DPUBASE is not 0.
In order to not overwrite u64DPBase, my suggestion is to change
case HDA_REG_DPLBASE: pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK;
to
case HDA_REG_DPLBASE: pThis->u64DPBase = RT_MAKE_U64(pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK, RT_HI_U32(pThis->u64DPBase));
After some debugging, I found this issue might related to audio controller. I have tried "Intel HD Audio" and "ICH AC97":
And I found the GPA the vbox log:
This 0xc6fb000 might also be allocated in guest memory, so there might be some issue when set it as HDA DMA address, such like not reserved from memory pool...