Commit a87600ec authored by Xin Jiang's avatar Xin Jiang Committed by hanliyang
Browse files

KVM: SVM: CSV: Add KVM_CSV3_INIT command

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


CVE: NA

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

The command initializes the CSV3 guest's context. The firmware
should be initialized before we issue any CSV3 guest commands.

Signed-off-by: default avatarXin Jiang <jiangxin@hygon.cn>
Signed-off-by: default avatarhanliyang <hanliyang@hygon.cn>
parent 91df1ee6
Loading
Loading
Loading
Loading
+114 −15
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@
/* Function and variable pointers for hooks */
struct hygon_kvm_hooks_table hygon_kvm_hooks;

/* enable/disable CSV3 support */
static bool csv3_enabled = true;

static struct kvm_x86_ops csv_x86_ops;
static const char csv_vm_mnonce[] = "VM_ATTESTATION";
static DEFINE_MUTEX(csv_cmd_batch_mutex);
@@ -134,7 +137,19 @@ static void csv_reset_mempool_offset(void)
	g_mempool_offset = 0;
}

int csv_alloc_trans_mempool(void)
static void csv_free_trans_mempool(void)
{
	int i;

	for (i = 0; i < TRANS_MEMPOOL_BLOCK_NUM; i++) {
		kfree(g_trans_mempool[i]);
		g_trans_mempool[i] = NULL;
	}

	csv_reset_mempool_offset();
}

static int csv_alloc_trans_mempool(void)
{
	int i;

@@ -157,18 +172,6 @@ int csv_alloc_trans_mempool(void)
	return -ENOMEM;
}

void csv_free_trans_mempool(void)
{
	int i;

	for (i = 0; i < TRANS_MEMPOOL_BLOCK_NUM; i++) {
		kfree(g_trans_mempool[i]);
		g_trans_mempool[i] = NULL;
	}

	csv_reset_mempool_offset();
}

static void __maybe_unused *get_trans_data_from_mempool(size_t size)
{
	void *trans = NULL;
@@ -795,6 +798,46 @@ static int csv_receive_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
	return ret;
}

struct kvm_csv_info {
	struct kvm_sev_info *sev;

	bool csv3_active;	/* CSV3 enabled guest */
	unsigned long nodemask; /* Nodemask where CSV3 guest's memory resides */
};

struct kvm_svm_csv {
	struct kvm_svm kvm_svm;
	struct kvm_csv_info csv_info;
};

static inline struct kvm_svm_csv *to_kvm_svm_csv(struct kvm *kvm)
{
	return (struct kvm_svm_csv *)container_of(kvm, struct kvm_svm, kvm);
}

static int csv3_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
{
	struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
	struct kvm_csv_info *csv = &to_kvm_svm_csv(kvm)->csv_info;
	struct kvm_csv3_init_data params;

	if (unlikely(csv->csv3_active))
		return -EINVAL;

	if (unlikely(!sev->es_active))
		return -EINVAL;

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

	csv->csv3_active = true;
	csv->sev = sev;
	csv->nodemask = (unsigned long)params.nodemask;

	return 0;
}

static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
{
	struct kvm_sev_cmd sev_cmd;
@@ -836,6 +879,13 @@ static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
		 */
		r = csv_receive_update_vmsa(kvm, &sev_cmd);
		break;
	case KVM_CSV3_INIT:
		if (!csv3_enabled) {
			r = -ENOTTY;
			goto out;
		}
		r = csv3_guest_init(kvm, &sev_cmd);
		break;
	default:
		/*
		 * If the command is compatible between CSV and SEV, the
@@ -851,6 +901,7 @@ static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
	if (copy_to_user(argp, &sev_cmd, sizeof(struct kvm_sev_cmd)))
		r = -EFAULT;

out:
	mutex_unlock(&kvm->lock);
	return r;
}
@@ -1062,7 +1113,7 @@ static int csv_control_post_system_reset(struct kvm *kvm)

struct csv_asid_userid *csv_asid_userid_array;

int csv_alloc_asid_userid_array(unsigned int nr_asids)
static int csv_alloc_asid_userid_array(unsigned int nr_asids)
{
	int ret = 0;

@@ -1077,14 +1128,59 @@ int csv_alloc_asid_userid_array(unsigned int nr_asids)
	return ret;
}

void csv_free_asid_userid_array(void)
static void csv_free_asid_userid_array(void)
{
	kfree(csv_asid_userid_array);
	csv_asid_userid_array = NULL;
}

#else	/* !CONFIG_KVM_SUPPORTS_CSV_REUSE_ASID */

static int csv_alloc_asid_userid_array(unsigned int nr_asids)
{
	pr_warn("reuse ASID is unavailable\n");
	return -EFAULT;
}

static void csv_free_asid_userid_array(void)
{
}

#endif	/* CONFIG_KVM_SUPPORTS_CSV_REUSE_ASID */

void __init csv_hardware_setup(unsigned int max_csv_asid)
{
	unsigned int nr_asids = max_csv_asid + 1;

	/*
	 * Allocate a memory pool to speed up live migration of
	 * the CSV/CSV2 guests. If the allocation fails, no
	 * acceleration is performed at live migration.
	 */
	csv_alloc_trans_mempool();
	/*
	 * Allocate a buffer to support reuse ASID, reuse ASID
	 * will not work if the allocation fails.
	 */
	csv_alloc_asid_userid_array(nr_asids);

	/* CSV3 depends on X86_FEATURE_CSV3 */
	if (boot_cpu_has(X86_FEATURE_SEV_ES) && boot_cpu_has(X86_FEATURE_CSV3))
		csv3_enabled = true;
	else
		csv3_enabled = false;

	pr_info("CSV3 %s (ASIDs 1 - %u)\n",
		csv3_enabled ? "enabled" : "disabled", max_csv_asid);
}

void csv_hardware_unsetup(void)
{
	/* Free the memory that allocated in csv_hardware_setup(). */
	csv_free_trans_mempool();
	csv_free_asid_userid_array();
}

void csv_exit(void)
{
}
@@ -1104,4 +1200,7 @@ void __init csv_init(struct kvm_x86_ops *ops)
	ops->vm_attestation = csv_vm_attestation;
	ops->control_pre_system_reset = csv_control_pre_system_reset;
	ops->control_post_system_reset = csv_control_post_system_reset;

	if (boot_cpu_has(X86_FEATURE_SEV_ES) && boot_cpu_has(X86_FEATURE_CSV3))
		ops->vm_size = sizeof(struct kvm_svm_csv);
}
+6 −13
Original line number Diff line number Diff line
@@ -41,17 +41,8 @@ struct csv_asid_userid {
	u32 userid_len;
	char userid[ASID_USERID_LENGTH];
};

extern struct csv_asid_userid *csv_asid_userid_array;

int csv_alloc_asid_userid_array(unsigned int nr_asids);
void csv_free_asid_userid_array(void);

#else

static inline int csv_alloc_asid_userid_array(unsigned int nr_asids) { return -ENOMEM; }
static inline void csv_free_asid_userid_array(void) { }

#endif	/* CONFIG_KVM_SUPPORTS_CSV_REUSE_ASID */

#ifdef CONFIG_HYGON_CSV
@@ -79,8 +70,9 @@ extern struct hygon_kvm_hooks_table {
void __init csv_init(struct kvm_x86_ops *ops);
void csv_exit(void);

int csv_alloc_trans_mempool(void);
void csv_free_trans_mempool(void);
void __init csv_hardware_setup(unsigned int max_csv_asid);
void csv_hardware_unsetup(void);

int csv_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
int csv_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
bool csv_has_emulated_ghcb_msr(struct kvm *kvm);
@@ -98,8 +90,9 @@ static inline bool csv2_state_unstable(struct vcpu_svm *svm)
static inline void __init csv_init(struct kvm_x86_ops *ops) { }
static inline void csv_exit(void) { }

static inline int csv_alloc_trans_mempool(void) { return 0; }
static inline void csv_free_trans_mempool(void) { }
static inline void __init csv_hardware_setup(unsigned int max_csv_asid) { }
static inline void csv_hardware_unsetup(void) { }

static inline
int csv_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { return 1; }
static inline
+4 −18
Original line number Diff line number Diff line
@@ -2450,19 +2450,8 @@ void __init sev_hardware_setup(void)
		 */
		sev_install_hooks();

		if (sev_enabled) {
			/*
			 * Allocate a memory pool to speed up live migration of
			 * the CSV/CSV2 guests. If the allocation fails, no
			 * acceleration is performed at live migration.
			 */
			csv_alloc_trans_mempool();
			/*
			 * Allocate a buffer to support reuse ASID, reuse ASID
			 * will not work if the allocation fails.
			 */
			csv_alloc_asid_userid_array(nr_asids);
		}
		if (sev_enabled)
			csv_hardware_setup(max_sev_asid);
	}
#endif

@@ -2474,11 +2463,8 @@ void sev_hardware_unsetup(void)
	if (!sev_enabled)
		return;

	/* Free the memory that allocated in sev_hardware_setup(). */
	if (is_x86_vendor_hygon()) {
		csv_free_trans_mempool();
		csv_free_asid_userid_array();
	}
	if (is_x86_vendor_hygon())
		csv_hardware_unsetup();

	/* No need to take sev_bitmap_lock, all VMs have been destroyed. */
	sev_flush_asids(1, max_sev_asid);