KVM: PPC: Book3S HV: Migrate hot plugged memory

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 <bharata@linux.ibm.com>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
[rearranged the code, and modified the commit log]
Signed-off-by: Laurent Dufour <ldufour@linux.ibm.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
Laurent Dufour 2020-07-27 11:07:18 -07:00 committed by Paul Mackerras
parent dfaa973ae9
commit a2ce720038
3 changed files with 39 additions and 12 deletions

View File

@ -23,6 +23,10 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn);
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__ */

View File

@ -4523,16 +4523,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 */

View File

@ -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;