[RFC PATCH 28/28] kvm: mmu: Support MMIO in the direct MMU

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add direct MMU handlers to the functions required to support MMIO

Signed-off-by: Ben Gardon <bgardon@xxxxxxxxxx>
---
 arch/x86/kvm/mmu.c | 91 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 68 insertions(+), 23 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 72c2289132c43..0a23daea0df50 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5464,49 +5464,94 @@ static bool mmio_info_in_cache(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 	return vcpu_match_mmio_gva(vcpu, addr);
 }
 
-/* return true if reserved bit is detected on spte. */
-static bool
-walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
+/*
+ * Return the level of the lowest level pte added to ptes.
+ * That pte may be non-present.
+ */
+static int direct_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *ptes)
 {
-	struct kvm_shadow_walk_iterator iterator;
-	u64 sptes[PT64_ROOT_MAX_LEVEL], spte = 0ull;
-	int root, leaf;
-	bool reserved = false;
+	struct direct_walk_iterator iter;
+	int leaf = vcpu->arch.mmu->root_level;
 
-	if (!VALID_PAGE(vcpu->arch.mmu->root_hpa))
-		goto exit;
+	direct_walk_iterator_setup_walk(&iter, vcpu->kvm,
+			kvm_arch_vcpu_memslots_id(vcpu), addr >> PAGE_SHIFT,
+			(addr >> PAGE_SHIFT) + 1, MMU_NO_LOCK);
+	while (direct_walk_iterator_next_pte(&iter)) {
+		leaf = iter.level;
+		ptes[leaf - 1] = iter.old_pte;
+		if (!is_shadow_present_pte(iter.old_pte))
+			break;
+	}
+	direct_walk_iterator_end_traversal(&iter);
+
+	return leaf;
+}
+
+/*
+ * Return the level of the lowest level spte added to sptes.
+ * That spte may be non-present.
+ */
+static int shadow_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes)
+{
+	struct kvm_shadow_walk_iterator iterator;
+	int leaf = vcpu->arch.mmu->root_level;
+	u64 spte;
 
 	walk_shadow_page_lockless_begin(vcpu);
 
-	for (shadow_walk_init(&iterator, vcpu, addr),
-		 leaf = root = iterator.level;
+	for (shadow_walk_init(&iterator, vcpu, addr);
 	     shadow_walk_okay(&iterator);
 	     __shadow_walk_next(&iterator, spte)) {
+		leaf = iterator.level;
 		spte = mmu_spte_get_lockless(iterator.sptep);
-
 		sptes[leaf - 1] = spte;
-		leaf--;
 
 		if (!is_shadow_present_pte(spte))
 			break;
-
-		reserved |= is_shadow_zero_bits_set(vcpu->arch.mmu, spte,
-						    iterator.level);
 	}
 
 	walk_shadow_page_lockless_end(vcpu);
 
+	return leaf;
+}
+
+/* return true if reserved bit is detected on spte. */
+static bool get_mmio_pte(struct kvm_vcpu *vcpu, u64 addr, bool direct,
+			 u64 *ptep)
+{
+	u64 ptes[PT64_ROOT_MAX_LEVEL];
+	int root = vcpu->arch.mmu->root_level;
+	int leaf;
+	int level;
+	bool reserved = false;
+
+
+	if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) {
+		*ptep = 0ull;
+		return reserved;
+	}
+
+	if (direct && vcpu->kvm->arch.direct_mmu_enabled)
+		leaf = direct_mmu_get_walk(vcpu, addr, ptes);
+	else
+		leaf = shadow_mmu_get_walk(vcpu, addr, ptes);
+
+	for (level = root; level >= leaf; level--) {
+		if (!is_shadow_present_pte(ptes[level - 1]))
+			break;
+		reserved |= is_shadow_zero_bits_set(vcpu->arch.mmu,
+				ptes[level - 1], level);
+	}
+
 	if (reserved) {
 		pr_err("%s: detect reserved bits on spte, addr 0x%llx, dump hierarchy:\n",
 		       __func__, addr);
-		while (root > leaf) {
+		for (level = root; level >= leaf; level--)
 			pr_err("------ spte 0x%llx level %d.\n",
-			       sptes[root - 1], root);
-			root--;
-		}
+			       ptes[level - 1], level);
 	}
-exit:
-	*sptep = spte;
+
+	*ptep = ptes[leaf - 1];
 	return reserved;
 }
 
@@ -5518,7 +5563,7 @@ static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 	if (mmio_info_in_cache(vcpu, addr, direct))
 		return RET_PF_EMULATE;
 
-	reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte);
+	reserved = get_mmio_pte(vcpu, addr, direct, &spte);
 	if (WARN_ON(reserved))
 		return -EINVAL;
 
-- 
2.23.0.444.g18eeb5a265-goog




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux