From: Laurent Dufour <ldufour@xxxxxxxxxxxxx> When a memory slot is hot plugged to a SVM, PFNs associated with the GFNs in that slot must be migrated to secure-PFNs, aka device-PFNs. Call kvmppc_uv_migrate_mem_slot() to accomplish this. Disable page-merge for all pages in the memory slot. Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx> [rearranged the code, and modified the commit log] Signed-off-by: Laurent Dufour <ldufour@xxxxxxxxxxxxx> --- arch/powerpc/include/asm/kvm_book3s_uvmem.h | 10 ++++++++++ arch/powerpc/kvm/book3s_hv.c | 10 ++-------- arch/powerpc/kvm/book3s_hv_uvmem.c | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_book3s_uvmem.h b/arch/powerpc/include/asm/kvm_book3s_uvmem.h index f229ab5..6f7da00 100644 --- a/arch/powerpc/include/asm/kvm_book3s_uvmem.h +++ b/arch/powerpc/include/asm/kvm_book3s_uvmem.h @@ -25,6 +25,9 @@ void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free, struct kvm *kvm, bool skip_page_out); int kvmppc_uv_migrate_mem_slot(struct kvm *kvm, const struct kvm_memory_slot *memslot); +void kvmppc_memslot_create(struct kvm *kvm, const struct kvm_memory_slot *new); +void kvmppc_memslot_delete(struct kvm *kvm, const struct kvm_memory_slot *old); + #else static inline int kvmppc_uvmem_init(void) { @@ -84,5 +87,12 @@ 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 void kvmppc_memslot_create(struct kvm *kvm, + const struct kvm_memory_slot *new) { } + +static inline void kvmppc_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..bf3be3b 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -4515,16 +4515,10 @@ 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); + kvmppc_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_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 a206984..a2b4d25 100644 --- a/arch/powerpc/kvm/book3s_hv_uvmem.c +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c @@ -1089,6 +1089,28 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn) return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT; } +void kvmppc_memslot_create(struct kvm *kvm, const struct kvm_memory_slot *new) +{ + if (kvmppc_uvmem_slot_init(kvm, new)) + return; + + if (kvmppc_memslot_page_merge(kvm, new, false)) + return; + + if (uv_register_mem_slot(kvm->arch.lpid, new->base_gfn << PAGE_SHIFT, + new->npages * PAGE_SIZE, 0, new->id)) + return; + + kvmppc_uv_migrate_mem_slot(kvm, new); +} + +void kvmppc_memslot_delete(struct kvm *kvm, const struct kvm_memory_slot *old) +{ + uv_unregister_mem_slot(kvm->arch.lpid, old->id); + kvmppc_memslot_page_merge(kvm, old, true); + kvmppc_uvmem_slot_free(kvm, old); +} + static u64 kvmppc_get_secmem_size(void) { struct device_node *np; -- 1.8.3.1