github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/devices/accel/device.go (about) 1 // Copyright 2023 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package accel 16 17 import ( 18 "fmt" 19 20 "golang.org/x/sys/unix" 21 "github.com/metacubex/gvisor/pkg/abi/linux" 22 "github.com/metacubex/gvisor/pkg/context" 23 "github.com/metacubex/gvisor/pkg/devutil" 24 "github.com/metacubex/gvisor/pkg/errors/linuxerr" 25 "github.com/metacubex/gvisor/pkg/fdnotifier" 26 "github.com/metacubex/gvisor/pkg/log" 27 "github.com/metacubex/gvisor/pkg/sentry/kernel" 28 "github.com/metacubex/gvisor/pkg/sentry/vfs" 29 "github.com/metacubex/gvisor/pkg/sync" 30 ) 31 32 // tpuV4Device implements vfs.Device for /dev/accel[0-9]+. 33 // 34 // +stateify savable 35 type tpuV4Device struct { 36 mu sync.Mutex 37 38 minor uint32 39 lite bool 40 // +checklocks:mu 41 openWriteFDs uint32 42 // +checklocks:mu 43 devAddrSet DevAddrSet 44 // +checklocks:mu 45 owner *kernel.ThreadGroup 46 } 47 48 func (dev *tpuV4Device) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 49 devClient := devutil.GoferClientFromContext(ctx) 50 if devClient == nil { 51 log.Warningf("devutil.CtxDevGoferClient is not set") 52 return nil, linuxerr.ENOENT 53 } 54 dev.mu.Lock() 55 defer dev.mu.Unlock() 56 name := fmt.Sprintf("accel%d", dev.minor) 57 hostFD, err := devClient.OpenAt(ctx, name, opts.Flags) 58 if err != nil { 59 ctx.Warningf("accelDevice: failed to open device %s: %v", name, err) 60 return nil, err 61 } 62 fd := &tpuV4FD{ 63 hostFD: int32(hostFD), 64 device: dev, 65 } 66 if err := fd.vfsfd.Init(fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{ 67 UseDentryMetadata: true, 68 }); err != nil { 69 unix.Close(hostFD) 70 return nil, err 71 } 72 if err := fdnotifier.AddFD(int32(hostFD), &fd.queue); err != nil { 73 unix.Close(hostFD) 74 return nil, err 75 } 76 fd.memmapFile.fd = fd 77 if vfs.MayWriteFileWithOpenFlags(opts.Flags) { 78 dev.openWriteFDs++ 79 } 80 if dev.owner == nil { 81 t := kernel.TaskFromContext(ctx) 82 if t == nil { 83 return nil, linuxerr.ESRCH 84 } 85 dev.owner = t.ThreadGroup() 86 } 87 return &fd.vfsfd, nil 88 } 89 90 // RegisterTPUDevice registers all devices implemented by this package in vfsObj. 91 func RegisterTPUDevice(vfsObj *vfs.VirtualFilesystem, minor uint32, lite bool) error { 92 return vfsObj.RegisterDevice(vfs.CharDevice, linux.ACCEL_MAJOR, minor, &tpuV4Device{ 93 lite: lite, 94 minor: minor, 95 }, &vfs.RegisterDeviceOptions{ 96 GroupName: "accel", 97 }) 98 }