From: Sean Christopherson <seanjc@google.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Ashutosh Desai <ashutoshdesai993@gmail.com>
Subject: [PATCH v2 6/6] KVM: SEV: Allocate only as many bytes as needed for temp crypt buffers
Date: Thu, 16 Apr 2026 16:10:43 -0700 [thread overview]
Message-ID: <20260416231043.3402410-7-seanjc@google.com> (raw)
In-Reply-To: <20260416231043.3402410-1-seanjc@google.com>
When using a temporary buffer to {de,en}crypt unaligned memory for debug,
allocate only the number of bytes that are needed instead of allocating an
entire page. The most common case for unaligned accesses will be reading
or writing less than 16 bytes.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/sev.c | 69 ++++++++++++++----------------------------
1 file changed, 22 insertions(+), 47 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 89586f821c9c..0865ce4bcecb 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1253,53 +1253,34 @@ static int sev_issue_dbg_cmd(struct kvm *kvm, unsigned long src_pa,
return sev_issue_cmd(kvm, cmd, &data, error);
}
-static struct page *sev_alloc_dbg_buffer(void **buf)
+static void *sev_dbg_crypt_slow_alloc(struct page *page, unsigned long __va,
+ unsigned int len, unsigned long *pa,
+ unsigned int *nr_bytes)
{
- struct page *buf_p;
-
- buf_p = alloc_page(GFP_KERNEL);
- if (!buf_p)
- return NULL;
-
- *buf = kmap_local_page(buf_p);
- return buf_p;
-}
-
-static void sev_free_dbg_buffer(struct page *buf_p, void *buf)
-{
- kunmap_local(buf);
- __free_page(buf_p);
-}
-
-static unsigned int sev_dbg_crypt_slow_addr_and_size(struct page *page,
- unsigned long __va,
- unsigned int len,
- unsigned long *pa)
-{
- /* The number of bytes to {de,en}crypt must be 16-byte aligned. */
- unsigned int nr_bytes = round_up(len, 16);
unsigned long va = ALIGN_DOWN(__va, 16);
+ /* The number of bytes to {de,en}crypt must be 16-byte aligned. */
+ *nr_bytes = round_up(len, 16);
+
/*
* Increase the number of bytes to {de,en}crypt by one chunk (16 bytes)
* if the aligned address and length doesn't cover the unaligned range,
* e.g. if the address is unaligned _and_ the access will split a chunk
* at the tail.
*/
- if (va + nr_bytes < __va + len)
- nr_bytes += 16;
+ if (va + *nr_bytes < __va + len)
+ *nr_bytes += 16;
*pa = __sme_page_pa(page) + (va & ~PAGE_MASK);
/*
* Sanity check that the new access won't split a page. This should
- * never happen; just squash the access and let the firmware command
- * fail.
+ * never happen; just pretend the allocation failed.
*/
- if (WARN_ON_ONCE((*pa & PAGE_MASK) != ((*pa + nr_bytes - 1) & PAGE_MASK)))
- return 0;
+ if (WARN_ON_ONCE((*pa & PAGE_MASK) != ((*pa + *nr_bytes - 1) & PAGE_MASK)))
+ return NULL;
- return nr_bytes;
+ return kmalloc(*nr_bytes, GFP_KERNEL);
}
static int sev_dbg_decrypt_slow(struct kvm *kvm, unsigned long src,
@@ -1308,17 +1289,14 @@ static int sev_dbg_decrypt_slow(struct kvm *kvm, unsigned long src,
{
unsigned int nr_bytes;
unsigned long src_pa;
- struct page *buf_p;
void *buf;
int r;
- buf_p = sev_alloc_dbg_buffer(&buf);
- if (!buf_p)
+ buf = sev_dbg_crypt_slow_alloc(src_p, src, len, &src_pa, &nr_bytes);
+ if (!buf)
return -ENOMEM;
- nr_bytes = sev_dbg_crypt_slow_addr_and_size(src_p, src, len, &src_pa);
-
- r = sev_issue_dbg_cmd(kvm, src_pa, __sme_page_pa(buf_p),
+ r = sev_issue_dbg_cmd(kvm, src_pa, __sme_set(__pa(buf)),
nr_bytes, KVM_SEV_DBG_DECRYPT, err);
if (r)
goto out;
@@ -1326,7 +1304,7 @@ static int sev_dbg_decrypt_slow(struct kvm *kvm, unsigned long src,
if (copy_to_user((void __user *)dst, buf + (src & 15), len))
r = -EFAULT;
out:
- sev_free_dbg_buffer(buf_p, buf);
+ kfree(buf);
return r;
}
@@ -1336,18 +1314,15 @@ static int sev_dbg_encrypt_slow(struct kvm *kvm, unsigned long src,
{
unsigned int nr_bytes;
unsigned long dst_pa;
- struct page *buf_p;
void *buf;
int r;
- buf_p = sev_alloc_dbg_buffer(&buf);
- if (!buf_p)
- return -ENOMEM;
-
/* Decrypt the _destination_ to do a RMW on plaintext. */
- nr_bytes = sev_dbg_crypt_slow_addr_and_size(dst_p, dst, len, &dst_pa);
+ buf = sev_dbg_crypt_slow_alloc(dst_p, dst, len, &dst_pa, &nr_bytes);
+ if (!buf)
+ return -ENOMEM;
- r = sev_issue_dbg_cmd(kvm, dst_pa, __sme_page_pa(buf_p),
+ r = sev_issue_dbg_cmd(kvm, dst_pa, __sme_set(__pa(buf)),
nr_bytes, KVM_SEV_DBG_DECRYPT, err);
if (r)
goto out;
@@ -1359,10 +1334,10 @@ static int sev_dbg_encrypt_slow(struct kvm *kvm, unsigned long src,
if (copy_from_user(buf + (dst & 15), (void __user *)src, len))
r = -EFAULT;
else
- r = sev_issue_dbg_cmd(kvm, __sme_page_pa(buf_p), dst_pa,
+ r = sev_issue_dbg_cmd(kvm, __sme_set(__pa(buf)), dst_pa,
nr_bytes, KVM_SEV_DBG_ENCRYPT, err);
out:
- sev_free_dbg_buffer(buf_p, buf);
+ kfree(buf);
return r;
}
--
2.54.0.rc1.513.gad8abe7a5a-goog
prev parent reply other threads:[~2026-04-16 23:11 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-16 23:10 [PATCH v2 0/6] KVM: SEV: sev_dbg_crypt() fix and overhaul Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 1/6] KVM: SVM: Fix page overflow in sev_dbg_crypt() for ENCRYPT path Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt debug ioctls Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 3/6] KVM: SEV: Explicitly validate the dst buffer for debug operations Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 4/6] KVM: SEV: Add helper function to pin/unpin a single page Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 5/6] KVM: SEV: Rewrite logic to {de,en}crypt memory for debug Sean Christopherson
2026-04-16 23:10 ` Sean Christopherson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260416231043.3402410-7-seanjc@google.com \
--to=seanjc@google.com \
--cc=ashutoshdesai993@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox