Implement pass through ioctl VFIO_IOMMU_UNMAP_DMA.

PiperOrigin-RevId: 620107765
This commit is contained in:
Jing Chen
2024-03-28 17:47:12 -07:00
committed by gVisor bot
parent 5a63761aff
commit 88ee65f3a8
2 changed files with 51 additions and 0 deletions
+21
View File
@@ -106,6 +106,10 @@ const (
VFIO_DMA_MAP_FLAG_VADDR
)
const (
VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP = 1
)
// IOCTLs for VFIO file descriptor from include/uapi/linux/vfio.h.
var (
VFIO_CHECK_EXTENSION = IO(VFIO_TYPE, VFIO_BASE+1)
@@ -118,6 +122,7 @@ var (
VFIO_DEVICE_SET_IRQS = IO(VFIO_TYPE, VFIO_BASE+10)
VFIO_DEVICE_RESET = IO(VFIO_TYPE, VFIO_BASE+11)
VFIO_IOMMU_MAP_DMA = IO(VFIO_TYPE, VFIO_BASE+13)
VFIO_IOMMU_UNMAP_DMA = IO(VFIO_TYPE, VFIO_BASE+14)
)
// VFIODeviceInfo is analogous to vfio_device_info
@@ -191,3 +196,19 @@ type VFIOIommuType1DmaMap struct {
// Size of mapping in bytes.
Size uint64
}
// VFIOIommuType1DmaUnmap is analogous to vfio_iommu_type1_dma_unmap
// from include/uapi/linux/vfio.h.
//
// +marshal
type VFIOIommuType1DmaUnmap struct {
Argsz uint32
Flags uint32
// IO virtual address.
IOVa uint64
// Size of mapping in bytes.
Size uint64
// The `data` field from vfio_iommu_type1_dma_unmap is omitted. The
// field is a flexible array member, and is needed only if the flag
// VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP is enabled.
}
+30
View File
@@ -96,6 +96,8 @@ func (fd *vfioFd) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args
return fd.setIOMMU(extension(args[2].Int()))
case linux.VFIO_IOMMU_MAP_DMA:
return fd.iommuMapDma(ctx, t, args[2].Pointer())
case linux.VFIO_IOMMU_UNMAP_DMA:
return fd.iommuUnmapDma(ctx, t, args[2].Pointer())
}
return 0, linuxerr.ENOSYS
}
@@ -209,6 +211,34 @@ func (fd *vfioFd) iommuMapDma(ctx context.Context, t *kernel.Task, arg hostarch.
return n, nil
}
func (fd *vfioFd) iommuUnmapDma(ctx context.Context, t *kernel.Task, arg hostarch.Addr) (uintptr, error) {
var dmaUnmap linux.VFIOIommuType1DmaUnmap
if _, err := dmaUnmap.CopyIn(t, arg); err != nil {
return 0, err
}
if dmaUnmap.Flags&linux.VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP != 0 {
// VFIO_DMA_UNMAP_FALGS_GET_DIRTY_BITMAP is not used by libtpu for
// gVisor working with TPU.
return 0, linuxerr.ENOSYS
}
n, err := IOCTLInvokePtrArg[uint32](fd.hostFd, linux.VFIO_IOMMU_MAP_DMA, &dmaUnmap)
if err != nil {
return 0, nil
}
fd.device.mu.Lock()
defer fd.device.mu.Unlock()
s := &fd.device.devAddrSet
r := DevAddrRange{Start: dmaUnmap.IOVa, End: dmaUnmap.IOVa + dmaUnmap.Size}
seg := s.LowerBoundSegment(r.Start)
for seg.Ok() && seg.Start() < r.End {
seg = s.Isolate(seg, r)
mm.Unpin([]mm.PinnedRange{seg.Value()})
gap := s.Remove(seg)
seg = gap.NextSegment()
}
return n, nil
}
// VFIO extension.
type extension int32