Implement pass through ioctl command VFIO_DEVICE_GET_INFO.

PiperOrigin-RevId: 617621125
This commit is contained in:
Jing Chen
2024-03-20 14:12:51 -07:00
committed by gVisor bot
parent 1f6bd75648
commit 705fb540ec
4 changed files with 110 additions and 23 deletions
+39
View File
@@ -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),
},
},
})
}
+59 -15
View File
@@ -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
}
+8 -8
View File
@@ -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)
}