From 9d2a513de11594b0da34384f7c82d283de4293f2 Mon Sep 17 00:00:00 2001 From: Jing Chen Date: Tue, 19 Mar 2024 20:24:19 -0700 Subject: [PATCH] Add more generic Ioctl helper functions for TPU pass through IOCTLs. PiperOrigin-RevId: 617378718 --- pkg/sentry/devices/accel/BUILD | 2 +- pkg/sentry/devices/accel/gasket.go | 7 ++-- pkg/sentry/devices/accel/gasket_unsafe.go | 35 ------------------- pkg/sentry/devices/accel/tpu_v4.go | 9 ++--- pkg/sentry/devices/tpuproxy/BUILD | 2 +- .../{vfio_unsafe.go => ioctl_unsafe.go} | 9 +++-- pkg/sentry/devices/tpuproxy/tpu.go | 4 +-- pkg/sentry/devices/tpuproxy/vfio.go | 4 +-- 8 files changed, 21 insertions(+), 51 deletions(-) delete mode 100644 pkg/sentry/devices/accel/gasket_unsafe.go rename pkg/sentry/devices/tpuproxy/{vfio_unsafe.go => ioctl_unsafe.go} (63%) diff --git a/pkg/sentry/devices/accel/BUILD b/pkg/sentry/devices/accel/BUILD index a1e640b38..6747d8cb2 100644 --- a/pkg/sentry/devices/accel/BUILD +++ b/pkg/sentry/devices/accel/BUILD @@ -10,7 +10,6 @@ go_library( "devaddr_set.go", "device.go", "gasket.go", - "gasket_unsafe.go", "seccomp_filters.go", "tpu_v4.go", "tpu_v4_mmap.go", @@ -30,6 +29,7 @@ go_library( "//pkg/safemem", "//pkg/seccomp", "//pkg/sentry/arch", + "//pkg/sentry/devices/tpuproxy", "//pkg/sentry/fsimpl/eventfd", "//pkg/sentry/kernel", "//pkg/sentry/memmap", diff --git a/pkg/sentry/devices/accel/gasket.go b/pkg/sentry/devices/accel/gasket.go index 04fa4c927..9a0d5da66 100644 --- a/pkg/sentry/devices/accel/gasket.go +++ b/pkg/sentry/devices/accel/gasket.go @@ -23,6 +23,7 @@ import ( "gvisor.dev/gvisor/pkg/context" "gvisor.dev/gvisor/pkg/errors/linuxerr" "gvisor.dev/gvisor/pkg/hostarch" + "gvisor.dev/gvisor/pkg/sentry/devices/tpuproxy" "gvisor.dev/gvisor/pkg/sentry/fsimpl/eventfd" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/memmap" @@ -103,7 +104,7 @@ func gasketMapBufferIoctl(ctx context.Context, t *kernel.Task, hostFd int32, fd } sentryIoctlParams := userIoctlParams sentryIoctlParams.HostAddress = uint64(m) - n, err := ioctlInvokePtrArg(hostFd, gasket.GASKET_IOCTL_MAP_BUFFER, &sentryIoctlParams) + n, err := tpuproxy.IOCTLInvokePtrArg[gasket.Ioctl](hostFd, gasket.GASKET_IOCTL_MAP_BUFFER, &sentryIoctlParams) if err != nil { return n, err } @@ -150,7 +151,7 @@ func gasketUnmapBufferIoctl(ctx context.Context, t *kernel.Task, hostFd int32, f sentryIoctlParams := userIoctlParams sentryIoctlParams.HostAddress = 0 // clobber this value, it's unused. - n, err := ioctlInvokePtrArg(hostFd, gasket.GASKET_IOCTL_UNMAP_BUFFER, &sentryIoctlParams) + n, err := tpuproxy.IOCTLInvokePtrArg[gasket.Ioctl](hostFd, gasket.GASKET_IOCTL_UNMAP_BUFFER, &sentryIoctlParams) if err != nil { return n, err } @@ -210,7 +211,7 @@ func gasketInterruptMappingIoctl(ctx context.Context, t *kernel.Task, hostFd int sentryIoctlParams := userIoctlParams sentryIoctlParams.EventFD = uint64(eventfd) - n, err := ioctlInvokePtrArg(hostFd, gasket.GASKET_IOCTL_REGISTER_INTERRUPT, &sentryIoctlParams) + n, err := tpuproxy.IOCTLInvokePtrArg[gasket.Ioctl](hostFd, gasket.GASKET_IOCTL_REGISTER_INTERRUPT, &sentryIoctlParams) if err != nil { return n, err } diff --git a/pkg/sentry/devices/accel/gasket_unsafe.go b/pkg/sentry/devices/accel/gasket_unsafe.go deleted file mode 100644 index c3e04336d..000000000 --- a/pkg/sentry/devices/accel/gasket_unsafe.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2023 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package accel - -import ( - "unsafe" - - "golang.org/x/exp/constraints" - "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/abi/gasket" -) - -func ioctlInvokePtrArg[Params any](hostFd int32, cmd gasket.Ioctl, params *Params) (uintptr, error) { - return ioctlInvoke[uintptr](hostFd, cmd, uintptr(unsafe.Pointer(params))) -} - -func ioctlInvoke[Arg constraints.Integer](hostFd int32, cmd gasket.Ioctl, arg Arg) (uintptr, error) { - n, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(hostFd), uintptr(cmd), uintptr(arg)) - if errno != 0 { - return n, errno - } - return n, nil -} diff --git a/pkg/sentry/devices/accel/tpu_v4.go b/pkg/sentry/devices/accel/tpu_v4.go index 71c9f49cb..31c40b585 100644 --- a/pkg/sentry/devices/accel/tpu_v4.go +++ b/pkg/sentry/devices/accel/tpu_v4.go @@ -27,6 +27,7 @@ import ( "gvisor.dev/gvisor/pkg/hostarch" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sentry/arch" + "gvisor.dev/gvisor/pkg/sentry/devices/tpuproxy" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/mm" "gvisor.dev/gvisor/pkg/sentry/vfs" @@ -67,7 +68,7 @@ func (fd *tpuV4FD) Release(context.Context) { Size: r.End - r.Start, HostAddress: 0, } - _, err := ioctlInvokePtrArg(fd.hostFD, gasket.GASKET_IOCTL_UNMAP_BUFFER, &gpti) + _, err := tpuproxy.IOCTLInvokePtrArg[gasket.Ioctl](fd.hostFD, gasket.GASKET_IOCTL_UNMAP_BUFFER, &gpti) if err != nil { log.Warningf("could not unmap range [%#x, %#x) (index %d) on device: %v", r.Start, r.End, v.pageTableIndex, err) } @@ -132,17 +133,17 @@ func (fd *tpuV4FD) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, arg gasket.GASKET_IOCTL_MAP_DMA_BUF: return 0, linuxerr.ENOSYS case gasket.GASKET_IOCTL_RESET: - return ioctlInvoke[uint64](fd.hostFD, gasket.GASKET_IOCTL_RESET, args[2].Uint64()) + return tpuproxy.IOCTLInvoke[gasket.Ioctl, uint64](fd.hostFD, gasket.GASKET_IOCTL_RESET, args[2].Uint64()) case gasket.GASKET_IOCTL_MAP_BUFFER: return gasketMapBufferIoctl(ctx, t, fd.hostFD, fd, argPtr) case gasket.GASKET_IOCTL_UNMAP_BUFFER: return gasketUnmapBufferIoctl(ctx, t, fd.hostFD, fd, argPtr) case gasket.GASKET_IOCTL_CLEAR_INTERRUPT_COUNTS: - return ioctlInvoke(fd.hostFD, gasket.GASKET_IOCTL_CLEAR_INTERRUPT_COUNTS, 0) + return tpuproxy.IOCTLInvoke[gasket.Ioctl](fd.hostFD, gasket.GASKET_IOCTL_CLEAR_INTERRUPT_COUNTS, 0) case gasket.GASKET_IOCTL_REGISTER_INTERRUPT: return gasketInterruptMappingIoctl(ctx, t, fd.hostFD, argPtr, fd.device.lite) case gasket.GASKET_IOCTL_UNREGISTER_INTERRUPT: - return ioctlInvoke[uint64](fd.hostFD, gasket.GASKET_IOCTL_UNREGISTER_INTERRUPT, args[2].Uint64()) + return tpuproxy.IOCTLInvoke[gasket.Ioctl, uint64](fd.hostFD, gasket.GASKET_IOCTL_UNREGISTER_INTERRUPT, args[2].Uint64()) default: return 0, linuxerr.EINVAL } diff --git a/pkg/sentry/devices/tpuproxy/BUILD b/pkg/sentry/devices/tpuproxy/BUILD index ef2330811..2b3605325 100644 --- a/pkg/sentry/devices/tpuproxy/BUILD +++ b/pkg/sentry/devices/tpuproxy/BUILD @@ -8,12 +8,12 @@ go_library( name = "tpuproxy", srcs = [ "device.go", + "ioctl_unsafe.go", "seccomp_filter.go", "tpu.go", "tpu_mmap.go", "vfio.go", "vfio_mmap.go", - "vfio_unsafe.go", ], visibility = [ "//pkg/sentry:internal", diff --git a/pkg/sentry/devices/tpuproxy/vfio_unsafe.go b/pkg/sentry/devices/tpuproxy/ioctl_unsafe.go similarity index 63% rename from pkg/sentry/devices/tpuproxy/vfio_unsafe.go rename to pkg/sentry/devices/tpuproxy/ioctl_unsafe.go index 3444d99ec..7df093917 100644 --- a/pkg/sentry/devices/tpuproxy/vfio_unsafe.go +++ b/pkg/sentry/devices/tpuproxy/ioctl_unsafe.go @@ -21,11 +21,14 @@ import ( "golang.org/x/sys/unix" ) -func ioctlInvokePtrArg[Params any](hostFd int32, cmd uint32, params *Params) (uintptr, error) { - return ioctlInvoke[uintptr](hostFd, cmd, uintptr(unsafe.Pointer(params))) +// IOCTLInvokePtrArg makes ioctl syscalls with the command of the integer type +// and the pointer to any given params. +func IOCTLInvokePtrArg[Cmd constraints.Integer, Params any](hostFd int32, cmd Cmd, params *Params) (uintptr, error) { + return IOCTLInvoke[Cmd, uintptr](hostFd, cmd, uintptr(unsafe.Pointer(params))) } -func ioctlInvoke[Arg constraints.Integer](hostFd int32, cmd uint32, arg Arg) (uintptr, error) { +// IOCTLInvoke makes ioctl syscalls with the arg of the integer type. +func IOCTLInvoke[Cmd, Arg constraints.Integer](hostFd int32, cmd Cmd, arg Arg) (uintptr, error) { n, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(hostFd), uintptr(cmd), uintptr(arg)) if errno != 0 { return n, errno diff --git a/pkg/sentry/devices/tpuproxy/tpu.go b/pkg/sentry/devices/tpuproxy/tpu.go index 451a491a1..59f509cba 100644 --- a/pkg/sentry/devices/tpuproxy/tpu.go +++ b/pkg/sentry/devices/tpuproxy/tpu.go @@ -115,7 +115,7 @@ func (fd *tpuFD) setContainer(ctx context.Context, t *kernel.Task, arg hostarch. if !ok { return 0, linuxerr.EINVAL } - return ioctlInvokePtrArg(fd.hostFD, linux.VFIO_GROUP_SET_CONTAINER, &vfioContainer.hostFd) + return IOCTLInvokePtrArg[uint32](fd.hostFD, linux.VFIO_GROUP_SET_CONTAINER, &vfioContainer.hostFd) } // It will be the caller's responsibility to call the returned cleanup function. @@ -124,7 +124,7 @@ func (fd *tpuFD) getPciDeviceFd(t *kernel.Task, arg hostarch.Addr) (uintptr, fun if err != nil { return 0, func() {}, err } - hostFD, err := ioctlInvokePtrArg(fd.hostFD, linux.VFIO_GROUP_GET_DEVICE_FD, &pciAddress) + hostFD, err := IOCTLInvokePtrArg[uint32](fd.hostFD, linux.VFIO_GROUP_GET_DEVICE_FD, &pciAddress) if err != nil { return 0, func() {}, err } diff --git a/pkg/sentry/devices/tpuproxy/vfio.go b/pkg/sentry/devices/tpuproxy/vfio.go index a0bc9d274..fd47550de 100644 --- a/pkg/sentry/devices/tpuproxy/vfio.go +++ b/pkg/sentry/devices/tpuproxy/vfio.go @@ -99,7 +99,7 @@ func (fd *vfioFd) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args func (fd *vfioFd) checkExtension(ext extension) (uintptr, error) { switch ext { case linux.VFIO_TYPE1_IOMMU, linux.VFIO_SPAPR_TCE_IOMMU, linux.VFIO_TYPE1v2_IOMMU: - ret, err := ioctlInvoke[int32](fd.hostFd, linux.VFIO_CHECK_EXTENSION, int32(ext)) + ret, err := IOCTLInvoke[uint32, int32](fd.hostFd, linux.VFIO_CHECK_EXTENSION, int32(ext)) if err != nil { log.Warningf("check VFIO extension %s: %v", ext, err) return 0, err @@ -114,7 +114,7 @@ func (fd *vfioFd) checkExtension(ext extension) (uintptr, error) { func (fd *vfioFd) setIOMMU(ext extension) (uintptr, error) { switch ext { case linux.VFIO_TYPE1_IOMMU, linux.VFIO_SPAPR_TCE_IOMMU, linux.VFIO_TYPE1v2_IOMMU: - ret, err := ioctlInvoke[int32](fd.hostFd, linux.VFIO_SET_IOMMU, int32(ext)) + ret, err := IOCTLInvoke[uint32, int32](fd.hostFd, linux.VFIO_SET_IOMMU, int32(ext)) if err != nil { log.Warningf("set the IOMMU group to %s: %v", ext, err) return 0, err