VirtualBox

Changeset 48898 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Oct 4, 2013 8:01:01 PM (11 years ago)
Author:
vboxsync
Message:

VMM,DBGC: Implemented DBGFR3RegNmSet and made the debugger side work.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp

    r46155 r48898  
    19011901
    19021902
     1903/**
     1904 * On CPU worker for the register modifications, used by DBGFR3RegNmSet.
     1905 *
     1906 * @returns VBox status code.
     1907 *
     1908 * @param   pUVM                The user mode VM handle.
     1909 * @param   pLookupRec          The register lookup record. Maybe be modified,
     1910 *                              so please pass a copy of the user's one.
     1911 * @param   pValue              The new register value.
     1912 * @param   enmType             The register value type.
     1913 */
     1914static DECLCALLBACK(int) dbgfR3RegNmSetWorkerOnCpu(PUVM pUVM, PDBGFREGLOOKUP pLookupRec,
     1915                                                   PCDBGFREGVAL pValue, PCDBGFREGVAL pMask)
     1916{
     1917    PCDBGFREGSUBFIELD pSubField = pLookupRec->pSubField;
     1918    if (pSubField && pSubField->pfnSet)
     1919        return pSubField->pfnSet(pLookupRec->pSet->uUserArg.pv, pSubField, pValue->u128, pMask->u128);
     1920    return pLookupRec->pDesc->pfnSet(pLookupRec->pSet->uUserArg.pv, pLookupRec->pDesc, pValue, pMask);
     1921}
     1922
     1923
     1924/**
     1925 * Worker for the register setting.
     1926 *
     1927 * @returns VBox status code.
     1928 * @retval  VINF_SUCCESS
     1929 * @retval  VERR_INVALID_VM_HANDLE
     1930 * @retval  VERR_INVALID_CPU_ID
     1931 * @retval  VERR_DBGF_REGISTER_NOT_FOUND
     1932 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     1933 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     1934 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     1935 *
     1936 * @param   pUVM                The user mode VM handle.
     1937 * @param   idDefCpu            The virtual CPU ID for the default CPU register
     1938 *                              set.  Can be OR'ed with DBGFREG_HYPER_VMCPUID.
     1939 * @param   pszReg              The register to query.
     1940 * @param   pValue              The value to set
     1941 * @param   enmType             How to interpret the value in @a pValue.
     1942 */
    19031943VMMR3DECL(int) DBGFR3RegNmSet(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType)
    19041944{
    1905     NOREF(pUVM); NOREF(idDefCpu); NOREF(pszReg); NOREF(pValue); NOREF(enmType);
    1906     return VERR_NOT_IMPLEMENTED;
     1945    /*
     1946     * Validate input.
     1947     */
     1948    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1949    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
     1950    AssertReturn((idDefCpu & ~DBGFREG_HYPER_VMCPUID) < pUVM->cCpus || idDefCpu == VMCPUID_ANY, VERR_INVALID_CPU_ID);
     1951    AssertPtrReturn(pszReg, VERR_INVALID_POINTER);
     1952    AssertReturn(enmType > DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
     1953    AssertPtrReturn(pValue, VERR_INVALID_PARAMETER);
     1954
     1955    /*
     1956     * Resolve the register and check that it is writable.
     1957     */
     1958    bool fGuestRegs = true;
     1959    if ((idDefCpu & DBGFREG_HYPER_VMCPUID) && idDefCpu != VMCPUID_ANY)
     1960    {
     1961        fGuestRegs = false;
     1962        idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     1963    }
     1964    PCDBGFREGLOOKUP pLookupRec = dbgfR3RegResolve(pUVM, idDefCpu, pszReg, fGuestRegs);
     1965    if (pLookupRec)
     1966    {
     1967        PCDBGFREGDESC       pDesc        = pLookupRec->pDesc;
     1968        PCDBGFREGSET        pSet         = pLookupRec->pSet;
     1969        PCDBGFREGSUBFIELD   pSubField    = pLookupRec->pSubField;
     1970
     1971        if (  !(pDesc->fFlags & DBGFREG_FLAGS_READ_ONLY)
     1972            && (pSubField
     1973                ?    !(pSubField->fFlags & DBGFREGSUBFIELD_FLAGS_READ_ONLY)
     1974                  && (pSubField->pfnSet != NULL || pDesc->pfnSet != NULL)
     1975                : pDesc->pfnSet != NULL) )
     1976        {
     1977            /*
     1978             * Calculate the modification mask and cast the input value to the
     1979             * type of the target register.
     1980             */
     1981            DBGFREGVAL Mask  = DBGFREGVAL_INITIALIZE_ZERO;
     1982            DBGFREGVAL Value = DBGFREGVAL_INITIALIZE_ZERO;
     1983            switch (enmType)
     1984            {
     1985                case DBGFREGVALTYPE_U8:
     1986                    Value.u8  = pValue->u8;
     1987                    Mask.u8   = UINT8_MAX;
     1988                    break;
     1989                case DBGFREGVALTYPE_U16:
     1990                    Value.u16 = pValue->u16;
     1991                    Mask.u16  = UINT16_MAX;
     1992                    break;
     1993                case DBGFREGVALTYPE_U32:
     1994                    Value.u32 = pValue->u32;
     1995                    Mask.u32  = UINT32_MAX;
     1996                    break;
     1997                case DBGFREGVALTYPE_U64:
     1998                    Value.u64 = pValue->u64;
     1999                    Mask.u64  = UINT64_MAX;
     2000                    break;
     2001                case DBGFREGVALTYPE_U128:
     2002                    Value.u128 = pValue->u128;
     2003                    Mask.u128.s.Lo = UINT64_MAX;
     2004                    Mask.u128.s.Hi = UINT64_MAX;
     2005                    break;
     2006                case DBGFREGVALTYPE_R80:
     2007#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
     2008                    Value.r80Ex.lrd = pValue->r80Ex.lrd;
     2009#else
     2010                    Value.r80Ex.au64[0] = pValue->r80Ex.au64[0];
     2011                    Value.r80Ex.au16[4] = pValue->r80Ex.au16[4];
     2012#endif
     2013                    Value.r80Ex.au64[0] = UINT64_MAX;
     2014                    Value.r80Ex.au16[4] = UINT16_MAX;
     2015                    break;
     2016                case DBGFREGVALTYPE_DTR:
     2017                    Value.dtr.u32Limit = pValue->dtr.u32Limit;
     2018                    Value.dtr.u64Base  = pValue->dtr.u64Base;
     2019                    Mask.dtr.u32Limit  = UINT32_MAX;
     2020                    Mask.dtr.u64Base   = UINT64_MAX;
     2021                    break;
     2022                case DBGFREGVALTYPE_32BIT_HACK:
     2023                case DBGFREGVALTYPE_END:
     2024                case DBGFREGVALTYPE_INVALID:
     2025                    AssertFailedReturn(VERR_INTERNAL_ERROR_3);
     2026            }
     2027
     2028            int rc = VINF_SUCCESS;
     2029            DBGFREGVALTYPE enmRegType = pDesc->enmType;
     2030            if (pSubField)
     2031            {
     2032                unsigned const cBits = pSubField->cBits + pSubField->cShift;
     2033                if (cBits <= 8)
     2034                    enmRegType = DBGFREGVALTYPE_U8;
     2035                else if (cBits <= 16)
     2036                    enmRegType = DBGFREGVALTYPE_U16;
     2037                else if (cBits <= 32)
     2038                    enmRegType = DBGFREGVALTYPE_U32;
     2039                else if (cBits <= 64)
     2040                    enmRegType = DBGFREGVALTYPE_U64;
     2041                else
     2042                    enmRegType = DBGFREGVALTYPE_U128;
     2043            }
     2044            else if (pLookupRec->pAlias)
     2045            {
     2046                /* Restrict the input to the size of the alias register. */
     2047                DBGFREGVALTYPE enmAliasType = pLookupRec->pAlias->enmType;
     2048                if (enmAliasType != enmType)
     2049                {
     2050                    rc = dbgfR3RegValCast(&Value, enmType, enmAliasType);
     2051                    if (RT_FAILURE(rc))
     2052                        return rc;
     2053                    dbgfR3RegValCast(&Mask, enmType, enmAliasType);
     2054                    enmType = enmAliasType;
     2055                }
     2056            }
     2057
     2058            if (enmType != enmRegType)
     2059            {
     2060                int rc2 = dbgfR3RegValCast(&Value, enmType, enmRegType);
     2061                if (RT_FAILURE(rc2))
     2062                    return rc2;
     2063                if (rc2 != VINF_SUCCESS && rc == VINF_SUCCESS)
     2064                    rc2 = VINF_SUCCESS;
     2065                dbgfR3RegValCast(&Mask, enmType, enmRegType);
     2066            }
     2067
     2068            /*
     2069             * Subfields needs some extra processing if there is no subfield
     2070             * setter, since we'll be feeding it to the normal register setter
     2071             * instead.  The mask and value must be shifted and truncated to the
     2072             * subfield position.
     2073             */
     2074            if (pSubField && !pSubField->pfnSet)
     2075            {
     2076                /* The shift factor is for displaying a subfield value
     2077                   2**cShift times larger than the stored value.  We have
     2078                   to undo this before adjusting value and mask.  */
     2079                if (pSubField->cShift)
     2080                {
     2081                    /* Warn about trunction of the lower bits that get
     2082                       shifted out below. */
     2083                    if (rc == VINF_SUCCESS)
     2084                    {
     2085                        DBGFREGVAL Value2 = Value;
     2086                        RTUInt128AssignAndNFirstBits(&Value2.u128, -pSubField->cShift);
     2087                        if (!RTUInt128BitAreAllClear(&Value2.u128))
     2088                            rc = VINF_DBGF_TRUNCATED_REGISTER;
     2089                    }
     2090                    RTUInt128AssignShiftRight(&Value.u128, pSubField->cShift);
     2091                }
     2092
     2093                DBGFREGVAL Value3 = Value;
     2094                RTUInt128AssignAndNFirstBits(&Value.u128, pSubField->cBits);
     2095                if (rc == VINF_SUCCESS && RTUInt128IsNotEqual(&Value.u128, &Value.u128))
     2096                    rc = VINF_DBGF_TRUNCATED_REGISTER;
     2097                RTUInt128AssignAndNFirstBits(&Mask.u128,  pSubField->cBits);
     2098
     2099                RTUInt128AssignShiftLeft(&Value.u128, pSubField->iFirstBit);
     2100                RTUInt128AssignShiftLeft(&Mask.u128,  pSubField->iFirstBit);
     2101            }
     2102
     2103            /*
     2104             * Do the actual work on an EMT.
     2105             */
     2106            if (pSet->enmType == DBGFREGSETTYPE_CPU)
     2107                idDefCpu = pSet->uUserArg.pVCpu->idCpu;
     2108            else if (idDefCpu != VMCPUID_ANY)
     2109                idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     2110
     2111            int rc2 = VMR3ReqPriorityCallWaitU(pUVM, idDefCpu, (PFNRT)dbgfR3RegNmSetWorkerOnCpu, 4,
     2112                                               pUVM, pLookupRec, &Value, &Mask);
     2113
     2114            if (rc == VINF_SUCCESS || RT_FAILURE(rc2))
     2115                rc = rc2;
     2116            return rc;
     2117        }
     2118        return VERR_DBGF_READ_ONLY_REGISTER;
     2119    }
     2120    return VERR_DBGF_REGISTER_NOT_FOUND;
    19072121}
    19082122
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