From nobody Wed Aug 26 12:57:43 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1782934387; cv=none; d=zohomail.com; s=zohoarc; b=oJ8YySQzuzPdKBuqsTCbxtIZoGWlUXHNa3z9mAsIth0sBwV6RXXCh4qyq/dJrftluKMvg5R47uy/6NKetH+vz/FnVShtiJ4bnZ6TOf6IzAZaFm7ywuDrbbwj+9956/lHPSNR7GSF1NNMqQ9ovlLJu+twlwsbbjYeFv9/ublNmYw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782934387; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=5dPlSt+N6Lt/Y9ZvBDGnN+olGzf3s7mk8869JKIa0HY=; b=l5wOoMPui4GHXObFKVS9/eVg9oU8u7l3gwHQXWVN1NaiJNEOLaQuUtG44uGUh18sQ8AReEn0LGPi8ssxJDXhcfaSYbuTHTtBpr7KYl+1JNHApY3f+Q+7Yk0FhFs+uAqCjLYClwFI49omnWe2ZzJsyvTPwzezjIxmArcxiKNg9T0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1782934387679627.1123805045935; Wed, 1 Jul 2026 12:33:07 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1350375.1607896 (Exim 4.92) (envelope-from ) id 1wf0fr-0001bV-Hh; Wed, 01 Jul 2026 19:32:43 +0000 Received: by outflank-mailman (output) from mailman id 1350375.1607896; Wed, 01 Jul 2026 19:32:43 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wf0fr-0001a3-AW; Wed, 01 Jul 2026 19:32:43 +0000 Received: by outflank-mailman (input) for mailman id 1350375; Wed, 01 Jul 2026 19:32:41 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from <3VmtFagYKCZsN95IE7BJJBG9.7JHS9I-89Q9GGDNON.S9IKMJE97O.JMB@flex--seanjc.bounces.google.com>) id 1wf0fp-00014U-4i for xen-devel@lists.xenproject.org; Wed, 01 Jul 2026 19:32:41 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wf0fo-00B3ua-Ho for xen-devel@lists.xenproject.org; Wed, 01 Jul 2026 21:32:40 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from <3VmtFagYKCZsN95IE7BJJBG9.7JHS9I-89Q9GGDNON.S9IKMJE97O.JMB@flex--seanjc.bounces.google.com>) id 6a456b2a-5cb7-0a2a0a5109dd-0a2a450184e4-20 for ; Wed, 01 Jul 2026 21:32:40 +0200 Received: from [209.85.215.202] (helo=mail-pg1-f202.google.com) by tlsNG-d62444.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from <3VmtFagYKCZsN95IE7BJJBG9.7JHS9I-89Q9GGDNON.S9IKMJE97O.JMB@flex--seanjc.bounces.google.com>) id 6a456b57-400f-0a2a45010019-d155d7cabc2b-3 for ; Wed, 01 Jul 2026 21:32:40 +0200 Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-c89704da8c7so1485718a12.0 for ; Wed, 01 Jul 2026 12:32:39 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=google.com header.i="@google.com" header.h="Content-Transfer-Encoding:Cc:To:From:Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1782934358; x=1783539158; darn=lists.xenproject.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:reply-to:from:to:cc:subject:date :message-id:reply-to; bh=5dPlSt+N6Lt/Y9ZvBDGnN+olGzf3s7mk8869JKIa0HY=; b=MkWv0KXC4MXx6lGf//onmiIqh4yNwvQDXfcA2irvSslqrWxpkVO2AQG2SHgvRLeKND xKFW4TMiXR4aqkmmS70BFTQW1muy4PT2/9/m6M3sff8IMcfGI2XJaZy+k+Ne3p3M172d JBWpgEqqipqXxNyS+aTPrdHrkqkvLfXKcOx+28orrpACwbKyKAnecDI9pcjAFA0j6Bcd XcAt7M6irExNt8aKY8sajLYg+ABjTJtyLkLYZVZUfoaF+1QUFL0anBbz/aRktlytvkmK MFDyKvV6CJuU68aStM+KniqZJcyL2C7KCd7qNRugVucRoQyfp0dU69HfuZOt//EhVCIB NZfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782934358; x=1783539158; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:reply-to:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=5dPlSt+N6Lt/Y9ZvBDGnN+olGzf3s7mk8869JKIa0HY=; b=I4V4xejZrMqrJoxpos/IBM65flAzDyv8iYUNX9XS4sGa9Bd/1WgWZastUdNm2/KQ2e ETfvwrrSY+kVRxVicBjTufXHQXhcWdRfPEq35Xq7xFDCuI4WHKWdF+AJuu4N34eW6Grt BxfzZoRvaNcE/wUj54549Kyb7BmG4uHMD7Ud4nYZPXu+rwGFAAIuPw3SKSeXXzLNlemv SZmaYZ9WiEooff02STzeD/GvaiSQj1bODEzCfjI+E+snNuPGWM5p4xmrkYpGaEFYg9jH dWmjb39daaVq684qW8lChgulMIh5OFbKBWQounbPoh3oU6jpIiUWbVj1V3jTs5PFPl2v d2XA== X-Forwarded-Encrypted: i=1; AFNElJ9ySgVDKW+YAMoOb2KW2j7br4eTbdCtDSYDYaFogGwtP99q48iCWzFzN5dZfKO7CBiHbGyoGcw/e+A=@lists.xenproject.org X-Gm-Message-State: AOJu0YyQb73iRe7wwEhIR1iwOmot+KvcigpGVIo5ILwVU7ZjE/sppkaj Z5uFeNC7ri8TwfOgQYS0zz1lPTRVR3icU8Iz8rUJsBD0CMEDRNvEED/vLph57p35v4RgsYPsqY6 ISYQjiw== X-Received: from pgmo11.prod.google.com ([2002:a63:5d4b:0:b0:c9e:63b8:11b5]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:d10e:b0:3b4:61f:1fec with SMTP id adf61e73a8af0-3bfed1c323amr3402841637.2.1782934358113; Wed, 01 Jul 2026 12:32:38 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 1 Jul 2026 12:31:31 -0700 In-Reply-To: <20260701193212.749551-1-seanjc@google.com> Mime-Version: 1.0 References: <20260701193212.749551-1-seanjc@google.com> X-Mailer: git-send-email 2.55.0.rc0.799.gd6f94ed593-goog Message-ID: <20260701193212.749551-11-seanjc@google.com> Subject: [PATCH v5 10/51] x86/tdx: Force TSC frequency with CPUID-based info provided by the TDX-Module From: Sean Christopherson To: Jonathan Corbet , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, Kiryl Shutsemau , Rick Edgecombe , Sean Christopherson , "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Ajay Kaher , Alexey Makhalov , Jan Kiszka , Andy Lutomirski , Peter Zijlstra , Juergen Gross , Daniel Lezcano , John Stultz Cc: Shuah Khan , "H. Peter Anvin" , Vitaly Kuznetsov , Broadcom internal kernel review list , Boris Ostrovsky , Stephen Boyd , linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev, linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev, xen-devel@lists.xenproject.org, Tom Lendacky , Nikunj A Dadhania , David Woodhouse , David Woodhouse , Michael Kelley , Thomas Gleixner Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d62444/1782934360-800EC1E0-D0B58536/0/0 X-purgate-type: clean X-purgate-size: 6605 X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1782934390230158500 Content-Type: text/plain; charset="utf-8" When running as a TDX guest, explicitly set the TSC frequency to a known value, using CPUID-based information, instead of potentially relying on a hypervisor-controlled PV routine. For TDX guests, CPUID.0x15 is always emulated by the TDX-Module, i.e. the information from CPUID is more trustworthy than the information provided by the hypervisor. To maintain backwards compatibility with TDX guest kernels that use native calibration, and because it's the least awful option, retain native_calibrate_tsc()'s stuffing of the local APIC bus period using the core crystal frequency. While it's entirely possible for the hypervisor to emulate the APIC timer at a different frequency than the core crystal frequency, the commonly accepted interpretation of Intel's SDM is that APIC timer runs at the core crystal frequency when that latter is enumerated via CPUID: The APIC timer frequency will be the processor=E2=80=99s bus clock or core crystal clock frequency (when TSC/core crystal clock ratio is enumerated in CPUID leaf 0x15). If the hypervisor is malicious and deliberately runs the APIC timer at the wrong frequency, nothing would stop the hypervisor from modifying the frequency at any time, i.e. attempting to manually calibrate the frequency out of paranoia would be futile. Deliberately leave CPU frequency calibration as is, since the TDX-Module doesn't provide any guarantees with respect to CPUID.0x16. Expose and use cpuid_get_tsc_info() instead of providing a wrapper to get the TSC and core crystal frequency, as TDX is the only anticipated user outside of the TSC code, i.e. adding a helper to dedup the math won't actually dedup anything. Having TDX use "struct cpuid_tsc_info" also avoids the temptation of declaring a local "tsc_khz" variable and thus unintentionally creating a shadow of the global "tsc_khz". Cc: Kiryl Shutsemau (Meta) Signed-off-by: Sean Christopherson --- .../admin-guide/kernel-parameters.txt | 4 ++-- arch/x86/coco/tdx/tdx.c | 20 ++++++++++++++++--- arch/x86/include/asm/tdx.h | 2 ++ arch/x86/include/asm/tsc.h | 7 +++++++ arch/x86/kernel/tsc.c | 11 ++++------ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index 181149f633c3..490e6aa72fc2 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -7947,8 +7947,8 @@ Kernel parameters Format: =20 Note, tsc_early_khz is ignored if the TSC frequency is - provided by trusted firmware when running as an SNP - guest. + provided by trusted firmware when running as an SNP or + TDX guest. =20 tsx=3D [X86] Control Transactional Synchronization Extensions (TSX) feature in Intel processors that diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 29b6f1ed59ec..ae2d35f2ef33 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1123,9 +1124,6 @@ void __init tdx_early_init(void) =20 setup_force_cpu_cap(X86_FEATURE_TDX_GUEST); =20 - /* TSC is the only reliable clock in TDX guest */ - setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); - cc_vendor =3D CC_VENDOR_INTEL; =20 /* Configure the TD */ @@ -1195,3 +1193,19 @@ void __init tdx_early_init(void) =20 tdx_announce(); } + +unsigned int __init tdx_tsc_init(void) +{ + struct cpuid_tsc_info info; + + if (WARN_ON_ONCE(cpuid_get_tsc_info(&info) || !info.crystal_khz)) + return 0; + + apic_set_timer_period_khz(info.crystal_khz, "TDX-Module via CPUID"); + + /* TSC is the only reliable clock in TDX guest */ + setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); + + return info.crystal_khz * info.numerator / info.denominator; +} diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 89e97d5761d8..d23ff06db41a 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -68,6 +68,7 @@ struct ve_info { #ifdef CONFIG_INTEL_TDX_GUEST =20 void __init tdx_early_init(void); +unsigned int __init tdx_tsc_init(void); =20 void tdx_get_ve_info(struct ve_info *ve); =20 @@ -89,6 +90,7 @@ void __init tdx_dump_td_ctls(u64 td_ctls); #else =20 static inline void tdx_early_init(void) { }; +static inline unsigned int tdx_tsc_init(void) { return 0; } static inline void tdx_halt(void) { }; =20 static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return fals= e; } diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 4d2d2f21ff06..b6b86e24e1bf 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -82,6 +82,13 @@ static inline cycles_t get_cycles(void) } #define get_cycles get_cycles =20 +struct cpuid_tsc_info { + unsigned int denominator; + unsigned int numerator; + unsigned int crystal_khz; +}; +extern int cpuid_get_tsc_info(struct cpuid_tsc_info *info); + extern void tsc_early_init(void); extern void tsc_init(void); extern void mark_tsc_unstable(char *reason); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 12043812c8f5..86384a83a5f6 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -34,6 +34,7 @@ #include #include #include +#include =20 unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ EXPORT_SYMBOL(cpu_khz); @@ -645,13 +646,7 @@ static unsigned long quick_pit_calibrate(void) return delta; } =20 -struct cpuid_tsc_info { - unsigned int denominator; - unsigned int numerator; - unsigned int crystal_khz; -}; - -static int cpuid_get_tsc_info(struct cpuid_tsc_info *info) +int cpuid_get_tsc_info(struct cpuid_tsc_info *info) { unsigned int ecx_hz, edx; =20 @@ -1529,6 +1524,8 @@ void __init tsc_early_init(void) =20 if (cc_platform_has(CC_ATTR_GUEST_SNP_SECURE_TSC)) known_tsc_khz =3D snp_secure_tsc_init(); + else if (boot_cpu_has(X86_FEATURE_TDX_GUEST)) + known_tsc_khz =3D tdx_tsc_init(); =20 /* * Ignore the user-provided TSC frequency if the exact frequency was --=20 2.55.0.rc0.799.gd6f94ed593-goog