Commit 9fe30842 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86-urgent-2024-04-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:

 - Fix MCE timer reinit locking

 - Fix/improve CoCo guest random entropy pool init

 - Fix SEV-SNP late disable bugs

 - Fix false positive objtool build warning

 - Fix header dependency bug

 - Fix resctrl CPU offlining bug

* tag 'x86-urgent-2024-04-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/retpoline: Add NOENDBR annotation to the SRSO dummy return thunk
  x86/mce: Make sure to grab mce_sysfs_mutex in set_bank()
  x86/CPU/AMD: Track SNP host status with cc_platform_*()
  x86/cc: Add cc_platform_set/_clear() helpers
  x86/kvm/Kconfig: Have KVM_AMD_SEV select ARCH_HAS_CC_PLATFORM
  x86/coco: Require seeding RNG with RDRAND on CoCo systems
  x86/numa/32: Include missing <asm/pgtable_areas.h>
  x86/resctrl: Fix uninitialized memory read when last CPU of domain goes offline
parents 3520c35e b377c66a
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
@@ -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));
}
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −2
Original line number Diff line number Diff line
@@ -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
+23 −15
Original line number Diff line number Diff line
@@ -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:
+3 −1
Original line number Diff line number Diff line
@@ -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;
}
Loading