void PDumpFreePageTable(enum PVRSRV_DEVICE_TYPE eDeviceType, void *pvLinAddr, u32 ui32NumBytes, void *hUniqueTag) { u8 *pui8LinAddr; u32 ui32NumPages; struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_DEV_PHYADDR sDevPAddr; u32 ui32Page; __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(); PVR_ASSERT(((u32) pvLinAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0); PVR_ASSERT(((u32) ui32NumBytes & (SGX_MMU_PAGE_SIZE - 1)) == 0); snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "-- FREE :SGXMEM:PAGE_TABLE\r\n"); PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS); pui8LinAddr = (u8 *) pvLinAddr; ui32NumPages = ui32NumBytes >> SGX_MMU_PAGE_SHIFT; while (ui32NumPages--) { sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT; pui8LinAddr += SGX_MMU_PAGE_SIZE; snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "FREE :SGXMEM:PA_%p%8.8lX\r\n", hUniqueTag, ui32Page * SGX_MMU_PAGE_SIZE); PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS); } }
IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType, IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Offset, IMG_UINT8 *pui8LinAddr, IMG_UINT32 ui32PageSize, IMG_DEV_PHYADDR *psDevPAddr) { if(hOSMemHandle) { IMG_CPU_PHYADDR sCpuPAddr; PVR_UNREFERENCED_PARAMETER(pui8LinAddr); sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset); PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0); *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); } else { IMG_CPU_PHYADDR sCpuPAddr; PVR_UNREFERENCED_PARAMETER(ui32Offset); sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr); *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); } }
void PDumpFreePageTable(void *pvLinAddr) { struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_DEV_PHYADDR sDevPAddr; PVR_ASSERT(((u32) pvLinAddr & ~PAGE_MASK) == 0); PDumpComment("FREE :SGXMEM:PAGE_TABLE\r\n"); sCpuPAddr = OSMapLinToCPUPhys(pvLinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(0, sCpuPAddr); pdump_print(PDUMP_FLAGS_CONTINUOUS, "FREE :SGXMEM:PA_%8.8X%8.8lX\r\n", PDUMP_PT_UNIQUETAG, sDevPAddr.uiAddr); }
void PDumpMallocPageTable(void *pvLinAddr, void *hUniqueTag) { struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_DEV_PHYADDR sDevPAddr; PVR_ASSERT(((u32) pvLinAddr & ~PAGE_MASK) == 0); PDumpComment("MALLOC :SGXMEM:PAGE_TABLE 0x%8.8X %lu\r\n", PAGE_SIZE, PAGE_SIZE); sCpuPAddr = OSMapLinToCPUPhys(pvLinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(0, sCpuPAddr); pdump_print(PDUMP_FLAGS_CONTINUOUS, "MALLOC :SGXMEM:PA_%8.8X%8.8lX " "0x%lX %lu 0x%8.8lX\r\n", (u32)hUniqueTag, sDevPAddr.uiAddr, PAGE_SIZE, PAGE_SIZE, sDevPAddr.uiAddr); }
PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType, char *pszMemSpace, u32 * pui32MMUContextID, u32 ui32MMUType, void *hUniqueTag1, void *pvPDCPUAddr) { u8 *pui8LinAddr = (u8 *) pvPDCPUAddr; IMG_CPU_PHYADDR sCpuPAddr; IMG_DEV_PHYADDR sDevPAddr; u32 ui32MMUContextID; PVRSRV_ERROR eError; eError = _PdumpAllocMMUContext(&ui32MMUContextID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eError)); return eError; } sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) - 1); PDumpComment("Set MMU Context\r\n"); PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n", pszMemSpace, ui32MMUContextID, ui32MMUType, pszMemSpace, hUniqueTag1, sDevPAddr.uiAddr); *pui32MMUContextID = ui32MMUContextID; return PVRSRV_OK; }
PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_VIRTADDR pvLinAddr, u32 ui32Bytes, u32 ui32Flags, int bInitialisePages, void *hUniqueTag1, void *hUniqueTag2) { PVRSRV_ERROR eErr; u32 ui32NumPages; u32 ui32PageOffset; u32 ui32BlockBytes; u8 *pui8LinAddr; IMG_DEV_PHYADDR sDevPAddr; IMG_CPU_PHYADDR sCpuPAddr; u32 ui32Offset; u32 ui32ParamOutPos; PDUMP_GET_SCRIPT_AND_FILE_STRING(); if (!pvLinAddr || !PDumpOSJTInitialised()) { return PVRSRV_ERROR_GENERIC; } if (PDumpOSIsSuspended()) { return PVRSRV_OK; } PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags); ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2); if (bInitialisePages) { if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2), pvLinAddr, ui32Bytes, PDUMP_FLAGS_CONTINUOUS)) { return PVRSRV_ERROR_GENERIC; } if (PDumpOSGetParamFileNum() == 0) { eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm"); } else { eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%%lu.prm", PDumpOSGetParamFileNum()); } if (eErr != PVRSRV_OK) { return eErr; } } ui32PageOffset = (u32) pvLinAddr & (HOST_PAGESIZE() - 1); ui32NumPages = (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE(); pui8LinAddr = (u8 *) pvLinAddr; while (ui32NumPages) { ui32NumPages--; sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE()) { ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset; } else { ui32BlockBytes = ui32Bytes; } if (bInitialisePages) { eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n", (u32) hUniqueTag1, sDevPAddr. uiAddr & ~(SGX_MMU_PAGE_MASK), sDevPAddr. uiAddr & (SGX_MMU_PAGE_MASK), ui32BlockBytes, ui32ParamOutPos, pszFileName); if (eErr != PVRSRV_OK) { return eErr; } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); } else { for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(u32)) { u32 ui32PTE = *((u32 *) (pui8LinAddr + ui32Offset)); if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0) { #if defined(SGX_FEATURE_36BIT_MMU) eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n", (u32) hUniqueTag2, (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT); if (eErr != PVRSRV_OK) { return eErr; } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n"); if (eErr != PVRSRV_OK) { return eErr; } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :SGXMEM:$1 :SGXMEM:$1 0x%8.8lX\r\n", ui32PTE & ~SGX_MMU_PDE_ADDR_MASK); if (eErr != PVRSRV_OK) { return eErr; } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$1\r\n", (u32) hUniqueTag1, (sDevPAddr.uiAddr + ui32Offset) & ~ (SGX_MMU_PAGE_MASK), (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK)); if (eErr != PVRSRV_OK) { return eErr; } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); #else eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n", (u32) hUniqueTag1, (sDevPAddr. uiAddr + ui32Offset) & ~ (SGX_MMU_PAGE_MASK), (sDevPAddr. uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK), (u32) hUniqueTag2, (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT, ui32PTE & ~SGX_MMU_PDE_ADDR_MASK); if (eErr != PVRSRV_OK) { return eErr; } #endif } else { PVR_ASSERT((ui32PTE & SGX_MMU_PTE_VALID) == 0UL); eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX%8.8lX\r\n", (u32) hUniqueTag1, (sDevPAddr.uiAddr + ui32Offset) & ~ (SGX_MMU_PAGE_MASK), (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK), (ui32PTE << SGX_MMU_PTE_ADDR_ALIGNSHIFT), (u32) hUniqueTag2); if (eErr != PVRSRV_OK) { return eErr; } } PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS); } } ui32PageOffset = 0; ui32Bytes -= ui32BlockBytes; pui8LinAddr += ui32BlockBytes; ui32ParamOutPos += ui32BlockBytes; } return PVRSRV_OK; }
enum PVRSRV_ERROR PDumpPageTableKM(void *pvLinAddr, u32 ui32Bytes, IMG_BOOL bInitialisePages, void *hUniqueTag1, void *hUniqueTag2) { struct IMG_DEV_PHYADDR sDevPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; enum PVRSRV_ERROR eError; if (!pvLinAddr) return PVRSRV_ERROR_GENERIC; if (bInitialisePages) { eError = pdump_dump(PDUMP_FLAGS_CONTINUOUS, pvLinAddr, ui32Bytes, false); if (eError != PVRSRV_OK) return eError; } while (ui32Bytes) { u32 ui32BlockBytes = min(ui32Bytes, (u32)(PAGE_SIZE - ((u32)pvLinAddr & ~PAGE_MASK))); sCpuPAddr = OSMapLinToCPUPhys(pvLinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(0, sCpuPAddr); if (bInitialisePages) { pdump_print(PDUMP_FLAGS_CONTINUOUS, "LDB :SGXMEM:" "PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X\r\n", (u32) hUniqueTag1, sDevPAddr.uiAddr & PAGE_MASK, sDevPAddr.uiAddr & ~PAGE_MASK, ui32BlockBytes); } else { u32 ui32Offset; for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(u32)) { u32 ui32PTE = *((u32 *)(pvLinAddr + ui32Offset)); if ((ui32PTE & ~PAGE_MASK) != 0) { pdump_print(PDUMP_FLAGS_CONTINUOUS, "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n", (u32)hUniqueTag1, sDevPAddr.uiAddr & PAGE_MASK, sDevPAddr.uiAddr & ~PAGE_MASK, (u32)hUniqueTag2, ui32PTE & PAGE_MASK, ui32PTE & ~PAGE_MASK); } else { PVR_ASSERT(! (ui32PTE & SGX_MMU_PTE_VALID)); pdump_print(PDUMP_FLAGS_CONTINUOUS, "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X%8.8X\r\n", (u32) hUniqueTag1, sDevPAddr.uiAddr & PAGE_MASK, sDevPAddr.uiAddr & ~PAGE_MASK, ui32PTE, (u32)hUniqueTag2); } sDevPAddr.uiAddr += sizeof(u32); } } ui32Bytes -= ui32BlockBytes; pvLinAddr += ui32BlockBytes; } return PVRSRV_OK; }
enum PVRSRV_ERROR PDumpMem2KM(enum PVRSRV_DEVICE_TYPE eDeviceType, void *pvLinAddr, u32 ui32Bytes, u32 ui32Flags, IMG_BOOL bInitialisePages, void *hUniqueTag1, void *hUniqueTag2) { u32 ui32NumPages; u32 ui32PageOffset; u32 ui32BlockBytes; u8 *pui8LinAddr; struct IMG_DEV_PHYADDR sDevPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; u32 ui32Offset; u32 ui32ParamOutPos; __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC); if (ui32Flags) ; if (!pvLinAddr) return PVRSRV_ERROR_GENERIC; if (gui32PDumpSuspended) return PVRSRV_OK; ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState. psStream[PDUMP_STREAM_PARAM2]); if (bInitialisePages) { if (!PDumpWriteILock (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pvLinAddr, ui32Bytes, PDUMP_FLAGS_CONTINUOUS)) return PVRSRV_ERROR_GENERIC; if (gsDBGPdumpState.ui32ParamFileNum == 0) snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm"); else snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm", gsDBGPdumpState.ui32ParamFileNum); } ui32PageOffset = (u32) pvLinAddr & (HOST_PAGESIZE() - 1); ui32NumPages = (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE(); pui8LinAddr = (u8 *) pvLinAddr; while (ui32NumPages--) { sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr); sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE()) ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset; else ui32BlockBytes = ui32Bytes; if (bInitialisePages) { snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "LDB :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX " "0x%8.8lX %s\r\n", hUniqueTag1, sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1), sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1), ui32BlockBytes, ui32ParamOutPos, pszFile); PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS); } else { for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(u32)) { u32 ui32PTE = *((u32 *) (pui8LinAddr + ui32Offset)); if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0) { snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "WRW :SGXMEM:PA_%p%8.8lX:" "0x%8.8lX :SGXMEM:" "PA_%p%8.8lX:0x%8.8lX\r\n", hUniqueTag1, (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_SIZE - 1), (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_SIZE - 1), hUniqueTag2, ui32PTE & SGX_MMU_PDE_ADDR_MASK, ui32PTE & ~SGX_MMU_PDE_ADDR_MASK); } else { PVR_ASSERT(! (ui32PTE & SGX_MMU_PTE_VALID)); snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "WRW :SGXMEM:PA_%p%8.8lX:" "0x%8.8lX 0x%8.8lX%p\r\n", hUniqueTag1, (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_SIZE - 1), (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_SIZE - 1), ui32PTE, hUniqueTag2); } PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS); } } ui32PageOffset = 0; ui32Bytes -= ui32BlockBytes; pui8LinAddr += ui32BlockBytes; ui32ParamOutPos += ui32BlockBytes; } return PVRSRV_OK; }
void MMU_Finalise(struct MMU_CONTEXT *psMMUContext) { u32 *pui32Tmp, i; struct SYS_DATA *psSysData; struct MMU_CONTEXT **ppsMMUContext; if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Finalise: ERROR call to SysAcquireData failed"); return; } PDUMPCOMMENT("Free page directory"); PDUMPFREEPAGETABLE(psMMUContext->pvPDCpuVAddr); pui32Tmp = (u32 *) psMMUContext->pvPDCpuVAddr; for (i = 0; i < SGX_MMU_PD_SIZE; i++) pui32Tmp[i] = 0; if (psMMUContext->psDeviceNode->psLocalDevMemArena == NULL) { OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, psMMUContext->pvPDCpuVAddr, psMMUContext->hPDOSMemHandle); } else { struct IMG_SYS_PHYADDR sSysPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->pvPDCpuVAddr); sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr); OSUnMapPhysToLin((void __iomem __force *) psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, psMMUContext->hPDOSMemHandle); RA_Free(psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); } PVR_DPF(PVR_DBG_MESSAGE, "MMU_Finalise"); ppsMMUContext = (struct MMU_CONTEXT **) &psMMUContext->psDevInfo->pvMMUContextList; while (*ppsMMUContext) { if (*ppsMMUContext == psMMUContext) { *ppsMMUContext = psMMUContext->psNext; break; } ppsMMUContext = &((*ppsMMUContext)->psNext); } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT), psMMUContext, NULL); }
enum PVRSRV_ERROR MMU_Initialise(struct PVRSRV_DEVICE_NODE *psDeviceNode, struct MMU_CONTEXT **ppsMMUContext, struct IMG_DEV_PHYADDR *psPDDevPAddr) { u32 *pui32Tmp; u32 i; void *pvPDCpuVAddr; struct IMG_DEV_PHYADDR sPDDevPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_SYS_PHYADDR sSysPAddr; struct MMU_CONTEXT *psMMUContext; void *hPDOSMemHandle; struct SYS_DATA *psSysData; struct PVRSRV_SGXDEV_INFO *psDevInfo; PVR_DPF(PVR_DBG_MESSAGE, "MMU_Initialise"); if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: ERROR call to SysAcquireData failed"); return PVRSRV_ERROR_GENERIC; } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT), (void **) &psMMUContext, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"); return PVRSRV_ERROR_GENERIC; } OSMemSet(psMMUContext, 0, sizeof(struct MMU_CONTEXT)); psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; psMMUContext->psDevInfo = psDevInfo; psMMUContext->psDeviceNode = psDeviceNode; if (psDeviceNode->psLocalDevMemArena == NULL) { if (OSAllocPages (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, &pvPDCpuVAddr, &hPDOSMemHandle) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR call to OSAllocPages failed"); goto err1; } if (pvPDCpuVAddr) sCpuPAddr = OSMapLinToCPUPhys(pvPDCpuVAddr); else sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0); sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); } else { if (RA_Alloc(psDeviceNode->psLocalDevMemArena, SGX_MMU_PAGE_SIZE, NULL, 0, SGX_MMU_PAGE_SIZE, &(sSysPAddr.uiAddr)) != IMG_TRUE) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR call to RA_Alloc failed"); goto err1; } sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr); pvPDCpuVAddr = (void __force *) OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, &hPDOSMemHandle); if (!pvPDCpuVAddr) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR failed to map page tables"); goto err2; } } PDUMPCOMMENT("Alloc page directory"); PDUMPMALLOCPAGETABLE(pvPDCpuVAddr, PDUMP_PD_UNIQUETAG); if (pvPDCpuVAddr) { pui32Tmp = (u32 *) pvPDCpuVAddr; } else { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"); goto err3; } for (i = 0; i < SGX_MMU_PD_SIZE; i++) pui32Tmp[i] = 0; PDUMPCOMMENT("Page directory contents"); PDUMPPAGETABLE(pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr; psMMUContext->sPDDevPAddr = sPDDevPAddr; psMMUContext->hPDOSMemHandle = hPDOSMemHandle; *ppsMMUContext = psMMUContext; *psPDDevPAddr = sPDDevPAddr; psMMUContext->psNext = (struct MMU_CONTEXT *) psDevInfo->pvMMUContextList; psDevInfo->pvMMUContextList = (void *) psMMUContext; return PVRSRV_OK; err3: if (psDeviceNode->psLocalDevMemArena) OSUnMapPhysToLin((void __iomem __force *)pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, hPDOSMemHandle); err2: if (!psDeviceNode->psLocalDevMemArena) OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, pvPDCpuVAddr, hPDOSMemHandle); else RA_Free(psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); err1: OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT), psMMUContext, NULL); return PVRSRV_ERROR_GENERIC; }
static IMG_BOOL _DeferredAllocPagetables(struct MMU_HEAP *pMMUHeap, struct IMG_DEV_VIRTADDR DevVAddr, u32 ui32Size) { u32 ui32PTPageCount; u32 ui32PDIndex; u32 i; u32 *pui32PDEntry; struct MMU_PT_INFO **ppsPTInfoList; struct SYS_DATA *psSysData; struct IMG_DEV_VIRTADDR sHighDevVAddr; PVR_ASSERT(DevVAddr.uiAddr < (1 << SGX_FEATURE_ADDRESS_SPACE_SIZE)); if (SysAcquireData(&psSysData) != PVRSRV_OK) return IMG_FALSE; ui32PDIndex = DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); if ((UINT32_MAX_VALUE - DevVAddr.uiAddr) < (ui32Size + (1 << (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT)) - 1)) { sHighDevVAddr.uiAddr = UINT32_MAX_VALUE; } else { sHighDevVAddr.uiAddr = DevVAddr.uiAddr + ui32Size + (1 << (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT)) - 1; } ui32PTPageCount = sHighDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); ui32PTPageCount -= ui32PDIndex; pui32PDEntry = (u32 *) pMMUHeap->psMMUContext->pvPDCpuVAddr; pui32PDEntry += ui32PDIndex; ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PTPageCount); PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PTPageCount); for (i = 0; i < ui32PTPageCount; i++) { if (ppsPTInfoList[i] == NULL) { if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_PT_INFO), (void **) &ppsPTInfoList[i], NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "_DeferredAllocPagetables: " "ERROR call to OSAllocMem failed"); return IMG_FALSE; } OSMemSet(ppsPTInfoList[i], 0, sizeof(struct MMU_PT_INFO)); } if (ppsPTInfoList[i]->hPTPageOSMemHandle == NULL && ppsPTInfoList[i]->PTPageCpuVAddr == NULL) { struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_DEV_PHYADDR sDevPAddr; PVR_ASSERT(pui32PDEntry[i] == 0); if (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo-> psLocalDevMemArena == NULL) { if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, (void **)&ppsPTInfoList[i]-> PTPageCpuVAddr, &ppsPTInfoList[i]-> hPTPageOSMemHandle) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "_DeferredAllocPagetables: " "ERROR call to OSAllocPages failed"); return IMG_FALSE; } if (ppsPTInfoList[i]->PTPageCpuVAddr) { sCpuPAddr = OSMapLinToCPUPhys(ppsPTInfoList[i]-> PTPageCpuVAddr); } else { sCpuPAddr = OSMemHandleToCpuPAddr( ppsPTInfoList[i]-> hPTPageOSMemHandle, 0); } sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); } else { struct IMG_SYS_PHYADDR sSysPAddr; if (RA_Alloc(pMMUHeap->psDevArena-> psDeviceMemoryHeapInfo->psLocalDevMemArena, SGX_MMU_PAGE_SIZE, NULL, 0, SGX_MMU_PAGE_SIZE, &(sSysPAddr.uiAddr)) != IMG_TRUE) { PVR_DPF(PVR_DBG_ERROR, "_DeferredAllocPagetables: " "ERROR call to RA_Alloc failed"); return IMG_FALSE; } sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); ppsPTInfoList[i]->PTPageCpuVAddr = (void __force *) OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, &ppsPTInfoList[i]-> hPTPageOSMemHandle); if (!ppsPTInfoList[i]->PTPageCpuVAddr) { PVR_DPF(PVR_DBG_ERROR, "_DeferredAllocPagetables: " "ERROR failed to map page tables"); return IMG_FALSE; } sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); } OSMemSet(ppsPTInfoList[i]->PTPageCpuVAddr, 0, SGX_MMU_PAGE_SIZE); PDUMPMALLOCPAGETABLE(ppsPTInfoList[i]->PTPageCpuVAddr, PDUMP_PT_UNIQUETAG); PDUMPPAGETABLE(ppsPTInfoList[i]->PTPageCpuVAddr, SGX_MMU_PAGE_SIZE, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG); switch (pMMUHeap->psDevArena->DevMemHeapType) { case DEVICE_MEMORY_HEAP_SHARED: case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: { struct MMU_CONTEXT *psMMUContext = (struct MMU_CONTEXT *)pMMUHeap-> psMMUContext->psDevInfo-> pvMMUContextList; while (psMMUContext) { pui32PDEntry = (u32 *)psMMUContext-> pvPDCpuVAddr; pui32PDEntry += ui32PDIndex; pui32PDEntry[i] = sDevPAddr.uiAddr | SGX_MMU_PDE_VALID; PDUMPPAGETABLE ((void *)&pui32PDEntry[i], sizeof(u32), IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); psMMUContext = psMMUContext->psNext; } break; } case DEVICE_MEMORY_HEAP_PERCONTEXT: case DEVICE_MEMORY_HEAP_KERNEL: { pui32PDEntry[i] = sDevPAddr.uiAddr | SGX_MMU_PDE_VALID; PDUMPPAGETABLE((void *)&pui32PDEntry[i], sizeof(u32), IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); break; } default: { PVR_DPF(PVR_DBG_ERROR, "_DeferredAllocPagetables: " "ERROR invalid heap type"); return IMG_FALSE; } } MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext-> psDevInfo); } else { PVR_ASSERT(pui32PDEntry[i] != 0); } } return IMG_TRUE; }
static void _DeferredFreePageTable(struct MMU_HEAP *pMMUHeap, u32 ui32PTIndex) { u32 *pui32PDEntry; u32 i; u32 ui32PDIndex; struct SYS_DATA *psSysData; struct MMU_PT_INFO **ppsPTInfoList; if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "_DeferredFreePageTables: " "ERROR call to SysAcquireData failed"); return; } ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; { PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0); } PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PTPageCount); if (ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr) PDUMPFREEPAGETABLE(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr); switch (pMMUHeap->psDevArena->DevMemHeapType) { case DEVICE_MEMORY_HEAP_SHARED: case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: { struct MMU_CONTEXT *psMMUContext = (struct MMU_CONTEXT *) pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList; while (psMMUContext) { pui32PDEntry = (u32 *) psMMUContext->pvPDCpuVAddr; pui32PDEntry += ui32PDIndex; pui32PDEntry[ui32PTIndex] = 0; PDUMPPAGETABLE((void *) &pui32PDEntry [ui32PTIndex], sizeof(u32), IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG); psMMUContext = psMMUContext->psNext; } break; } case DEVICE_MEMORY_HEAP_PERCONTEXT: case DEVICE_MEMORY_HEAP_KERNEL: { pui32PDEntry = (u32 *) pMMUHeap->psMMUContext->pvPDCpuVAddr; pui32PDEntry += ui32PDIndex; pui32PDEntry[ui32PTIndex] = 0; PDUMPPAGETABLE((void *) &pui32PDEntry[ui32PTIndex], sizeof(u32), IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); break; } default: { PVR_DPF(PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"); return; } } if (ppsPTInfoList[ui32PTIndex] != NULL) { if (ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != NULL) { u32 *pui32Tmp; pui32Tmp = (u32 *) ppsPTInfoList[ui32PTIndex]-> PTPageCpuVAddr; for (i = 0; (i < pMMUHeap->ui32PTEntryCount) && (i < 1024); i++) pui32Tmp[i] = 0; if (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo-> psLocalDevMemArena == NULL) { OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, ppsPTInfoList[ui32PTIndex]-> PTPageCpuVAddr, ppsPTInfoList[ui32PTIndex]-> hPTPageOSMemHandle); } else { struct IMG_SYS_PHYADDR sSysPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; sCpuPAddr = OSMapLinToCPUPhys(ppsPTInfoList [ui32PTIndex]-> PTPageCpuVAddr); sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr); OSUnMapPhysToLin((void __force __iomem *) ppsPTInfoList[ui32PTIndex]-> PTPageCpuVAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, ppsPTInfoList[ui32PTIndex]-> hPTPageOSMemHandle); RA_Free(pMMUHeap->psDevArena-> psDeviceMemoryHeapInfo-> psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); } pMMUHeap->ui32PTEntryCount -= i; } else { pMMUHeap->ui32PTEntryCount -= 1024; } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_PT_INFO), ppsPTInfoList[ui32PTIndex], NULL); ppsPTInfoList[ui32PTIndex] = NULL; } else { pMMUHeap->ui32PTEntryCount -= 1024; } PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PTPageCount); }