mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Implement pass through ioctl command VFIO_DEVICE_GET_INFO.
PiperOrigin-RevId: 617621125
This commit is contained in:
@@ -27,10 +27,49 @@ const (
|
||||
VFIO_TYPE1v2_IOMMU = 3
|
||||
)
|
||||
|
||||
// VFIO device info flags.
|
||||
const (
|
||||
// Device supports reset.
|
||||
VFIO_DEVICE_FLAGS_RESET = 1 << iota
|
||||
// VFIO-pci device.
|
||||
VFIO_DEVICE_FLAGS_PCI
|
||||
// VFIO-platform device.
|
||||
VFIO_DEVICE_FLAGS_PLATFORM
|
||||
// VFIO-amba device.
|
||||
VFIO_DEVICE_FLAGS_AMBA
|
||||
// VFIO-ccw device.
|
||||
VFIO_DEVICE_FLAGS_CCW
|
||||
// VFIO-ap device.
|
||||
VFIO_DEVICE_FLAGS_AP
|
||||
// VFIO-fsl-mc device.
|
||||
VFIO_DEVICE_FLAGS_FSL_MC
|
||||
// Info supports caps.
|
||||
VFIO_DEVICE_FLAGS_CAPS
|
||||
// VFIO-cdx device.
|
||||
VFIO_DEVICE_FLAGS_CDX
|
||||
)
|
||||
|
||||
// IOCTLs for VFIO file descriptor from include/uapi/linux/vfio.h.
|
||||
var (
|
||||
VFIO_CHECK_EXTENSION = IO(VFIO_TYPE, VFIO_BASE+1)
|
||||
VFIO_SET_IOMMU = IO(VFIO_TYPE, VFIO_BASE+2)
|
||||
VFIO_GROUP_SET_CONTAINER = IO(VFIO_TYPE, VFIO_BASE+4)
|
||||
VFIO_GROUP_GET_DEVICE_FD = IO(VFIO_TYPE, VFIO_BASE+6)
|
||||
VFIO_DEVICE_GET_INFO = IO(VFIO_TYPE, VFIO_BASE+7)
|
||||
)
|
||||
|
||||
// VFIODeviceInfo is analogous to vfio_device_info
|
||||
// from include/uapi/linux/vfio.h.
|
||||
//
|
||||
// +marshal
|
||||
type VFIODeviceInfo struct {
|
||||
Argsz uint32
|
||||
Flags uint32
|
||||
// The total amount of regions.
|
||||
NumRegions uint32
|
||||
// The maximum number of IRQ.
|
||||
NumIrqs uint32
|
||||
// Offset within info struct of first cap.
|
||||
CapOffset uint32
|
||||
pad uint32
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ func Filters() seccomp.SyscallRules {
|
||||
seccomp.NonNegativeFD{},
|
||||
seccomp.EqualTo(linux.VFIO_GROUP_GET_DEVICE_FD),
|
||||
},
|
||||
seccomp.PerArg{
|
||||
seccomp.NonNegativeFD{},
|
||||
seccomp.EqualTo(linux.VFIO_DEVICE_GET_INFO),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,6 +32,15 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
var (
|
||||
// vfioDeviceInfoFlags contains all available flags for
|
||||
// IOCTL command VFIO_DEVICE_GET_INFO.
|
||||
vfioDeviceInfoFlags uint32 = linux.VFIO_DEVICE_FLAGS_RESET | linux.VFIO_DEVICE_FLAGS_PCI |
|
||||
linux.VFIO_DEVICE_FLAGS_PLATFORM | linux.VFIO_DEVICE_FLAGS_AMBA |
|
||||
linux.VFIO_DEVICE_FLAGS_CCW | linux.VFIO_DEVICE_FLAGS_AP | linux.VFIO_DEVICE_FLAGS_FSL_MC |
|
||||
linux.VFIO_DEVICE_FLAGS_CAPS | linux.VFIO_DEVICE_FLAGS_CDX
|
||||
)
|
||||
|
||||
// tpuFD implements vfs.FileDescriptionImpl for /dev/vfio/[0-9]+
|
||||
//
|
||||
// tpuFD is not savable until TPU save/restore is needed.
|
||||
@@ -135,8 +144,8 @@ func (fd *tpuFD) getPciDeviceFd(t *kernel.Task, arg hostarch.Addr) (uintptr, fun
|
||||
if err != nil {
|
||||
return 0, func() {}, err
|
||||
}
|
||||
pciDevFD := &pciDeviceFd{
|
||||
hostFd: int32(hostFD),
|
||||
pciDevFD := &pciDeviceFD{
|
||||
hostFD: int32(hostFD),
|
||||
}
|
||||
cleanup := func() {
|
||||
unix.Close(int(hostFD))
|
||||
@@ -160,28 +169,28 @@ func (fd *tpuFD) getPciDeviceFd(t *kernel.Task, arg hostarch.Addr) (uintptr, fun
|
||||
}
|
||||
|
||||
// pciDeviceFD implements vfs.FileDescriptionImpl for TPU's PCI device.
|
||||
type pciDeviceFd struct {
|
||||
type pciDeviceFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.DentryMetadataFileDescriptionImpl
|
||||
vfs.NoLockFD
|
||||
|
||||
hostFd int32
|
||||
hostFD int32
|
||||
queue waiter.Queue
|
||||
memmapFile tpuFDMemmapFile
|
||||
}
|
||||
|
||||
// Release implements vfs.FileDescriptionImpl.Release.
|
||||
func (fd *pciDeviceFd) Release(context.Context) {
|
||||
fdnotifier.RemoveFD(fd.hostFd)
|
||||
func (fd *pciDeviceFD) Release(context.Context) {
|
||||
fdnotifier.RemoveFD(fd.hostFD)
|
||||
fd.queue.Notify(waiter.EventHUp)
|
||||
unix.Close(int(fd.hostFd))
|
||||
unix.Close(int(fd.hostFD))
|
||||
}
|
||||
|
||||
// EventRegister implements waiter.Waitable.EventRegister.
|
||||
func (fd *pciDeviceFd) EventRegister(e *waiter.Entry) error {
|
||||
func (fd *pciDeviceFD) EventRegister(e *waiter.Entry) error {
|
||||
fd.queue.EventRegister(e)
|
||||
if err := fdnotifier.UpdateFD(fd.hostFd); err != nil {
|
||||
if err := fdnotifier.UpdateFD(fd.hostFD); err != nil {
|
||||
fd.queue.EventUnregister(e)
|
||||
return err
|
||||
}
|
||||
@@ -189,24 +198,59 @@ func (fd *pciDeviceFd) EventRegister(e *waiter.Entry) error {
|
||||
}
|
||||
|
||||
// EventUnregister implements waiter.Waitable.EventUnregister.
|
||||
func (fd *pciDeviceFd) EventUnregister(e *waiter.Entry) {
|
||||
func (fd *pciDeviceFD) EventUnregister(e *waiter.Entry) {
|
||||
fd.queue.EventUnregister(e)
|
||||
if err := fdnotifier.UpdateFD(fd.hostFd); err != nil {
|
||||
if err := fdnotifier.UpdateFD(fd.hostFD); err != nil {
|
||||
panic(fmt.Sprint("UpdateFD:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Readiness implements waiter.Waitable.Readiness.
|
||||
func (fd *pciDeviceFd) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return fdnotifier.NonBlockingPoll(fd.hostFd, mask)
|
||||
func (fd *pciDeviceFD) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return fdnotifier.NonBlockingPoll(fd.hostFD, mask)
|
||||
}
|
||||
|
||||
// Epollable implements vfs.FileDescriptionImpl.Epollable.
|
||||
func (fd *pciDeviceFd) Epollable() bool {
|
||||
func (fd *pciDeviceFD) Epollable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Ioctl implements vfs.FileDescriptionImpl.Ioctl.
|
||||
func (fd *pciDeviceFd) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args arch.SyscallArguments) (uintptr, error) {
|
||||
func (fd *pciDeviceFD) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args arch.SyscallArguments) (uintptr, error) {
|
||||
cmd := args[1].Uint()
|
||||
|
||||
t := kernel.TaskFromContext(ctx)
|
||||
if t == nil {
|
||||
panic("Ioctl should be called from a task context")
|
||||
}
|
||||
switch cmd {
|
||||
case linux.VFIO_DEVICE_GET_INFO:
|
||||
return fd.vfioDeviceInfo(ctx, t, args[2].Pointer())
|
||||
}
|
||||
return 0, linuxerr.ENOSYS
|
||||
}
|
||||
|
||||
func (fd *pciDeviceFD) vfioDeviceInfo(ctx context.Context, t *kernel.Task, arg hostarch.Addr) (uintptr, error) {
|
||||
var deviceInfo linux.VFIODeviceInfo
|
||||
if _, err := deviceInfo.CopyIn(t, arg); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Callers must set VFIODevice.Argsz.
|
||||
if deviceInfo.Argsz == 0 {
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
if deviceInfo.Flags&^vfioDeviceInfoFlags != 0 {
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
ret, err := IOCTLInvokePtrArg[uint32](fd.hostFD, linux.VFIO_DEVICE_GET_INFO, &deviceInfo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// gVisor is not supposed to change any device information that is
|
||||
// returned from the host since gVisor doesn't own the device.
|
||||
// Passing the device info back to the caller will be just fine.
|
||||
if _, err := deviceInfo.CopyOut(t, arg); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -84,26 +84,26 @@ func (mf *tpuFDMemmapFile) FD() int {
|
||||
}
|
||||
|
||||
// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
|
||||
func (fd *pciDeviceFd) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
|
||||
func (fd *pciDeviceFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
|
||||
return vfs.GenericConfigureMMap(&fd.vfsfd, fd, opts)
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (fd *pciDeviceFd) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) error {
|
||||
func (fd *pciDeviceFD) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (fd *pciDeviceFd) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) {
|
||||
func (fd *pciDeviceFD) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) {
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (fd *pciDeviceFd) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR hostarch.AddrRange, offset uint64, writable bool) error {
|
||||
func (fd *pciDeviceFD) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR hostarch.AddrRange, offset uint64, writable bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Translate implements memmap.Mappable.Translate.
|
||||
func (fd *pciDeviceFd) Translate(ctx context.Context, required, optional memmap.MappableRange, at hostarch.AccessType) ([]memmap.Translation, error) {
|
||||
func (fd *pciDeviceFD) Translate(ctx context.Context, required, optional memmap.MappableRange, at hostarch.AccessType) ([]memmap.Translation, error) {
|
||||
return []memmap.Translation{
|
||||
{
|
||||
Source: optional,
|
||||
@@ -115,12 +115,12 @@ func (fd *pciDeviceFd) Translate(ctx context.Context, required, optional memmap.
|
||||
}
|
||||
|
||||
// InvalidateUnsavable implements memmap.Mappable.InvalidateUnsavable.
|
||||
func (fd *pciDeviceFd) InvalidateUnsavable(ctx context.Context) error {
|
||||
func (fd *pciDeviceFD) InvalidateUnsavable(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type pciDeviceFdMemmapFile struct {
|
||||
fd *pciDeviceFd
|
||||
fd *pciDeviceFD
|
||||
}
|
||||
|
||||
// IncRef implements memmap.File.IncRef.
|
||||
@@ -139,5 +139,5 @@ func (mf *pciDeviceFdMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.Ac
|
||||
|
||||
// FD implements memmap.File.FD.
|
||||
func (mf *pciDeviceFdMemmapFile) FD() int {
|
||||
return int(mf.fd.hostFd)
|
||||
return int(mf.fd.hostFD)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user