From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 B652F3C2798 for ; Mon, 23 Mar 2026 16:41:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284098; cv=none; b=c9iY1swqYRCdDcj1pNLlFqx75v51WsAXwQ+PBLBoGJk1Oucwus+f1o2RZp2DzQKKse89dDAgqJQoZ6mhishPOq0xI5gcR6hrzv4EC0PmD3UYQMwIAksSlYqrdyTKYzJfIsywn9C7jitk2sYsyXPC9i1fMWqm5s4TwmhzXJ8wR5A= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284098; c=relaxed/simple; bh=UeP0Jc9ScLlNXFHH6xFzjkEqbuLq7EKTaQ0Viww18/E=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=kh8SYGXwDxrl67sjJcDogHd1MXSu94vit9JugmPcShNpH/B2oRwkYp6wbRp8+h19U7pcWOeyo8BYwBGe+AYRUlpf9a86YZ+krc2FflHT600AXF9zPecrLA5wXztFbYTQuuiy7O2simwVt/yN/E6rhxz6bPzHFwtNSGNYXGh8HP8= 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=pNWK4N45; arc=none smtp.client-ip=209.85.214.181 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="pNWK4N45" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2b04c9e3eb7so2845ad.0 for ; Mon, 23 Mar 2026 09:41:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774284096; x=1774888896; 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=58Y5zB7xDhthTmxBXC2s4CGQm6/MPS5c4NtdfV6RXIc=; b=pNWK4N45Orxf9mjJqm8MiqyK7+tnZkF+J+3mfSVSz4WJyNb+44l2F9Woz3E4/IKM5f zRbuojpXYrknPCBbW+YhsBIQD1y/f170Oa3JfXvlRkWjmGpYkCwSFQsP1u4y/cxKFz5J K69/kYS/kq2t0ZgBvKiGCsTXk5AOURwp5M0oKV5fDhlQy1hKF36PIKocDxgpAARXB7Lm a/BFHya+Xsm/NJdm3hc/uZZ+1/7VPskI89qGsS3A6BUON5cn0W0zN56gDe1jwB5jW220 V4wbJfu8lmZnNw0QgtcPDAWH/fHYsKmkDgmiaVdbQiC7BHU25yg0OStQItqixZV5PK03 TQmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774284096; x=1774888896; 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=58Y5zB7xDhthTmxBXC2s4CGQm6/MPS5c4NtdfV6RXIc=; b=boij1g2dHnHcBPeURmRreGX0jo6N6Iu02YLZOuc3oRergnsmoveEDmVkRFoQGfdwJ8 MknKTMa1nSmNME5egdfh9dYKOa1DPofNZZTvTYjTfvzg9uyZcB8T6eOPMYuOYHIZ4+R4 jXdijIiQ6LxAJDtZku53QHFZ2JQXxhXKaKFkHMgz1QuZx101+eX7bGTVPE6t4cvCmDfv DrW7QTDW1Yp9ajIg2vu4rSszFhCAawBJilo1mPmTnr5rYfeuC1xnN6p/ndN439AJZ1LT QrBhIpEbVhUxXNo9gEheGpkwjqTgvhkTB891yK5q6ad0NldkyVbPNcAQEoT61/hV1yfQ TFVA== X-Forwarded-Encrypted: i=1; AJvYcCWLXidEkjBxE3MOL/5gOPr4V1mvhFWU4PwfRS6d91fG2wWfSQUcJBDqUuSieHdL+OVYp5yogWUEou13eCo=@vger.kernel.org X-Gm-Message-State: AOJu0YxgUqgOdsUCq0h78LxQuvrtFDeELxQFw5bAp0HIGIlBPmgmf1gV MpZH0WDwmv5btbCM5oKZEUDF/g9cfxt//L9xzUVjJtqEb+ugkOKB8Hfj/af+2i8GliKmkdfr1Zb xDVw/jN8z X-Gm-Gg: ATEYQzztZ5xbMKgbUav87sAjbdUvn8dhvM9hftE+EqCLoK0Xy9jFnwx5xbhjPI2Z4Np R+ODvEszhorzM6Mv0IUnQJiQs+KcZMdVhZbx7xCGjaYppnLFHKeW/Z5IloR0M4CgEuJF2LlHkV1 UjsVdWqiy23GMVf+Gcm3RxKXXzEkk+Klm1Dt1xpgNx5f1uIvXy+Zm45H2aI6Ge5x4MWQT65uTKj WyHMjwTh9yIIaKp4kWG2TurfSGP7RAqtTEQPHP7oIFBYT9XIzqMlf0V0cs6PlQVSD6BA+/cCcXc YNLb32yfvKcnIPM4vbIWPMe0LSemZeg9gyiUd3d0sScfB1nNk9XT2RwjDgyKoJwtSOSxFZ7GgVv dm8ZVyg8YfugzOXoelgLgLBPGgwIM23SvQ5BCPu+WSBdzOSy1pGeGo8A7kVGdv+L915qjGFH9KX 3mS62oSQDsaQhR+s1QrlC1s9m4I26nyGfEVEB8LeuZnpd6A3hroEiCHB/3GiFK8g== X-Received: by 2002:a17:902:f60e:b0:2b0:5683:1cf with SMTP id d9443c01a7336-2b08c4a1360mr4458125ad.13.1774284095381; Mon, 23 Mar 2026 09:41:35 -0700 (PDT) Received: from google.com (168.136.83.34.bc.googleusercontent.com. [34.83.136.168]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35bd271c507sm3728683a91.5.2026.03.23.09.41.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2026 09:41:34 -0700 (PDT) Date: Mon, 23 Mar 2026 16:41:30 +0000 From: Samiullah Khawaja To: Pranjal Shrivastava 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; format=flowed Content-Disposition: inline In-Reply-To: On Fri, Mar 20, 2026 at 09:57:08PM +0000, Pranjal Shrivastava wrote: >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? Hmm.. this is tricky. Its not needed for GPT, but to keep the unpreserve() callback complete, "ser" should be there as some IOMMU that preserves/unpreserves more state with each domain might need this. I am ok either way, WDYT? > >> +{ >> + 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? Agreed. Will update. > >> + */ >> +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) ? Yes, a failed restore here should be fatal. Looking at pt_descend source, it should not fail here anyways as table_lower is init. I will add a BUG_ON here. > >> + } >> + } >> + 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? Agreed. > >> + */ >> +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