summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_host.h3
-rw-r--r--arch/x86/kvm/svm/sev.c27
-rw-r--r--arch/x86/kvm/svm/svm.h2
-rw-r--r--arch/x86/kvm/x86.c5
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--virt/kvm/guest_memfd.c2
6 files changed, 19 insertions, 22 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index ae9a229c6b11..7643e078ba36 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1904,7 +1904,8 @@ struct kvm_x86_ops {
gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
- int (*gmem_make_private)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
+ int (*gmem_make_private)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages);
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
void (*gmem_make_shared)(kvm_pfn_t pfn, kvm_pfn_t nr_pages);
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 779889f5e994..5dd45b7a09f2 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -5088,15 +5088,7 @@ static bool is_pfn_range_shared(kvm_pfn_t start, kvm_pfn_t end)
return true;
}
-static u8 max_level_for_order(int order)
-{
- if (order >= KVM_HPAGE_GFN_SHIFT(PG_LEVEL_2M))
- return PG_LEVEL_2M;
-
- return PG_LEVEL_4K;
-}
-
-static bool is_large_rmp_possible(struct kvm *kvm, kvm_pfn_t pfn, int order)
+static bool is_large_rmp_possible(kvm_pfn_t pfn, kvm_pfn_t nr_pages)
{
kvm_pfn_t pfn_aligned = ALIGN_DOWN(pfn, PTRS_PER_PMD);
@@ -5105,14 +5097,14 @@ static bool is_large_rmp_possible(struct kvm *kvm, kvm_pfn_t pfn, int order)
* PFN is currently shared, then the entire 2M-aligned range can be
* set to private via a single 2M RMP entry.
*/
- if (max_level_for_order(order) > PG_LEVEL_4K &&
+ if (nr_pages >= KVM_PAGES_PER_HPAGE(PG_LEVEL_2M) &&
is_pfn_range_shared(pfn_aligned, pfn_aligned + PTRS_PER_PMD))
return true;
return false;
}
-int sev_gmem_make_private(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)
+int sev_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, kvm_pfn_t nr_pages)
{
struct kvm_sev_info *sev = to_kvm_sev_info(kvm);
kvm_pfn_t pfn_aligned;
@@ -5123,6 +5115,9 @@ int sev_gmem_make_private(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_ord
if (!sev_snp_guest(kvm))
return 0;
+ if (WARN_ON_ONCE(nr_pages != 1))
+ return -EIO;
+
rc = snp_lookup_rmpentry(pfn, &assigned, &level);
if (rc) {
pr_err_ratelimited("SEV: Failed to look up RMP entry: GFN %llx PFN %llx error %d\n",
@@ -5131,12 +5126,12 @@ int sev_gmem_make_private(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_ord
}
if (assigned) {
- pr_debug("%s: already assigned: gfn %llx pfn %llx max_order %d level %d\n",
- __func__, gfn, pfn, max_order, level);
+ pr_debug("%s: already assigned: gfn %llx pfn %llx nr_pages %llx level %d\n",
+ __func__, gfn, pfn, nr_pages, level);
return 0;
}
- if (is_large_rmp_possible(kvm, pfn, max_order)) {
+ if (is_large_rmp_possible(pfn, nr_pages)) {
level = PG_LEVEL_2M;
pfn_aligned = ALIGN_DOWN(pfn, PTRS_PER_PMD);
gfn_aligned = ALIGN_DOWN(gfn, PTRS_PER_PMD);
@@ -5153,8 +5148,8 @@ int sev_gmem_make_private(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_ord
return -EINVAL;
}
- pr_debug("%s: updated: gfn %llx pfn %llx pfn_aligned %llx max_order %d level %d\n",
- __func__, gfn, pfn, pfn_aligned, max_order, level);
+ pr_debug("%s: updated: gfn %llx pfn %llx pfn_aligned %llx nr_pages %llx level %d\n",
+ __func__, gfn, pfn, pfn_aligned, nr_pages, level);
return 0;
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index b5cd8437988f..da4c66eb8d70 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -1009,7 +1009,7 @@ int sev_cpu_init(struct svm_cpu_data *sd);
int sev_dev_get_attr(u32 group, u64 attr, u64 *val);
extern unsigned int max_sev_asid;
void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code);
-int sev_gmem_make_private(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
+int sev_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, kvm_pfn_t nr_pages);
void sev_gmem_make_shared(kvm_pfn_t pfn, kvm_pfn_t nr_pages);
void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 512bcc35507a..9390e0d4c1e5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10590,9 +10590,10 @@ bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
}
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
-int kvm_arch_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order)
+int kvm_arch_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages)
{
- return kvm_x86_call(gmem_make_private)(kvm, pfn, gfn, max_order);
+ return kvm_x86_call(gmem_make_private)(kvm, gfn, pfn, nr_pages);
}
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ecdda1f00c6c..b24a090eb34d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2574,7 +2574,7 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
int kvm_arch_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
- int max_order);
+ kvm_pfn_t nr_pages);
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_POPULATE
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 6635ed05f411..0c1ee3e49176 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -77,7 +77,7 @@ static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slo
kvm_pfn_t pfn = folio_file_pfn(folio, index);
gfn_t gfn = slot->base_gfn + index - slot->gmem.pgoff;
- return kvm_arch_gmem_make_private(kvm, gfn, pfn, folio_order(folio));
+ return kvm_arch_gmem_make_private(kvm, gfn, pfn, folio_nr_pages(folio));
#else
return 0;
#endif