From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4544C52D71 for ; Tue, 6 Aug 2024 15:48:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id F01686B0083; Tue, 6 Aug 2024 11:48:33 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EB0E36B0085; Tue, 6 Aug 2024 11:48:33 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D781F6B0088; Tue, 6 Aug 2024 11:48:33 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id B79966B0085 for ; Tue, 6 Aug 2024 11:48:33 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 314F81A031D for ; Tue, 6 Aug 2024 15:48:33 +0000 (UTC) X-FDA: 82422252906.11.895B53F Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) by imf18.hostedemail.com (Postfix) with ESMTP id E6CB51C0006 for ; Tue, 6 Aug 2024 15:48:30 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=amazon.co.uk header.s=amazon201209 header.b=HvuJfUd9; spf=pass (imf18.hostedemail.com: domain of "prvs=941b31e91=roypat@amazon.co.uk" designates 207.171.190.10 as permitted sender) smtp.mailfrom="prvs=941b31e91=roypat@amazon.co.uk"; dmarc=pass (policy=quarantine) header.from=amazon.co.uk ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1722959261; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=yc/1mWs6SeF5HnWAzCvUQzyjIjCuiLTryEo53m/a1v4=; b=pUb6JaRE++0A8fyN+glMmQWt1rE1/QcOECHsTll2HFZDB1kUCrjkEi+J9TvE258W5tt8XH EiUYX1KgF8Url9wjU7ge/GtQ8So+iWjlVWc8tW6z2ma6L4NPFnWE1BlGP/JSXSa/CCzWXT PKf5FT0qp9cbUotrWmUVQAkD3IhYrxg= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=amazon.co.uk header.s=amazon201209 header.b=HvuJfUd9; spf=pass (imf18.hostedemail.com: domain of "prvs=941b31e91=roypat@amazon.co.uk" designates 207.171.190.10 as permitted sender) smtp.mailfrom="prvs=941b31e91=roypat@amazon.co.uk"; dmarc=pass (policy=quarantine) header.from=amazon.co.uk ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1722959261; a=rsa-sha256; cv=none; b=5nb7v5cvlRwTxJWJoJZ54otoRJdYXNydVEmwZfR99H01+z7u+ik68XQR4CD5cWNR3jczvS d2K1OaxIgdQsduMmWbEcoHhATnbPcic3e8YW8mzB7BQ8Law9qLoY90KNTYqWwczmAyLnyf H3ZPaENP1jPcW+Aw7iQfFTq+fYD2ulc= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.co.uk; i=@amazon.co.uk; q=dns/txt; s=amazon201209; t=1722959311; x=1754495311; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=yc/1mWs6SeF5HnWAzCvUQzyjIjCuiLTryEo53m/a1v4=; b=HvuJfUd9dQIB4Plkbct/T3G3A+ll+Ca+N8Y9NohiafC2w6IgWRLQBESP u9/KP6I8hq/aCerqDbSd1RCvwb15eTxNiWhtRjabo9vN/K2NFhu7guV9r Tbl1VVgz3xa7auXPkJB0yhZ2GYOmH2exzVvzgLg/ABdbjTJju8FTUR0Tg I=; X-IronPort-AV: E=Sophos;i="6.09,268,1716249600"; d="scan'208";a="360852274" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO smtpout.prod.us-west-2.prod.farcaster.email.amazon.dev) ([10.43.8.6]) by smtp-border-fw-33001.sea14.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Aug 2024 15:48:27 +0000 Received: from EX19MTAEUA001.ant.amazon.com [10.0.17.79:8908] by smtpin.naws.eu-west-1.prod.farcaster.email.amazon.dev [10.0.26.94:2525] with esmtp (Farcaster) id 114b04b0-66ae-461d-8af3-867b0de2b6ff; Tue, 6 Aug 2024 15:48:26 +0000 (UTC) X-Farcaster-Flow-ID: 114b04b0-66ae-461d-8af3-867b0de2b6ff Received: from EX19D022EUC002.ant.amazon.com (10.252.51.137) by EX19MTAEUA001.ant.amazon.com (10.252.50.50) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.34; Tue, 6 Aug 2024 15:48:25 +0000 Received: from EX19MTAUEB001.ant.amazon.com (10.252.135.35) by EX19D022EUC002.ant.amazon.com (10.252.51.137) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.34; Tue, 6 Aug 2024 15:48:25 +0000 Received: from [127.0.0.1] (172.19.88.180) by mail-relay.amazon.com (10.252.135.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.34 via Frontend Transport; Tue, 6 Aug 2024 15:48:23 +0000 Message-ID: <6660faa6-4cea-4ddc-a378-ab9da9139ee9@amazon.co.uk> Date: Tue, 6 Aug 2024 16:48:22 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH RFC 4/4] mm: guest_memfd: Add ability for mmap'ing pages To: Elliot Berman , Andrew Morton , Paolo Bonzini , "Sean Christopherson" , Fuad Tabba , "David Hildenbrand" , , Ackerley Tng CC: , , , , , James Gowans , "Kalyazin, Nikita" , "Manwaring, Derek" , "Cali, Marco" References: <20240805-guest-memfd-lib-v1-0-e5a29a4ff5d7@quicinc.com> <20240805-guest-memfd-lib-v1-4-e5a29a4ff5d7@quicinc.com> From: Patrick Roy Content-Language: en-US Autocrypt: addr=roypat@amazon.co.uk; keydata= xjMEY0UgYhYJKwYBBAHaRw8BAQdA7lj+ADr5b96qBcdINFVJSOg8RGtKthL5x77F2ABMh4PN NVBhdHJpY2sgUm95IChHaXRodWIga2V5IGFtYXpvbikgPHJveXBhdEBhbWF6b24uY28udWs+ wpMEExYKADsWIQQ5DAcjaM+IvmZPLohVg4tqeAbEAgUCY0UgYgIbAwULCQgHAgIiAgYVCgkI CwIEFgIDAQIeBwIXgAAKCRBVg4tqeAbEAmQKAQC1jMl/KT9pQHEdALF7SA1iJ9tpA5ppl1J9 AOIP7Nr9SwD/fvIWkq0QDnq69eK7HqW14CA7AToCF6NBqZ8r7ksi+QLOOARjRSBiEgorBgEE AZdVAQUBAQdAqoMhGmiXJ3DMGeXrlaDA+v/aF/ah7ARbFV4ukHyz+CkDAQgHwngEGBYKACAW IQQ5DAcjaM+IvmZPLohVg4tqeAbEAgUCY0UgYgIbDAAKCRBVg4tqeAbEAtjHAQDkh5jZRIsZ 7JMNkPMSCd5PuSy0/Gdx8LGgsxxPMZwePgEAn5Tnh4fVbf00esnoK588bYQgJBioXtuXhtom 8hlxFQM= In-Reply-To: <20240805-guest-memfd-lib-v1-4-e5a29a4ff5d7@quicinc.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Stat-Signature: ycsugk1dsx846upwe88knwwp7i5kzwaf X-Rspam-User: X-Rspamd-Queue-Id: E6CB51C0006 X-Rspamd-Server: rspam02 X-HE-Tag: 1722959310-616174 X-HE-Meta: U2FsdGVkX1+eSb3a/PVLb7eE0eZiHHY2sqcPrvzWElSVZJkQ4pit3gKmEb0H+8tS1y1N/0uOE2t+HqyNe5A8L5WO4higA6Fugt0s/HtsGTHMTZgSTNu1AicQfp+elCgMPfx5bagROeYfBKBFA3w20FA+XE2ivOQD7KLtaMuhga7oPMIJVqeuvDrlIrRDfwGPIaVap/Qr3AIegLiMSRKFcE0M/g95NDz5GF4Dw4+AaaNRHDwOkUbd6A2sAtOyjFRbmPs6seMv0BTZ7XxjDvWiRJ2UNCJvVJMvLkKGVm+uhg83I3imoiua0wkdwf1DbzisNfZTII5mZSFNZ4980SzGuVeyc6LTEXecmUMaTiSYcRPvsn0+URJXeYRYQnKLtWZ1Hqk/ePyOE1h85pHOyHHZOO3BNw0VHQV0i3ZWNNcp110rvwlCdShhRTR+EX6XQCZxHZG4xc0pYvKtMz42XWlnAyzd9yqq65xknVeqyQvsoNpNr6kWiRblKz5DsxdyKGHFpYL9qfbNX6AYrIsMq5aa4IHmLzq9t9xWEyO3Gx1RjmolSnvpGLgk//9pwgZD9zJ2Bocc03Cs7dMD+fBqSq1x7T2Pvac/9FbajevhwD7MFJY+9i3O2pAJBtIMzNXJcKBZhfCUrueANlKhr+J5N/Uc1h6ryCThansOQwxOYNBFRKAJJD22DuBd3jhFY9mV/btl1bcRGDpI8eesGB3ChFRXZYPfpfAPWSsdvIWAHhzwaAWNV1p3lWB/y24xEW9khEHkMd3ryhPc550C/wMAOQHraWCcHplCWIAHNGgvdpP3pNHMDXazaldE4fOWUxFpwNJsYvtLdQlLkQBl6v75PiD/2dmbQMwpLL3JjwKeBtUaBRTVBAzJjJEexdgEGT+KS/jT+/pEQxMSijaulig7tpVK5nJh3g6GCMEeoq4WF5GGuMlfvygjTQ2a6s4mdUNQl2cS8oBkPyV6h23OZ2hO8eC AZ9vf0Sj AyCisEcsz9YkAO0x8+/ywLuUY0Evl44uies6Vgkdz4fWGaMwJp+AMu6BZ2kIswTFQuUts6ZWtJFAQzcYEN9N8vM/BUr8bWvg2Wdue7xbCyh1KnIF8GPXOCaNkjW9Adh4eqi7u8gMFe6Xo4tdP8G8hvW5EP7apXmx51ToMEVsvwxrT6fON+K1gJ/P+laUpGrdMB/zu54V498ccvlP7K8e30cLWWikLKdR15UPw7rnW7OZRZ5pRLXsVtbQ9RnrIqQndA0adl0YpgdRcYITWf9CcOSivf67B4InCss92MueeNa+A5FE1qcy25MkgIveNjkmjUdcQKxMf9xnM9S0fOWyEmk59dj7dZ614ctM41gUcbVouD2QrIc6aR9XaE3OpdC1Ds7j2xrub9OpBNrhHgnTfyAGBTfSggJ8SG+dHifs/oXX9w0m8khLyRsX0y71S7zz5r0AG4L5F1zOiTvJMFh7Tb02V6mIyKPsxMC8nh3Ij9zga4dLpb2pELxXfj48Jo7Wa8394mVEI+MFupi/VLWtP2LAkau6QtCQn+gFd X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On Mon, 2024-08-05 at 19:34 +0100, Elliot Berman wrote: > Confidential/protected guest virtual machines want to share some memory > back with the host Linux. For example, virtqueues allow host and > protected guest to exchange data. In MMU-only isolation of protected > guest virtual machines, the transition between "shared" and "private" > can be done in-place without a trusted hypervisor copying pages. > > Add support for this feature and allow Linux to mmap host-accessible > pages. When the owner provides an ->accessible() callback in the > struct guest_memfd_operations, guest_memfd allows folios to be mapped > when the ->accessible() callback returns 0. Wouldn't the set of inaccessible folios always match exactly the set of folios that have PG_private=1 set? At least guest_memfd instances that have GUEST_MEMFD_FLAG_NO_DIRECT_MAP set, having folios without direct map entries marked "accessible" sound like it may cause a lot of mayhem (as those folios would essentially be secretmem folios, but this time without the GUP checks). But even more generally, wouldn't tracking accessibility via PG_private be enough? > To safely make inaccessible: > > ``` > folio = guest_memfd_grab_folio(inode, index, flags); > r = guest_memfd_make_inaccessible(inode, folio); > if (r) > goto err; > > hypervisor_does_guest_mapping(folio); > > folio_unlock(folio); > ``` > > hypervisor_does_s2_mapping(folio) should make it so > ops->accessible(...) on those folios fails. > > The folio lock ensures atomicity. > > Signed-off-by: Elliot Berman > --- > include/linux/guest_memfd.h | 7 ++++ > mm/guest_memfd.c | 81 ++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 87 insertions(+), 1 deletion(-) > > diff --git a/include/linux/guest_memfd.h b/include/linux/guest_memfd.h > index f9e4a27aed67..edcb4ba60cb0 100644 > --- a/include/linux/guest_memfd.h > +++ b/include/linux/guest_memfd.h > @@ -16,12 +16,18 @@ > * @invalidate_end: called after invalidate_begin returns success. Optional. > * @prepare: called before a folio is mapped into the guest address space. > * Optional. > + * @accessible: called after prepare returns success and before it's mapped > + * into the guest address space. Returns 0 if the folio can be > + * accessed. > + * Optional. If not present, assumes folios are never accessible. > * @release: Called when releasing the guest_memfd file. Required. > */ > struct guest_memfd_operations { > int (*invalidate_begin)(struct inode *inode, pgoff_t offset, unsigned long nr); > void (*invalidate_end)(struct inode *inode, pgoff_t offset, unsigned long nr); > int (*prepare)(struct inode *inode, pgoff_t offset, struct folio *folio); > + int (*accessible)(struct inode *inode, struct folio *folio, > + pgoff_t offset, unsigned long nr); > int (*release)(struct inode *inode); > }; > > @@ -48,5 +54,6 @@ struct file *guest_memfd_alloc(const char *name, > const struct guest_memfd_operations *ops, > loff_t size, unsigned long flags); > bool is_guest_memfd(struct file *file, const struct guest_memfd_operations *ops); > +int guest_memfd_make_inaccessible(struct file *file, struct folio *folio); > > #endif > diff --git a/mm/guest_memfd.c b/mm/guest_memfd.c > index e9d8cab72b28..6b5609932ca5 100644 > --- a/mm/guest_memfd.c > +++ b/mm/guest_memfd.c > @@ -9,6 +9,8 @@ > #include > #include > > +#include "internal.h" > + > static inline int guest_memfd_folio_private(struct folio *folio) > { > unsigned long nr_pages = folio_nr_pages(folio); > @@ -89,7 +91,7 @@ struct folio *guest_memfd_grab_folio(struct file *file, pgoff_t index, u32 flags > goto out_err; > } > > - if (gmem_flags & GUEST_MEMFD_FLAG_NO_DIRECT_MAP) { > + if (!ops->accessible && (gmem_flags & GUEST_MEMFD_FLAG_NO_DIRECT_MAP)) { > r = guest_memfd_folio_private(folio); > if (r) > goto out_err; > @@ -107,6 +109,82 @@ struct folio *guest_memfd_grab_folio(struct file *file, pgoff_t index, u32 flags > } > EXPORT_SYMBOL_GPL(guest_memfd_grab_folio); > > +int guest_memfd_make_inaccessible(struct file *file, struct folio *folio) > +{ > + unsigned long gmem_flags = (unsigned long)file->private_data; > + unsigned long i; > + int r; > + > + unmap_mapping_folio(folio); > + > + /** > + * We can't use the refcount. It might be elevated due to > + * guest/vcpu trying to access same folio as another vcpu > + * or because userspace is trying to access folio for same reason > + * > + * folio_lock serializes the transitions between (in)accessible > + */ > + if (folio_maybe_dma_pinned(folio)) > + return -EBUSY; > + > + if (gmem_flags & GUEST_MEMFD_FLAG_NO_DIRECT_MAP) { > + r = guest_memfd_folio_private(folio); > + if (r) > + return r; > + } > + > + return 0; > +} > + > +static vm_fault_t gmem_fault(struct vm_fault *vmf) > +{ > + struct file *file = vmf->vma->vm_file; > + struct inode *inode = file_inode(file); > + const struct guest_memfd_operations *ops = inode->i_private; > + struct folio *folio; > + pgoff_t off; > + int r; > + > + folio = guest_memfd_grab_folio(file, vmf->pgoff, GUEST_MEMFD_GRAB_UPTODATE); > + if (!folio) > + return VM_FAULT_SIGBUS; > + > + off = vmf->pgoff & (folio_nr_pages(folio) - 1); > + r = ops->accessible(inode, folio, off, 1); > + if (r) { This made be stumble at first. I know you say ops->accessible returning 0 means "this is accessible", but if I only look at this if-statement it reads as "if the folio is accessible, send a SIGBUS", which is not what's actually happening. > + folio_unlock(folio); > + folio_put(folio); > + return VM_FAULT_SIGBUS; > + } > + > + guest_memfd_folio_clear_private(folio); > + > + vmf->page = folio_page(folio, off); > + > + return VM_FAULT_LOCKED; > +} > + > +static const struct vm_operations_struct gmem_vm_ops = { > + .fault = gmem_fault, > +}; > + > +static int gmem_mmap(struct file *file, struct vm_area_struct *vma) > +{ > + const struct guest_memfd_operations *ops = file_inode(file)->i_private; > + > + if (!ops->accessible) > + return -EPERM; > + > + /* No support for private mappings to avoid COW. */ > + if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) != > + (VM_SHARED | VM_MAYSHARE)) > + return -EINVAL; > + > + file_accessed(file); > + vma->vm_ops = &gmem_vm_ops; > + return 0; > +} > + > static long gmem_punch_hole(struct file *file, loff_t offset, loff_t len) > { > struct inode *inode = file_inode(file); > @@ -220,6 +298,7 @@ static int gmem_release(struct inode *inode, struct file *file) > static struct file_operations gmem_fops = { > .open = generic_file_open, > .llseek = generic_file_llseek, > + .mmap = gmem_mmap, > .release = gmem_release, > .fallocate = gmem_fallocate, > .owner = THIS_MODULE, > > -- > 2.34.1 >