From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: Nicolas Saenz Julienne <nsaenz@amazon.com>
Subject: [PATCH 35/45] KVM: x86/mmu: Propagate errors from nested GPA translation
Date: Mon, 2 Nov 2026 12:45:02 -0500 [thread overview]
Message-ID: <20261102174512.8903-19-pbonzini@redhat.com> (raw)
In-Reply-To: <20261102174130.8779-1-pbonzini@redhat.com>
The nested translation callbacks currently discard errors returned
by gva_to_gpa(). Adjust translate_nested_gpa()'s calling convention
similar to what was done to gva_to_gpa(), so that errors can be
propagated from page walk as well as from users that directly care
about L2 GPAs.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 8 ++++----
arch/x86/kvm/hyperv.c | 6 ++++--
arch/x86/kvm/mmu.h | 18 ++++++++++--------
arch/x86/kvm/mmu/mmu.c | 5 ++---
arch/x86/kvm/mmu/paging_tmpl.h | 12 ++++++------
arch/x86/kvm/regs.c | 8 +++++---
arch/x86/kvm/svm/nested.c | 18 +++++++++---------
arch/x86/kvm/vmx/nested.c | 18 +++++++++---------
arch/x86/kvm/x86.c | 15 +++++++++++----
9 files changed, 60 insertions(+), 48 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 99f9c9269f2f..7fbcf60e56cf 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1780,10 +1780,10 @@ struct kvm_x86_nested_ops {
struct kvm_nested_state *kvm_state);
bool (*get_nested_state_pages)(struct kvm_vcpu *vcpu);
int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
- gpa_t (*translate_nested_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa,
- u64 access,
- struct x86_exception *exception,
- u64 pte_access);
+ int (*translate_nested_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa,
+ u64 access, gpa_t *translated_gpa,
+ struct x86_exception *exception,
+ u64 pte_access);
int (*enable_evmcs)(struct kvm_vcpu *vcpu,
uint16_t *vmcs_version);
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index ee5189815a06..090955541518 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2119,8 +2119,10 @@ static s64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
/* Slow direct hypercalls from L2 provide a nested GPA. */
if (!hc->fast) {
- hc->ingpa = kvm_translate_gpa(vcpu, &vcpu->arch.gva_walk, hc->ingpa,
- PFERR_GUEST_FINAL_MASK, NULL, 0);
+ r = kvm_translate_gpa(vcpu, &vcpu->arch.gva_walk, hc->ingpa,
+ PFERR_GUEST_FINAL_MASK, &hc->ingpa, NULL, 0);
+ if (r)
+ return r;
if (unlikely(hc->ingpa == INVALID_GPA))
return HV_STATUS_INVALID_HYPERCALL_INPUT;
}
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 224f4c1a957e..40dcbcbae173 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -377,15 +377,17 @@ static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
return vcpu->arch.mmu == &vcpu->arch.guest_mmu;
}
-static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
- struct kvm_pagewalk *w,
- gpa_t gpa, u64 access,
- struct x86_exception *exception,
- u64 pte_access)
+static inline int kvm_translate_gpa(struct kvm_vcpu *vcpu,
+ struct kvm_pagewalk *w,
+ gpa_t gpa, u64 access, gpa_t *translated_gpa,
+ struct x86_exception *exception,
+ u64 pte_access)
{
- if (!mmu_is_nested(vcpu) || w == &vcpu->arch.ngpa_walk)
- return gpa;
- return kvm_nested_call(translate_nested_gpa)(vcpu, gpa, access,
+ if (!mmu_is_nested(vcpu) || w == &vcpu->arch.ngpa_walk) {
+ *translated_gpa = gpa;
+ return 0;
+ }
+ return kvm_nested_call(translate_nested_gpa)(vcpu, gpa, access, translated_gpa,
exception, pte_access);
}
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index c827f2e1f3d1..9567c109306b 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -4474,9 +4474,8 @@ static int nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, struct kvm_pagewalk *w,
* user-mode address if CR0.PG=0. Therefore *include* ACC_USER_MASK in
* the last argument to kvm_translate_gpa (which NPT does not use).
*/
- *gpa = kvm_translate_gpa(vcpu, w, vaddr, access | PFERR_GUEST_FINAL_MASK,
- exception, ACC_ALL);
- return 0;
+ return kvm_translate_gpa(vcpu, w, vaddr, access | PFERR_GUEST_FINAL_MASK,
+ gpa, exception, ACC_ALL);
}
static bool mmio_info_in_cache(struct kvm_vcpu *vcpu, u64 addr, bool direct)
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index 7775ba789258..a76ec22ce3f2 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -398,9 +398,9 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
walker->table_gfn[walker->level - 1] = table_gfn;
walker->pte_gpa[walker->level - 1] = pte_gpa;
- real_gpa = kvm_translate_gpa(vcpu, w, gfn_to_gpa(table_gfn),
- nested_access | PFERR_GUEST_PAGE_MASK,
- &walker->fault, 0);
+ kvm_translate_gpa(vcpu, w, gfn_to_gpa(table_gfn),
+ nested_access | PFERR_GUEST_PAGE_MASK,
+ &real_gpa, &walker->fault, 0);
if (unlikely(real_gpa == INVALID_GPA))
return 0;
@@ -458,9 +458,9 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
gfn += pse36_gfn_delta(pte);
#endif
- real_gpa = kvm_translate_gpa(vcpu, w, gfn_to_gpa(gfn),
- access | PFERR_GUEST_FINAL_MASK,
- &walker->fault, walker->pte_access);
+ kvm_translate_gpa(vcpu, w, gfn_to_gpa(gfn),
+ access | PFERR_GUEST_FINAL_MASK, &real_gpa,
+ &walker->fault, walker->pte_access);
if (real_gpa == INVALID_GPA)
return 0;
diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index 3621f1a47d37..3969b769f1c1 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -165,9 +165,11 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
* If the MMU is nested, CR3 holds an L2 GPA and needs to be translated
* to an L1 GPA.
*/
- real_gpa = kvm_translate_gpa(vcpu, w, gfn_to_gpa(pdpt_gfn),
- PFERR_USER_MASK | PFERR_WRITE_MASK |
- PFERR_GUEST_PAGE_MASK, NULL, 0);
+ ret = kvm_translate_gpa(vcpu, w, gfn_to_gpa(pdpt_gfn),
+ PFERR_USER_MASK | PFERR_WRITE_MASK | PFERR_GUEST_PAGE_MASK,
+ &real_gpa, NULL, 0);
+ if (ret)
+ return ret;
if (real_gpa == INVALID_GPA)
return 0;
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 5d0a2f658365..73f1f40aad47 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -2148,24 +2148,24 @@ static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
return true;
}
-static gpa_t svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
- u64 access,
- struct x86_exception *exception,
- u64 pte_access)
+static int svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
+ u64 access, gpa_t *translated_gpa,
+ struct x86_exception *exception,
+ u64 pte_access)
{
struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_pagewalk *w = &vcpu->arch.ngpa_walk;
- gpa_t result;
- if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
- return gpa;
+ if (WARN_ON_ONCE(!mmu_is_nested(vcpu))) {
+ *translated_gpa = gpa;
+ return 0;
+ }
/* Non-GMET walks are always user-walks */
if (!(svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_GMET))
access |= PFERR_USER_MASK;
- w->gva_to_gpa(vcpu, w, gpa, access, &result, exception);
- return result;
+ return w->gva_to_gpa(vcpu, w, gpa, access, translated_gpa, exception);
}
struct kvm_x86_nested_ops svm_nested_ops __initdata = {
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index a666c2908889..f6994a95523a 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -7477,16 +7477,17 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *))
}
-static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
- u64 access,
- struct x86_exception *exception,
- u64 pte_access)
+static int vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
+ u64 access, gpa_t *translated_gpa,
+ struct x86_exception *exception,
+ u64 pte_access)
{
struct kvm_pagewalk *w = &vcpu->arch.ngpa_walk;
- gpa_t result;
- if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
- return gpa;
+ if (WARN_ON_ONCE(!mmu_is_nested(vcpu))) {
+ *translated_gpa = gpa;
+ return 0;
+ }
/*
* MBEC differentiates based on the effective U/S bit of
@@ -7496,8 +7497,7 @@ static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
if ((pte_access & ACC_USER_MASK) && (access & PFERR_GUEST_FINAL_MASK))
access |= PFERR_USER_MASK;
- w->gva_to_gpa(vcpu, w, gpa, access, &result, exception);
- return result;
+ return w->gva_to_gpa(vcpu, w, gpa, access, translated_gpa, exception);
}
struct kvm_x86_nested_ops vmx_nested_ops __initdata = {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 53400fda9f44..59b38484a0d4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7315,10 +7315,17 @@ static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
*ret = -KVM_EFAULT;
while (offset < sizeof(clock_pairing)) {
- gpa_t gpa = kvm_translate_gpa(vcpu, &vcpu->arch.gva_walk, paddr + offset,
- PFERR_WRITE_MASK | PFERR_GUEST_FINAL_MASK, NULL, 0);
- size_t len = min_t(size_t, sizeof(clock_pairing) - offset,
- PAGE_SIZE - offset_in_page(gpa));
+ gpa_t gpa;
+ size_t len;
+ int r;
+
+ r = kvm_translate_gpa(vcpu, &vcpu->arch.gva_walk, paddr + offset,
+ PFERR_WRITE_MASK | PFERR_GUEST_FINAL_MASK,
+ &gpa, NULL, 0);
+ if (r)
+ return r;
+ len = min_t(size_t, sizeof(clock_pairing) - offset,
+ PAGE_SIZE - offset_in_page(gpa));
if (gpa == INVALID_GPA)
return 0;
--
2.52.0
next prev parent reply other threads:[~2026-11-02 17:45 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 17:40 [PATCH v4 00/45] KVM: x86: Introduce memory protection attributes Paolo Bonzini
2026-11-02 17:40 ` [PATCH 01/45] KVM: nVMX/nSVM: check unconditionally whether CR3 is valid Paolo Bonzini
2026-11-02 17:40 ` [PATCH 02/45] KVM: x86/hyperv: do not overwrite hc->ingpa for SIGNAL_EVENT hypercall Paolo Bonzini
2026-11-02 17:40 ` [PATCH 03/45] KVM: x86: apply nGPA->GPA translation to KVM_HC_CLOCK_PAIRING Paolo Bonzini
2026-11-02 17:40 ` [PATCH 04/45] KVM: x86/emulate: Check TSS busy-bit writes during task switches Paolo Bonzini
2026-11-02 17:40 ` [PATCH 05/45] KVM: loongarch: do full validity check on the gfn-to-hva cache Paolo Bonzini
2026-11-02 17:40 ` [PATCH 06/45] KVM: selftests: Test address translation for Hyper-V direct L2 hypercalls Paolo Bonzini
2026-11-02 17:40 ` [PATCH 07/45] KVM: selftests: Take into account mixed memory fault flags Paolo Bonzini
2026-11-02 17:40 ` [PATCH 08/45] selftests: kvm: drop TEST_ASSERT_SUPPORTED_ATTRIBUTES Paolo Bonzini
2026-11-02 17:40 ` [PATCH 09/45] KVM: Define and communicate KVM_EXIT_MEMORY_FAULT RWX flags to userspace Paolo Bonzini
2026-11-02 17:40 ` [PATCH 10/45] KVM: x86: Introduce memory fault on invalid hypercalls reads/writes Paolo Bonzini
2026-11-02 17:40 ` [PATCH 11/45] KVM: selftests: test hypercall memory fault exits Paolo Bonzini
2026-11-02 17:40 ` [PATCH 12/45] KVM: x86/mmu: intersect writability from __kvm_faultin_pfn with fault->map_writable Paolo Bonzini
2026-11-02 17:40 ` [PATCH 13/45] KVM: x86/mmu: Extend map_writable to a full ACC_* mask Paolo Bonzini
2026-11-02 17:40 ` [PATCH 14/45] KVM: x86/mmu: Init memslot hugepage information for non-private_mem VMs too Paolo Bonzini
2026-11-02 17:40 ` [PATCH 15/45] KVM: VMX: return error from kvm_set_cr* Paolo Bonzini
2026-11-02 17:41 ` [PATCH 16/45] KVM: adjust for presence of more than one attribute Paolo Bonzini
2026-11-02 17:44 ` [PATCH 17/45] KVM: Introduce NR/NW/NX memory attributes Paolo Bonzini
2026-11-02 17:44 ` [PATCH 18/45] KVM: Include memory protections in result of gfn->hva conversion Paolo Bonzini
2026-11-02 17:44 ` [PATCH 19/45] KVM: Introduce kvm_fetch_guest_page() and use it for x86 Paolo Bonzini
2026-11-02 17:44 ` [PATCH 20/45] KVM: Take memory protections into account for memory read/write/fetch Paolo Bonzini
2026-11-02 17:44 ` [PATCH 21/45] KVM: Take memory protections into account for __kvm_vcpu_map Paolo Bonzini
2026-11-02 17:44 ` [PATCH 22/45] KVM: Encapsulate memattrs array into anonymous struct Paolo Bonzini
2026-11-02 17:44 ` [PATCH 23/45] KVM: Introduce kvm_check_gen()/kvm_memslots_check_gen() Paolo Bonzini
2026-11-02 17:44 ` [PATCH 24/45] KVM: Introduce a generation number for memory attributes Paolo Bonzini
2026-11-02 17:44 ` [PATCH 25/45] KVM: Take memory protections into account for accesses with cached gfn->hva Paolo Bonzini
2026-11-02 17:44 ` [PATCH 26/45] KVM: pfncache: Fail to refresh if it contains memory protections Paolo Bonzini
2026-11-02 17:44 ` [PATCH 27/45] KVM: x86/mmu: Do not prefetch sptes on gfns backed by memory attributes Paolo Bonzini
2026-11-02 17:44 ` [PATCH 28/45] KVM: x86/mmu: Take memory protection attributes into account during faults Paolo Bonzini
2026-11-02 17:44 ` [PATCH 29/45] KVM: x86/emulate: change return value of emulator_io_permitted to int Paolo Bonzini
2026-11-02 17:44 ` [PATCH 30/45] KVM: x86/emulate: Propagate memory faults to userspace Paolo Bonzini
2026-11-02 17:44 ` [PATCH 31/45] KVM: x86: "Handle" failed decode when skipping instructions Paolo Bonzini
2026-11-02 17:44 ` [PATCH 32/45] KVM: vmx/sgx: make return value of sgx_gva_to_gpa consistent with its callers Paolo Bonzini
2026-11-02 17:45 ` [PATCH 33/45] KVM: x86: Allow page fault fixup to return errors Paolo Bonzini
2026-11-02 17:45 ` [PATCH 34/45] KVM: x86/mmu: Adjust gva_to_gpa to allow returning an error Paolo Bonzini
2026-11-02 17:45 ` Paolo Bonzini [this message]
2026-11-02 17:45 ` [PATCH 36/45] KVM: x86: Propagate memory faults through load_pdptrs() Paolo Bonzini
2026-11-02 17:45 ` [PATCH 37/45] KVM: x86/mmu: Issue memory fault exit if walk failed due to memory attribute Paolo Bonzini
2026-11-02 17:45 ` [PATCH 38/45] KVM: x86: mark VM as dead after KVM_SET_SREGS fails to load PDPTRs Paolo Bonzini
2026-11-02 17:45 ` [PATCH 39/45] KVM: VMX: mark VM dead on shadow VMCS or eVMCS access failures Paolo Bonzini
2026-11-02 17:45 ` [PATCH 40/45] KVM: let kvm_arch_post_set_memory_attributes drop mmu_lock Paolo Bonzini
2026-11-02 17:45 ` [PATCH 41/45] KVM: x86/mmu: Obsolete all roots if memattr contains gPTEs Paolo Bonzini
2026-11-02 17:45 ` [PATCH 42/45] KVM: x86: selftests: Introduce memory protection attributes test Paolo Bonzini
2026-11-02 17:45 ` [PATCH 43/45] KVM: x86: selftests: Introduce memory attributes PTE test Paolo Bonzini
2026-11-02 17:45 ` [PATCH 44/45] KVM: x86: selftests: Introduce memory attributes side-channel tests Paolo Bonzini
2026-11-02 17:45 ` [PATCH 45/45] KVM: x86: split out parts of load_pdptrs Paolo Bonzini
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=20261102174512.8903-19-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nsaenz@amazon.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
all inboxes | Powered by JetHome®