/** * Initializes the tracing. * * @returns VBox status code * @param pVM The cross context VM structure. * @param cbEntry The trace entry size. * @param cEntries The number of entries. */ static int dbgfR3TraceEnable(PVM pVM, uint32_t cbEntry, uint32_t cEntries) { /* * Don't enable it twice. */ if (pVM->hTraceBufR3 != NIL_RTTRACEBUF) return VERR_ALREADY_EXISTS; /* * Resolve default parameter values. */ int rc; if (!cbEntry) { rc = CFGMR3QueryU32Def(CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGF"), "TraceBufEntrySize", &cbEntry, 128); AssertRCReturn(rc, rc); } if (!cEntries) { rc = CFGMR3QueryU32Def(CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGF"), "TraceBufEntries", &cEntries, 4096); AssertRCReturn(rc, rc); } /* * Figure the required size. */ RTTRACEBUF hTraceBuf; size_t cbBlock = 0; rc = RTTraceBufCarve(&hTraceBuf, cEntries, cbEntry, 0 /*fFlags*/, NULL, &cbBlock); if (rc != VERR_BUFFER_OVERFLOW) { AssertReturn(!RT_SUCCESS_NP(rc), VERR_IPE_UNEXPECTED_INFO_STATUS); return rc; } /* * Allocate a hyper heap block and carve a trace buffer out of it. * * Note! We ASSUME that the returned trace buffer handle has the same value * as the heap block. */ cbBlock = RT_ALIGN_Z(cbBlock, PAGE_SIZE); void *pvBlock; rc = MMR3HyperAllocOnceNoRel(pVM, cbBlock, PAGE_SIZE, MM_TAG_DBGF, &pvBlock); if (RT_FAILURE(rc)) return rc; rc = RTTraceBufCarve(&hTraceBuf, cEntries, cbEntry, 0 /*fFlags*/, pvBlock, &cbBlock); AssertRCReturn(rc, rc); AssertRelease(hTraceBuf == (RTTRACEBUF)pvBlock); AssertRelease((void *)hTraceBuf == pvBlock); pVM->hTraceBufR3 = hTraceBuf; pVM->hTraceBufR0 = MMHyperCCToR0(pVM, hTraceBuf); pVM->hTraceBufRC = MMHyperCCToRC(pVM, hTraceBuf); return VINF_SUCCESS; }
/** * @interface_method_impl(PDMINVRAMCONNECTOR,pfnVarQueryByIndex) */ DECLCALLBACK(int) drvNvram_VarQueryByIndex(PPDMINVRAMCONNECTOR pInterface, uint32_t idxVariable, PRTUUID pVendorUuid, char *pszName, uint32_t *pcchName, uint32_t *pfAttributes, uint8_t *pbValue, uint32_t *pcbValue) { PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector); /* * Find the requested variable node. */ PCFGMNODE pVarNode; if (pThis->idxLastVar + 1 == idxVariable && pThis->pLastVarNode) pVarNode = CFGMR3GetNextChild(pThis->pLastVarNode); else { pVarNode = CFGMR3GetFirstChild(pThis->pCfgVarRoot); for (uint32_t i = 0; i < idxVariable && pVarNode; i++) pVarNode = CFGMR3GetNextChild(pVarNode); } if (!pVarNode) return VERR_NOT_FOUND; /* cache it */ pThis->pLastVarNode = pVarNode; pThis->idxLastVar = idxVariable; /* * Read the variable node. */ int rc = CFGMR3QueryString(pVarNode, "Name", pszName, *pcchName); AssertRCReturn(rc, rc); *pcchName = (uint32_t)strlen(pszName); char szUuid[RTUUID_STR_LENGTH]; rc = CFGMR3QueryString(pVarNode, "Uuid", szUuid, sizeof(szUuid)); AssertRCReturn(rc, rc); rc = RTUuidFromStr(pVendorUuid, szUuid); AssertRCReturn(rc, rc); rc = CFGMR3QueryU32Def(pVarNode, "Attribs", pfAttributes, NVRAM_DEFAULT_ATTRIB); AssertRCReturn(rc, rc); size_t cbValue; rc = CFGMR3QuerySize(pVarNode, "Value", &cbValue); AssertRCReturn(rc, rc); AssertReturn(cbValue <= *pcbValue, VERR_BUFFER_OVERFLOW); rc = CFGMR3QueryBytes(pVarNode, "Value", pbValue, cbValue); AssertRCReturn(rc, rc); *pcbValue = (uint32_t)cbValue; return VINF_SUCCESS; }
/** @interface_method_impl{PDMDEVREG,pfnConstruct} */ static DECLCALLBACK(int) ox958R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) { RT_NOREF(iInstance); PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958); bool fRCEnabled = true; bool fR0Enabled = true; bool fMsiXSupported = false; int rc; PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* * Validate and read configuration. */ if (!CFGMR3AreValuesValid(pCfg, "RCEnabled\0" "R0Enabled\0" "MsiXSupported\0" "UartCount\0")) return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, N_("OXPCIe958 configuration error: Unknown option specified")); rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: Failed to read \"RCEnabled\" as boolean")); rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"R0Enabled\" as boolean")); rc = CFGMR3QueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean")); rc = CFGMR3QueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer")); if (!pThis->cUarts || pThis->cUarts > OX958_UARTS_MAX) return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("OXPCIe958 configuration error: \"UartCount\" has invalid value %u (must be in range [1 .. %u]"), pThis->cUarts, OX958_UARTS_MAX); /* * Init instance data. */ pThis->fR0Enabled = fR0Enabled; pThis->fRCEnabled = fRCEnabled; pThis->pDevInsR3 = pDevIns; pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); /* Fill PCI config space. */ PDMPciDevSetVendorId (&pThis->PciDev, OX958_PCI_VENDOR_ID); PDMPciDevSetDeviceId (&pThis->PciDev, OX958_PCI_DEVICE_ID); PDMPciDevSetCommand (&pThis->PciDev, 0x0000); #ifdef VBOX_WITH_MSI_DEVICES PDMPciDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); PDMPciDevSetCapabilityList (&pThis->PciDev, OX958_PCI_MSI_CAP_OFS); #else PDMPciDevSetCapabilityList (&pThis->PciDev, 0x70); #endif PDMPciDevSetRevisionId (&pThis->PciDev, 0x00); PDMPciDevSetClassBase (&pThis->PciDev, 0x07); /* Communication controller. */ PDMPciDevSetClassSub (&pThis->PciDev, 0x00); /* Serial controller. */ PDMPciDevSetClassProg (&pThis->PciDev, 0x02); /* 16550. */ PDMPciDevSetRevisionId (&pThis->PciDev, 0x00); PDMPciDevSetSubSystemVendorId(&pThis->PciDev, OX958_PCI_VENDOR_ID); PDMPciDevSetSubSystemId (&pThis->PciDev, OX958_PCI_DEVICE_ID); PDMPciDevSetInterruptLine (&pThis->PciDev, 0x00); PDMPciDevSetInterruptPin (&pThis->PciDev, 0x01); /** @todo More Capabilities. */ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); if (RT_FAILURE(rc)) return rc; /* * Register PCI device and I/O region. */ rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev); if (RT_FAILURE(rc)) return rc; #ifdef VBOX_WITH_MSI_DEVICES PDMMSIREG MsiReg; RT_ZERO(MsiReg); MsiReg.cMsiVectors = 1; MsiReg.iMsiCapOffset = OX958_PCI_MSI_CAP_OFS; MsiReg.iMsiNextOffset = OX958_PCI_MSIX_CAP_OFS; MsiReg.fMsi64bit = true; if (fMsiXSupported) { MsiReg.cMsixVectors = VBOX_MSIX_MAX_ENTRIES; MsiReg.iMsixCapOffset = OX958_PCI_MSIX_CAP_OFS; MsiReg.iMsixNextOffset = 0x00; MsiReg.iMsixBar = OX958_PCI_MSIX_BAR; } rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg); if (RT_FAILURE(rc)) { PCIDevSetCapabilityList(&pThis->PciDev, 0x0); /* That's OK, we can work without MSI */ } #endif rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, _16K, PCI_ADDRESS_SPACE_MEM, ox958R3Map); if (RT_FAILURE(rc)) return rc; PVM pVM = PDMDevHlpGetVM(pDevIns); RTR0PTR pfnSerialIrqReqR0 = NIL_RTR0PTR; RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR; if ( fRCEnabled && VM_IS_RAW_MODE_ENABLED(pVM)) { rc = PDMR3LdrGetSymbolRC(pVM, pDevIns->pReg->szRCMod, "ox958IrqReq", &pfnSerialIrqReqRC); if (RT_FAILURE(rc)) return rc; } if (fR0Enabled) { rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->szR0Mod, "ox958IrqReq", &pfnSerialIrqReqR0); if (RT_FAILURE(rc)) return rc; } for (uint32_t i = 0; i < pThis->cUarts; i++) { POX958UART pUart = &pThis->aUarts[i]; rc = uartR3Init(&pUart->UartCore, pDevIns, UARTTYPE_16550A, i, 0, ox958IrqReq, pfnSerialIrqReqR0, pfnSerialIrqReqRC); if (RT_FAILURE(rc)) return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("OXPCIe958 configuration error: failed to initialize UART %u"), i); } ox958R3Reset(pDevIns); return VINF_SUCCESS; }
/** * Construct a disk integrity driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { int rc = VINF_SUCCESS; PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY); LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Validate configuration. */ if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0" "TraceRequests\0" "CheckIntervalMs\0" "ExpireIntervalMs\0" "CheckDoubleCompletions\0" "HistorySize\0" "IoLog\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false); AssertRC(rc); rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false); AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */ AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */ AssertRC(rc); rc = CFGMR3QueryBoolDef(pCfg, "CheckDoubleCompletions", &pThis->fCheckDoubleCompletion, false); AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "HistorySize", &pThis->cEntries, 512); AssertRC(rc); char *pszIoLogFilename = NULL; rc = CFGMR3QueryStringAlloc(pCfg, "IoLog", &pszIoLogFilename); Assert(RT_SUCCESS(rc) || rc == VERR_CFGM_VALUE_NOT_FOUND); /* * Initialize most of the data members. */ pThis->pDrvIns = pDrvIns; /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface; /* IMedia */ pThis->IMedia.pfnRead = drvdiskintRead; pThis->IMedia.pfnWrite = drvdiskintWrite; pThis->IMedia.pfnFlush = drvdiskintFlush; pThis->IMedia.pfnGetSize = drvdiskintGetSize; pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly; pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry; pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry; pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry; pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry; pThis->IMedia.pfnGetUuid = drvdiskintGetUuid; /* IMediaAsync */ pThis->IMediaAsync.pfnStartRead = drvdiskintStartRead; pThis->IMediaAsync.pfnStartWrite = drvdiskintStartWrite; pThis->IMediaAsync.pfnStartFlush = drvdiskintStartFlush; /* IMediaAsyncPort. */ pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvdiskintAsyncTransferCompleteNotify; /* IMediaPort. */ pThis->IMediaPort.pfnQueryDeviceLocation = drvdiskintQueryDeviceLocation; /* Query the media port interface above us. */ pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT); if (!pThis->pDrvMediaPort) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, N_("No media port inrerface above")); /* Try to attach async media port interface above.*/ pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT); /* * Try attach driver below and query it's media interface. */ PPDMIBASE pBase; rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Failed to attach driver below us! %Rrc"), rc); pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA); if (!pThis->pDrvMedia) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, N_("No media or async media interface below")); pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC); if (pThis->pDrvMedia->pfnDiscard) pThis->IMedia.pfnDiscard = drvdiskintDiscard; if ( pThis->pDrvMediaAsync && pThis->pDrvMediaAsync->pfnStartDiscard) pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard; if (pThis->fCheckConsistency) { /* Create the AVL tree. */ pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE)); if (!pThis->pTreeSegments) rc = VERR_NO_MEMORY; } if (pThis->fTraceRequests) { for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++) { pThis->apReqActive[i].pIoReq = NULL; pThis->apReqActive[i].tsStart = 0; } pThis->iNextFreeSlot = 0; /* Init event semaphore. */ rc = RTSemEventCreate(&pThis->SemEvent); AssertRC(rc); pThis->fRunning = true; rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis, 0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity"); AssertRC(rc); } if (pThis->fCheckDoubleCompletion) { pThis->iEntry = 0; pThis->papIoReq = (PDRVDISKAIOREQ *)RTMemAllocZ(pThis->cEntries * sizeof(PDRVDISKAIOREQ)); AssertPtr(pThis->papIoReq); } if (pszIoLogFilename) { rc = VDDbgIoLogCreate(&pThis->hIoLogger, pszIoLogFilename, VDDBG_IOLOG_LOG_DATA); MMR3HeapFree(pszIoLogFilename); } return rc; }