From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (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 4AA202C08D4 for ; Fri, 20 Mar 2026 21:57:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774043839; cv=none; b=UaQB3B0KQCWcxrJzEaR+dg/m/5PogEyCh+wsIeMiylaKk3Xav6wMAI60AXMyOX4Cbrpd4le/sm1SkopjUt/T1XtR0QOrWCTQ8mBMTYUhT3unetM0htnXBNEohIi18ZT2zUZBsb36I2eU1QkMvpchq2Mfe7J2rQbgECOjzOpzAVg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774043839; c=relaxed/simple; bh=6xX94lNKuO8BJj4VJ5mCgOyTaqmlEHPePKXQLfsPth4=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Hs9ZT2Q/1qzi7ENPMilnl6UyaIyd7gw1S6A39pccHLk8MWsW6MlogIFKqqp6mB425v+PxdazBMFAJMcHPY+Ai69301jn0Qoo3l8JGUj8kVsMNPoekDSQ/zW1DEt01qq/3Ebj9fOyRpUKkajRBGTGH7DXaRpRJLtecoHINf81AUw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=F3QQR+a1; arc=none smtp.client-ip=209.85.214.175 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=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="F3QQR+a1" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2b052ec7176so13815ad.1 for ; Fri, 20 Mar 2026 14:57:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774043838; x=1774648638; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=ByWF9dCBnyH2oWxXkKU4G3r/BAZXT29KzMbckrH9HdY=; b=F3QQR+a1eh0o9JwYCxLYFH6Wd6AyrJ91wz/dmMDxAG//lzeU/u7wPNIBRLSjIQtbcO uE4AjTJI9oxUSRf+zDBMyU9qafou4OeJw3wekFq3kRodyAUVRxAMNlQW4OGtxcD1ihQN QNclZMLZ2sAgwia3LnSq/mWSulHy9DA/+HKkivRHReZ1a01sKk5IBBRy1jOqqoIgpQjj i83bO1SS98NdVlSOD51XXv3A8NEq26B2XCE4oZz4Hb1Uwd/Unm0g8R9fmG11aUP8J1Qm lqxFvNkZSN2jxLrP8sCKRKnmoBOF5pgVuW1HfVrGcoqjgpsFtu2EbNl3F1Htl/NuCeKZ tq2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774043838; x=1774648638; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ByWF9dCBnyH2oWxXkKU4G3r/BAZXT29KzMbckrH9HdY=; b=R7VG3JBQADK8fU9ooGOU06bWhyXVAZMOy8IINRSMSFBQyuyKY3RKCoFPcPzPQ5jvds I44gDDffS8fgD8onkOUtAXjPf0UrmMdkfO/ofzf7G721lPpsyVqmKWUJEbUN6j+T7wHz grcetT06NoWBsUF/gKlvnwP4bAdxIZVLja/0Dfo17ORETPwYvZ47FeXZ8I7acWnQ17N4 V6bswNyjPmSyD17f1/egAyMMJWgm3Rq7WRsoUYjAaAo0q5DNR+au8itRciNXAKCnxRFW CXOaFdXH36zsSGqU6a5QKZDBW6Kzs80a8uOa7J13LyyPsbwV7ysg+8hLJ1TsKz7d5UCX 425A== X-Forwarded-Encrypted: i=1; AJvYcCVMVXT0Wp514V04osMU0WBukpBPxPSmBogI17Y7WdnO+kd5ag4vZlSNKGKYzMBWGtFVGSkWYDwNttoMvB0=@vger.kernel.org X-Gm-Message-State: AOJu0YygwtdteC6SoEkj1k7jJNVVrDj3T4xG0NeUFEbdrLvkPGIJC02X scOOSeWomylfxiprhVvk/LR4tTGKdGZ17D4Kn5Z5NFOJ3Jfj4g8dMUtj/8GjKJe9hw== X-Gm-Gg: ATEYQzyXLPip2cncmY299SWSu74jH8cLhnt3iv5UvtbLFqeO6F6GtissICNmMkWgYo7 wjTkKSZ/MsttUxdNhLVNVZlw1/qdx2zZDdBBpLbblkCVQhbkw5vnb8eQgqGglwfURDsS/p3ty6z vVJFEqr/WJiYm0+sQMV4ibdEalWFjkk+xBN/DPxlsMW3mMLt5swGaXA/Or1UFYiuBg3dEqKxa12 Hwt4a9N/Jjn63NBxb/StflI8xCpqPrAISS8cof7PiDn2nvHtK9qAxqETAQJh2YSAosepmCSjIk4 FhYB+d4T19DqmZOhSksYsiqvTK6NOv6lchj2gm0RR+f5EVZ/W1tDdXbP6s2Rnp4LI1gW4gXdgrr NtnxjDB+X2THLgbx2UV++HiSSaVMue4eoWGsvOqQ2dCjP531B2qMLRoE1VZr6oxzsehuM7ni7xP KGDPnRfrSVAQ1S2WNUS9kwwcfhWcOOWTuWVYIBw10pTRY9TEW2DfNeIWPMqw== X-Received: by 2002:a17:903:290:b0:2b0:5b4c:a439 with SMTP id d9443c01a7336-2b08b408c91mr957925ad.2.1774043837210; Fri, 20 Mar 2026 14:57:17 -0700 (PDT) Received: from google.com (10.129.124.34.bc.googleusercontent.com. [34.124.129.10]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35bd3458655sm1477816a91.3.2026.03.20.14.57.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 14:57:16 -0700 (PDT) Date: Fri, 20 Mar 2026 21:57:08 +0000 From: Pranjal Shrivastava To: Samiullah Khawaja Cc: David Woodhouse , Lu Baolu , Joerg Roedel , Will Deacon , Jason Gunthorpe , 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 , Vipin Sharma , YiFei Zhu Subject: Re: [PATCH 05/14] iommupt: Implement preserve/unpreserve/restore callbacks Message-ID: References: <20260203220948.2176157-1-skhawaja@google.com> <20260203220948.2176157-6-skhawaja@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260203220948.2176157-6-skhawaja@google.com> On Tue, Feb 03, 2026 at 10:09:39PM +0000, Samiullah Khawaja wrote: > Implement the iommu domain ops for presevation, unpresevation and > restoration of iommu domains for liveupdate. Use the existing page > walker to preserve the ioptdesc of the top_table and the lower tables. > Preserve the top_level also so it can be restored during boot. > > Signed-off-by: Samiullah Khawaja > --- > drivers/iommu/generic_pt/iommu_pt.h | 96 +++++++++++++++++++++++++++++ > include/linux/generic_pt/iommu.h | 10 +++ > 2 files changed, 106 insertions(+) > > diff --git a/drivers/iommu/generic_pt/iommu_pt.h b/drivers/iommu/generic_pt/iommu_pt.h > index 3327116a441c..0a1adb6312dd 100644 > --- a/drivers/iommu/generic_pt/iommu_pt.h > +++ b/drivers/iommu/generic_pt/iommu_pt.h > @@ -921,6 +921,102 @@ int DOMAIN_NS(map_pages)(struct iommu_domain *domain, unsigned long iova, > } > EXPORT_SYMBOL_NS_GPL(DOMAIN_NS(map_pages), "GENERIC_PT_IOMMU"); > > +/** > + * unpreserve() - Unpreserve page tables and other state of a domain. > + * @domain: Domain to unpreserve > + */ > +void DOMAIN_NS(unpreserve)(struct iommu_domain *domain, struct iommu_domain_ser *ser) I don't see us using the `ser` arg in this function? Shall we remove it? > +{ > + struct pt_iommu *iommu_table = > + container_of(domain, struct pt_iommu, domain); > + struct pt_common *common = common_from_iommu(iommu_table); > + struct pt_range range = pt_all_range(common); > + struct pt_iommu_collect_args collect = { > + .free_list = IOMMU_PAGES_LIST_INIT(collect.free_list), > + }; > + > + iommu_pages_list_add(&collect.free_list, range.top_table); > + pt_walk_range(&range, __collect_tables, &collect); > + > + iommu_unpreserve_pages(&collect.free_list, -1); > +} > +EXPORT_SYMBOL_NS_GPL(DOMAIN_NS(unpreserve), "GENERIC_PT_IOMMU"); > + > +/** > + * preserve() - Preserve page tables and other state of a domain. > + * @domain: Domain to preserve > + * > + * Returns: -ERRNO on failure, on success. Nit: 0 on success? > + */ > +int DOMAIN_NS(preserve)(struct iommu_domain *domain, struct iommu_domain_ser *ser) > +{ > + struct pt_iommu *iommu_table = > + container_of(domain, struct pt_iommu, domain); > + struct pt_common *common = common_from_iommu(iommu_table); > + struct pt_range range = pt_all_range(common); > + struct pt_iommu_collect_args collect = { > + .free_list = IOMMU_PAGES_LIST_INIT(collect.free_list), > + }; > + int ret; > + > + iommu_pages_list_add(&collect.free_list, range.top_table); > + pt_walk_range(&range, __collect_tables, &collect); > + > + ret = iommu_preserve_pages(&collect.free_list); > + if (ret) > + return ret; > + > + ser->top_table = virt_to_phys(range.top_table); > + ser->top_level = range.top_level; > + > + return 0; > +} > +EXPORT_SYMBOL_NS_GPL(DOMAIN_NS(preserve), "GENERIC_PT_IOMMU"); > + > +static int __restore_tables(struct pt_range *range, void *arg, > + unsigned int level, struct pt_table_p *table) > +{ > + struct pt_state pts = pt_init(range, level, table); > + int ret; > + > + for_each_pt_level_entry(&pts) { > + if (pts.type == PT_ENTRY_TABLE) { > + iommu_restore_page(virt_to_phys(pts.table_lower)); > + ret = pt_descend(&pts, arg, __restore_tables); > + if (ret) > + return ret; If pt_descend() returns an error, we immediately return ret. However, we have already successfully called iommu_restore_page() on pts.table_lower and potentially many other tables earlier in the loop or higher up in the tree.. If the domain restore fails halfway through the tree walk, how are these partially restored pages cleaned up? Should we clean them up / free them in an err label or does the caller perform a BUG_ON(ret) ? > + } > + } > + return 0; > +} > + > +/** > + * restore() - Restore page tables and other state of a domain. > + * @domain: Domain to preserve > + * > + * Returns: -ERRNO on failure, on success. Nit: 0 on success? > + */ > +int DOMAIN_NS(restore)(struct iommu_domain *domain, struct iommu_domain_ser *ser) > +{ > + struct pt_iommu *iommu_table = > + container_of(domain, struct pt_iommu, domain); > + struct pt_common *common = common_from_iommu(iommu_table); > + struct pt_range range = pt_all_range(common); > + > + iommu_restore_page(ser->top_table); > + > + /* Free new table */ > + iommu_free_pages(range.top_table); > + > + /* Set the restored top table */ > + pt_top_set(common, phys_to_virt(ser->top_table), ser->top_level); > + > + /* Restore all pages*/ > + range = pt_all_range(common); > + return pt_walk_range(&range, __restore_tables, NULL); > +} > +EXPORT_SYMBOL_NS_GPL(DOMAIN_NS(restore), "GENERIC_PT_IOMMU"); > + [ ------ >8 Snip >8------] Thanks, Praan