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

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
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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__ */
+6 −8
Original line number Diff line number Diff line
@@ -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 */
+19 −4
Original line number Diff line number Diff line
@@ -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;