Commit c97c1d01 authored by yangwencheng's avatar yangwencheng Committed by hanliyang
Browse files

KVM: SVM: CSV: Add ioctl API to unpin shared pages of CSV3 guest

hygon inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAYGKY


CVE: NA

---------------------------

The shared pages between CSV3 guest and host are pinned in memory,
and managed in list, they will be released to system till the guest
VM was destroyed.

The new ioctl API supports to unpin the shared pages, and remove
them from the list.

For shared memory allocated from guest user-space process, they
must be unpinned dynamically when the process exits.

Signed-off-by: default avataryangwencheng <yangwencheng@hygon.cn>
Signed-off-by: default avatarhanliyang <hanliyang@hygon.cn>
parent f11dc54e
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -2033,6 +2033,36 @@ static int csv3_pin_shared_memory(struct kvm_vcpu *vcpu,
	return 0;
}

/**
 *  Return negative error code on fail,
 *  or return the number of pages unpinned successfully
 */
static int csv3_unpin_shared_memory(struct kvm *kvm, gpa_t gpa, u32 num_pages)
{
	struct kvm_csv_info *csv;
	struct shared_page *sp;
	gfn_t gfn;
	unsigned long i;
	int unpin_cnt = 0;

	csv = &to_kvm_svm_csv(kvm)->csv_info;
	gfn = gpa_to_gfn(gpa);

	mutex_lock(&csv->sp_lock);
	for (i = 0; i < num_pages; i++, gfn++) {
		sp = shared_page_remove(&csv->sp_mgr, gfn);
		if (sp) {
			unpin_user_page(sp->page);
			kmem_cache_free(csv->sp_slab, sp);
			csv->sp_mgr.count--;
			unpin_cnt++;
		}
	}
	mutex_unlock(&csv->sp_lock);

	return unpin_cnt;
}

static int __pfn_mapping_level(struct kvm *kvm, gfn_t gfn,
			       const struct kvm_memory_slot *slot)
{
@@ -2277,6 +2307,29 @@ static void csv_guest_memory_reclaimed(struct kvm *kvm)
	}
}

static int csv3_handle_memory(struct kvm *kvm, struct kvm_sev_cmd *argp)
{
	struct kvm_csv3_handle_memory params;
	int r = -EINVAL;

	if (!csv3_guest(kvm))
		return -ENOTTY;

	if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
			   sizeof(params)))
		return -EFAULT;

	switch (params.opcode) {
	case KVM_CSV3_RELEASE_SHARED_MEMORY:
		r = csv3_unpin_shared_memory(kvm, params.gpa, params.num_pages);
		break;
	default:
		break;
	}

	return r;
};

static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
{
	struct kvm_sev_cmd sev_cmd;
@@ -2343,6 +2396,9 @@ static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
	case KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT:
		r = csv3_receive_encrypt_context(kvm, &sev_cmd);
		break;
	case KVM_CSV3_HANDLE_MEMORY:
		r = csv3_handle_memory(kvm, &sev_cmd);
		break;
	default:
		/*
		 * If the command is compatible between CSV and SEV, the
+9 −0
Original line number Diff line number Diff line
@@ -2367,6 +2367,7 @@ enum csv3_cmd_id {
	KVM_CSV3_SEND_ENCRYPT_CONTEXT,
	KVM_CSV3_RECEIVE_ENCRYPT_DATA,
	KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT,
	KVM_CSV3_HANDLE_MEMORY,

	KVM_CSV3_NR_MAX,
};
@@ -2413,4 +2414,12 @@ struct kvm_csv3_receive_encrypt_context {
	__u32 trans_len;
};

#define KVM_CSV3_RELEASE_SHARED_MEMORY (0x0001)

struct kvm_csv3_handle_memory {
	__u64 gpa;
	__u32 num_pages;
	__u32 opcode;
};

#endif /* __LINUX_KVM_H */