Changeset 48898 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 4, 2013 8:01:01 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp
r46155 r48898 1901 1901 1902 1902 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 */ 1914 static 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 */ 1903 1943 VMMR3DECL(int) DBGFR3RegNmSet(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType) 1904 1944 { 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; 1907 2121 } 1908 2122
Note:
See TracChangeset
for help on using the changeset viewer.