From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Ben Gardon <bgardon@google.com>,
Brijesh Singh <brijesh.singh@amd.com>,
Tom Lendacky <thomas.lendacky@amd.com>
Subject: [PATCH 04/15] KVM: x86/mmu: Allocate the lm_root before allocating PAE roots
Date: Tue, 2 Mar 2021 10:45:29 -0800 [thread overview]
Message-ID: <20210302184540.2829328-5-seanjc@google.com> (raw)
In-Reply-To: <20210302184540.2829328-1-seanjc@google.com>
Allocate lm_root before the PAE roots so that the PAE roots aren't
leaked if the memory allocation for the lm_root happens to fail.
Note, KVM can _still_ leak PAE roots if mmu_check_root() fails on a
guest's PDPTR. That too will be fixed in a future commit.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/mmu/mmu.c | 65 +++++++++++++++++++++---------------------
1 file changed, 32 insertions(+), 33 deletions(-)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 1f129001a30c..e5c3701112f8 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3292,21 +3292,39 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
* the shadow page table may be a PAE or a long mode page table.
*/
pm_mask = PT_PRESENT_MASK;
- if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL) {
+ if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL)
pm_mask |= PT_ACCESSED_MASK | PT_WRITABLE_MASK | PT_USER_MASK;
- /*
- * Allocate the page for the PDPTEs when shadowing 32-bit NPT
- * with 64-bit only when needed. Unlike 32-bit NPT, it doesn't
- * need to be in low mem. See also lm_root below.
- */
- if (!vcpu->arch.mmu->pae_root) {
- WARN_ON_ONCE(!tdp_enabled);
+ /*
+ * When shadowing 32-bit or PAE NPT with 64-bit NPT, the PML4 and PDP
+ * tables are allocated and initialized at root creation as there is no
+ * equivalent level in the guest's NPT to shadow. Allocate the tables
+ * on demand, as running a 32-bit L1 VMM is very rare. Unlike 32-bit
+ * NPT, the PDP table doesn't need to be in low mem. Preallocate the
+ * pages so that the PAE roots aren't leaked on failure.
+ */
+ if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL &&
+ (!vcpu->arch.mmu->pae_root || !vcpu->arch.mmu->lm_root)) {
+ u64 *lm_root, *pae_root;
- vcpu->arch.mmu->pae_root = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
- if (!vcpu->arch.mmu->pae_root)
- return -ENOMEM;
+ if (WARN_ON_ONCE(!tdp_enabled || vcpu->arch.mmu->pae_root ||
+ vcpu->arch.mmu->lm_root))
+ return -EIO;
+
+ pae_root = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
+ if (!pae_root)
+ return -ENOMEM;
+
+ lm_root = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
+ if (!lm_root) {
+ free_page((unsigned long)pae_root);
+ return -ENOMEM;
}
+
+ vcpu->arch.mmu->pae_root = pae_root;
+ vcpu->arch.mmu->lm_root = lm_root;
+
+ lm_root[0] = __pa(vcpu->arch.mmu->pae_root) | pm_mask;
}
for (i = 0; i < 4; ++i) {
@@ -3327,30 +3345,11 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
PT32_ROOT_LEVEL, false);
vcpu->arch.mmu->pae_root[i] = root | pm_mask;
}
- vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->pae_root);
-
- /*
- * When shadowing 32-bit or PAE NPT with 64-bit NPT, the PML4 and PDP
- * tables are allocated and initialized at MMU creation as there is no
- * equivalent level in the guest's NPT to shadow. Allocate the tables
- * on demand, as running a 32-bit L1 VMM is very rare. The PDP is
- * handled above (to share logic with PAE), deal with the PML4 here.
- */
- if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL) {
- if (vcpu->arch.mmu->lm_root == NULL) {
- u64 *lm_root;
-
- lm_root = (void*)get_zeroed_page(GFP_KERNEL_ACCOUNT);
- if (!lm_root)
- return -ENOMEM;
-
- lm_root[0] = __pa(vcpu->arch.mmu->pae_root) | pm_mask;
-
- vcpu->arch.mmu->lm_root = lm_root;
- }
+ if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL)
vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->lm_root);
- }
+ else
+ vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->pae_root);
set_root_pgd:
vcpu->arch.mmu->root_pgd = root_pgd;
--
2.30.1.766.gb4fecdf3b7-goog
next prev parent reply other threads:[~2021-03-03 7:23 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-02 18:45 [PATCH 00/15] KVM: x86/mmu: Lots of bug fixes Sean Christopherson
2021-03-02 18:45 ` [PATCH 01/15] KVM: nSVM: Set the shadow root level to the TDP level for nested NPT Sean Christopherson
2021-03-02 18:45 ` [PATCH 02/15] KVM: x86/mmu: Alloc page for PDPTEs when shadowing 32-bit NPT with 64-bit Sean Christopherson
2021-03-03 17:28 ` Ben Gardon
2021-03-02 18:45 ` [PATCH 03/15] KVM: x86/mmu: Ensure MMU pages are available when allocating roots Sean Christopherson
2021-03-03 0:21 ` Ben Gardon
2021-03-03 16:46 ` Sean Christopherson
2021-03-02 18:45 ` Sean Christopherson [this message]
2021-03-02 18:45 ` [PATCH 05/15] KVM: x86/mmu: Check PDPTRs before allocating PAE roots Sean Christopherson
2021-03-02 18:45 ` [PATCH 06/15] KVM: x86/mmu: Fix and unconditionally enable WARNs to detect PAE leaks Sean Christopherson
2021-03-02 18:45 ` [PATCH 07/15] KVM: x86/mmu: Use '0' as the one and only value for an invalid PAE root Sean Christopherson
2021-03-02 18:45 ` [PATCH 08/15] KVM: x86/mmu: Set the C-bit in the PDPTRs and LM pseudo-PDPTRs Sean Christopherson
2021-03-02 18:45 ` [PATCH 09/15] KVM: x86/mmu: Mark the PAE roots as decrypted for shadow paging Sean Christopherson
2021-03-02 18:45 ` [PATCH 10/15] KVM: SVM: Don't strip the C-bit from CR2 on #PF interception Sean Christopherson
2021-03-02 18:45 ` [PATCH 11/15] KVM: nVMX: Defer the MMU reload to the normal path on an EPTP switch Sean Christopherson
2021-03-02 18:45 ` [PATCH 12/15] KVM: x86: Defer the MMU unload to the normal path on an global INVPCID Sean Christopherson
2021-03-02 18:45 ` [PATCH 13/15] KVM: x86/mmu: Unexport MMU load/unload functions Sean Christopherson
2021-03-02 18:45 ` [PATCH 14/15] KVM: x86/mmu: Sync roots after MMU load iff load as successful Sean Christopherson
2021-03-02 18:45 ` [PATCH 15/15] KVM: x86/mmu: WARN on NULL pae_root and bad shadow root level Sean Christopherson
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=20210302184540.2829328-5-seanjc@google.com \
--to=seanjc@google.com \
--cc=bgardon@google.com \
--cc=brijesh.singh@amd.com \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=thomas.lendacky@amd.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.