2019-07-04 12:17:42 +02:00
/*
2023-01-03 01:03:44 +00:00
* Copyright ( C ) 2019 - 2023 Intel Corporation
2019-07-04 12:17:42 +02:00
*
* SPDX - License - Identifier : MIT
*
*/
2020-02-23 22:44:01 +01:00
# include "shared/source/page_fault_manager/cpu_page_fault_manager.h"
2019-07-04 12:17:42 +02:00
2022-05-17 19:04:23 +00:00
# include "shared/source/debug_settings/debug_settings_manager.h"
2022-01-31 10:12:51 +00:00
# include "shared/source/helpers/memory_properties_helpers.h"
2022-12-15 17:32:03 +00:00
# include "shared/source/helpers/options.h"
2020-02-23 22:44:01 +01:00
# include "shared/source/memory_manager/unified_memory_manager.h"
2022-05-17 19:04:23 +00:00
# include "shared/source/utilities/spinlock.h"
2019-07-04 12:17:42 +02:00
2022-03-09 14:55:32 +00:00
# include <algorithm>
2019-07-04 12:17:42 +02:00
namespace NEO {
2020-09-14 16:39:12 +02:00
void PageFaultManager : : insertAllocation ( void * ptr , size_t size , SVMAllocsManager * unifiedMemoryManager , void * cmdQ , const MemoryProperties & memoryProperties ) {
2022-01-31 10:12:51 +00:00
auto initialPlacement = MemoryPropertiesHelper : : getUSMInitialPlacement ( memoryProperties ) ;
const auto domain = ( initialPlacement = = GraphicsAllocation : : UsmInitialPlacement : : CPU ) ? AllocationDomain : : Cpu : AllocationDomain : : None ;
2020-09-14 16:39:12 +02:00
2019-07-04 12:17:42 +02:00
std : : unique_lock < SpinLock > lock { mtx } ;
2020-09-14 16:39:12 +02:00
this - > memoryData . insert ( std : : make_pair ( ptr , PageFaultData { size , unifiedMemoryManager , cmdQ , domain } ) ) ;
2022-01-31 10:12:51 +00:00
if ( initialPlacement ! = GraphicsAllocation : : UsmInitialPlacement : : CPU ) {
2020-09-14 16:39:12 +02:00
this - > protectCPUMemoryAccess ( ptr , size ) ;
}
2022-03-09 14:55:32 +00:00
unifiedMemoryManager - > nonGpuDomainAllocs . push_back ( ptr ) ;
2019-07-04 12:17:42 +02: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 ;
2020-09-14 16:39:12 +02:00
if ( pageFaultData . domain = = AllocationDomain : : Gpu ) {
2019-07-04 12:17:42 +02:00
allowCPUMemoryAccess ( ptr , pageFaultData . size ) ;
2022-03-09 14:55:32 +00: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 12:17:42 +02: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 ;
2020-09-14 16:39:12 +02:00
if ( pageFaultData . domain ! = AllocationDomain : : Gpu ) {
2022-03-09 14:55:32 +00: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 16:39:12 +02:00
}
2019-07-04 12:17:42 +02:00
}
}
}
void PageFaultManager : : moveAllocationsWithinUMAllocsManagerToGpuDomain ( SVMAllocsManager * unifiedMemoryManager ) {
std : : unique_lock < SpinLock > lock { mtx } ;
2022-03-09 14:55:32 +00: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 ) {
if ( pageFaultData . domain = = AllocationDomain : : Cpu ) {
2023-07-12 09:18:03 +00:00
this - > setCpuAllocEvictable ( false , ptr , pageFaultData . unifiedMemoryManager ) ;
2022-07-16 01:54:49 +00:00
std : : chrono : : steady_clock : : time_point start ;
std : : chrono : : steady_clock : : time_point end ;
2023-08-04 01:48:26 +00:00
if ( this - > checkFaultHandlerFromPageFaultManager ( ) = = false ) {
this - > registerFaultHandler ( ) ;
}
2022-07-16 01:54:49 +00: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 08:32:25 +00:00
if ( debugManager . flags . PrintUmdSharedMigration . get ( ) ) {
2023-01-03 01:03:44 +00: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 12:17:42 +02:00
}
2022-07-16 01:54:49 +00:00
2022-03-09 14:55:32 +00:00
this - > protectCPUMemoryAccess ( ptr , pageFaultData . size ) ;
2019-07-04 12:17:42 +02:00
}
2022-03-09 14:55:32 +00:00
pageFaultData . domain = AllocationDomain : : Gpu ;
2019-07-04 12:17:42 +02: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 14:19:55 +01:00
this - > setAubWritable ( true , allocPtr , pageFaultData . unifiedMemoryManager ) ;
2021-03-08 11:39:07 +00:00
gpuDomainHandler ( this , allocPtr , pageFaultData ) ;
2019-07-04 12:17:42 +02:00
return true ;
}
}
return false ;
}
2019-11-13 14:19:55 +01:00
2021-07-01 21:41:52 +00:00
void PageFaultManager : : setGpuDomainHandler ( gpuDomainHandlerFunc gpuHandlerFuncPtr ) {
this - > gpuDomainHandler = gpuHandlerFuncPtr ;
}
2022-11-17 09:03:18 +00:00
void PageFaultManager : : transferAndUnprotectMemory ( PageFaultManager * pageFaultHandler , void * allocPtr , PageFaultData & pageFaultData ) {
2022-03-09 14:55:32 +00:00
pageFaultHandler - > migrateStorageToCpuDomain ( allocPtr , pageFaultData ) ;
2021-03-08 11:39:07 +00:00
pageFaultHandler - > allowCPUMemoryAccess ( allocPtr , pageFaultData . size ) ;
2023-07-12 09:18:03 +00:00
pageFaultHandler - > setCpuAllocEvictable ( true , allocPtr , pageFaultData . unifiedMemoryManager ) ;
2023-07-25 09:01:53 +00:00
pageFaultHandler - > allowCPUMemoryEviction ( allocPtr , pageFaultData ) ;
2021-03-08 11:39:07 +00:00
}
2022-11-17 09:03:18 +00:00
void PageFaultManager : : unprotectAndTransferMemory ( PageFaultManager * pageFaultHandler , void * allocPtr , PageFaultData & pageFaultData ) {
2021-03-08 11:39:07 +00:00
pageFaultHandler - > allowCPUMemoryAccess ( allocPtr , pageFaultData . size ) ;
2022-03-09 14:55:32 +00:00
pageFaultHandler - > migrateStorageToCpuDomain ( allocPtr , pageFaultData ) ;
}
2021-03-08 11:39:07 +00:00
2022-03-09 14:55:32 +00:00
inline void PageFaultManager : : migrateStorageToCpuDomain ( void * ptr , PageFaultData & pageFaultData ) {
2021-03-08 11:39:07 +00:00
if ( pageFaultData . domain = = AllocationDomain : : Gpu ) {
2022-07-16 01:54:49 +00: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 08:32:25 +00:00
if ( debugManager . flags . PrintUmdSharedMigration . get ( ) ) {
2023-01-03 01:03:44 +00: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 00:53:50 +00:00
}
2022-03-09 14:55:32 +00:00
pageFaultData . unifiedMemoryManager - > nonGpuDomainAllocs . push_back ( ptr ) ;
2021-03-08 11:39:07 +00:00
}
pageFaultData . domain = AllocationDomain : : Cpu ;
}
void PageFaultManager : : selectGpuDomainHandler ( ) {
2023-11-30 08:32:25 +00:00
if ( debugManager . flags . SetCommandStreamReceiver . get ( ) > CommandStreamReceiverType : : CSR_HW | | debugManager . flags . NEO_CAL_ENABLED . get ( ) ) {
2022-11-17 09:03:18 +00:00
this - > gpuDomainHandler = & PageFaultManager : : unprotectAndTransferMemory ;
2021-03-08 11:39:07 +00:00
}
}
2019-11-13 14:19:55 +01:00
void PageFaultManager : : setAubWritable ( bool writable , void * ptr , SVMAllocsManager * unifiedMemoryManager ) {
2019-11-29 17:34:18 +01:00
UNRECOVERABLE_IF ( ptr = = nullptr ) ;
2020-06-29 12:47:13 +02:00
auto gpuAlloc = unifiedMemoryManager - > getSVMAlloc ( ptr ) - > gpuAllocations . getDefaultGraphicsAllocation ( ) ;
2019-11-13 14:19:55 +01:00
gpuAlloc - > setAubWritable ( writable , GraphicsAllocation : : allBanks ) ;
}
2020-07-06 13:09:12 +02:00
2023-07-12 09:18:03 +00: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 12:17:42 +02:00
} // namespace NEO