Merge tag 'x86_urgent_for_v6.2_rc6' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / x86 / boot / compressed / sev.c
index c93930d5ccbd0f1b4894012e09c885e20ee1ba0a..d63ad8f99f83a3c616f3560cd12f3ea03acbe049 100644 (file)
@@ -208,6 +208,23 @@ void sev_es_shutdown_ghcb(void)
                error("Can't unmap GHCB page");
 }
 
+static void __noreturn sev_es_ghcb_terminate(struct ghcb *ghcb, unsigned int set,
+                                            unsigned int reason, u64 exit_info_2)
+{
+       u64 exit_info_1 = SVM_VMGEXIT_TERM_REASON(set, reason);
+
+       vc_ghcb_invalidate(ghcb);
+       ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_TERM_REQUEST);
+       ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
+       ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
+
+       sev_es_wr_ghcb_msr(__pa(ghcb));
+       VMGEXIT();
+
+       while (true)
+               asm volatile("hlt\n" : : : "memory");
+}
+
 bool sev_es_check_ghcb_fault(unsigned long address)
 {
        /* Check whether the fault was on the GHCB page */
@@ -270,6 +287,59 @@ static void enforce_vmpl0(void)
                sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
 }
 
+/*
+ * SNP_FEATURES_IMPL_REQ is the mask of SNP features that will need
+ * guest side implementation for proper functioning of the guest. If any
+ * of these features are enabled in the hypervisor but are lacking guest
+ * side implementation, the behavior of the guest will be undefined. The
+ * guest could fail in non-obvious way making it difficult to debug.
+ *
+ * As the behavior of reserved feature bits is unknown to be on the
+ * safe side add them to the required features mask.
+ */
+#define SNP_FEATURES_IMPL_REQ  (MSR_AMD64_SNP_VTOM |                   \
+                                MSR_AMD64_SNP_REFLECT_VC |             \
+                                MSR_AMD64_SNP_RESTRICTED_INJ |         \
+                                MSR_AMD64_SNP_ALT_INJ |                \
+                                MSR_AMD64_SNP_DEBUG_SWAP |             \
+                                MSR_AMD64_SNP_VMPL_SSS |               \
+                                MSR_AMD64_SNP_SECURE_TSC |             \
+                                MSR_AMD64_SNP_VMGEXIT_PARAM |          \
+                                MSR_AMD64_SNP_VMSA_REG_PROTECTION |    \
+                                MSR_AMD64_SNP_RESERVED_BIT13 |         \
+                                MSR_AMD64_SNP_RESERVED_BIT15 |         \
+                                MSR_AMD64_SNP_RESERVED_MASK)
+
+/*
+ * SNP_FEATURES_PRESENT is the mask of SNP features that are implemented
+ * by the guest kernel. As and when a new feature is implemented in the
+ * guest kernel, a corresponding bit should be added to the mask.
+ */
+#define SNP_FEATURES_PRESENT (0)
+
+void snp_check_features(void)
+{
+       u64 unsupported;
+
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
+               return;
+
+       /*
+        * Terminate the boot if hypervisor has enabled any feature lacking
+        * guest side implementation. Pass on the unsupported features mask through
+        * EXIT_INFO_2 of the GHCB protocol so that those features can be reported
+        * as part of the guest boot failure.
+        */
+       unsupported = sev_status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT;
+       if (unsupported) {
+               if (ghcb_version < 2 || (!boot_ghcb && !early_setup_ghcb()))
+                       sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+
+               sev_es_ghcb_terminate(boot_ghcb, SEV_TERM_SET_GEN,
+                                     GHCB_SNP_UNSUPPORTED, unsupported);
+       }
+}
+
 void sev_enable(struct boot_params *bp)
 {
        unsigned int eax, ebx, ecx, edx;