github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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/MerlinKodo/gvisor/pkg/abi/linux" 22 "github.com/MerlinKodo/gvisor/pkg/context" 23 "github.com/MerlinKodo/gvisor/pkg/fdnotifier" 24 "github.com/MerlinKodo/gvisor/pkg/sentry/fsimpl/devtmpfs" 25 "github.com/MerlinKodo/gvisor/pkg/sentry/vfs" 26 "github.com/MerlinKodo/gvisor/pkg/sync" 27 ) 28 29 // accelDevice implements vfs.Device for /dev/accel[0-9]+. 30 // 31 // +stateify savable 32 type accelDevice struct { 33 mu sync.Mutex 34 35 minor uint32 36 // +checklocks:mu 37 openWriteFDs uint32 38 // +checklocks:mu 39 devAddrSet DevAddrSet 40 } 41 42 func (dev *accelDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 43 dev.mu.Lock() 44 defer dev.mu.Unlock() 45 hostPath := fmt.Sprintf("/dev/accel%d", dev.minor) 46 hostFD, err := unix.Openat(-1, hostPath, int((opts.Flags&unix.O_ACCMODE)|unix.O_NOFOLLOW), 0) 47 if err != nil { 48 ctx.Warningf("accelDevice: failed to open host %s: %v", hostPath, err) 49 return nil, err 50 } 51 fd := &accelFD{ 52 hostFD: int32(hostFD), 53 device: dev, 54 } 55 if err := fd.vfsfd.Init(fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{ 56 UseDentryMetadata: true, 57 }); err != nil { 58 unix.Close(hostFD) 59 return nil, err 60 } 61 if err := fdnotifier.AddFD(int32(hostFD), &fd.queue); err != nil { 62 unix.Close(hostFD) 63 return nil, err 64 } 65 fd.memmapFile.fd = fd 66 if vfs.MayWriteFileWithOpenFlags(opts.Flags) { 67 dev.openWriteFDs++ 68 } 69 return &fd.vfsfd, nil 70 } 71 72 // CreateDevtmpfsFile creates a /dev/accel[0-9]+ device file. 73 func CreateDevtmpfsFile(ctx context.Context, dev *devtmpfs.Accessor, num uint32) error { 74 return dev.CreateDeviceFile(ctx, fmt.Sprintf("accel%d", num), vfs.CharDevice, linux.ACCEL_MAJOR, num, 0666) 75 } 76 77 // Register registers all devices implemented by this package in vfsObj. 78 func Register(vfsObj *vfs.VirtualFilesystem, minor uint32) error { 79 return vfsObj.RegisterDevice(vfs.CharDevice, linux.ACCEL_MAJOR, minor, &accelDevice{ 80 minor: minor, 81 }, &vfs.RegisterDeviceOptions{ 82 GroupName: "accel", 83 }) 84 }