Commit a2ce7200 authored by Laurent Dufour's avatar Laurent Dufour Committed by Paul Mackerras

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: default avatarBharata B Rao <bharata@linux.ibm.com>
Signed-off-by: default avatarRam Pai <linuxram@us.ibm.com>
[rearranged the code, and modified the commit log]
Signed-off-by: default avatarLaurent Dufour <ldufour@linux.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent dfaa973a
...@@ -23,6 +23,10 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn); ...@@ -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); unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm);
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free, void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
struct kvm *kvm, bool skip_page_out); 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 #else
static inline int kvmppc_uvmem_init(void) 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) ...@@ -82,5 +86,15 @@ static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
static inline void static inline void
kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free, kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
struct kvm *kvm, bool skip_page_out) { } 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 /* CONFIG_PPC_UV */
#endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */ #endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */
...@@ -4523,16 +4523,14 @@ static void kvmppc_core_commit_memory_region_hv(struct kvm *kvm, ...@@ -4523,16 +4523,14 @@ static void kvmppc_core_commit_memory_region_hv(struct kvm *kvm,
switch (change) { switch (change) {
case KVM_MR_CREATE: case KVM_MR_CREATE:
if (kvmppc_uvmem_slot_init(kvm, new)) /*
return; * @TODO kvmppc_uvmem_memslot_create() can fail and
uv_register_mem_slot(kvm->arch.lpid, * return error. Fix this.
new->base_gfn << PAGE_SHIFT, */
new->npages * PAGE_SIZE, kvmppc_uvmem_memslot_create(kvm, new);
0, new->id);
break; break;
case KVM_MR_DELETE: case KVM_MR_DELETE:
uv_unregister_mem_slot(kvm->arch.lpid, old->id); kvmppc_uvmem_memslot_delete(kvm, old);
kvmppc_uvmem_slot_free(kvm, old);
break; break;
default: default:
/* TODO: Handle KVM_MR_MOVE */ /* TODO: Handle KVM_MR_MOVE */
......
...@@ -418,7 +418,7 @@ static int kvmppc_memslot_page_merge(struct kvm *kvm, ...@@ -418,7 +418,7 @@ static int kvmppc_memslot_page_merge(struct kvm *kvm,
return ret; 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) const struct kvm_memory_slot *memslot)
{ {
uv_unregister_mem_slot(kvm->arch.lpid, memslot->id); uv_unregister_mem_slot(kvm->arch.lpid, memslot->id);
...@@ -426,7 +426,7 @@ static void kvmppc_uvmem_memslot_delete(struct kvm *kvm, ...@@ -426,7 +426,7 @@ static void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
kvmppc_memslot_page_merge(kvm, memslot, true); 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) const struct kvm_memory_slot *memslot)
{ {
int ret = H_PARAMETER; int ret = H_PARAMETER;
...@@ -478,7 +478,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm) ...@@ -478,7 +478,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
/* register the memslot */ /* register the memslot */
slots = kvm_memslots(kvm); slots = kvm_memslots(kvm);
kvm_for_each_memslot(memslot, slots) { kvm_for_each_memslot(memslot, slots) {
ret = kvmppc_uvmem_memslot_create(kvm, memslot); ret = __kvmppc_uvmem_memslot_create(kvm, memslot);
if (ret) if (ret)
break; break;
} }
...@@ -488,7 +488,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm) ...@@ -488,7 +488,7 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
kvm_for_each_memslot(m, slots) { kvm_for_each_memslot(m, slots) {
if (m == memslot) if (m == memslot)
break; 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) ...@@ -1057,6 +1057,21 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT; 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) static u64 kvmppc_get_secmem_size(void)
{ {
struct device_node *np; struct device_node *np;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment