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

KVM: SVM: CSV: Add KVM_CSV3_LAUNCH_ENCRYPT_VMCB command

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


CVE: NA

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

The command is used to get secure VMCB physical address which is
allocated in private memory by firmware. Besides, shadow VMCB
physical address will be updated in secure VMCB. Also the firmware
creates a new private page for guest's VMSA per vcpu.

Signed-off-by: default avatarXin Jiang <jiangxin@hygon.cn>
Signed-off-by: default avatarhanliyang <hanliyang@hygon.cn>
parent e23a88d6
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -1103,6 +1103,73 @@ static int csv3_launch_encrypt_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
	return ret;
}

static int csv3_sync_vmsa(struct vcpu_svm *svm)
{
	struct sev_es_save_area *save = svm->sev_es.vmsa;

	/* Check some debug related fields before encrypting the VMSA */
	if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
		return -EINVAL;

	memcpy(save, &svm->vmcb->save, sizeof(svm->vmcb->save));

	/* Sync registgers per spec. */
	save->rax = svm->vcpu.arch.regs[VCPU_REGS_RAX];
	save->rdx = svm->vcpu.arch.regs[VCPU_REGS_RDX];
	save->rip = svm->vcpu.arch.regs[VCPU_REGS_RIP];
	save->xcr0 = svm->vcpu.arch.xcr0;
	save->xss  = svm->vcpu.arch.ia32_xss;

	return 0;
}

static int csv3_launch_encrypt_vmcb(struct kvm *kvm, struct kvm_sev_cmd *argp)
{
	struct kvm_csv_info *csv = &to_kvm_svm_csv(kvm)->csv_info;
	struct csv3_data_launch_encrypt_vmcb *encrypt_vmcb = NULL;
	struct kvm_vcpu *vcpu;
	int ret = 0;
	unsigned long i = 0;

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

	encrypt_vmcb = kzalloc(sizeof(*encrypt_vmcb), GFP_KERNEL);
	if (!encrypt_vmcb) {
		ret = -ENOMEM;
		goto exit;
	}

	kvm_for_each_vcpu(i, vcpu, kvm) {
		struct vcpu_svm *svm = to_svm(vcpu);

		ret = csv3_sync_vmsa(svm);
		if (ret)
			goto e_free;
		clflush_cache_range(svm->sev_es.vmsa, PAGE_SIZE);
		clflush_cache_range(svm->vmcb, PAGE_SIZE);
		encrypt_vmcb->handle = csv->sev->handle;
		encrypt_vmcb->vcpu_id = i;
		encrypt_vmcb->vmsa_addr = __sme_pa(svm->sev_es.vmsa);
		encrypt_vmcb->vmsa_len = PAGE_SIZE;
		encrypt_vmcb->shadow_vmcb_addr = __sme_pa(svm->vmcb);
		encrypt_vmcb->shadow_vmcb_len = PAGE_SIZE;
		ret = hygon_kvm_hooks.sev_issue_cmd(kvm,
						CSV3_CMD_LAUNCH_ENCRYPT_VMCB,
						encrypt_vmcb, &argp->error);
		if (ret)
			goto e_free;

		svm->current_vmcb->pa = encrypt_vmcb->secure_vmcb_addr;
		svm->vcpu.arch.guest_state_protected = true;
	}

e_free:
	kfree(encrypt_vmcb);
exit:
	return ret;
}

static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
{
	struct kvm_sev_cmd sev_cmd;
@@ -1154,6 +1221,9 @@ static int csv_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
	case KVM_CSV3_LAUNCH_ENCRYPT_DATA:
		r = csv3_launch_encrypt_data(kvm, &sev_cmd);
		break;
	case KVM_CSV3_LAUNCH_ENCRYPT_VMCB:
		r = csv3_launch_encrypt_vmcb(kvm, &sev_cmd);
		break;
	default:
		/*
		 * If the command is compatible between CSV and SEV, the