2019-07-04 18:17:42 +08:00
/*
2024-04-09 20:43:12 +08:00
* Copyright ( C ) 2019 - 2024 Intel Corporation
2019-07-04 18:17:42 +08:00
*
* SPDX - License - Identifier : MIT
*
*/
2020-02-24 05:44:01 +08:00
# include "shared/source/page_fault_manager/cpu_page_fault_manager.h"
2019-07-04 18:17:42 +08:00
2022-05-18 03:04:23 +08:00
# include "shared/source/debug_settings/debug_settings_manager.h"
2022-01-31 18:12:51 +08:00
# include "shared/source/helpers/memory_properties_helpers.h"
2022-12-16 01:32:03 +08:00
# include "shared/source/helpers/options.h"
2020-02-24 05:44:01 +08:00
# include "shared/source/memory_manager/unified_memory_manager.h"
2022-05-18 03:04:23 +08:00
# include "shared/source/utilities/spinlock.h"
2019-07-04 18:17:42 +08:00
2022-03-09 22:55:32 +08:00
# include <algorithm>
2019-07-04 18:17:42 +08:00
namespace NEO {
2020-09-14 22:39:12 +08:00
void PageFaultManager : : insertAllocation ( void * ptr , size_t size , SVMAllocsManager * unifiedMemoryManager , void * cmdQ , const MemoryProperties & memoryProperties ) {
2022-01-31 18:12:51 +08:00
auto initialPlacement = MemoryPropertiesHelper : : getUSMInitialPlacement ( memoryProperties ) ;
2023-12-14 00:09:52 +08:00
const auto domain = ( initialPlacement = = GraphicsAllocation : : UsmInitialPlacement : : CPU ) ? AllocationDomain : : cpu : AllocationDomain : : none ;
2020-09-14 22:39:12 +08:00
2019-07-04 18:17:42 +08:00
std : : unique_lock < SpinLock > lock { mtx } ;
2020-09-14 22:39:12 +08:00
this - > memoryData . insert ( std : : make_pair ( ptr , PageFaultData { size , unifiedMemoryManager , cmdQ , domain } ) ) ;
2022-01-31 18:12:51 +08:00
if ( initialPlacement ! = GraphicsAllocation : : UsmInitialPlacement : : CPU ) {
2020-09-14 22:39:12 +08:00
this - > protectCPUMemoryAccess ( ptr , size ) ;
}
2022-03-09 22:55:32 +08:00
unifiedMemoryManager - > nonGpuDomainAllocs . push_back ( ptr ) ;
2019-07-04 18:17:42 +08:00
}
void PageFaultManager : : removeAllocation ( void * ptr ) {
std : : unique_lock < SpinLock > lock { mtx } ;
auto alloc = memoryData . find ( ptr ) ;
if ( alloc ! = memoryData . end ( ) ) {
auto & pageFaultData = alloc - > second ;
2023-12-14 00:09:52 +08:00
if ( pageFaultData . domain = = AllocationDomain : : gpu ) {
2019-07-04 18:17:42 +08:00
allowCPUMemoryAccess ( ptr , pageFaultData . size ) ;
2022-03-09 22:55:32 +08:00
} else {
auto & cpuAllocs = pageFaultData . unifiedMemoryManager - > nonGpuDomainAllocs ;
if ( auto it = std : : find ( cpuAllocs . begin ( ) , cpuAllocs . end ( ) , ptr ) ; it ! = cpuAllocs . end ( ) ) {
cpuAllocs . erase ( it ) ;
}
2019-07-04 18:17:42 +08:00
}
this - > memoryData . erase ( ptr ) ;
}
}
void PageFaultManager : : moveAllocationToGpuDomain ( void * ptr ) {
std : : unique_lock < SpinLock > lock { mtx } ;
auto alloc = memoryData . find ( ptr ) ;
if ( alloc ! = memoryData . end ( ) ) {
auto & pageFaultData = alloc - > second ;
2023-12-14 00:09:52 +08:00
if ( pageFaultData . domain ! = AllocationDomain : : gpu ) {
2022-03-09 22:55:32 +08:00
this - > migrateStorageToGpuDomain ( ptr , pageFaultData ) ;
auto & cpuAllocs = pageFaultData . unifiedMemoryManager - > nonGpuDomainAllocs ;
if ( auto it = std : : find ( cpuAllocs . begin ( ) , cpuAllocs . end ( ) , ptr ) ; it ! = cpuAllocs . end ( ) ) {
cpuAllocs . erase ( it ) ;
2020-09-14 22:39:12 +08:00
}
2019-07-04 18:17:42 +08:00
}
}
}
void PageFaultManager : : moveAllocationsWithinUMAllocsManagerToGpuDomain ( SVMAllocsManager * unifiedMemoryManager ) {
std : : unique_lock < SpinLock > lock { mtx } ;
2022-03-09 22:55:32 +08:00
for ( auto allocPtr : unifiedMemoryManager - > nonGpuDomainAllocs ) {
auto & pageFaultData = this - > memoryData [ allocPtr ] ;
this - > migrateStorageToGpuDomain ( allocPtr , pageFaultData ) ;
}
unifiedMemoryManager - > nonGpuDomainAllocs . clear ( ) ;
}
inline void PageFaultManager : : migrateStorageToGpuDomain ( void * ptr , PageFaultData & pageFaultData ) {
2023-12-14 00:09:52 +08:00
if ( pageFaultData . domain = = AllocationDomain : : cpu ) {
2023-07-12 17:18:03 +08:00
this - > setCpuAllocEvictable ( false , ptr , pageFaultData . unifiedMemoryManager ) ;
2022-07-16 09:54:49 +08:00
std : : chrono : : steady_clock : : time_point start ;
std : : chrono : : steady_clock : : time_point end ;
2024-05-28 15:40:24 +08:00
if ( debugManager . flags . RegisterPageFaultHandlerOnMigration . get ( ) ) {
if ( this - > checkFaultHandlerFromPageFaultManager ( ) = = false ) {
this - > registerFaultHandler ( ) ;
}
2023-08-04 09:48:26 +08:00
}
2024-05-28 15:40:24 +08:00
2022-07-16 09:54:49 +08:00
start = std : : chrono : : steady_clock : : now ( ) ;
this - > transferToGpu ( ptr , pageFaultData . cmdQ ) ;
end = std : : chrono : : steady_clock : : now ( ) ;
long long elapsedTime = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( end - start ) . count ( ) ;
2023-11-30 16:32:25 +08:00
if ( debugManager . flags . PrintUmdSharedMigration . get ( ) ) {
2023-01-03 09:03:44 +08:00
printf ( " UMD transferred shared allocation 0x%llx (%zu B) from CPU to GPU (%f us) \n " , reinterpret_cast < unsigned long long int > ( ptr ) , pageFaultData . size , elapsedTime / 1e3 ) ;
2019-07-04 18:17:42 +08:00
}
2022-07-16 09:54:49 +08:00
2022-03-09 22:55:32 +08:00
this - > protectCPUMemoryAccess ( ptr , pageFaultData . size ) ;
2019-07-04 18:17:42 +08:00
}
2023-12-14 00:09:52 +08:00
pageFaultData . domain = AllocationDomain : : gpu ;
2019-07-04 18:17:42 +08:00
}
bool PageFaultManager : : verifyPageFault ( void * ptr ) {
std : : unique_lock < SpinLock > lock { mtx } ;
for ( auto & alloc : this - > memoryData ) {
auto allocPtr = alloc . first ;
auto & pageFaultData = alloc . second ;
if ( ptr > = allocPtr & & ptr < ptrOffset ( allocPtr , pageFaultData . size ) ) {
2019-11-13 21:19:55 +08:00
this - > setAubWritable ( true , allocPtr , pageFaultData . unifiedMemoryManager ) ;
2021-03-08 19:39:07 +08:00
gpuDomainHandler ( this , allocPtr , pageFaultData ) ;
2019-07-04 18:17:42 +08:00
return true ;
}
}
return false ;
}
2019-11-13 21:19:55 +08:00
2021-07-02 05:41:52 +08:00
void PageFaultManager : : setGpuDomainHandler ( gpuDomainHandlerFunc gpuHandlerFuncPtr ) {
this - > gpuDomainHandler = gpuHandlerFuncPtr ;
}
2022-11-17 17:03:18 +08:00
void PageFaultManager : : transferAndUnprotectMemory ( PageFaultManager * pageFaultHandler , void * allocPtr , PageFaultData & pageFaultData ) {
2022-03-09 22:55:32 +08:00
pageFaultHandler - > migrateStorageToCpuDomain ( allocPtr , pageFaultData ) ;
2021-03-08 19:39:07 +08:00
pageFaultHandler - > allowCPUMemoryAccess ( allocPtr , pageFaultData . size ) ;
2023-07-12 17:18:03 +08:00
pageFaultHandler - > setCpuAllocEvictable ( true , allocPtr , pageFaultData . unifiedMemoryManager ) ;
2023-07-25 17:01:53 +08:00
pageFaultHandler - > allowCPUMemoryEviction ( allocPtr , pageFaultData ) ;
2021-03-08 19:39:07 +08:00
}
2022-11-17 17:03:18 +08:00
void PageFaultManager : : unprotectAndTransferMemory ( PageFaultManager * pageFaultHandler , void * allocPtr , PageFaultData & pageFaultData ) {
2021-03-08 19:39:07 +08:00
pageFaultHandler - > allowCPUMemoryAccess ( allocPtr , pageFaultData . size ) ;
2022-03-09 22:55:32 +08:00
pageFaultHandler - > migrateStorageToCpuDomain ( allocPtr , pageFaultData ) ;
}
2021-03-08 19:39:07 +08:00
2022-03-09 22:55:32 +08:00
inline void PageFaultManager : : migrateStorageToCpuDomain ( void * ptr , PageFaultData & pageFaultData ) {
2023-12-14 00:09:52 +08:00
if ( pageFaultData . domain = = AllocationDomain : : gpu ) {
2022-07-16 09:54:49 +08:00
std : : chrono : : steady_clock : : time_point start ;
std : : chrono : : steady_clock : : time_point end ;
start = std : : chrono : : steady_clock : : now ( ) ;
this - > transferToCpu ( ptr , pageFaultData . size , pageFaultData . cmdQ ) ;
end = std : : chrono : : steady_clock : : now ( ) ;
long long elapsedTime = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( end - start ) . count ( ) ;
2023-11-30 16:32:25 +08:00
if ( debugManager . flags . PrintUmdSharedMigration . get ( ) ) {
2023-01-03 09:03:44 +08:00
printf ( " UMD transferred shared allocation 0x%llx (%zu B) from GPU to CPU (%f us) \n " , reinterpret_cast < unsigned long long int > ( ptr ) , pageFaultData . size , elapsedTime / 1e3 ) ;
2021-07-22 08:53:50 +08:00
}
2022-03-09 22:55:32 +08:00
pageFaultData . unifiedMemoryManager - > nonGpuDomainAllocs . push_back ( ptr ) ;
2021-03-08 19:39:07 +08:00
}
2023-12-14 00:09:52 +08:00
pageFaultData . domain = AllocationDomain : : cpu ;
2021-03-08 19:39:07 +08:00
}
void PageFaultManager : : selectGpuDomainHandler ( ) {
2024-04-09 20:43:12 +08:00
if ( debugManager . flags . SetCommandStreamReceiver . get ( ) > static_cast < int32_t > ( CommandStreamReceiverType : : hardware ) | | debugManager . flags . NEO_CAL_ENABLED . get ( ) ) {
2022-11-17 17:03:18 +08:00
this - > gpuDomainHandler = & PageFaultManager : : unprotectAndTransferMemory ;
2021-03-08 19:39:07 +08:00
}
}
2019-11-13 21:19:55 +08:00
void PageFaultManager : : setAubWritable ( bool writable , void * ptr , SVMAllocsManager * unifiedMemoryManager ) {
2019-11-30 00:34:18 +08:00
UNRECOVERABLE_IF ( ptr = = nullptr ) ;
2020-06-29 18:47:13 +08:00
auto gpuAlloc = unifiedMemoryManager - > getSVMAlloc ( ptr ) - > gpuAllocations . getDefaultGraphicsAllocation ( ) ;
2019-11-13 21:19:55 +08:00
gpuAlloc - > setAubWritable ( writable , GraphicsAllocation : : allBanks ) ;
}
2020-07-06 19:09:12 +08:00
2023-07-12 17:18:03 +08:00
void PageFaultManager : : setCpuAllocEvictable ( bool evictable , void * ptr , SVMAllocsManager * unifiedMemoryManager ) {
UNRECOVERABLE_IF ( ptr = = nullptr ) ;
auto cpuAlloc = unifiedMemoryManager - > getSVMAlloc ( ptr ) - > cpuAllocation ;
cpuAlloc - > setEvictable ( evictable ) ;
}
2019-07-04 18:17:42 +08:00
} // namespace NEO