VirtualBox

Changeset 99310 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 6, 2023 6:33:11 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
156698
Message:

Audio/HDA: Additional checks for register aliasing. bugref:10349

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHda.cpp

    r98103 r99310  
    784784
    785785#ifdef IN_RING3
    786 
    787786/**
    788787 * Looks up a register covering the offset given by @a offReg.
    789788 *
    790789 * @returns Register index on success, -1 if not found.
    791  * @param   offReg              The register offset.
    792  */
    793 static int hdaR3RegLookupWithin(uint32_t offReg)
     790 * @param   offReg      The register offset.
     791 * @param   pcbBefore   Where to return the number of bytes in the matching
     792 *                      register preceeding @a offReg.
     793 */
     794static int hdaR3RegLookupWithin(uint32_t offReg, uint32_t *pcbBefore)
    794795{
    795796    /*
    796797     * Aliases.
     798     *
     799     * We ASSUME the aliases are for whole registers and that they have the
     800     * same alignment (release-asserted in the constructor), so we don't need
     801     * to calculate the within-register-offset twice here.
    797802     */
    798803    if (offReg >= g_aHdaRegAliases[0].offReg)
     
    800805        for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
    801806        {
    802             uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
    803             if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].cb)
    804                 return g_aHdaRegAliases[i].idxAlias;
     807            uint32_t const off = offReg - g_aHdaRegAliases[i].offReg;
     808            if (off < 4)  /* No register is wider than 4 bytes (release-asserted in constructor). */
     809            {
     810                const uint32_t idxAlias = g_aHdaRegAliases[i].idxAlias;
     811                if (off < g_aHdaRegMap[idxAlias].cb)
     812                {
     813                    Assert(off > 0); /* ASSUMES the caller already did a hdaRegLookup which failed. */
     814                    Assert((g_aHdaRegAliases[i].offReg & 3) == (g_aHdaRegMap[idxAlias].off & 3));
     815                    *pcbBefore = off;
     816                    return idxAlias;
     817                }
     818            }
    805819        }
    806820        Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].off < offReg);
     821        *pcbBefore = 0;
    807822        return -1;
    808823    }
     
    829844        }
    830845        else
     846        {
     847            offReg -= g_aHdaRegMap[idxMiddle].off;
     848            *pcbBefore = offReg;
     849            Assert(offReg > 0); /* ASSUMES the caller already did a hdaRegLookup which failed. */
     850            Assert(g_aHdaRegMap[idxMiddle].cb <= 4); /* This is release-asserted in the constructor. */
    831851            return idxMiddle;
     852        }
    832853    }
    833854
     
    836857        Assert(offReg - g_aHdaRegMap[i].off >= g_aHdaRegMap[i].cb);
    837858# endif
     859    *pcbBefore = 0;
    838860    return -1;
    839861}
    840 
    841862#endif /* IN_RING3 */
    842863
     
    34113432        if (idxRegDsc < 0)
    34123433        {
    3413             idxRegDsc = hdaR3RegLookupWithin(off);
     3434            uint32_t cbBefore;
     3435            idxRegDsc = hdaR3RegLookupWithin(off, &cbBefore);
    34143436            if (idxRegDsc != -1)
    34153437            {
    3416                 uint32_t const cbBefore = (uint32_t)off - g_aHdaRegMap[idxRegDsc].off;
    3417                 Assert(cbBefore > 0 && cbBefore < 4);
     3438                Assert(cbBefore > 0 && cbBefore < 4 /* no register is wider than 4 bytes, we check in the constructor */);
    34183439                off      -= cbBefore;
    34193440                idxRegMem = g_aHdaRegMap[idxRegDsc].idxReg;
     
    34723493            else
    34733494            {
     3495                /** @todo r=bird: This doesn't work for aliased registers, since the incremented
     3496                 * offset won't match as it's still the aliased one.  Only scenario, though
     3497                 * would be misaligned accesses (2, 4 or 8 bytes), and the result would be that
     3498                 * only the first part will be written.  Given that the aliases we have are lone
     3499                 * registers, that seems like they shouldn't have anything else around them,
     3500                 * this is probably the correct behaviour, though real hw may of course
     3501                 * disagree.  Only look into it if we have a sane guest running into this. */
    34743502                idxRegDsc++;
    34753503                if (   (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
     
    52205248        AssertReleaseMsg(pNextReg || ((pReg->off + pReg->cb) & 3) == 0,
    52215249                         ("[%#x] = {%#x LB %#x}\n", i, pReg->off, pReg->cb));
     5250    }
     5251    for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
     5252    {
     5253        /* Valid alias index. */
     5254        uint32_t const idxAlias = g_aHdaRegAliases[i].idxAlias;
     5255        AssertReleaseMsg(g_aHdaRegAliases[i].idxAlias < (int)RT_ELEMENTS(g_aHdaRegMap), ("[%#x] idxAlias=%#x\n", i, idxAlias));
     5256        /* Same register alignment. */
     5257        AssertReleaseMsg((g_aHdaRegAliases[i].offReg & 3) == (g_aHdaRegMap[idxAlias].off & 3),
     5258                         ("[%#x] idxAlias=%#x offReg=%#x vs off=%#x\n",
     5259                          i, idxAlias, g_aHdaRegAliases[i].offReg, g_aHdaRegMap[idxAlias].off));
     5260        /* Register is four or fewer bytes wide (already checked above). */
     5261        AssertReleaseMsg(g_aHdaRegMap[idxAlias].cb <= 4, ("[%#x] idxAlias=%#x cb=%d\n", i, idxAlias, g_aHdaRegMap[idxAlias].cb));
    52225262    }
    52235263    Assert(strcmp(g_aHdaRegMap[HDA_REG_SSYNC].pszName, "SSYNC") == 0);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette