All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jarkko Sakkinen <jarkko@profian.com>
To: Sean Christopherson <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>
Cc: Harald Hoyer <harald@profian.com>, Tom Dohrmann <erbse.13@gmx.de>,
	Ashish Kalra <ashish.kalra@amd.com>,
	Michael Roth <michael.roth@amd.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Jarkko Sakkinen <jarkko@profian.com>,
	kvm@vger.kernel.org (open list:KERNEL VIRTUAL MACHINE FOR X86
	(KVM/x86)),
	linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT
	AND 64-BIT))
Subject: [PATCH RFC 6/8] KVM: SVM: KVM_SEV_SNP_LAUNCH_RESET_VECTOR
Date: Fri, 27 Jan 2023 02:52:35 +0000	[thread overview]
Message-ID: <20230127025237.269680-7-jarkko@profian.com> (raw)
In-Reply-To: <20230127025237.269680-1-jarkko@profian.com>

The attestation of the workload includes the CPU state information.

When the workload that was running in the VM exits, the system stores
the state in the special area (VMSA).  When the workload is started again,
it loads the state back.  This is a well-defined process and works.

However, the *initial state* needs to be better defined.  Currently, it is
defined by kernel without userspace knowledge or ability to influence.  As
a result, Enarx does not know the initial state and has to make a guess
whenever there is need to offline digest calculation.  After all, the core
idea of confidential computing that everything can be validated and
verified in order to reach trust.

The variation could come mainly from either sev_features and vintr_ctrl.

Allow to user space to define them when the new KVM_SEV_SNP_RESET_VECTOR
init flag is set but at the same time verify that they are set only to
those values that kernel is aware of.

Link: https://enarx.dev/
Signed-off-by: Jarkko Sakkinen <jarkko@profian.com>
---
 arch/x86/include/asm/svm.h | 15 ++++++----
 arch/x86/kvm/svm/sev.c     | 57 +++++++++++++++++++++++++++++++-------
 arch/x86/kvm/svm/svm.h     |  1 +
 include/uapi/linux/kvm.h   |  5 ++++
 4 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index e76ad26ba64f..b3b7131a1ce7 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -278,12 +278,17 @@ enum avic_ipi_failure_cause {
 #define AVIC_HPA_MASK	~((0xFFFULL << 52) | 0xFFF)
 #define VMCB_AVIC_APIC_BAR_MASK		0xFFFFFFFFFF000ULL
 
-#define SVM_SEV_FEAT_SNP_ACTIVE			BIT(0)
-#define SVM_SEV_FEAT_RESTRICTED_INJECTION	BIT(3)
-#define SVM_SEV_FEAT_ALTERNATE_INJECTION	BIT(4)
-#define SVM_SEV_FEAT_INT_INJ_MODES		\
-	(SVM_SEV_FEAT_RESTRICTED_INJECTION |	\
+
+#define SVM_SEV_FEAT_SNP_ACTIVE			BIT_ULL(0)
+#define SVM_SEV_FEAT_RESTRICTED_INJECTION	BIT_ULL(3)
+#define SVM_SEV_FEAT_ALTERNATE_INJECTION	BIT_ULL(4)
+#define SVM_SEV_FEAT_INT_INJ_MODES \
+	(SVM_SEV_FEAT_RESTRICTED_INJECTION |\
 	 SVM_SEV_FEAT_ALTERNATE_INJECTION)
+#define SVM_SEV_FEAT_UNSUPPORTED_MASK \
+	~(SVM_SEV_FEAT_SNP_ACTIVE |\
+	  SVM_SEV_FEAT_RESTRICTED_INJECTION |\
+	  SVM_SEV_FEAT_ALTERNATE_INJECTION)
 
 struct vmcb_seg {
 	u16 selector;
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 899c78d03c35..5e4666b79689 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -303,6 +303,11 @@ static int verify_snp_init_flags(struct kvm *kvm, struct kvm_sev_cmd *argp)
 	/* Save the supplied flags value */
 	sev->snp_init_flags = params.flags;
 
+	if (params.flags & KVM_SEV_SNP_RESET_VECTOR) {
+		sev->sev_features = params.sev_features;
+		sev->vintr_ctrl = params.vintr_ctrl;
+	}
+
 	/* Return the supported flags value */
 	params.flags = SEV_SNP_SUPPORTED_FLAGS;
 
@@ -785,6 +790,33 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
 	if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
 		return -EINVAL;
 
+	/* Validate that the user defined reset vector meets the expectations: */
+	if (sev->snp_init_flags & KVM_SEV_SNP_RESET_VECTOR) {
+		u64 unsupported = sev->sev_features & SVM_SEV_FEAT_UNSUPPORTED_MASK;
+
+		if (sev->sev_features & unsupported) {
+			pr_debug("sev_features: unsupported flags: 0x%016llx\n", unsupported);
+			return -EINVAL;
+		}
+
+		if (!(sev_snp_guest(svm->vcpu.kvm) &&
+		    (sev->sev_features & SVM_SEV_FEAT_SNP_ACTIVE))) {
+			pr_debug("sev_features: SNP_ACTIVE is not set\n");
+			return -EINVAL;
+		}
+
+		if (!((sev->snp_init_flags & KVM_SEV_SNP_RESTRICTED_INJET) &&
+		    (sev->sev_features & SVM_SEV_FEAT_RESTRICTED_INJECTION))) {
+			pr_debug("sev_features: SNP_SEV_FEAT_RESTRICTED_INJECTION is not set\n");
+			return -EINVAL;
+		}
+
+		if (sev->vintr_ctrl) {
+			pr_debug("vintr_ctrl: unsupported flags: 0x%016llx\n", sev->vintr_ctrl);
+			return -EINVAL;
+		}
+	}
+
 	/*
 	 * SEV-ES will use a VMSA that is pointed to by the VMCB, not
 	 * the traditional VMSA that is part of the VMCB. Copy the
@@ -820,18 +852,23 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
 	save->xss  = svm->vcpu.arch.ia32_xss;
 	save->dr6  = svm->vcpu.arch.dr6;
 
-	/* Enable the SEV-SNP feature */
-	if (sev_snp_guest(svm->vcpu.kvm))
-		save->sev_features |= SVM_SEV_FEAT_SNP_ACTIVE;
+	if (sev->snp_init_flags & KVM_SEV_SNP_RESET_VECTOR) {
+		save->sev_features = sev->sev_features;
+		save->vintr_ctrl = sev->vintr_ctrl;
+	} else {
+		/* Enable the SEV-SNP feature */
+		if (sev_snp_guest(svm->vcpu.kvm))
+			save->sev_features |= SVM_SEV_FEAT_SNP_ACTIVE;
 
-	if (sev->snp_init_flags & KVM_SEV_SNP_RESTRICTED_INJET)
-		save->sev_features |= SVM_SEV_FEAT_RESTRICTED_INJECTION;
+		if (sev->snp_init_flags & KVM_SEV_SNP_RESTRICTED_INJET)
+			save->sev_features |= SVM_SEV_FEAT_RESTRICTED_INJECTION;
 
-	/*
-	 * Save the VMSA synced SEV features. For now, they are the same for
-	 * all vCPUs, so just save each time.
-	 */
-	sev->sev_features = save->sev_features;
+		/*
+		 * Save the VMSA synced SEV features. For now, they are the same for
+		 * all vCPUs, so just save each time.
+		 */
+		sev->sev_features = save->sev_features;
+	}
 
 	pr_debug("Virtual Machine Save Area (VMSA):\n");
 	print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, save, sizeof(*save), false);
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 4dab13084363..5dce17eefd5d 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -106,6 +106,7 @@ struct kvm_sev_info {
 	struct mutex guest_req_lock;
 
 	u64 sev_features;	/* Features set at VMSA creation */
+	u64 vintr_ctrl;
 };
 
 struct kvm_svm {
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 48bcc59cf86b..e176d0ec6c54 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -2054,8 +2054,13 @@ struct kvm_sev_receive_update_data {
 /* enable the restricted injection timer */
 #define KVM_SEV_SNP_RESTRICTED_TIMER_INJET   (1 << 1)
 
+/* use the given reset vector for sev_features and vintr_ctrl */
+#define KVM_SEV_SNP_RESET_VECTOR   (1 << 2)
+
 struct kvm_snp_init {
 	__u64 flags;
+	__u64 sev_features;
+	__u64 vintr_ctrl;
 };
 
 struct kvm_sev_snp_launch_start {
-- 
2.38.1


  parent reply	other threads:[~2023-01-27  2:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20230127025237.269680-1-jarkko@profian.com>
2023-01-27  2:52 ` [PATCH RFC 1/8] KVM: SVM: fix: calculate end instead of passing size Jarkko Sakkinen
2023-01-27  2:52 ` [PATCH RFC 2/8] KVM: SVM: fix: initialize `npinned` Jarkko Sakkinen
2023-01-27  2:52 ` [PATCH RFC 3/8] KVM: SVM: write back corrected CPUID page Jarkko Sakkinen
2023-01-27 22:46   ` Tom Lendacky
2023-01-27  2:52 ` [PATCH RFC 4/8] KVM: SVM: fix: add separate error for missing slot Jarkko Sakkinen
2023-01-27  2:52 ` [PATCH RFC 5/8] KVM: SVM: fix: Don't return an error for `GHCB_MSR_PSC_REQ` Jarkko Sakkinen
2023-01-27  2:52 ` Jarkko Sakkinen [this message]
2023-01-27  2:52 ` [PATCH RFC 7/8] crypto: ccp: Prevent a spurious SEV_CMD_SNP_INIT triggered by sev_guest_init() Jarkko Sakkinen
2023-01-27  2:52 ` [PATCH RFC 8/8] crypto: ccp: Move __sev_snp_init_locked() call inside __sev_platform_init_locked() Jarkko Sakkinen
2023-01-27  2:56   ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230127025237.269680-7-jarkko@profian.com \
    --to=jarkko@profian.com \
    --cc=ashish.kalra@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=erbse.13@gmx.de \
    --cc=harald@profian.com \
    --cc=hpa@zytor.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.roth@amd.com \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.