From nobody Mon Feb 9 14:33:08 2026 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32749387364 for ; Tue, 3 Feb 2026 22:10:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770156614; cv=none; b=l3GTj64YX39Z2HwuhQnAcfIQ3ghvwL6Uv6Sj+K0MpIQa86LBhBlvlC7TafGmMOueEzuWy84U2dULTx9KQCsaPz0GhsIzYTMJiEg/jnYea+59SHtTzYoA6k8MH9hycWBSxXPPsnDCpx1UqdgQBmjG1I/R1ysXdkpdLhHKGaUa5GM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770156614; c=relaxed/simple; bh=+jbk5dN4Kg0hIbvLC9M49kRaC9JuOCkxvufz9fXJbrA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XWCF1nFHSg2rKgvqAQcnuJkFPA7f5xT5VU56Rv1TvNZU+cpzr6jwtqOeLRsLJYMoLopn4xdBIQ/8MbODd/2GT0WAqs+ubj8C0Fay+/05WQC4XW/fyygseq3EuMcJLoWnDiXxnRHqe37gCZUO8dqkcLFLpF7icjMBPZYkb7T3h3c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=RTVKNeGW; arc=none smtp.client-ip=209.85.210.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="RTVKNeGW" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-81f8c209cfbso3314674b3a.2 for ; Tue, 03 Feb 2026 14:10:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770156613; x=1770761413; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=0BadSv0cPbiUnIcaCmXI9N9Iq0BsivzkGFYVhjIgVFI=; b=RTVKNeGWKSqzkCZeYxarW9+99koTNKK42ZUM336PLgI3h6hz6Lj0vMWXC0YUPOYPVU 3mwk5orD3AyEYAp59IT0DMmltGNANDv0OYq6q6rzau8Ep5MIez1wjNfGd/prCsb2NxKb zAGHDCxt+k8fklWTZFMWCJ1+O4pgop6tPnHpxW9/km7Q7vhrp65dCvTVuXbRcBGo19NY Os+ZU/BPLDrZ3KK5oNSn5fm8Pmk/1NgPuv2bkcx4wy4hSbRAYvQNF1o0pklh0iB9afb9 DNdRxs1lUIFLvGeUEOuGCp9FutepGTh0nq0dQ6EgcOp3TZ/+6hust1c+2TR2znvhihPa MgYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770156613; x=1770761413; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0BadSv0cPbiUnIcaCmXI9N9Iq0BsivzkGFYVhjIgVFI=; b=sTCMztlHg5dUXY6tOmSsC9usadtHprf5T4RPi1SVVDhVpDhuu65DkQq1l7H15Rfzgv ObFpzPKd0wU4hpdk7Rw+xzHR/YDKSh0w1g9k4AzXJ62Mz8gv8m3sjgs9Iw284olkiHvd ZQnwcsMCoQyxbjdjpex6OATqJesIzyAO4HXuUy8JCZCoMY4u89LWIvdpxrEWqQDM9yP+ Og7cpxMrkYrC/hbQ6RxUVqMe3pZKWrkboTi+dC7Fs/3jkGAnNY2msIXv5KWosRchrrMg S3uGOvUxVar1XG5ZGTnpbCA9+/2pPTczN8GxAmzwwlRFOKkhBySk5UH/d2YEatmpzoWa 7uTA== X-Forwarded-Encrypted: i=1; AJvYcCUQVzUTQsJ3jLSPYiTvqAn6OiuwcYmrO3Ghlov3E0sKaDWXu04e0I1m77332l5Erd9cmWW8EWPruFi1Ojg=@vger.kernel.org X-Gm-Message-State: AOJu0YzlcU8jhB6o/YeAcuHbDDTbSo3yOVY5nGQxZREHQzBg9MNSQa5F /8/tHFHu+FzzA7/gy6zC9y52rTUfG4uVE67RSV3L/1/b/dH+LBdDPD689dOb9LDV+kuqfMutyLT sNRgSnCO4Y6feuA== X-Received: from pfld15.prod.google.com ([2002:a05:6a00:198f:b0:77f:33ea:96e9]) (user=skhawaja job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2307:b0:823:1276:9a86 with SMTP id d2e1a72fcca58-8241c5efdabmr771793b3a.39.1770156612602; Tue, 03 Feb 2026 14:10:12 -0800 (PST) Date: Tue, 3 Feb 2026 22:09:48 +0000 In-Reply-To: <20260203220948.2176157-1-skhawaja@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203220948.2176157-1-skhawaja@google.com> X-Mailer: git-send-email 2.53.0.rc2.204.g2597b5adb4-goog Message-ID: <20260203220948.2176157-15-skhawaja@google.com> Subject: [PATCH 14/14] iommufd/selftest: Add test to verify iommufd preservation From: Samiullah Khawaja To: David Woodhouse , Lu Baolu , Joerg Roedel , Will Deacon , Jason Gunthorpe Cc: Samiullah Khawaja , Robin Murphy , Kevin Tian , Alex Williamson , Shuah Khan , iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Saeed Mahameed , Adithya Jayachandran , Parav Pandit , Leon Romanovsky , William Tu , Pratyush Yadav , Pasha Tatashin , David Matlack , Andrew Morton , Chris Li , Pranjal Shrivastava , Vipin Sharma , YiFei Zhu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Test iommufd preservation by setting up an iommufd and vfio cdev and preserve it across live update. Test takes VFIO cdev path of a device bound to vfio-pci driver and binds it to an iommufd being preserved. It also preserves the vfio cdev so the iommufd state associated with it is also preserved. The restore path is tested by restoring the preserved vfio cdev only. Test tries to finish the session without restoring iommufd and confirms that it fails. Signed-off-by: Samiullah Khawaja Signed-off-by: YiFei Zhu --- tools/testing/selftests/iommu/Makefile | 12 + .../selftests/iommu/iommufd_liveupdate.c | 209 ++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 tools/testing/selftests/iommu/iommufd_liveupdate.c diff --git a/tools/testing/selftests/iommu/Makefile b/tools/testing/selftes= ts/iommu/Makefile index 84abeb2f0949..263195af4d6a 100644 --- a/tools/testing/selftests/iommu/Makefile +++ b/tools/testing/selftests/iommu/Makefile @@ -7,4 +7,16 @@ TEST_GEN_PROGS :=3D TEST_GEN_PROGS +=3D iommufd TEST_GEN_PROGS +=3D iommufd_fail_nth =20 +TEST_GEN_PROGS_EXTENDED +=3D iommufd_liveupdate + include ../lib.mk +include ../liveupdate/lib/libliveupdate.mk + +CFLAGS +=3D -I$(top_srcdir)/tools/include +CFLAGS +=3D -MD +CFLAGS +=3D $(EXTRA_CFLAGS) + +$(TEST_GEN_PROGS_EXTENDED): %: %.o $(LIBLIVEUPDATE_O) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) $< $(LIBLIVEUPDATE_= O) $(LDLIBS) -static -o $@ + +EXTRA_CLEAN +=3D $(LIBLIVEUPDATE_O) diff --git a/tools/testing/selftests/iommu/iommufd_liveupdate.c b/tools/tes= ting/selftests/iommu/iommufd_liveupdate.c new file mode 100644 index 000000000000..8b4ea9f2b7e9 --- /dev/null +++ b/tools/testing/selftests/iommu/iommufd_liveupdate.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright (c) 2025, Google LLC. + * Samiullah Khawaja + */ + +#include +#include +#include +#include +#include + +#define __EXPORTED_HEADERS__ +#include +#include +#include +#include +#include + +#include "../kselftest.h" + +#define ksft_assert(condition) \ + do { if (!(condition)) \ + ksft_exit_fail_msg("Failed: %s at %s %d: %s\n", \ + #condition, __FILE__, __LINE__, strerror(errno)); } while (0) + +int setup_cdev(const char *vfio_cdev_path) +{ + int cdev_fd; + + cdev_fd =3D open(vfio_cdev_path, O_RDWR); + if (cdev_fd < 0) + ksft_exit_skip("Failed to open VFIO cdev: %s\n", vfio_cdev_path); + + return cdev_fd; +} + +int open_iommufd(void) +{ + int iommufd; + + iommufd =3D open("/dev/iommu", O_RDWR); + if (iommufd < 0) + ksft_exit_skip("Failed to open /dev/iommu. IOMMUFD support not enabled.\= n"); + + return iommufd; +} + +int setup_iommufd(int iommufd, int memfd, int cdev_fd, int hwpt_token) +{ + int ret; + + struct vfio_device_bind_iommufd bind =3D { + .argsz =3D sizeof(bind), + .flags =3D 0, + }; + struct iommu_ioas_alloc alloc_data =3D { + .size =3D sizeof(alloc_data), + .flags =3D 0, + }; + struct iommu_hwpt_alloc hwpt_alloc =3D { + .size =3D sizeof(hwpt_alloc), + .flags =3D 0, + }; + struct vfio_device_attach_iommufd_pt attach_data =3D { + .argsz =3D sizeof(attach_data), + .flags =3D 0, + }; + struct iommu_hwpt_lu_set_preserve set_preserve =3D { + .size =3D sizeof(set_preserve), + .hwpt_token =3D hwpt_token, + }; + struct iommu_ioas_map_file map_file =3D { + .size =3D sizeof(map_file), + .length =3D SZ_1M, + .flags =3D IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE, + .iova =3D SZ_4G, + .fd =3D memfd, + .start =3D 0, + }; + + bind.iommufd =3D iommufd; + ret =3D ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind); + ksft_assert(!ret); + + ret =3D ioctl(iommufd, IOMMU_IOAS_ALLOC, &alloc_data); + ksft_assert(!ret); + + hwpt_alloc.dev_id =3D bind.out_devid; + hwpt_alloc.pt_id =3D alloc_data.out_ioas_id; + ret =3D ioctl(iommufd, IOMMU_HWPT_ALLOC, &hwpt_alloc); + ksft_assert(!ret); + + attach_data.pt_id =3D hwpt_alloc.out_hwpt_id; + ret =3D ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data); + ksft_assert(!ret); + + map_file.ioas_id =3D alloc_data.out_ioas_id; + ret =3D ioctl(iommufd, IOMMU_IOAS_MAP_FILE, &map_file); + ksft_assert(!ret); + + set_preserve.hwpt_id =3D attach_data.pt_id; + ret =3D ioctl(iommufd, IOMMU_HWPT_LU_SET_PRESERVE, &set_preserve); + ksft_assert(!ret); + + return ret; +} + +static int create_sealed_memfd(size_t size) +{ + int fd, ret; + + fd =3D memfd_create("buffer", MFD_ALLOW_SEALING); + ksft_assert(fd > 0); + + ret =3D ftruncate(fd, size); + ksft_assert(!ret); + + ret =3D fcntl(fd, F_ADD_SEALS, + F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL); + ksft_assert(!ret); + + return fd; +} + +int main(int argc, char *argv[]) +{ + int iommufd, cdev_fd, memfd, luo, session, ret; + const int token =3D 0x123456; + const int cdev_token =3D 0x654321; + const int hwpt_token =3D 0x789012; + const int memfd_token =3D 0x890123; + + if (argc < 2) { + printf("Usage: ./iommufd_liveupdate \n"); + return 1; + } + + luo =3D luo_open_device(); + ksft_assert(luo > 0); + + session =3D luo_retrieve_session(luo, "iommufd-test"); + if (session =3D=3D -ENOENT) { + session =3D luo_create_session(luo, "iommufd-test"); + + iommufd =3D open_iommufd(); + memfd =3D create_sealed_memfd(SZ_1M); + cdev_fd =3D setup_cdev(argv[1]); + + ret =3D setup_iommufd(iommufd, memfd, cdev_fd, hwpt_token); + ksft_assert(!ret); + + /* Cannot preserve cdev without iommufd */ + ret =3D luo_session_preserve_fd(session, cdev_fd, cdev_token); + ksft_assert(ret); + + /* Cannot preserve iommufd without preserving memfd. */ + ret =3D luo_session_preserve_fd(session, iommufd, token); + ksft_assert(ret); + + ret =3D luo_session_preserve_fd(session, memfd, memfd_token); + ksft_assert(!ret); + + ret =3D luo_session_preserve_fd(session, iommufd, token); + ksft_assert(!ret); + + ret =3D luo_session_preserve_fd(session, cdev_fd, cdev_token); + ksft_assert(!ret); + + close(session); + session =3D luo_create_session(luo, "iommufd-test"); + + ret =3D luo_session_preserve_fd(session, memfd, memfd_token); + ksft_assert(!ret); + + ret =3D luo_session_preserve_fd(session, iommufd, token); + ksft_assert(!ret); + + ret =3D luo_session_preserve_fd(session, cdev_fd, cdev_token); + ksft_assert(!ret); + + daemonize_and_wait(); + } else { + struct vfio_device_bind_iommufd bind =3D { + .argsz =3D sizeof(bind), + .flags =3D 0, + }; + + cdev_fd =3D luo_session_retrieve_fd(session, cdev_token); + ksft_assert(cdev_fd > 0); + + iommufd =3D luo_session_retrieve_fd(session, token); + ksft_assert(iommufd < 0); + + iommufd =3D open_iommufd(); + + bind.iommufd =3D iommufd; + ret =3D ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind); + ksft_assert(ret); + ksft_assert(errno =3D=3D EPERM); + + /* Should fail */ + ret =3D luo_session_finish(session); + ksft_assert(ret); + } + + return 0; +} --=20 2.53.0.rc2.204.g2597b5adb4-goog