From: Laurent Dufour <lduf...@linux.ibm.com>

When a memory slot is hot plugged to a SVM, PFNs associated with the
GFNs in that slot must be migrated to the secure-PFNs, aka device-PFNs.

Call kvmppc_uv_migrate_mem_slot() to accomplish this.
Disable page-merge for all pages in the memory slot.

Reviewed-by: Bharata B Rao <bhar...@linux.ibm.com>
Signed-off-by: Ram Pai <linux...@us.ibm.com>
[rearranged the code, and modified the commit log]
Signed-off-by: Laurent Dufour <lduf...@linux.ibm.com>
---
 arch/powerpc/include/asm/kvm_book3s_uvmem.h | 14 ++++++++++++++
 arch/powerpc/kvm/book3s_hv.c                | 14 ++++++--------
 arch/powerpc/kvm/book3s_hv_uvmem.c          | 23 +++++++++++++++++++----
 3 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s_uvmem.h 
b/arch/powerpc/include/asm/kvm_book3s_uvmem.h
index 9cb7d8b..0a63194 100644
--- a/arch/powerpc/include/asm/kvm_book3s_uvmem.h
+++ b/arch/powerpc/include/asm/kvm_book3s_uvmem.h
@@ -23,6 +23,10 @@ unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
 unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm);
 void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
                             struct kvm *kvm, bool skip_page_out);
+int kvmppc_uvmem_memslot_create(struct kvm *kvm,
+               const struct kvm_memory_slot *new);
+void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
+               const struct kvm_memory_slot *old);
 #else
 static inline int kvmppc_uvmem_init(void)
 {
@@ -82,5 +86,15 @@ static inline int kvmppc_send_page_to_uv(struct kvm *kvm, 
unsigned long gfn)
 static inline void
 kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
                        struct kvm *kvm, bool skip_page_out) { }
+
+static inline int  kvmppc_uvmem_memslot_create(struct kvm *kvm,
+               const struct kvm_memory_slot *new)
+{
+       return H_UNSUPPORTED;
+}
+
+static inline void  kvmppc_uvmem_memslot_delete(struct kvm *kvm,
+               const struct kvm_memory_slot *old) { }
+
 #endif /* CONFIG_PPC_UV */
 #endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index d331b46..a93bc65 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4515,16 +4515,14 @@ static void kvmppc_core_commit_memory_region_hv(struct 
kvm *kvm,
 
        switch (change) {
        case KVM_MR_CREATE:
-               if (kvmppc_uvmem_slot_init(kvm, new))
-                       return;
-               uv_register_mem_slot(kvm->arch.lpid,
-                                    new->base_gfn << PAGE_SHIFT,
-                                    new->npages * PAGE_SIZE,
-                                    0, new->id);
+               /*
+                * @TODO kvmppc_uvmem_memslot_create() can fail and
+                * return error. Fix this.
+                */
+               kvmppc_uvmem_memslot_create(kvm, new);
                break;
        case KVM_MR_DELETE:
-               uv_unregister_mem_slot(kvm->arch.lpid, old->id);
-               kvmppc_uvmem_slot_free(kvm, old);
+               kvmppc_uvmem_memslot_delete(kvm, old);
                break;
        default:
                /* TODO: Handle KVM_MR_MOVE */
diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c 
b/arch/powerpc/kvm/book3s_hv_uvmem.c
index a1664ae..5b917ea 100644
--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
+++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
@@ -418,7 +418,7 @@ static int kvmppc_memslot_page_merge(struct kvm *kvm,
        return ret;
 }
 
-static void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
+static void __kvmppc_uvmem_memslot_delete(struct kvm *kvm,
                const struct kvm_memory_slot *memslot)
 {
        uv_unregister_mem_slot(kvm->arch.lpid, memslot->id);
@@ -426,7 +426,7 @@ static void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
        kvmppc_memslot_page_merge(kvm, memslot, true);
 }
 
-static int kvmppc_uvmem_memslot_create(struct kvm *kvm,
+static int __kvmppc_uvmem_memslot_create(struct kvm *kvm,
                const struct kvm_memory_slot *memslot)
 {
        int ret = H_PARAMETER;
@@ -478,7 +478,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
        /* register the memslot */
        slots = kvm_memslots(kvm);
        kvm_for_each_memslot(memslot, slots) {
-               ret = kvmppc_uvmem_memslot_create(kvm, memslot);
+               ret = __kvmppc_uvmem_memslot_create(kvm, memslot);
                if (ret)
                        break;
        }
@@ -488,7 +488,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
                kvm_for_each_memslot(m, slots) {
                        if (m == memslot)
                                break;
-                       kvmppc_uvmem_memslot_delete(kvm, memslot);
+                       __kvmppc_uvmem_memslot_delete(kvm, memslot);
                }
        }
 
@@ -1057,6 +1057,21 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned 
long gfn)
        return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT;
 }
 
+int kvmppc_uvmem_memslot_create(struct kvm *kvm, const struct kvm_memory_slot 
*new)
+{
+       int ret = __kvmppc_uvmem_memslot_create(kvm, new);
+
+       if (!ret)
+               ret = kvmppc_uv_migrate_mem_slot(kvm, new);
+
+       return ret;
+}
+
+void kvmppc_uvmem_memslot_delete(struct kvm *kvm, const struct kvm_memory_slot 
*old)
+{
+       __kvmppc_uvmem_memslot_delete(kvm, old);
+}
+
 static u64 kvmppc_get_secmem_size(void)
 {
        struct device_node *np;
-- 
1.8.3.1

Reply via email to