VirtualBox

Changeset 107026 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Nov 18, 2024 2:21:58 PM (2 months ago)
Author:
vboxsync
Message:

VMM/NEM/ARM: Loading a 32-bit value into a register clears the upper half on real hardware, workaround for ldp instruction accessing the TPM MMIO area caused by tpm.sys in a Windows 11/ARM guest, bugref:10777

Location:
trunk/src/VBox/VMM/VMMR3
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin-armv8.cpp

    r106761 r107026  
    15661566        pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val;
    15671567    else
    1568         pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */
     1568        pVCpu->cpum.GstCtx.aGRegs[uReg].x = (uint64_t)(fSignExtend ? (int32_t)u64Val : (uint32_t)u64Val);
    15691569
    15701570    /* Mark the register as not extern anymore. */
     
    17461746                        /* Update the indexed register. */
    17471747                        pVCpu->cpum.GstCtx.aGRegs[Dis.aParams[1].armv8.Op.Reg.idReg].x += Dis.aParams[1].armv8.u.offBase;
     1748                    }
     1749                }
     1750                /*
     1751                 * Seeing the following with the Windows 11/ARM TPM driver:
     1752                 *     %fffff800e5342888 48 25 45 29             ldp w8, w9, [x10, #+0x0028]
     1753                 */
     1754                else if (   Dis.pCurInstr->uOpcode == OP_ARMV8_A64_LDP
     1755                         && Dis.aParams[0].armv8.enmType == kDisArmv8OpParmReg
     1756                         && Dis.aParams[0].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_32Bit
     1757                         && Dis.aParams[1].armv8.enmType == kDisArmv8OpParmReg
     1758                         && Dis.aParams[1].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_32Bit
     1759                         && Dis.aParams[2].armv8.enmType == kDisArmv8OpParmAddrInGpr
     1760                         && Dis.aParams[2].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_64Bit)
     1761                {
     1762                    /** @todo This is tricky to handle if the first register read returns something else than VINF_SUCCESS... */
     1763                    /* The fault address is already the final address. */
     1764                    uint32_t u32Val1 = 0;
     1765                    uint32_t u32Val2 = 0;
     1766                    rcStrict = PGMPhysRead(pVM, GCPhysDataAbrt, &u32Val1, sizeof(u32Val1), PGMACCESSORIGIN_HM);
     1767                    if (rcStrict == VINF_SUCCESS)
     1768                        rcStrict = PGMPhysRead(pVM, GCPhysDataAbrt + sizeof(uint32_t), &u32Val2, sizeof(u32Val2), PGMACCESSORIGIN_HM);
     1769                    Log4(("MmioExit/%u: %08RX64: READ %#RGp LB %u -> %.*Rhxs %.*Rhxs rcStrict=%Rrc\n",
     1770                          pVCpu->idCpu, pVCpu->cpum.GstCtx.Pc.u64, GCPhysDataAbrt, 2 * sizeof(uint32_t), sizeof(u32Val1),
     1771                          &u32Val1, sizeof(u32Val2), &u32Val2, VBOXSTRICTRC_VAL(rcStrict) ));
     1772                    if (rcStrict == VINF_SUCCESS)
     1773                    {
     1774                        nemR3DarwinSetGReg(pVCpu, Dis.aParams[0].armv8.Op.Reg.idReg, false /*f64BitReg*/, false /*fSignExtend*/, u32Val1);
     1775                        nemR3DarwinSetGReg(pVCpu, Dis.aParams[1].armv8.Op.Reg.idReg, false /*f64BitReg*/, false /*fSignExtend*/, u32Val2);
    17481776                    }
    17491777                }
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-linux-armv8.cpp

    r104729 r107026  
    555555        pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val;
    556556    else
    557         pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */
     557        pVCpu->cpum.GstCtx.aGRegs[uReg].x = (uint64_t)(fSignExtend ? (int32_t)u64Val : (uint32_t)u64Val);
    558558
    559559    /* Mark the register as not extern anymore. */
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win-armv8.cpp

    r106996 r107026  
    20512051        pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val;
    20522052    else
    2053         pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */
     2053        pVCpu->cpum.GstCtx.aGRegs[uReg].x = (uint64_t)(fSignExtend ? (int32_t)u64Val : (uint32_t)u64Val);
    20542054
    20552055    /* Mark the register as not extern anymore. */
     
    22572257                        /* Update the indexed register. */
    22582258                        pVCpu->cpum.GstCtx.aGRegs[Dis.aParams[1].armv8.Op.Reg.idReg].x += Dis.aParams[1].armv8.u.offBase;
     2259                    }
     2260                }
     2261                /*
     2262                 * Seeing the following with the Windows 11/ARM TPM driver:
     2263                 *     %fffff800e5342888 48 25 45 29             ldp w8, w9, [x10, #+0x0028]
     2264                 */
     2265                else if (   Dis.pCurInstr->uOpcode == OP_ARMV8_A64_LDP
     2266                         && Dis.aParams[0].armv8.enmType == kDisArmv8OpParmReg
     2267                         && Dis.aParams[0].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_32Bit
     2268                         && Dis.aParams[1].armv8.enmType == kDisArmv8OpParmReg
     2269                         && Dis.aParams[1].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_32Bit
     2270                         && Dis.aParams[2].armv8.enmType == kDisArmv8OpParmAddrInGpr
     2271                         && Dis.aParams[2].armv8.Op.Reg.enmRegType == kDisOpParamArmV8RegType_Gpr_64Bit)
     2272                {
     2273                    /** @todo This is tricky to handle if the first register read returns something else than VINF_SUCCESS... */
     2274                    /* The fault address is already the final address. */
     2275                    uint32_t u32Val1 = 0;
     2276                    uint32_t u32Val2 = 0;
     2277                    rcStrict = PGMPhysRead(pVM, GCPhysDataAbrt, &u32Val1, sizeof(u32Val1), PGMACCESSORIGIN_HM);
     2278                    if (rcStrict == VINF_SUCCESS)
     2279                        rcStrict = PGMPhysRead(pVM, GCPhysDataAbrt + sizeof(uint32_t), &u32Val2, sizeof(u32Val2), PGMACCESSORIGIN_HM);
     2280                    Log4(("MmioExit/%u: %08RX64: READ %#RGp LB %u -> %.*Rhxs %.*Rhxs rcStrict=%Rrc\n",
     2281                          pVCpu->idCpu, pVCpu->cpum.GstCtx.Pc.u64, GCPhysDataAbrt, 2 * sizeof(uint32_t), sizeof(u32Val1),
     2282                          &u32Val1, sizeof(u32Val2), &u32Val2, VBOXSTRICTRC_VAL(rcStrict) ));
     2283                    if (rcStrict == VINF_SUCCESS)
     2284                    {
     2285                        nemR3WinSetGReg(pVCpu, Dis.aParams[0].armv8.Op.Reg.idReg, false /*f64BitReg*/, false /*fSignExtend*/, u32Val1);
     2286                        nemR3WinSetGReg(pVCpu, Dis.aParams[1].armv8.Op.Reg.idReg, false /*f64BitReg*/, false /*fSignExtend*/, u32Val2);
    22592287                    }
    22602288                }
Note: See TracChangeset for help on using the changeset viewer.

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