From patchwork Fri Jan 17 16:29:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fuad Tabba X-Patchwork-Id: 13943555 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 1EFE2C02185 for ; Fri, 17 Jan 2025 16:30:29 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B7A5E6B009B; Fri, 17 Jan 2025 11:30:24 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B002C6B009E; Fri, 17 Jan 2025 11:30:24 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 958066B009F; Fri, 17 Jan 2025 11:30:24 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 6B8CB6B009B for ; Fri, 17 Jan 2025 11:30:24 -0500 (EST) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 298481A05B2 for ; Fri, 17 Jan 2025 16:30:24 +0000 (UTC) X-FDA: 83017481568.18.7CFBFE8 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) by imf07.hostedemail.com (Postfix) with ESMTP id 2FB754000B for ; Fri, 17 Jan 2025 16:30:21 +0000 (UTC) Authentication-Results: imf07.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=q47Jv5iS; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf07.hostedemail.com: domain of 3nIWKZwUKCBUEvwwv19916z.x97638FI-775Gvx5.9C1@flex--tabba.bounces.google.com designates 209.85.128.74 as permitted sender) smtp.mailfrom=3nIWKZwUKCBUEvwwv19916z.x97638FI-775Gvx5.9C1@flex--tabba.bounces.google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1737131422; a=rsa-sha256; cv=none; b=SKATEc8DozljNQhJda5mc03UPCa72scjpYx1xyJD6gvrAKwETQL/DFnU4rUaBYXoMBXvaf Ct9mE2odXrM1Qho7MqSb3XFoMl1JumyeRbbWbT8rUxM8GUbYyUx+zBhMjbBFFfsnPxuZOb 5hwXIy4Wy3NdExxIxKlxPUJMn9qCS+A= ARC-Authentication-Results: i=1; imf07.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=q47Jv5iS; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf07.hostedemail.com: domain of 3nIWKZwUKCBUEvwwv19916z.x97638FI-775Gvx5.9C1@flex--tabba.bounces.google.com designates 209.85.128.74 as permitted sender) smtp.mailfrom=3nIWKZwUKCBUEvwwv19916z.x97638FI-775Gvx5.9C1@flex--tabba.bounces.google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1737131422; 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: in-reply-to:in-reply-to:references:references:dkim-signature; bh=OBxaOc1Oq/7r5hpyeIybyfEKVewLBSFq8w5fQigelgs=; b=ETLzCEC1XVtHl1rxx5+Nnbw/ljBLVB9crxGlNeRlUsaQWzSJ1rSg6C26dfv4rQOsAi3RI9 wqdsNGJEpmVZHKC10yzgxYHeqlx7Y+Z2iLizb+F5vgczJkE6HZXIetNRW6IwoE1Wg6nJ9k U9GEJPXMHaXKqtkCfj7MnPxnolOqCEY= Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-43631d8d9c7so11920065e9.1 for ; Fri, 17 Jan 2025 08:30:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1737131421; x=1737736221; darn=kvack.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=OBxaOc1Oq/7r5hpyeIybyfEKVewLBSFq8w5fQigelgs=; b=q47Jv5iSFmVEtEFSJKsIaQi0MEk7oGxWdVGCQkEptLcVNQcGLuagcxwXyiWBKThEIy q/fSZcT7Si74pAj5DnYXa5dtbDX2+YfmVpI/8kb+U/j9xEPo790jIQo0rm4eQ7QKveMu 6PxAkUgWy/lnNdmgDYlw5CtFwQzku783FsprrLsygVJshWkI72I/GjYJ2FiIDYZkdRBB 8kfWR7rEKepS+/IpwGR2OofYYl25T/i4YM28yco9yX7scoIChvqpTeJoD0lO16yXA9Ko 2R5bXKfbTIXT7aNh0x6x/tMgNP33O6SP16d6Do6kcx2FCYsC4JsW5406qmtIgfVxq/1H WPZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737131421; x=1737736221; 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=OBxaOc1Oq/7r5hpyeIybyfEKVewLBSFq8w5fQigelgs=; b=s7XQFO07i+6L+Aq1hC03Oxp1UVBWfyp25ZTkvkLclpbedH9/yFl47culUMi9vBIEZO R3JBkb2rsRrGs9jq7Kx2AhPMPL8I/XoktOmG3InmnsmAZtC3evryhMRSc/MdfGapxUmC XB6+TpKg5EekKZ5Vr183L0IYzBVwg+E1r4a8h9X57VIiTn1YnMhX/h4RETk2ix25igGv 3otcB7AKJ5tcDnthTwzpTLhrn4F1hR1dLE9fytnlcpKRGcenfQomVFEz4Bhy/Jlb2NPK W3IEN/o/6SZI6qeJdmo1DwsaLAcdgOpfc1zleDTRRyQXSDInN8gToaql1yOdVuZt2tl6 D82g== X-Forwarded-Encrypted: i=1; AJvYcCWDJbmge8f/KsZ9rKJSTaBMQ8jD71vnNfVgfSOC/zNBlwk9DjJ96283UrAt/HNeBc6aacuRYxbkGA==@kvack.org X-Gm-Message-State: AOJu0YznzTBPFpgxb366oW5xuG/pD5+YXByahQZZ4MvEief4IYRK72gM 7FNciy7LiqGow93Lz1KmVuZKecLNi3AbAEDELH5MDRBWvARDbLJPVrpIwTJ5gYyBwvXxjFcpVQ= = X-Google-Smtp-Source: AGHT+IFkVUsgGxCt8u55ieXPYflUnbcSMN6hxhrnCXAB/29entNP9EJfjs2xWohE/JZhqpVEKXf+xlIxAw== X-Received: from wmqe20.prod.google.com ([2002:a05:600c:4e54:b0:434:f350:9fc]) (user=tabba job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:8712:b0:436:1b0b:2633 with SMTP id 5b1f17b1804b1-438918d9008mr33597535e9.9.1737131420833; Fri, 17 Jan 2025 08:30:20 -0800 (PST) Date: Fri, 17 Jan 2025 16:29:54 +0000 In-Reply-To: <20250117163001.2326672-1-tabba@google.com> Mime-Version: 1.0 References: <20250117163001.2326672-1-tabba@google.com> X-Mailer: git-send-email 2.48.0.rc2.279.g1de40edade-goog Message-ID: <20250117163001.2326672-9-tabba@google.com> Subject: [RFC PATCH v5 08/15] KVM: guest_memfd: Add guest_memfd support to kvm_(read|/write)_guest_page() From: Fuad Tabba To: kvm@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-mm@kvack.org Cc: pbonzini@redhat.com, chenhuacai@kernel.org, mpe@ellerman.id.au, anup@brainfault.org, paul.walmsley@sifive.com, palmer@dabbelt.com, aou@eecs.berkeley.edu, seanjc@google.com, viro@zeniv.linux.org.uk, brauner@kernel.org, willy@infradead.org, akpm@linux-foundation.org, xiaoyao.li@intel.com, yilun.xu@intel.com, chao.p.peng@linux.intel.com, jarkko@kernel.org, amoorthy@google.com, dmatlack@google.com, yu.c.zhang@linux.intel.com, isaku.yamahata@intel.com, mic@digikod.net, vbabka@suse.cz, vannapurve@google.com, ackerleytng@google.com, mail@maciej.szmigiero.name, david@redhat.com, michael.roth@amd.com, wei.w.wang@intel.com, liam.merwick@oracle.com, isaku.yamahata@gmail.com, kirill.shutemov@linux.intel.com, suzuki.poulose@arm.com, steven.price@arm.com, quic_eberman@quicinc.com, quic_mnalajal@quicinc.com, quic_tsoni@quicinc.com, quic_svaddagi@quicinc.com, quic_cvanscha@quicinc.com, quic_pderrin@quicinc.com, quic_pheragu@quicinc.com, catalin.marinas@arm.com, james.morse@arm.com, yuzenghui@huawei.com, oliver.upton@linux.dev, maz@kernel.org, will@kernel.org, qperret@google.com, keirf@google.com, roypat@amazon.co.uk, shuah@kernel.org, hch@infradead.org, jgg@nvidia.com, rientjes@google.com, jhubbard@nvidia.com, fvdl@google.com, hughd@google.com, jthoughton@google.com, tabba@google.com X-Rspam-User: X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: 2FB754000B X-Stat-Signature: m1w8hq9rue8344b3xfn56djdga893o3z X-HE-Tag: 1737131421-248992 X-HE-Meta: U2FsdGVkX1/wraAkI1Za1VMji3nLp3J7jMUmW2wy0A5Ucf7eToKDA8fbAjTZCcX0qEYRTecw5Fg+JOii/sO0S9VjHz2qbmtKvs2UJGohmdjDdXoQaWJauDOuyXVEud15Qruk4MS+gs9Ns4VumTpsFVU5CVqqxpzxH1588llxt0g2WPwsQY9Y0571SkpIkc1EcgSMLC/T76lb82sziBp+QRIrphhO0ZRScMRqVUFtZ3/Pbjl0DWCVzVK0+Xyg7tG4dQjzleh9AJ++ZsCmpo6FWoifoUDAMmIZEuwPmd2mOqVJlhuxXbwAdOB2rOxmdaHfMiJaIOCI97G4E7rbHvDOvZ196NAmzUrerx8oMQrDrJJ5BqIAkT3D2mIdCIT3fGK9EDwpbDnpopUe++DWbDCi3nJfwhnKo3zGgoIRzOaU9kjwlWi2C9rajwGi9uMJQ8RWYieTJN3QvVsSh0l1NLF7e32fH/DMsWCiCLeaHWlb31Lu69DK98NAB0HmoJe+BKywOo6RdQbIx/89rW6YE4CbRvmCy9XWOyMURJmpvE52xef1syNn4nu9e5gwy4kwm7TUAJV9StwNm51M8nrT3JJim6Cip/ZnfeIpj6ko/tl/sJMLD0zM8U33U72XrNEWfYtJNsyq3AzaA+G2NYnBlsiqp5jWM3Y7B5OjzxX6TSKgP3i+iRQq98rsnmycv2EsLCgNaIpsNrgq6s6tOdfV0cHXYlOYr4gI6HwT3g/4HuIOJn6jOY2q3wrn1LyY5Tok0G2e3vO5oh4CEGGlL9VztQ/lLYqxnl4DOXUHWxewrtT8XBi7d5oBvyIl3loaqedIXUoMvFXgG2P1p1VK042xsmgQRYJqjsY/op43Sa+KIcwrukqM/hzIOwP2kwZTlaHirIn3TD05qxYin8snrRu+fmEOgJxAIFq2uQZWYgFVKUVccl9bQEoDjpFJ/U6srtGIreeGNzjGR724elFQT5Mkrey iXYn71Eb HrWGmHZnGG4IQSI+dvjzOtjMJoxuVknDVSGDZt1hMgotmcFM39ziAOFFNYJcObPsP5OLDqP3yRriJ4ACX45vqOgSiDXvn7G0dG7TD9FXcm9D3RFZrfcADwknS7mmUF6i+FnsG9YpPtrvlaz+eofxX8k1qPtWcjHbZbCdF9EOfsPa0pHwbC7UHARmIqW8OpqqXv5AHqdhSRnAS5d3Gi3JheofGWGZEKZ43ViTYwp+zlpwRuzuhH6e3wNsG5hV/UJDr3+u/wkDsdwiCQF74gMkOZ/tga8AZbXA4nRsMeKvbu8PlSpNojLB3cTM+ISZW0vLwtqqOX4bL18PtlnZ2JslS7Qq/tucui+Dsbjt/fbdT5bx7+gyPyJYpoHNK9LgU2zzD5DpUBCTPWXRSx9yhQ4GMxYN2CSEn2+iR1nvK67bTDI0mUyyqsnPbb8vulpOV0gsgS4VVarSJUDNfL5LYOzV8OGm9ygslGDGYOoyiaN4zSE4hEYv/aXw4HuOF6SHq0ay70m+2Gd+Uegl9fDpZbS4jjGZ4KOcOmSk+f3mnPJ+u3FvNJGSM01dcjJVo5Bk9p1Kyls+CPOXwbQNdygk+2j2bEO50qkVgqGAfxff4EJCOIZDNQbKRjCwFoNztpNA9LnFDAiw7SeAOjBZ7nrmErKQ30jQXOA== 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: Make kvm_(read|/write)_guest_page() capable of accessing guest memory for slots that don't have a userspace address, but only if the memory is mappable, which also indicates that it is accessible by the host. Signed-off-by: Fuad Tabba --- virt/kvm/kvm_main.c | 133 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 114 insertions(+), 19 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fffff01cebe7..53692feb6213 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3184,23 +3184,110 @@ int kvm_gmem_clear_mappable(struct kvm *kvm, gfn_t start, gfn_t end) return r; } +static int __kvm_read_guest_memfd_page(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn, void *data, int offset, + int len) +{ + struct page *page; + u64 pfn; + int r; + + /* + * Holds the folio lock until after checking whether it can be faulted + * in, to avoid races with paths that change a folio's mappability. + */ + r = kvm_gmem_get_pfn_locked(kvm, slot, gfn, &pfn, &page, NULL); + if (r) + return r; + + if (!kvm_gmem_is_mappable(kvm, gfn, gfn + 1)) { + r = -EPERM; + goto unlock; + } + memcpy(data, page_address(page) + offset, len); +unlock: + unlock_page(page); + if (r) + put_page(page); + else + kvm_release_page_clean(page); + + return r; +} + +static int __kvm_write_guest_memfd_page(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn, const void *data, + int offset, int len) +{ + struct page *page; + u64 pfn; + int r; + + /* + * Holds the folio lock until after checking whether it can be faulted + * in, to avoid races with paths that change a folio's mappability. + */ + r = kvm_gmem_get_pfn_locked(kvm, slot, gfn, &pfn, &page, NULL); + if (r) + return r; + + if (!kvm_gmem_is_mappable(kvm, gfn, gfn + 1)) { + r = -EPERM; + goto unlock; + } + memcpy(page_address(page) + offset, data, len); +unlock: + unlock_page(page); + if (r) + put_page(page); + else + kvm_release_page_dirty(page); + + return r; +} +#else +static int __kvm_read_guest_memfd_page(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn, void *data, int offset, + int len) +{ + WARN_ON_ONCE(1); + return -EIO; +} + +static int __kvm_write_guest_memfd_page(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn, const void *data, + int offset, int len) +{ + WARN_ON_ONCE(1); + return -EIO; +} #endif /* CONFIG_KVM_GMEM_MAPPABLE */ /* Copy @len bytes from guest memory at '(@gfn * PAGE_SIZE) + @offset' to @data */ -static int __kvm_read_guest_page(struct kvm_memory_slot *slot, gfn_t gfn, - void *data, int offset, int len) + +static int __kvm_read_guest_page(struct kvm *kvm, struct kvm_memory_slot *slot, + gfn_t gfn, void *data, int offset, int len) { - int r; unsigned long addr; if (WARN_ON_ONCE(offset + len > PAGE_SIZE)) return -EFAULT; + if (IS_ENABLED(CONFIG_KVM_GMEM_MAPPABLE) && + kvm_slot_can_be_private(slot) && + !slot->userspace_addr) { + return __kvm_read_guest_memfd_page(kvm, slot, gfn, data, + offset, len); + } + addr = gfn_to_hva_memslot_prot(slot, gfn, NULL); if (kvm_is_error_hva(addr)) return -EFAULT; - r = __copy_from_user(data, (void __user *)addr + offset, len); - if (r) + if (__copy_from_user(data, (void __user *)addr + offset, len)) return -EFAULT; return 0; } @@ -3210,7 +3297,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, { struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); - return __kvm_read_guest_page(slot, gfn, data, offset, len); + return __kvm_read_guest_page(kvm, slot, gfn, data, offset, len); } EXPORT_SYMBOL_GPL(kvm_read_guest_page); @@ -3219,7 +3306,7 @@ int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, { struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); - return __kvm_read_guest_page(slot, gfn, data, offset, len); + return __kvm_read_guest_page(vcpu->kvm, slot, gfn, data, offset, len); } EXPORT_SYMBOL_GPL(kvm_vcpu_read_guest_page); @@ -3296,22 +3383,30 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_read_guest_atomic); /* Copy @len bytes from @data into guest memory at '(@gfn * PAGE_SIZE) + @offset' */ static int __kvm_write_guest_page(struct kvm *kvm, - struct kvm_memory_slot *memslot, gfn_t gfn, - const void *data, int offset, int len) + struct kvm_memory_slot *slot, gfn_t gfn, + const void *data, int offset, int len) { - int r; - unsigned long addr; - if (WARN_ON_ONCE(offset + len > PAGE_SIZE)) return -EFAULT; - addr = gfn_to_hva_memslot(memslot, gfn); - if (kvm_is_error_hva(addr)) - return -EFAULT; - r = __copy_to_user((void __user *)addr + offset, data, len); - if (r) - return -EFAULT; - mark_page_dirty_in_slot(kvm, memslot, gfn); + if (IS_ENABLED(CONFIG_KVM_GMEM_MAPPABLE) && + kvm_slot_can_be_private(slot) && + !slot->userspace_addr) { + int r = __kvm_write_guest_memfd_page(kvm, slot, gfn, data, + offset, len); + + if (r) + return r; + } else { + unsigned long addr = gfn_to_hva_memslot(slot, gfn); + + if (kvm_is_error_hva(addr)) + return -EFAULT; + if (__copy_to_user((void __user *)addr + offset, data, len)) + return -EFAULT; + } + + mark_page_dirty_in_slot(kvm, slot, gfn); return 0; }