VirtualBox

Opened 13 months ago

Last modified 12 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):

  1. Create a 1G file, e.g.: head -c 1G < /dev/zero | LANG=C tr "\000" "\377" > t1
  2. Playing a video(repeat mode)
  3. In terminal, run 3 backgound processes to copy t1 to t2/t2/t3.
  4. 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)

ub.vbox (3.0 KB ) - added by Yadong 13 months ago.

Download all attachments as: .zip

Change History (3)

by Yadong, 13 months ago

Attachment: ub.vbox added

comment:1 by Yadong, 13 months ago

After some debugging, I found this issue might related to audio controller. I have tried "Intel HD Audio" and "ICH AC97":

  • Intel HD Audio -- issue reproduced
  • ICH AC97 -- issue NOT reproduced

And I found the GPA the vbox log:

HDA: DP base (lower) set: 0x000000000c6fb000

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...

comment:2 by Yadong, 12 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:

  1. in snd_hdac_bus_init_chip(): write both DPLBASE(DISABLE) and DPUBASE
  2. 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));
Note: See TracTickets for help on using tickets.

© 2023 Oracle
ContactPrivacy policyTerms of Use