On 22.02.24 17:10, Fuad Tabba wrote:
Guest private memory should never be mapped by the host.
Therefore, do not allow setting the private attribute to guest
memory if that memory is mapped by the host.
Signed-off-by: Fuad Tabba <tabba@xxxxxxxxxx>
---
include/linux/kvm_host.h | 7 ++++++
virt/kvm/kvm_main.c | 51 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index fad296baa84e..f52d5503ddef 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2408,11 +2408,18 @@ static inline bool kvm_gmem_is_mappable(struct kvm *kvm, gfn_t gfn)
return !(kvm_get_memory_attributes(kvm, gfn) &
KVM_MEMORY_ATTRIBUTE_NOT_MAPPABLE);
}
+
+bool kvm_is_gmem_mapped(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
#else
static inline bool kvm_gmem_is_mappable(struct kvm *kvm, gfn_t gfn)
{
return false;
}
+
+static inline bool kvm_is_gmem_mapped(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
+{
+ return false;
+}
#endif /* CONFIG_KVM_GENERIC_PRIVATE_MEM_MAPPABLE */
#endif
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index fba4dc6e4107..9f6ff314bda3 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2516,6 +2516,48 @@ static __always_inline void kvm_handle_gfn_range(struct kvm *kvm,
KVM_MMU_UNLOCK(kvm);
}
+#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM_MAPPABLE
+bool kvm_is_gmem_mapped(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
+{
+ struct kvm_memslot_iter iter;
+
+ kvm_for_each_memslot_in_gfn_range(&iter, kvm_memslots(kvm), gfn_start, gfn_end) {
+ struct kvm_memory_slot *memslot = iter.slot;
+ gfn_t start, end, i;
+
+ start = max(gfn_start, memslot->base_gfn);
+ end = min(gfn_end, memslot->base_gfn + memslot->npages);
+ if (WARN_ON_ONCE(start >= end))
+ continue;
+
+ for (i = start; i < end; i++) {
+ struct page *page;
+ bool is_mapped;
+ kvm_pfn_t pfn;
+ int ret;
+
+ /*
+ * Check the page_mapcount with the page lock held to
+ * avoid racing with kvm_gmem_fault().
+ */
+ ret = kvm_gmem_get_pfn_locked(kvm, memslot, i, &pfn, NULL);
+ if (WARN_ON_ONCE(ret))
+ continue;
+
+ page = pfn_to_page(pfn);
+ is_mapped = page_mapcount(page);
+ unlock_page(page);
+ put_page(page);
Stumbling over this, please avoid using page_mapcount(). page_mapped()
-- or better folio_mapped() -- is what you should be using here (iow,
convert it to work on folios).
--
Cheers,
David / dhildenb