[PATCH 12/24] KVM: SEV: Add an anonymous "psc" struct to track current PSC metadata
From: Paolo Bonzini
Date: Fri May 29 2026 - 14:42:54 EST
From: Sean Christopherson <seanjc@xxxxxxxxxx>
Add a "psc" struct to vcpu_sev_es_state to avoid having to prefix all of
the fields with "psc_".
Take advantage of the code churn to opportunistically rename local
variables to "guest_psc" to make it more obvious that the buffer is guest
data, and more importantly, guest accessible!
Opportunistically rename inflight => batch_size as well, because there can
really only be one operation in-flight (per-vCPU), i.e. "inflight" _looks_
like a boolean, but in actuality is an integer tracking how many pages are
being handled by the current operation.
No functional change intended.
Reviewed-by: Tom Lendacky <thomas.lendacky@xxxxxxx>
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Message-ID: <20260501202250.2115252-13-seanjc@xxxxxxxxxx>
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
arch/x86/kvm/svm/sev.c | 43 +++++++++++++++++++-----------------------
arch/x86/kvm/svm/svm.h | 8 +++++---
2 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 1982d13e71d9..9f6543cebedf 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3845,9 +3845,7 @@ static int snp_begin_psc(struct vcpu_svm *svm);
static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret)
{
- svm->sev_es.psc_inflight = 0;
- svm->sev_es.psc_idx = 0;
- svm->sev_es.psc_2m = false;
+ memset(&svm->sev_es.psc, 0, sizeof(svm->sev_es.psc));
/*
* PSC requests always get a "no action" response in SW_EXITINFO1, with
@@ -3860,9 +3858,8 @@ static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret)
static void __snp_complete_one_psc(struct vcpu_svm *svm)
{
- struct psc_buffer *psc = svm->sev_es.ghcb_sa;
- struct psc_entry *entries = psc->entries;
- struct psc_hdr *hdr = &psc->hdr;
+ struct vcpu_sev_es_state *sev_es = &svm->sev_es;
+ struct psc_buffer *guest_psc = sev_es->ghcb_sa;
__u16 idx;
/*
@@ -3870,14 +3867,14 @@ static void __snp_complete_one_psc(struct vcpu_svm *svm)
* corresponding entries in the guest's PSC buffer and zero out the
* count of in-flight PSC entries.
*/
- for (idx = svm->sev_es.psc_idx; svm->sev_es.psc_inflight;
- svm->sev_es.psc_inflight--, idx++) {
- struct psc_entry entry = READ_ONCE(entries[idx]);
+ for (idx = sev_es->psc.cur_idx; sev_es->psc.batch_size;
+ sev_es->psc.batch_size--, idx++) {
+ struct psc_entry entry = READ_ONCE(guest_psc->entries[idx]);
- entries[idx].cur_page = entry.pagesize ? 512 : 1;
+ guest_psc->entries[idx].cur_page = entry.pagesize ? 512 : 1;
}
- hdr->cur_entry = idx;
+ guest_psc->hdr.cur_entry = idx;
}
static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
@@ -3898,10 +3895,8 @@ static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
static int snp_begin_psc(struct vcpu_svm *svm)
{
struct vcpu_sev_es_state *sev_es = &svm->sev_es;
- struct psc_buffer *psc = sev_es->ghcb_sa;
- struct psc_entry *entries = psc->entries;
+ struct psc_buffer *guest_psc = sev_es->ghcb_sa;
struct kvm_vcpu *vcpu = &svm->vcpu;
- struct psc_hdr *hdr = &psc->hdr;
struct psc_entry entry_start;
u16 idx, idx_start, idx_end, max_nr_entries;
int npages;
@@ -3928,7 +3923,7 @@ static int snp_begin_psc(struct vcpu_svm *svm)
next_range:
/* There should be no other PSCs in-flight at this point. */
- if (WARN_ON_ONCE(svm->sev_es.psc_inflight)) {
+ if (WARN_ON_ONCE(svm->sev_es.psc.batch_size)) {
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
return 1;
}
@@ -3938,8 +3933,8 @@ static int snp_begin_psc(struct vcpu_svm *svm)
* validation, so take care to only use validated copies of values used
* for things like array indexing.
*/
- idx_start = READ_ONCE(hdr->cur_entry);
- idx_end = READ_ONCE(hdr->end_entry);
+ idx_start = READ_ONCE(guest_psc->hdr.cur_entry);
+ idx_end = READ_ONCE(guest_psc->hdr.end_entry);
if (idx_end >= max_nr_entries) {
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR);
@@ -3948,7 +3943,7 @@ static int snp_begin_psc(struct vcpu_svm *svm)
/* Find the start of the next range which needs processing. */
for (idx = idx_start; idx <= idx_end; idx++) {
- entry_start = READ_ONCE(entries[idx]);
+ entry_start = READ_ONCE(guest_psc->entries[idx]);
gfn = entry_start.gfn;
huge = entry_start.pagesize;
@@ -3981,7 +3976,7 @@ static int snp_begin_psc(struct vcpu_svm *svm)
* for READ_ONCE() as KVM doesn't consume the field, i.e. a
* misbehaving guest can only break itself.
*/
- hdr->cur_entry++;
+ guest_psc->hdr.cur_entry++;
}
if (idx > idx_end) {
@@ -3990,9 +3985,9 @@ static int snp_begin_psc(struct vcpu_svm *svm)
return 1;
}
- svm->sev_es.psc_2m = huge;
- svm->sev_es.psc_idx = idx;
- svm->sev_es.psc_inflight = 1;
+ sev_es->psc.is_2m = huge;
+ sev_es->psc.cur_idx = idx;
+ sev_es->psc.batch_size = 1;
/*
* Find all subsequent PSC entries that contain adjacent GPA
@@ -4000,14 +3995,14 @@ static int snp_begin_psc(struct vcpu_svm *svm)
* KVM_HC_MAP_GPA_RANGE exit.
*/
while (++idx <= idx_end) {
- struct psc_entry entry = READ_ONCE(entries[idx]);
+ struct psc_entry entry = READ_ONCE(guest_psc->entries[idx]);
if (entry.operation != entry_start.operation ||
entry.gfn != entry_start.gfn + npages ||
entry.cur_page || !!entry.pagesize != huge)
break;
- svm->sev_es.psc_inflight++;
+ sev_es->psc.batch_size++;
npages += huge ? 512 : 1;
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index a10668d17a16..06192bc9c107 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -257,9 +257,11 @@ struct vcpu_sev_es_state {
bool ghcb_sa_free;
/* SNP Page-State-Change buffer entries currently being processed */
- u16 psc_idx;
- u16 psc_inflight;
- bool psc_2m;
+ struct {
+ u16 cur_idx;
+ u16 batch_size;
+ bool is_2m;
+ } psc;
u64 ghcb_registered_gpa;
--
2.54.0