Merge branch 'linus' into x86/urgent, to pick up dependent commit
authorIngo Molnar <mingo@kernel.org>
Sat, 6 Apr 2024 11:00:32 +0000 (13:00 +0200)
committerIngo Molnar <mingo@kernel.org>
Sat, 6 Apr 2024 11:00:32 +0000 (13:00 +0200)
We want to fix:

  0e110732473e ("x86/retpoline: Do the necessary fixup to the Zen3/4 srso return thunk for !SRSO")

So merge in Linus's latest into x86/urgent to have it available.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
16 files changed:
arch/x86/coco/core.c
arch/x86/include/asm/coco.h
arch/x86/include/asm/sev.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/resctrl/internal.h
arch/x86/kernel/setup.c
arch/x86/kernel/sev.c
arch/x86/kvm/Kconfig
arch/x86/kvm/svm/sev.c
arch/x86/mm/numa_32.c
arch/x86/virt/svm/sev.c
drivers/crypto/ccp/sev-dev.c
drivers/iommu/amd/init.c
include/linux/cc_platform.h

index d07be9d05cd03781072798e5802a5ef34d7a057a..b31ef2424d194b96d07b601d4eeac4b23d637d27 100644 (file)
@@ -3,19 +3,28 @@
  * Confidential Computing Platform Capability checks
  *
  * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ * Copyright (C) 2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  *
  * Author: Tom Lendacky <thomas.lendacky@amd.com>
  */
 
 #include <linux/export.h>
 #include <linux/cc_platform.h>
+#include <linux/string.h>
+#include <linux/random.h>
 
+#include <asm/archrandom.h>
 #include <asm/coco.h>
 #include <asm/processor.h>
 
 enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE;
 u64 cc_mask __ro_after_init;
 
+static struct cc_attr_flags {
+       __u64 host_sev_snp      : 1,
+             __resv            : 63;
+} cc_flags;
+
 static bool noinstr intel_cc_platform_has(enum cc_attr attr)
 {
        switch (attr) {
@@ -89,6 +98,9 @@ static bool noinstr amd_cc_platform_has(enum cc_attr attr)
        case CC_ATTR_GUEST_SEV_SNP:
                return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
 
+       case CC_ATTR_HOST_SEV_SNP:
+               return cc_flags.host_sev_snp;
+
        default:
                return false;
        }
@@ -148,3 +160,84 @@ u64 cc_mkdec(u64 val)
        }
 }
 EXPORT_SYMBOL_GPL(cc_mkdec);
+
+static void amd_cc_platform_clear(enum cc_attr attr)
+{
+       switch (attr) {
+       case CC_ATTR_HOST_SEV_SNP:
+               cc_flags.host_sev_snp = 0;
+               break;
+       default:
+               break;
+       }
+}
+
+void cc_platform_clear(enum cc_attr attr)
+{
+       switch (cc_vendor) {
+       case CC_VENDOR_AMD:
+               amd_cc_platform_clear(attr);
+               break;
+       default:
+               break;
+       }
+}
+
+static void amd_cc_platform_set(enum cc_attr attr)
+{
+       switch (attr) {
+       case CC_ATTR_HOST_SEV_SNP:
+               cc_flags.host_sev_snp = 1;
+               break;
+       default:
+               break;
+       }
+}
+
+void cc_platform_set(enum cc_attr attr)
+{
+       switch (cc_vendor) {
+       case CC_VENDOR_AMD:
+               amd_cc_platform_set(attr);
+               break;
+       default:
+               break;
+       }
+}
+
+__init void cc_random_init(void)
+{
+       /*
+        * The seed is 32 bytes (in units of longs), which is 256 bits, which
+        * is the security level that the RNG is targeting.
+        */
+       unsigned long rng_seed[32 / sizeof(long)];
+       size_t i, longs;
+
+       if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
+               return;
+
+       /*
+        * Since the CoCo threat model includes the host, the only reliable
+        * source of entropy that can be neither observed nor manipulated is
+        * RDRAND. Usually, RDRAND failure is considered tolerable, but since
+        * CoCo guests have no other unobservable source of entropy, it's
+        * important to at least ensure the RNG gets some initial random seeds.
+        */
+       for (i = 0; i < ARRAY_SIZE(rng_seed); i += longs) {
+               longs = arch_get_random_longs(&rng_seed[i], ARRAY_SIZE(rng_seed) - i);
+
+               /*
+                * A zero return value means that the guest doesn't have RDRAND
+                * or the CPU is physically broken, and in both cases that
+                * means most crypto inside of the CoCo instance will be
+                * broken, defeating the purpose of CoCo in the first place. So
+                * just panic here because it's absolutely unsafe to continue
+                * executing.
+                */
+               if (longs == 0)
+                       panic("RDRAND is defective.");
+       }
+       add_device_randomness(rng_seed, sizeof(rng_seed));
+       memzero_explicit(rng_seed, sizeof(rng_seed));
+}
index fb7388bbc212f9b1435b47206ae586cf84505846..c086699b0d0c59fc62834bb457963f1b81b541d3 100644 (file)
@@ -22,6 +22,7 @@ static inline void cc_set_mask(u64 mask)
 
 u64 cc_mkenc(u64 val);
 u64 cc_mkdec(u64 val);
+void cc_random_init(void);
 #else
 #define cc_vendor (CC_VENDOR_NONE)
 
@@ -34,6 +35,7 @@ static inline u64 cc_mkdec(u64 val)
 {
        return val;
 }
+static inline void cc_random_init(void) { }
 #endif
 
 #endif /* _ASM_X86_COCO_H */
index 07e125f32528394df24c06de44e3232eaf15e4cd..7f57382afee41754beb8164244f199e4ac30a148 100644 (file)
@@ -228,7 +228,6 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn
 void snp_accept_memory(phys_addr_t start, phys_addr_t end);
 u64 snp_get_unsupported_features(u64 status);
 u64 sev_get_status(void);
-void kdump_sev_callback(void);
 void sev_show_status(void);
 #else
 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
@@ -258,7 +257,6 @@ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *in
 static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
 static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
 static inline u64 sev_get_status(void) { return 0; }
-static inline void kdump_sev_callback(void) { }
 static inline void sev_show_status(void) { }
 #endif
 
@@ -270,6 +268,7 @@ int psmash(u64 pfn);
 int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immutable);
 int rmp_make_shared(u64 pfn, enum pg_level level);
 void snp_leak_pages(u64 pfn, unsigned int npages);
+void kdump_sev_callback(void);
 #else
 static inline bool snp_probe_rmptable_info(void) { return false; }
 static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -282,6 +281,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
 }
 static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
 static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
+static inline void kdump_sev_callback(void) { }
 #endif
 
 #endif
index 6d8677e80ddbb17c94ec7fcda9e5bae502c0dcb2..9bf17c9c29dad2e3f3c38c07253accc667cadea3 100644 (file)
@@ -345,6 +345,28 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
 #endif
 }
 
+static void bsp_determine_snp(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
+       cc_vendor = CC_VENDOR_AMD;
+
+       if (cpu_has(c, X86_FEATURE_SEV_SNP)) {
+               /*
+                * RMP table entry format is not architectural and is defined by the
+                * per-processor PPR. Restrict SNP support on the known CPU models
+                * for which the RMP table entry format is currently defined for.
+                */
+               if (!cpu_has(c, X86_FEATURE_HYPERVISOR) &&
+                   c->x86 >= 0x19 && snp_probe_rmptable_info()) {
+                       cc_platform_set(CC_ATTR_HOST_SEV_SNP);
+               } else {
+                       setup_clear_cpu_cap(X86_FEATURE_SEV_SNP);
+                       cc_platform_clear(CC_ATTR_HOST_SEV_SNP);
+               }
+       }
+#endif
+}
+
 static void bsp_init_amd(struct cpuinfo_x86 *c)
 {
        if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -452,21 +474,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
                break;
        }
 
-       if (cpu_has(c, X86_FEATURE_SEV_SNP)) {
-               /*
-                * RMP table entry format is not architectural and it can vary by processor
-                * and is defined by the per-processor PPR. Restrict SNP support on the
-                * known CPU model and family for which the RMP table entry format is
-                * currently defined for.
-                */
-               if (!boot_cpu_has(X86_FEATURE_ZEN3) &&
-                   !boot_cpu_has(X86_FEATURE_ZEN4) &&
-                   !boot_cpu_has(X86_FEATURE_ZEN5))
-                       setup_clear_cpu_cap(X86_FEATURE_SEV_SNP);
-               else if (!snp_probe_rmptable_info())
-                       setup_clear_cpu_cap(X86_FEATURE_SEV_SNP);
-       }
-
+       bsp_determine_snp(c);
        return;
 
 warn:
index b5cc557cfc3736708d96be6372f34c9ad0be85e4..84d41be6d06ba4e79f49ae069f5f1d5ae20b00de 100644 (file)
@@ -2500,12 +2500,14 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr,
                return -EINVAL;
 
        b = &per_cpu(mce_banks_array, s->id)[bank];
-
        if (!b->init)
                return -ENODEV;
 
        b->ctl = new;
+
+       mutex_lock(&mce_sysfs_mutex);
        mce_restart();
+       mutex_unlock(&mce_sysfs_mutex);
 
        return size;
 }
index 422a4ddc2ab7c9408f1d2d21433fea7f320c6f85..7b29ebda024f4e69bc9a9326f9cecd8a86ee2abb 100644 (file)
@@ -108,7 +108,7 @@ static inline void k8_check_syscfg_dram_mod_en(void)
              (boot_cpu_data.x86 >= 0x0f)))
                return;
 
-       if (cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return;
 
        rdmsr(MSR_AMD64_SYSCFG, lo, hi);
index c99f26ebe7a6537a7cd43274701ac4f489648081..1a8687f8073a89f3335038c8b3ba7e2ee45aa6d4 100644 (file)
@@ -78,7 +78,8 @@ cpumask_any_housekeeping(const struct cpumask *mask, int exclude_cpu)
        else
                cpu = cpumask_any_but(mask, exclude_cpu);
 
-       if (!IS_ENABLED(CONFIG_NO_HZ_FULL))
+       /* Only continue if tick_nohz_full_mask has been initialized. */
+       if (!tick_nohz_full_enabled())
                return cpu;
 
        /* If the CPU picked isn't marked nohz_full nothing more needs doing. */
index 0109e6c510e02fcced0e2bbbfedc6af8e48ba90e..e125e059e2c45d3e6657716777426b926d950aee 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/bios_ebda.h>
 #include <asm/bugs.h>
 #include <asm/cacheinfo.h>
+#include <asm/coco.h>
 #include <asm/cpu.h>
 #include <asm/efi.h>
 #include <asm/gart.h>
@@ -991,6 +992,7 @@ void __init setup_arch(char **cmdline_p)
         * memory size.
         */
        mem_encrypt_setup_arch();
+       cc_random_init();
 
        efi_fake_memmap();
        efi_find_mirror();
index 7e1e63cc48e67dcc3f3abc84362ba805fef5a93d..38ad066179d81fe7efc2b2469fbe583c12586e06 100644 (file)
@@ -2284,16 +2284,6 @@ static int __init snp_init_platform_device(void)
 }
 device_initcall(snp_init_platform_device);
 
-void kdump_sev_callback(void)
-{
-       /*
-        * Do wbinvd() on remote CPUs when SNP is enabled in order to
-        * safely do SNP_SHUTDOWN on the local CPU.
-        */
-       if (cpu_feature_enabled(X86_FEATURE_SEV_SNP))
-               wbinvd();
-}
-
 void sev_show_status(void)
 {
        int i;
index 3aaf7e86a859a2f680625b4d13b1c27d43fa5629..0ebdd088f28b852261786cb5f90d285b2af42ebc 100644 (file)
@@ -122,6 +122,7 @@ config KVM_AMD_SEV
        default y
        depends on KVM_AMD && X86_64
        depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)
+       select ARCH_HAS_CC_PLATFORM
        help
          Provides support for launching Encrypted VMs (SEV) and Encrypted VMs
          with Encrypted State (SEV-ES) on AMD processors.
index e5a4d9b0e79fd23e2dfc8224aa7a89d3b243c103..61a7531d41b019a7f263b9c4e02ccfdf960dd09f 100644 (file)
@@ -3184,7 +3184,7 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu)
        unsigned long pfn;
        struct page *p;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
 
        /*
index 104544359d69cd20ef1e37449d32a687ee1f3433..025fd7ea5d69f5bfba07a712a14ef85671d68af5 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/memblock.h>
 #include <linux/init.h>
+#include <asm/pgtable_areas.h>
 
 #include "numa_internal.h"
 
index cffe1157a90acfcf741b31ac216d6fd3a9ed4fd2..ab0e8448bb6eb2bfbc4fab29321cd0ddbe876f7e 100644 (file)
@@ -77,7 +77,7 @@ static int __mfd_enable(unsigned int cpu)
 {
        u64 val;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return 0;
 
        rdmsrl(MSR_AMD64_SYSCFG, val);
@@ -98,7 +98,7 @@ static int __snp_enable(unsigned int cpu)
 {
        u64 val;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return 0;
 
        rdmsrl(MSR_AMD64_SYSCFG, val);
@@ -174,11 +174,11 @@ static int __init snp_rmptable_init(void)
        u64 rmptable_size;
        u64 val;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return 0;
 
        if (!amd_iommu_snp_en)
-               return 0;
+               goto nosnp;
 
        if (!probed_rmp_size)
                goto nosnp;
@@ -225,7 +225,7 @@ skip_enable:
        return 0;
 
 nosnp:
-       setup_clear_cpu_cap(X86_FEATURE_SEV_SNP);
+       cc_platform_clear(CC_ATTR_HOST_SEV_SNP);
        return -ENOSYS;
 }
 
@@ -246,7 +246,7 @@ static struct rmpentry *__snp_lookup_rmpentry(u64 pfn, int *level)
 {
        struct rmpentry *large_entry, *entry;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return ERR_PTR(-ENODEV);
 
        entry = get_rmpentry(pfn);
@@ -363,7 +363,7 @@ int psmash(u64 pfn)
        unsigned long paddr = pfn << PAGE_SHIFT;
        int ret;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return -ENODEV;
 
        if (!pfn_valid(pfn))
@@ -472,7 +472,7 @@ static int rmpupdate(u64 pfn, struct rmp_state *state)
        unsigned long paddr = pfn << PAGE_SHIFT;
        int ret, level;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return -ENODEV;
 
        level = RMP_TO_PG_LEVEL(state->pagesize);
@@ -558,3 +558,13 @@ void snp_leak_pages(u64 pfn, unsigned int npages)
        spin_unlock(&snp_leaked_pages_list_lock);
 }
 EXPORT_SYMBOL_GPL(snp_leak_pages);
+
+void kdump_sev_callback(void)
+{
+       /*
+        * Do wbinvd() on remote CPUs when SNP is enabled in order to
+        * safely do SNP_SHUTDOWN on the local CPU.
+        */
+       if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
+               wbinvd();
+}
index f44efbb89c346a8e0b72c3d262ec9213c95aab18..2102377f727b1eecac8d28423e10a3e313b38683 100644 (file)
@@ -1090,7 +1090,7 @@ static int __sev_snp_init_locked(int *error)
        void *arg = &data;
        int cmd, rc = 0;
 
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return -ENODEV;
 
        sev = psp->sev_data;
index e7a44929f0daf71f017ec8fe0d1b56243ab47ba5..33228c1c8980f32a5e8af323587601a4783b5b7f 100644 (file)
@@ -3228,7 +3228,7 @@ out:
 static void iommu_snp_enable(void)
 {
 #ifdef CONFIG_KVM_AMD_SEV
-       if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+       if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
                return;
        /*
         * The SNP support requires that IOMMU must be enabled, and is
@@ -3236,12 +3236,14 @@ static void iommu_snp_enable(void)
         */
        if (no_iommu || iommu_default_passthrough()) {
                pr_err("SNP: IOMMU disabled or configured in passthrough mode, SNP cannot be supported.\n");
+               cc_platform_clear(CC_ATTR_HOST_SEV_SNP);
                return;
        }
 
        amd_iommu_snp_en = check_feature(FEATURE_SNP);
        if (!amd_iommu_snp_en) {
                pr_err("SNP: IOMMU SNP feature not enabled, SNP cannot be supported.\n");
+               cc_platform_clear(CC_ATTR_HOST_SEV_SNP);
                return;
        }
 
index cb0d6cd1c12f24e1dd8681b5f9f0302675bec7d5..60693a1458946223f791aae517210cb67ba13050 100644 (file)
@@ -90,6 +90,14 @@ enum cc_attr {
         * Examples include TDX Guest.
         */
        CC_ATTR_HOTPLUG_DISABLED,
+
+       /**
+        * @CC_ATTR_HOST_SEV_SNP: AMD SNP enabled on the host.
+        *
+        * The host kernel is running with the necessary features
+        * enabled to run SEV-SNP guests.
+        */
+       CC_ATTR_HOST_SEV_SNP,
 };
 
 #ifdef CONFIG_ARCH_HAS_CC_PLATFORM
@@ -107,10 +115,14 @@ enum cc_attr {
  * * FALSE - Specified Confidential Computing attribute is not active
  */
 bool cc_platform_has(enum cc_attr attr);
+void cc_platform_set(enum cc_attr attr);
+void cc_platform_clear(enum cc_attr attr);
 
 #else  /* !CONFIG_ARCH_HAS_CC_PLATFORM */
 
 static inline bool cc_platform_has(enum cc_attr attr) { return false; }
+static inline void cc_platform_set(enum cc_attr attr) { }
+static inline void cc_platform_clear(enum cc_attr attr) { }
 
 #endif /* CONFIG_ARCH_HAS_CC_PLATFORM */