[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<SN6PR02MB41579F676A4F30B1421A0376D4C82@SN6PR02MB4157.namprd02.prod.outlook.com>
Date: Tue, 4 Mar 2025 04:17:22 +0000
From: Michael Kelley <mhklinux@...look.com>
To: Sean Christopherson <seanjc@...gle.com>, Thomas Gleixner
<tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>, Borislav Petkov
<bp@...en8.de>, Dave Hansen <dave.hansen@...ux.intel.com>, "x86@...nel.org"
<x86@...nel.org>, "Kirill A. Shutemov" <kirill.shutemov@...ux.intel.com>,
Paolo Bonzini <pbonzini@...hat.com>, Juergen Gross <jgross@...e.com>, "K. Y.
Srinivasan" <kys@...rosoft.com>, Haiyang Zhang <haiyangz@...rosoft.com>, Wei
Liu <wei.liu@...nel.org>, Dexuan Cui <decui@...rosoft.com>, Ajay Kaher
<ajay.kaher@...adcom.com>, Jan Kiszka <jan.kiszka@...mens.com>, Andy
Lutomirski <luto@...nel.org>, Peter Zijlstra <peterz@...radead.org>, Daniel
Lezcano <daniel.lezcano@...aro.org>, John Stultz <jstultz@...gle.com>
CC: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"linux-coco@...ts.linux.dev" <linux-coco@...ts.linux.dev>,
"kvm@...r.kernel.org" <kvm@...r.kernel.org>, "virtualization@...ts.linux.dev"
<virtualization@...ts.linux.dev>, "linux-hyperv@...r.kernel.org"
<linux-hyperv@...r.kernel.org>, "xen-devel@...ts.xenproject.org"
<xen-devel@...ts.xenproject.org>, Tom Lendacky <thomas.lendacky@....com>,
Nikunj A Dadhania <nikunj@....com>
Subject: RE: [PATCH v2 03/38] x86/tsc: Add helper to register CPU and TSC freq
calibration routines
From: Sean Christopherson <seanjc@...gle.com> Sent: Wednesday, February 26, 2025 6:18 PM
>
> Add a helper to register non-native, i.e. PV and CoCo, CPU and TSC
> frequency calibration routines. This will allow consolidating handling
> of common TSC properties that are forced by hypervisor (PV routines),
> and will also allow adding sanity checks to guard against overriding a
> TSC calibration routine with a routine that is less robust/trusted.
>
> Make the CPU calibration routine optional, as Xen (very sanely) doesn't
> assume the CPU runs as the same frequency as the TSC.
>
> Wrap the helper in an #ifdef to document that the kernel overrides
> the native routines when running as a VM, and to guard against unwanted
> usage. Add a TODO to call out that AMD_MEM_ENCRYPT is a mess and doesn't
> depend on HYPERVISOR_GUEST because it gates both guest and host code.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@...gle.com>
> ---
> arch/x86/coco/sev/core.c | 4 ++--
> arch/x86/include/asm/tsc.h | 4 ++++
> arch/x86/kernel/cpu/acrn.c | 4 ++--
> arch/x86/kernel/cpu/mshyperv.c | 3 +--
> arch/x86/kernel/cpu/vmware.c | 4 ++--
> arch/x86/kernel/jailhouse.c | 4 ++--
> arch/x86/kernel/kvmclock.c | 4 ++--
> arch/x86/kernel/tsc.c | 17 +++++++++++++++++
> arch/x86/xen/time.c | 2 +-
> 9 files changed, 33 insertions(+), 13 deletions(-)
>
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 82492efc5d94..684cef70edc1 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -3291,6 +3291,6 @@ void __init snp_secure_tsc_init(void)
> rdmsrl(MSR_AMD64_GUEST_TSC_FREQ, tsc_freq_mhz);
> snp_tsc_freq_khz = (unsigned long)(tsc_freq_mhz * 1000);
>
> - x86_platform.calibrate_cpu = securetsc_get_tsc_khz;
> - x86_platform.calibrate_tsc = securetsc_get_tsc_khz;
> + tsc_register_calibration_routines(securetsc_get_tsc_khz,
> + securetsc_get_tsc_khz);
> }
> diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
> index c3a14df46327..9318c74e8d13 100644
> --- a/arch/x86/include/asm/tsc.h
> +++ b/arch/x86/include/asm/tsc.h
> @@ -40,6 +40,10 @@ extern int cpuid_get_cpu_freq(unsigned int *cpu_khz);
>
> extern void tsc_early_init(void);
> extern void tsc_init(void);
> +#if defined(CONFIG_HYPERVISOR_GUEST) || defined(CONFIG_AMD_MEM_ENCRYPT)
> +extern void tsc_register_calibration_routines(unsigned long (*calibrate_tsc)(void),
> + unsigned long (*calibrate_cpu)(void));
> +#endif
> extern void mark_tsc_unstable(char *reason);
> extern int unsynchronized_tsc(void);
> extern int check_tsc_unstable(void);
> diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
> index 2c5b51aad91a..c1506cb87d8c 100644
> --- a/arch/x86/kernel/cpu/acrn.c
> +++ b/arch/x86/kernel/cpu/acrn.c
> @@ -29,8 +29,8 @@ static void __init acrn_init_platform(void)
> /* Install system interrupt handler for ACRN hypervisor callback */
> sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_acrn_hv_callback);
>
> - x86_platform.calibrate_tsc = acrn_get_tsc_khz;
> - x86_platform.calibrate_cpu = acrn_get_tsc_khz;
> + tsc_register_calibration_routines(acrn_get_tsc_khz,
> + acrn_get_tsc_khz);
> }
>
> static bool acrn_x2apic_available(void)
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index f285757618fc..aa60491bf738 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -478,8 +478,7 @@ static void __init ms_hyperv_init_platform(void)
>
> if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS &&
> ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
> - x86_platform.calibrate_tsc = hv_get_tsc_khz;
> - x86_platform.calibrate_cpu = hv_get_tsc_khz;
> + tsc_register_calibration_routines(hv_get_tsc_khz, hv_get_tsc_khz);
> setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> }
>
For the Hyper-V guest code,
Reviewed-by: Michael Kelley <mhklinux@...look.com>
Tested-by: Michael Kelley <mhklinux@...look.com>
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 00189cdeb775..d6f079a75f05 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -416,8 +416,8 @@ static void __init vmware_platform_setup(void)
> }
>
> vmware_tsc_khz = tsc_khz;
> - x86_platform.calibrate_tsc = vmware_get_tsc_khz;
> - x86_platform.calibrate_cpu = vmware_get_tsc_khz;
> + tsc_register_calibration_routines(vmware_get_tsc_khz,
> + vmware_get_tsc_khz);
>
> #ifdef CONFIG_X86_LOCAL_APIC
> /* Skip lapic calibration since we know the bus frequency. */
> diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
> index cd8ed1edbf9e..b0a053692161 100644
> --- a/arch/x86/kernel/jailhouse.c
> +++ b/arch/x86/kernel/jailhouse.c
> @@ -209,8 +209,6 @@ static void __init jailhouse_init_platform(void)
> x86_init.mpparse.parse_smp_cfg = jailhouse_parse_smp_config;
> x86_init.pci.arch_init = jailhouse_pci_arch_init;
>
> - x86_platform.calibrate_cpu = jailhouse_get_tsc;
> - x86_platform.calibrate_tsc = jailhouse_get_tsc;
> x86_platform.get_wallclock = jailhouse_get_wallclock;
> x86_platform.legacy.rtc = 0;
> x86_platform.legacy.warm_reset = 0;
> @@ -220,6 +218,8 @@ static void __init jailhouse_init_platform(void)
>
> machine_ops.emergency_restart = jailhouse_no_restart;
>
> + tsc_register_calibration_routines(jailhouse_get_tsc, jailhouse_get_tsc);
> +
> while (pa_data) {
> mapping = early_memremap(pa_data, sizeof(header));
> memcpy(&header, mapping, sizeof(header));
> diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> index 5b2c15214a6b..b898b95a7d50 100644
> --- a/arch/x86/kernel/kvmclock.c
> +++ b/arch/x86/kernel/kvmclock.c
> @@ -320,8 +320,8 @@ void __init kvmclock_init(void)
> flags = pvclock_read_flags(&hv_clock_boot[0].pvti);
> kvm_sched_clock_init(flags & PVCLOCK_TSC_STABLE_BIT);
>
> - x86_platform.calibrate_tsc = kvm_get_tsc_khz;
> - x86_platform.calibrate_cpu = kvm_get_tsc_khz;
> + tsc_register_calibration_routines(kvm_get_tsc_khz, kvm_get_tsc_khz);
> +
> x86_platform.get_wallclock = kvm_get_wallclock;
> x86_platform.set_wallclock = kvm_set_wallclock;
> #ifdef CONFIG_X86_LOCAL_APIC
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index bb4619148161..d65e85929d3e 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -1294,6 +1294,23 @@ static void __init check_system_tsc_reliable(void)
> tsc_disable_clocksource_watchdog();
> }
>
> +/*
> + * TODO: Disentangle AMD_MEM_ENCRYPT and make SEV guest support depend on
> + * HYPERVISOR_GUEST.
> + */
> +#if defined(CONFIG_HYPERVISOR_GUEST) || defined(CONFIG_AMD_MEM_ENCRYPT)
> +void tsc_register_calibration_routines(unsigned long (*calibrate_tsc)(void),
> + unsigned long (*calibrate_cpu)(void))
> +{
> + if (WARN_ON_ONCE(!calibrate_tsc))
> + return;
> +
> + x86_platform.calibrate_tsc = calibrate_tsc;
> + if (calibrate_cpu)
> + x86_platform.calibrate_cpu = calibrate_cpu;
> +}
> +#endif
> +
> /*
> * Make an educated guess if the TSC is trustworthy and synchronized
> * over all CPUs.
> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
> index 96521b1874ac..9e2e900dc0c7 100644
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -566,7 +566,7 @@ static void __init xen_init_time_common(void)
> static_call_update(pv_steal_clock, xen_steal_clock);
> paravirt_set_sched_clock(xen_sched_clock);
>
> - x86_platform.calibrate_tsc = xen_tsc_khz;
> + tsc_register_calibration_routines(xen_tsc_khz, NULL);
> x86_platform.get_wallclock = xen_get_wallclock;
> }
>
> --
> 2.48.1.711.g2feabab25a-goog
>
Powered by blists - more mailing lists