2017-12-21 07:45:38 +08:00
/*
2021-05-17 02:51:16 +08:00
* Copyright ( C ) 2018 - 2021 Intel Corporation
2017-12-21 07:45:38 +08:00
*
2018-09-18 15:11:08 +08:00
* SPDX - License - Identifier : MIT
2017-12-21 07:45:38 +08:00
*
*/
2020-02-24 05:44:01 +08:00
# include "shared/source/os_interface/linux/drm_buffer_object.h"
2019-02-27 18:39:32 +08:00
2020-05-06 18:37:15 +08:00
# include "shared/source/helpers/aligned_memory.h"
2020-02-24 05:44:01 +08:00
# include "shared/source/helpers/debug_helpers.h"
# include "shared/source/os_interface/linux/drm_memory_manager.h"
2021-06-17 22:14:05 +08:00
# include "shared/source/os_interface/linux/drm_memory_operations_handler.h"
2020-05-06 18:37:15 +08:00
# include "shared/source/os_interface/linux/drm_neo.h"
2021-09-03 19:40:34 +08:00
# include "shared/source/os_interface/linux/os_context_linux.h"
2020-02-24 05:44:01 +08:00
# include "shared/source/os_interface/linux/os_time_linux.h"
2020-08-11 20:00:41 +08:00
# include "shared/source/os_interface/os_context.h"
2020-02-24 05:44:01 +08:00
# include "shared/source/utilities/stackvec.h"
2017-12-21 07:45:38 +08:00
2020-05-06 18:37:15 +08:00
# include "drm/i915_drm.h"
2017-12-21 07:45:38 +08:00
# include <errno.h>
# include <fcntl.h>
2020-05-06 18:37:15 +08:00
# include <map>
2019-02-27 18:39:32 +08:00
# include <stdarg.h>
2020-05-06 18:37:15 +08:00
# include <string.h>
2019-02-27 18:39:32 +08:00
# include <sys/ioctl.h>
# include <sys/mman.h>
# include <sys/syscall.h>
# include <sys/types.h>
2017-12-21 07:45:38 +08:00
# include <unistd.h>
2019-03-26 18:59:46 +08:00
namespace NEO {
2017-12-21 07:45:38 +08:00
2020-08-20 19:20:20 +08:00
BufferObject : : BufferObject ( Drm * drm , int handle , size_t size , size_t maxOsContextCount ) : drm ( drm ) , refCount ( 1 ) , handle ( handle ) , size ( size ) , isReused ( false ) {
2017-12-21 07:45:38 +08:00
this - > tiling_mode = I915_TILING_NONE ;
2018-02-27 06:23:43 +08:00
this - > lockedAddress = nullptr ;
2020-08-11 20:00:41 +08:00
perContextVmsUsed = drm - > isPerContextVMRequired ( ) ;
if ( perContextVmsUsed ) {
2020-08-20 19:20:20 +08:00
bindInfo . resize ( maxOsContextCount ) ;
2020-08-11 20:00:41 +08:00
for ( auto & iter : bindInfo ) {
iter . fill ( false ) ;
}
} else {
bindInfo . resize ( 1 ) ;
bindInfo [ 0 ] . fill ( false ) ;
}
2017-12-21 07:45:38 +08:00
}
uint32_t BufferObject : : getRefCount ( ) const {
return this - > refCount . load ( ) ;
}
bool BufferObject : : close ( ) {
2018-03-20 17:49:09 +08:00
drm_gem_close close = { } ;
2017-12-21 07:45:38 +08:00
close . handle = this - > handle ;
2020-09-25 17:24:15 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintBOCreateDestroyResult . get ( ) , stdout , " Calling gem close on handle: BO-%d \n " , this - > handle ) ;
2020-08-13 16:10:48 +08:00
2017-12-21 07:45:38 +08:00
int ret = this - > drm - > ioctl ( DRM_IOCTL_GEM_CLOSE , & close ) ;
if ( ret ! = 0 ) {
int err = errno ;
2020-09-25 17:24:15 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintDebugMessages . get ( ) , stderr , " ioctl(GEM_CLOSE) failed with %d. errno=%d(%s) \n " , ret , err , strerror ( err ) ) ;
2017-12-20 21:28:42 +08:00
DEBUG_BREAK_IF ( true ) ;
2017-12-21 07:45:38 +08:00
return false ;
}
this - > handle = - 1 ;
return true ;
}
int BufferObject : : wait ( int64_t timeoutNs ) {
2021-04-29 16:58:16 +08:00
if ( this - > drm - > isVmBindAvailable ( ) ) {
2021-02-16 23:25:26 +08:00
return 0 ;
}
2021-06-15 19:31:12 +08:00
int ret = this - > drm - > waitHandle ( this - > handle , - 1 ) ;
2017-12-21 07:45:38 +08:00
UNRECOVERABLE_IF ( ret ! = 0 ) ;
return ret ;
}
bool BufferObject : : setTiling ( uint32_t mode , uint32_t stride ) {
if ( this - > tiling_mode = = mode ) {
return true ;
}
2018-03-20 17:49:09 +08:00
drm_i915_gem_set_tiling set_tiling = { } ;
2017-12-21 07:45:38 +08:00
set_tiling . handle = this - > handle ;
set_tiling . tiling_mode = mode ;
set_tiling . stride = stride ;
2018-03-20 17:49:09 +08:00
if ( this - > drm - > ioctl ( DRM_IOCTL_I915_GEM_SET_TILING , & set_tiling ) ! = 0 ) {
2017-12-21 07:45:38 +08:00
return false ;
}
this - > tiling_mode = set_tiling . tiling_mode ;
return set_tiling . tiling_mode = = mode ;
2018-02-27 06:23:43 +08:00
}
2017-12-21 07:45:38 +08:00
2020-10-15 14:48:58 +08:00
uint32_t BufferObject : : getOsContextId ( OsContext * osContext ) {
return perContextVmsUsed ? osContext - > getContextId ( ) : 0u ;
}
2020-08-11 20:00:41 +08:00
void BufferObject : : fillExecObject ( drm_i915_gem_exec_object2 & execObject , OsContext * osContext , uint32_t vmHandleId , uint32_t drmContextId ) {
2017-12-21 07:45:38 +08:00
execObject . handle = this - > handle ;
2018-03-09 20:03:48 +08:00
execObject . relocation_count = 0 ; //No relocations, we are SoftPinning
2017-12-21 07:45:38 +08:00
execObject . relocs_ptr = 0ul ;
execObject . alignment = 0 ;
2019-02-20 22:08:03 +08:00
execObject . offset = this - > gpuAddress ;
2019-09-03 15:26:49 +08:00
execObject . flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_SUPPORTS_48B_ADDRESS ;
2021-01-29 22:00:01 +08:00
2021-02-05 00:38:03 +08:00
if ( DebugManager . flags . UseAsyncDrmExec . get ( ) = = 1 ) {
execObject . flags | = EXEC_OBJECT_ASYNC ;
2021-01-29 22:00:01 +08:00
}
2020-10-26 18:01:33 +08:00
if ( this - > isMarkedForCapture ( ) ) {
execObject . flags | = EXEC_OBJECT_CAPTURE ;
}
2018-12-11 15:21:56 +08:00
execObject . rsvd1 = drmContextId ;
2017-12-21 07:45:38 +08:00
execObject . rsvd2 = 0 ;
2021-01-27 21:40:33 +08:00
this - > fillExecObjectImpl ( execObject , osContext , vmHandleId ) ;
2017-12-21 07:45:38 +08:00
}
2020-08-11 20:00:41 +08:00
int BufferObject : : exec ( uint32_t used , size_t startOffset , unsigned int flags , bool requiresCoherency , OsContext * osContext , uint32_t vmHandleId , uint32_t drmContextId , BufferObject * const residency [ ] , size_t residencyCount , drm_i915_gem_exec_object2 * execObjectsStorage ) {
2020-05-06 18:37:15 +08:00
for ( size_t i = 0 ; i < residencyCount ; i + + ) {
2020-08-11 20:00:41 +08:00
residency [ i ] - > fillExecObject ( execObjectsStorage [ i ] , osContext , vmHandleId , drmContextId ) ;
2020-05-06 18:37:15 +08:00
}
2020-08-11 20:00:41 +08:00
this - > fillExecObject ( execObjectsStorage [ residencyCount ] , osContext , vmHandleId , drmContextId ) ;
2020-05-06 18:37:15 +08:00
drm_i915_gem_execbuffer2 execbuf { } ;
execbuf . buffers_ptr = reinterpret_cast < uintptr_t > ( execObjectsStorage ) ;
execbuf . buffer_count = static_cast < uint32_t > ( residencyCount + 1u ) ;
execbuf . batch_start_offset = static_cast < uint32_t > ( startOffset ) ;
execbuf . batch_len = alignUp ( used , 8 ) ;
execbuf . flags = flags ;
execbuf . rsvd1 = drmContextId ;
2020-06-09 16:00:59 +08:00
if ( DebugManager . flags . PrintExecutionBuffer . get ( ) ) {
2021-09-03 19:40:34 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintExecutionBuffer . get ( ) , stdout , " Exec called with drmVmId = %u \n " ,
static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) . size ( ) ? static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) [ vmHandleId ] : 0 ) ;
2020-08-13 16:10:48 +08:00
printExecutionBuffer ( execbuf , residencyCount , execObjectsStorage , residency ) ;
2020-06-09 16:00:59 +08:00
}
2020-05-06 18:37:15 +08:00
int ret = this - > drm - > ioctl ( DRM_IOCTL_I915_GEM_EXECBUFFER2 , & execbuf ) ;
2021-05-27 17:41:28 +08:00
2021-06-17 22:14:05 +08:00
if ( ret ! = 0 ) {
2021-10-12 09:32:45 +08:00
int err = this - > drm - > getErrno ( ) ;
if ( err = = EOPNOTSUPP ) {
PRINT_DEBUG_STRING ( DebugManager . flags . PrintDebugMessages . get ( ) , stderr , " ioctl(I915_GEM_EXECBUFFER2) failed with %d. errno=%d(%s) \n " , ret , err , strerror ( err ) ) ;
return err ;
}
2021-10-06 08:37:16 +08:00
static_cast < DrmMemoryOperationsHandler * > ( this - > drm - > getRootDeviceEnvironment ( ) . memoryOperationsInterface . get ( ) ) - > evictUnusedAllocations ( false , true ) ;
2021-07-28 20:35:06 +08:00
ret = this - > drm - > ioctl ( DRM_IOCTL_I915_GEM_EXECBUFFER2 , & execbuf ) ;
}
if ( ret ! = 0 ) {
2021-10-06 08:37:16 +08:00
static_cast < DrmMemoryOperationsHandler * > ( this - > drm - > getRootDeviceEnvironment ( ) . memoryOperationsInterface . get ( ) ) - > evictUnusedAllocations ( true , true ) ;
2021-06-17 22:14:05 +08:00
ret = this - > drm - > ioctl ( DRM_IOCTL_I915_GEM_EXECBUFFER2 , & execbuf ) ;
}
2020-05-06 18:37:15 +08:00
if ( ret = = 0 ) {
return 0 ;
}
int err = this - > drm - > getErrno ( ) ;
2020-09-25 17:24:15 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintDebugMessages . get ( ) , stderr , " ioctl(I915_GEM_EXECBUFFER2) failed with %d. errno=%d(%s) \n " , ret , err , strerror ( err ) ) ;
2020-05-06 18:37:15 +08:00
return err ;
}
2020-10-16 18:59:27 +08:00
int BufferObject : : bind ( OsContext * osContext , uint32_t vmHandleId ) {
int retVal = 0 ;
2020-10-15 14:48:58 +08:00
auto contextId = getOsContextId ( osContext ) ;
2020-08-11 20:00:41 +08:00
if ( ! this - > bindInfo [ contextId ] [ vmHandleId ] ) {
2020-10-16 18:59:27 +08:00
retVal = this - > drm - > bindBufferObject ( osContext , vmHandleId , this ) ;
2020-07-28 13:48:41 +08:00
auto err = this - > drm - > getErrno ( ) ;
2021-09-03 19:40:34 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintBOBindingResult . get ( ) , stderr , " bind BO-%d to VM %u, drmVmId = %u, range: %llx - %llx, size: %lld, result: %d, errno: %d(%s) \n " ,
this - > handle , vmHandleId , static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) . size ( ) ? static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) [ vmHandleId ] : 0 , this - > gpuAddress , ptrOffset ( this - > gpuAddress , this - > size ) , this - > size , retVal , err , strerror ( err ) ) ;
2020-10-16 18:59:27 +08:00
if ( ! retVal ) {
this - > bindInfo [ contextId ] [ vmHandleId ] = true ;
}
2020-07-28 13:48:41 +08:00
}
2020-10-16 18:59:27 +08:00
return retVal ;
2020-07-02 17:49:46 +08:00
}
2020-10-16 18:59:27 +08:00
int BufferObject : : unbind ( OsContext * osContext , uint32_t vmHandleId ) {
int retVal = 0 ;
2020-10-15 14:48:58 +08:00
auto contextId = getOsContextId ( osContext ) ;
2020-08-11 20:00:41 +08:00
if ( this - > bindInfo [ contextId ] [ vmHandleId ] ) {
2020-10-16 18:59:27 +08:00
retVal = this - > drm - > unbindBufferObject ( osContext , vmHandleId , this ) ;
2020-07-28 13:48:41 +08:00
auto err = this - > drm - > getErrno ( ) ;
2021-09-03 19:40:34 +08:00
PRINT_DEBUG_STRING ( DebugManager . flags . PrintBOBindingResult . get ( ) , stderr , " unbind BO-%d from VM %u, drmVmId = %u, range: %llx - %llx, size: %lld, result: %d, errno: %d(%s) \n " ,
this - > handle , vmHandleId , static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) . size ( ) ? static_cast < const OsContextLinux * > ( osContext ) - > getDrmVmIds ( ) [ vmHandleId ] : 0 , this - > gpuAddress , ptrOffset ( this - > gpuAddress , this - > size ) , this - > size , retVal , err , strerror ( err ) ) ;
2020-10-16 18:59:27 +08:00
if ( ! retVal ) {
this - > bindInfo [ contextId ] [ vmHandleId ] = false ;
}
2020-07-28 13:48:41 +08:00
}
2020-10-16 18:59:27 +08:00
return retVal ;
2020-07-02 17:49:46 +08:00
}
2020-08-13 16:10:48 +08:00
void BufferObject : : printExecutionBuffer ( drm_i915_gem_execbuffer2 & execbuf , const size_t & residencyCount , drm_i915_gem_exec_object2 * execObjectsStorage , BufferObject * const residency [ ] ) {
std : : stringstream logger ;
logger < < " drm_i915_gem_execbuffer2 { "
< < " buffer_ptr: " + std : : to_string ( execbuf . buffers_ptr )
< < " , buffer_count: " + std : : to_string ( execbuf . buffer_count )
< < " , batch_start_offset: " + std : : to_string ( execbuf . batch_start_offset )
< < " , batch_len: " + std : : to_string ( execbuf . batch_len )
< < " , flags: " + std : : to_string ( execbuf . flags )
< < " , rsvd1: " + std : : to_string ( execbuf . rsvd1 )
< < " } \n " ;
size_t i ;
for ( i = 0 ; i < residencyCount ; i + + ) {
2020-09-17 21:39:44 +08:00
logger < < " Buffer Object = { handle: BO- " < < execObjectsStorage [ i ] . handle
2020-08-13 16:10:48 +08:00
< < " , address range: 0x " < < ( void * ) execObjectsStorage [ i ] . offset
< < " - 0x " < < ( void * ) ptrOffset ( execObjectsStorage [ i ] . offset , residency [ i ] - > peekSize ( ) )
2021-02-02 12:30:36 +08:00
< < " , flags: " < < std : : hex < < execObjectsStorage [ i ] . flags < < std : : dec
2020-08-13 16:10:48 +08:00
< < " , size: " < < residency [ i ] - > peekSize ( ) < < " } \n " ;
2020-06-09 16:00:59 +08:00
}
2020-09-17 21:39:44 +08:00
logger < < " Command Buffer Object = { handle: BO- " < < execObjectsStorage [ i ] . handle
2020-08-13 16:10:48 +08:00
< < " , address range: 0x " < < ( void * ) execObjectsStorage [ i ] . offset
< < " - 0x " < < ( void * ) ptrOffset ( execObjectsStorage [ i ] . offset , this - > peekSize ( ) )
2021-02-02 12:30:36 +08:00
< < " , flags: " < < std : : hex < < execObjectsStorage [ i ] . flags < < std : : dec
2020-08-13 16:10:48 +08:00
< < " , size: " < < this - > peekSize ( ) < < " } \n " ;
2021-05-27 17:41:28 +08:00
printf ( " %s \n " , logger . str ( ) . c_str ( ) ) ;
2020-06-09 16:00:59 +08:00
}
2021-08-04 19:56:36 +08:00
int bindBOsWithinContext ( BufferObject * const boToPin [ ] , size_t numberOfBos , OsContext * osContext , uint32_t vmHandleId ) {
2020-09-30 14:29:12 +08:00
auto retVal = 0 ;
2020-10-15 14:48:58 +08:00
2020-10-16 19:46:25 +08:00
for ( auto drmIterator = 0u ; drmIterator < osContext - > getDeviceBitfield ( ) . size ( ) ; drmIterator + + ) {
if ( osContext - > getDeviceBitfield ( ) . test ( drmIterator ) ) {
for ( size_t i = 0 ; i < numberOfBos ; i + + ) {
retVal | = boToPin [ i ] - > bind ( osContext , drmIterator ) ;
2020-09-30 14:29:12 +08:00
}
}
2020-10-16 19:46:25 +08:00
}
return retVal ;
}
int BufferObject : : pin ( BufferObject * const boToPin [ ] , size_t numberOfBos , OsContext * osContext , uint32_t vmHandleId , uint32_t drmContextId ) {
auto retVal = 0 ;
2020-11-20 04:43:01 +08:00
if ( this - > drm - > isVmBindAvailable ( ) ) {
2021-08-04 19:56:36 +08:00
retVal = bindBOsWithinContext ( boToPin , numberOfBos , osContext , vmHandleId ) ;
2020-10-16 19:46:25 +08:00
} else {
StackVec < drm_i915_gem_exec_object2 , maxFragmentsCount + 1 > execObject ( numberOfBos + 1 ) ;
retVal = this - > exec ( 4u , 0u , 0u , false , osContext , vmHandleId , drmContextId , boToPin , numberOfBos , & execObject [ 0 ] ) ;
}
return retVal ;
}
int BufferObject : : validateHostPtr ( BufferObject * const boToPin [ ] , size_t numberOfBos , OsContext * osContext , uint32_t vmHandleId , uint32_t drmContextId ) {
auto retVal = 0 ;
2021-05-13 22:28:51 +08:00
if ( this - > drm - > isVmBindAvailable ( ) ) {
2021-08-04 19:56:36 +08:00
for ( size_t i = 0 ; i < numberOfBos ; i + + ) {
retVal = boToPin [ i ] - > bind ( osContext , vmHandleId ) ;
if ( retVal ) {
break ;
}
}
2020-09-30 14:29:12 +08:00
} else {
StackVec < drm_i915_gem_exec_object2 , maxFragmentsCount + 1 > execObject ( numberOfBos + 1 ) ;
retVal = this - > exec ( 4u , 0u , 0u , false , osContext , vmHandleId , drmContextId , boToPin , numberOfBos , & execObject [ 0 ] ) ;
}
2020-10-15 14:48:58 +08:00
2020-09-30 14:29:12 +08:00
return retVal ;
2017-12-21 07:45:38 +08:00
}
2018-02-28 19:09:48 +08:00
2020-09-14 19:28:47 +08:00
void BufferObject : : addBindExtHandle ( uint32_t handle ) {
bindExtHandles . push_back ( handle ) ;
}
2019-03-26 18:59:46 +08:00
} // namespace NEO