mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
nvproxy: track objects created by NV_ESC_RM_DUP_OBJECT
PiperOrigin-RevId: 704502046
This commit is contained in:
@@ -40,6 +40,9 @@ func (h Handle) String() string {
|
||||
return fmt.Sprintf("%#x", h.Val)
|
||||
}
|
||||
|
||||
// NV01_NULL_OBJECT is a Handle representing no object.
|
||||
var NV01_NULL_OBJECT = Handle{0}
|
||||
|
||||
// P64 is NvP64, from src/common/sdk/nvidia/inc/nvtypes.h.
|
||||
//
|
||||
// +marshal
|
||||
|
||||
@@ -493,6 +493,32 @@ func rmAllocOSDescriptor(fi *frontendIoctlState, ioctlParams *nvgpu.IoctlNVOS02P
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func rmDupObject(fi *frontendIoctlState) (uintptr, error) {
|
||||
var ioctlParams nvgpu.NVOS55Parameters
|
||||
if fi.ioctlParamsSize != nvgpu.SizeofNVOS55Parameters {
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
if _, err := ioctlParams.CopyIn(fi.t, fi.ioctlParamsAddr); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
nvp := fi.fd.dev.nvp
|
||||
nvp.objsLock()
|
||||
n, err := frontendIoctlInvoke(fi, &ioctlParams)
|
||||
if err == nil && ioctlParams.Status == nvgpu.NV_OK {
|
||||
nvp.objDup(fi.ctx, ioctlParams.HClient, ioctlParams.HObject, ioctlParams.HParent, ioctlParams.HClientSrc, ioctlParams.HObjectSrc)
|
||||
}
|
||||
nvp.objsUnlock()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
if _, err := ioctlParams.CopyOut(fi.t, fi.ioctlParamsAddr); err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func rmFree(fi *frontendIoctlState) (uintptr, error) {
|
||||
var ioctlParams nvgpu.NVOS00Parameters
|
||||
if fi.ioctlParamsSize != nvgpu.SizeofNVOS00Parameters {
|
||||
@@ -902,7 +928,7 @@ func rmAllocNoParams(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parameters
|
||||
|
||||
func rmAllocRootClient(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parameters, isNVOS64 bool) (uintptr, error) {
|
||||
return rmAllocSimpleParams(fi, ioctlParams, isNVOS64, func(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parameters, rightsRequested nvgpu.RS_ACCESS_MASK, allocParams *nvgpu.Handle) {
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, ioctlParams.HObjectNew, ioctlParams.HClass, newRootClient(fi.fd, ioctlParams, rightsRequested, allocParams))
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, ioctlParams.HObjectNew, ioctlParams.HClass, newRootClient(fi.fd, ioctlParams, rightsRequested, allocParams), nvgpu.NV01_NULL_OBJECT /* parentH */)
|
||||
if fi.fd.clients == nil {
|
||||
fi.fd.clients = make(map[nvgpu.Handle]struct{})
|
||||
}
|
||||
@@ -928,7 +954,7 @@ func rmAllocEventOSEvent(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parame
|
||||
allocParams.Data = nvgpu.P64(uint64(eventFile.hostFD))
|
||||
|
||||
n, err := rmAllocInvoke(fi, ioctlParams, &allocParams, isNVOS64, func(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parameters, rightsRequested nvgpu.RS_ACCESS_MASK, allocParams *nvgpu.NV0005_ALLOC_PARAMETERS) {
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, ioctlParams.HObjectNew, ioctlParams.HClass, &osEvent{}, ioctlParams.HObjectParent)
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, ioctlParams.HObjectNew, ioctlParams.HClass, &miscObject{}, ioctlParams.HObjectParent)
|
||||
})
|
||||
if err != nil {
|
||||
return n, err
|
||||
|
||||
@@ -326,7 +326,7 @@ func rmVidHeapControlAllocSize(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS32
|
||||
n, err := frontendIoctlInvoke(fi, ioctlParams)
|
||||
if err == nil && ioctlParams.Status == nvgpu.NV_OK {
|
||||
// src/nvidia/src/kernel/mem_mgr/virtual_mem.c:virtmemConstruct_IMPL() => refAddDependant()
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, allocSizeParams.HMemory, nvgpu.NV50_MEMORY_VIRTUAL, &virtMem{}, ioctlParams.HObjectParent, ioctlParams.HVASpace)
|
||||
fi.fd.dev.nvp.objAdd(fi.ctx, ioctlParams.HRoot, allocSizeParams.HMemory, nvgpu.NV50_MEMORY_VIRTUAL, &miscObject{}, ioctlParams.HObjectParent, ioctlParams.HVASpace)
|
||||
}
|
||||
fi.fd.dev.nvp.objsUnlock()
|
||||
allocSizeParams.Address = origAddress
|
||||
|
||||
@@ -31,6 +31,7 @@ type object struct {
|
||||
client *rootClient // may be == impl
|
||||
class nvgpu.ClassID
|
||||
handle nvgpu.Handle // in client.resources, and also nvp.clients if impl is rootClient
|
||||
parent nvgpu.Handle
|
||||
impl objectImpl
|
||||
|
||||
// The driver tracks parent/child relationships and "arbitrary dependency"
|
||||
@@ -73,13 +74,15 @@ func (nvp *nvproxy) objsUnlock() {
|
||||
|
||||
// objAdd records the allocation of a driver object with class c and handle h,
|
||||
// in the client with handle clientH, represented by oi. Each non-zero handle
|
||||
// in deps is a dependency of the created object, such that the freeing of any
|
||||
// of those objects also results in the freeing of the recorded object.
|
||||
func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu.ClassID, oi objectImpl, deps ...nvgpu.Handle) {
|
||||
if h.Val == 0 {
|
||||
log.Traceback("nvproxy: new object (class %v) has invalid handle 0", c)
|
||||
// in parentH and deps is a dependency of the created object, such that the
|
||||
// freeing of any of those objects also results in the freeing of the recorded
|
||||
// object.
|
||||
func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu.ClassID, oi objectImpl, parentH nvgpu.Handle, deps ...nvgpu.Handle) {
|
||||
if h == nvgpu.NV01_NULL_OBJECT {
|
||||
log.Traceback("nvproxy: new object (class %v) has invalid handle %v", c, h)
|
||||
return
|
||||
}
|
||||
|
||||
var client *rootClient
|
||||
// The driver forced NV01_ROOT and NV01_ROOT_NON_PRIV to NV01_ROOT_CLIENT,
|
||||
// so we only need to check for the latter.
|
||||
@@ -98,18 +101,29 @@ func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
o := oi.Object()
|
||||
o.nvp = nvp
|
||||
o.client = client
|
||||
o.class = c
|
||||
o.handle = h
|
||||
o.parent = parentH
|
||||
o.impl = oi
|
||||
if _, ok := client.resources[h]; ok {
|
||||
ctx.Warningf("nvproxy: handle %v:%v already in use", clientH, h)
|
||||
}
|
||||
client.resources[h] = o
|
||||
|
||||
if parentH != nvgpu.NV01_NULL_OBJECT {
|
||||
parent, ok := client.resources[parentH]
|
||||
if !ok {
|
||||
log.Traceback("nvproxy: new object %v:%v (class %v) has invalid parent handle %v", clientH, h, c, parentH)
|
||||
} else {
|
||||
nvp.objDep(o, parent)
|
||||
}
|
||||
}
|
||||
for _, depH := range deps {
|
||||
if depH.Val == 0 /* aka NV01_NULL_OBJECT */ {
|
||||
if depH == nvgpu.NV01_NULL_OBJECT {
|
||||
continue
|
||||
}
|
||||
dep, ok := client.resources[depH]
|
||||
@@ -119,8 +133,9 @@ func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu
|
||||
}
|
||||
nvp.objDep(o, dep)
|
||||
}
|
||||
|
||||
if ctx.IsLogging(log.Debug) {
|
||||
ctx.Debugf("nvproxy: added object %v:%v (class %v) with dependencies %v", clientH, h, c, deps)
|
||||
ctx.Debugf("nvproxy: added object %v:%v (class %v) with parent %v, dependencies %v", clientH, h, c, parentH, deps)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +176,31 @@ func (nvp *nvproxy) objDep(o1, o2 *object) {
|
||||
o2.rdeps[o1] = struct{}{}
|
||||
}
|
||||
|
||||
// objDup records the duplication of the driver object with handle srcH in the
|
||||
// client with handle clientSrcH, to handle dstH in the client with handle
|
||||
// clientDstH, with new parent parentDstH.
|
||||
func (nvp *nvproxy) objDup(ctx context.Context, clientDstH, dstH, parentDstH, clientSrcH, srcH nvgpu.Handle) {
|
||||
clientSrc, ok := nvp.clients[clientSrcH]
|
||||
if !ok {
|
||||
ctx.Warningf("nvproxy: duplicating object handle %v with unknown client handle %v", srcH, clientSrcH)
|
||||
return
|
||||
}
|
||||
oSrc, ok := clientSrc.resources[srcH]
|
||||
if !ok {
|
||||
ctx.Warningf("nvproxy: duplicating object with unknown handle %v:%v", clientSrcH, srcH)
|
||||
return
|
||||
}
|
||||
oDst := &miscObject{}
|
||||
nvp.objAdd(ctx, clientDstH, dstH, oSrc.class, oDst, parentDstH)
|
||||
parentSrc := clientSrc.resources[oSrc.parent]
|
||||
// Copy all non-parent dependencies.
|
||||
for dep := range oSrc.deps {
|
||||
if dep != parentSrc {
|
||||
nvp.objDep(oDst.Object(), dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// objFree marks an object and its transitive dependents as freed.
|
||||
//
|
||||
// Compare
|
||||
@@ -279,6 +319,18 @@ func (o *rmAllocObject) Release(ctx context.Context) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// miscObject is an objectImpl tracking a driver object allocated by something
|
||||
// other than an invocation of NV_ESC_RM_ALLOC, whose class is not represented
|
||||
// by a more specific type.
|
||||
type miscObject struct {
|
||||
object
|
||||
}
|
||||
|
||||
// Release implements objectImpl.Release.
|
||||
func (o *miscObject) Release(ctx context.Context) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// rootClient is an objectImpl tracking a NV01_ROOT_CLIENT.
|
||||
//
|
||||
// +stateify savable
|
||||
@@ -323,23 +375,3 @@ func (o *osDescMem) Release(ctx context.Context) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// osEvent is an objectImpl tracking a NV01_EVENT_OS_EVENT.
|
||||
type osEvent struct {
|
||||
object
|
||||
}
|
||||
|
||||
// Release implements objectImpl.Release.
|
||||
func (o *osEvent) Release(ctx context.Context) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// virtMem is an objectImpl tracking a NV50_MEMORY_VIRTUAL.
|
||||
type virtMem struct {
|
||||
object
|
||||
}
|
||||
|
||||
// Release implements objectImpl.Release.
|
||||
func (o *virtMem) Release(ctx context.Context) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ func Init() {
|
||||
nvgpu.NV_ESC_CHECK_VERSION_STR: feHandler(frontendIoctlSimple, compUtil), // nv_rm_api_version_t
|
||||
nvgpu.NV_ESC_ATTACH_GPUS_TO_FD: feHandler(frontendIoctlSimple, compUtil), // NvU32 array containing GPU IDs
|
||||
nvgpu.NV_ESC_SYS_PARAMS: feHandler(frontendIoctlSimple, compUtil), // nv_ioctl_sys_params_t
|
||||
nvgpu.NV_ESC_RM_DUP_OBJECT: feHandler(frontendIoctlSimple, compUtil), // NVOS55_PARAMETERS
|
||||
nvgpu.NV_ESC_RM_DUP_OBJECT: feHandler(rmDupObject, compUtil), // NVOS55_PARAMETERS
|
||||
nvgpu.NV_ESC_RM_SHARE: feHandler(frontendIoctlSimple, compUtil), // NVOS57_PARAMETERS
|
||||
nvgpu.NV_ESC_RM_UNMAP_MEMORY: feHandler(frontendIoctlSimple, compUtil), // NVOS34_PARAMETERS
|
||||
nvgpu.NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO: feHandler(frontendIoctlSimple, compUtil), // NVOS56_PARAMETERS
|
||||
|
||||
Reference in New Issue
Block a user