Commit 5fc2e891 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_urgent_for_v6.16_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fix from Borislav Petkov:

 - Make sure AMD SEV guests using secure TSC, include a TSC_FACTOR which
   prevents their TSCs from going skewed from the hypervisor's

* tag 'x86_urgent_for_v6.16_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/sev: Use TSC_FACTOR for Secure TSC frequency calculation
parents 463b1b2a 52e1a03e
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ static const char * const sev_status_feat_names[] = {
 */
static u64 snp_tsc_scale __ro_after_init;
static u64 snp_tsc_offset __ro_after_init;
static u64 snp_tsc_freq_khz __ro_after_init;
static unsigned long snp_tsc_freq_khz __ro_after_init;

DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data);
DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa);
@@ -2167,15 +2167,31 @@ static unsigned long securetsc_get_tsc_khz(void)

void __init snp_secure_tsc_init(void)
{
	unsigned long long tsc_freq_mhz;
	struct snp_secrets_page *secrets;
	unsigned long tsc_freq_mhz;
	void *mem;

	if (!cc_platform_has(CC_ATTR_GUEST_SNP_SECURE_TSC))
		return;

	mem = early_memremap_encrypted(sev_secrets_pa, PAGE_SIZE);
	if (!mem) {
		pr_err("Unable to get TSC_FACTOR: failed to map the SNP secrets page.\n");
		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SECURE_TSC);
	}

	secrets = (__force struct snp_secrets_page *)mem;

	setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
	rdmsrq(MSR_AMD64_GUEST_TSC_FREQ, tsc_freq_mhz);
	snp_tsc_freq_khz = (unsigned long)(tsc_freq_mhz * 1000);

	/* Extract the GUEST TSC MHZ from BIT[17:0], rest is reserved space */
	tsc_freq_mhz &= GENMASK_ULL(17, 0);

	snp_tsc_freq_khz = SNP_SCALE_TSC_FREQ(tsc_freq_mhz * 1000, secrets->tsc_factor);

	x86_platform.calibrate_cpu = securetsc_get_tsc_khz;
	x86_platform.calibrate_tsc = securetsc_get_tsc_khz;

	early_memunmap(mem, PAGE_SIZE);
}
+16 −1
Original line number Diff line number Diff line
@@ -223,6 +223,18 @@ struct snp_tsc_info_resp {
	u8 rsvd2[100];
} __packed;

/*
 * Obtain the mean TSC frequency by decreasing the nominal TSC frequency with
 * TSC_FACTOR as documented in the SNP Firmware ABI specification:
 *
 * GUEST_TSC_FREQ * (1 - (TSC_FACTOR * 0.00001))
 *
 * which is equivalent to:
 *
 * GUEST_TSC_FREQ -= (GUEST_TSC_FREQ * TSC_FACTOR) / 100000;
 */
#define SNP_SCALE_TSC_FREQ(freq, factor) ((freq) - (freq) * (factor) / 100000)

struct snp_guest_req {
	void *req_buf;
	size_t req_sz;
@@ -282,8 +294,11 @@ struct snp_secrets_page {
	u8 svsm_guest_vmpl;
	u8 rsvd3[3];

	/* The percentage decrease from nominal to mean TSC frequency. */
	u32 tsc_factor;

	/* Remainder of page */
	u8 rsvd4[3744];
	u8 rsvd4[3740];
} __packed;

struct snp_msg_desc {