diff mbox

[0/2] KVM: kvm-coco-queue: Support protected TSC

Message ID cover.1728719037.git.isaku.yamahata@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Isaku Yamahata Oct. 12, 2024, 7:55 a.m. UTC
This patch series is for the kvm-coco-queue branch.  The change for TDX KVM is
included at the last.  The test is done by create TDX vCPU and run, get TSC
offset via vCPU device attributes and compare it with the TDX TSC OFFSET
metadata.  Because the test requires the TDX KVM and TDX KVM kselftests, don't
include it in this patch series.


Background
----------
X86 confidential computing technology defines protected guest TSC so that the
VMM can't change the TSC offset/multiplier once vCPU is initialized and the
guest can trust TSC.  The SEV-SNP defines Secure TSC as optional.  TDX mandates
it.  The TDX module determines the TSC offset/multiplier.  The VMM has to
retrieve them.

On the other hand, the x86 KVM common logic tries to guess or adjust the TSC
offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU
creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU
(kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and
guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()).


Problem
-------
The current x86 KVM implementation conflicts with protected TSC because the
VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
logic to change/adjust the TSC offset/multiplier somehow.

Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
offset/multiplier, the TSC timer interrupts are injected to the guest at the
wrong time if the KVM TSC offset is different from what the TDX module
determined.

Originally the issue was found by cyclic test of rt-test [1] as the latency in
TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
the KVM TSC offset is different from what the TDX module determines.


Solution
--------
The solution is to keep the KVM TSC offset/multiplier the same as the value of
the TDX module somehow.  Possible solutions are as follows.
- Skip the logic
  Ignore (or don't call related functions) the request to change the TSC
  offset/multiplier.
  Pros
  - Logically clean.  This is similar to the guest_protected case.
  Cons
  - Needs to identify the call sites.

- Revert the change at the hooks after TSC adjustment
  x86 KVM defines the vendor hooks when the TSC offset/multiplier are
  changed.  The callback can revert the change.
  Pros
  - We don't need to care about the logic to change the TSC offset/multiplier.
  Cons:
  - Hacky to revert the KVM x86 common code logic.

Choose the first one.  With this patch series, SEV-SNP secure TSC can be
supported.


Patches:
1: Preparation for the next patch
2: Skip the logic to adjust the TSC offset/multiplier in the common x86 KVM logic

[1] https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git

Changes for TDX KVM


---
Isaku Yamahata (2):
  KVM: x86: Push down setting vcpu.arch.user_set_tsc
  KVM: x86: Don't allow tsc_offset, tsc_scaling_ratio to change

 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/x86.c              | 21 ++++++++++++++-------
 2 files changed, 15 insertions(+), 7 deletions(-)


base-commit: 909f9d422f59f863d7b6e4e2c6e57abb97a27d4d

Comments

Nikunj A. Dadhania Oct. 14, 2024, 2:47 p.m. UTC | #1
Hi Isaku,

On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
> This patch series is for the kvm-coco-queue branch.  The change for TDX KVM is
> included at the last.  The test is done by create TDX vCPU and run, get TSC
> offset via vCPU device attributes and compare it with the TDX TSC OFFSET
> metadata.  Because the test requires the TDX KVM and TDX KVM kselftests, don't
> include it in this patch series.
> 
> 
> Background
> ----------
> X86 confidential computing technology defines protected guest TSC so that the
> VMM can't change the TSC offset/multiplier once vCPU is initialized and the
> guest can trust TSC.  The SEV-SNP defines Secure TSC as optional.  TDX mandates
> it.  The TDX module determines the TSC offset/multiplier.  The VMM has to
> retrieve them.
> 
> On the other hand, the x86 KVM common logic tries to guess or adjust the TSC
> offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU
> creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU
> (kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and
> guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()).
> 
> 
> Problem
> -------
> The current x86 KVM implementation conflicts with protected TSC because the
> VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
> logic to change/adjust the TSC offset/multiplier somehow.
> 
> Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
> offset/multiplier, the TSC timer interrupts are injected to the guest at the
> wrong time if the KVM TSC offset is different from what the TDX module
> determined.
> 
> Originally the issue was found by cyclic test of rt-test [1] as the latency in
> TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
> the KVM TSC offset is different from what the TDX module determines.

Can you provide what is the exact command line to reproduce this problem ? 
Any links to this reported issue ?

> 
> 
> Solution
> --------
> The solution is to keep the KVM TSC offset/multiplier the same as the value of
> the TDX module somehow.  Possible solutions are as follows.
> - Skip the logic
>   Ignore (or don't call related functions) the request to change the TSC
>   offset/multiplier.
>   Pros
>   - Logically clean.  This is similar to the guest_protected case.
>   Cons
>   - Needs to identify the call sites.
> 
> - Revert the change at the hooks after TSC adjustment
>   x86 KVM defines the vendor hooks when the TSC offset/multiplier are
>   changed.  The callback can revert the change.
>   Pros
>   - We don't need to care about the logic to change the TSC offset/multiplier.
>   Cons:
>   - Hacky to revert the KVM x86 common code logic.
> 
> Choose the first one.  With this patch series, SEV-SNP secure TSC can be
> supported.

I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and 
GUEST_TSC_SCALE are only available to the guest.

Regards,
Nikunj
Marcelo Tosatti Oct. 25, 2024, 4:24 p.m. UTC | #2
On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
> Hi Isaku,
> 
> On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
> > This patch series is for the kvm-coco-queue branch.  The change for TDX KVM is
> > included at the last.  The test is done by create TDX vCPU and run, get TSC
> > offset via vCPU device attributes and compare it with the TDX TSC OFFSET
> > metadata.  Because the test requires the TDX KVM and TDX KVM kselftests, don't
> > include it in this patch series.
> > 
> > 
> > Background
> > ----------
> > X86 confidential computing technology defines protected guest TSC so that the
> > VMM can't change the TSC offset/multiplier once vCPU is initialized and the
> > guest can trust TSC.  The SEV-SNP defines Secure TSC as optional.  TDX mandates
> > it.  The TDX module determines the TSC offset/multiplier.  The VMM has to
> > retrieve them.
> > 
> > On the other hand, the x86 KVM common logic tries to guess or adjust the TSC
> > offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU
> > creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU
> > (kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and
> > guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()).
> > 
> > 
> > Problem
> > -------
> > The current x86 KVM implementation conflicts with protected TSC because the
> > VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
> > logic to change/adjust the TSC offset/multiplier somehow.
> > 
> > Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
> > offset/multiplier, the TSC timer interrupts are injected to the guest at the
> > wrong time if the KVM TSC offset is different from what the TDX module
> > determined.
> > 
> > Originally the issue was found by cyclic test of rt-test [1] as the latency in
> > TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
> > the KVM TSC offset is different from what the TDX module determines.
> 
> Can you provide what is the exact command line to reproduce this problem ? 

Nikunj,

Run cyclictest, on an isolated CPU, in a VM. For the maximum latency
metric, rather than 50us, one gets 500us at times.

> Any links to this reported issue ?

This was not posted publically. But its not hard to reproduce.

> > Solution
> > --------
> > The solution is to keep the KVM TSC offset/multiplier the same as the value of
> > the TDX module somehow.  Possible solutions are as follows.
> > - Skip the logic
> >   Ignore (or don't call related functions) the request to change the TSC
> >   offset/multiplier.
> >   Pros
> >   - Logically clean.  This is similar to the guest_protected case.
> >   Cons
> >   - Needs to identify the call sites.
> > 
> > - Revert the change at the hooks after TSC adjustment
> >   x86 KVM defines the vendor hooks when the TSC offset/multiplier are
> >   changed.  The callback can revert the change.
> >   Pros
> >   - We don't need to care about the logic to change the TSC offset/multiplier.
> >   Cons:
> >   - Hacky to revert the KVM x86 common code logic.
> > 
> > Choose the first one.  With this patch series, SEV-SNP secure TSC can be
> > supported.
> 
> I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and 
> GUEST_TSC_SCALE are only available to the guest.

Nikunj,

FYI:

SEV-SNP processors (at least the one below) do not seem affected by this problem.

At least this one:

vendor_id	: AuthenticAMD
cpu family	: 25
model		: 17
model name	: AMD EPYC 9124 16-Core Processor
Xiaoyao Li Oct. 27, 2024, 2:06 p.m. UTC | #3
On 10/26/2024 12:24 AM, Marcelo Tosatti wrote:
> On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
>> Hi Isaku,
>>
>> On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
>>> This patch series is for the kvm-coco-queue branch.  The change for TDX KVM is
>>> included at the last.  The test is done by create TDX vCPU and run, get TSC
>>> offset via vCPU device attributes and compare it with the TDX TSC OFFSET
>>> metadata.  Because the test requires the TDX KVM and TDX KVM kselftests, don't
>>> include it in this patch series.
>>>
>>>
>>> Background
>>> ----------
>>> X86 confidential computing technology defines protected guest TSC so that the
>>> VMM can't change the TSC offset/multiplier once vCPU is initialized and the
>>> guest can trust TSC.  The SEV-SNP defines Secure TSC as optional.  TDX mandates
>>> it.  The TDX module determines the TSC offset/multiplier.  The VMM has to
>>> retrieve them.
>>>
>>> On the other hand, the x86 KVM common logic tries to guess or adjust the TSC
>>> offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU
>>> creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU
>>> (kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and
>>> guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()).
>>>
>>>
>>> Problem
>>> -------
>>> The current x86 KVM implementation conflicts with protected TSC because the
>>> VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
>>> logic to change/adjust the TSC offset/multiplier somehow.
>>>
>>> Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
>>> offset/multiplier, the TSC timer interrupts are injected to the guest at the
>>> wrong time if the KVM TSC offset is different from what the TDX module
>>> determined.
>>>
>>> Originally the issue was found by cyclic test of rt-test [1] as the latency in
>>> TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
>>> the KVM TSC offset is different from what the TDX module determines.
>>
>> Can you provide what is the exact command line to reproduce this problem ?
> 
> Nikunj,
> 
> Run cyclictest, on an isolated CPU, in a VM. For the maximum latency
> metric, rather than 50us, one gets 500us at times.
> 
>> Any links to this reported issue ?
> 
> This was not posted publically. But its not hard to reproduce.
> 
>>> Solution
>>> --------
>>> The solution is to keep the KVM TSC offset/multiplier the same as the value of
>>> the TDX module somehow.  Possible solutions are as follows.
>>> - Skip the logic
>>>    Ignore (or don't call related functions) the request to change the TSC
>>>    offset/multiplier.
>>>    Pros
>>>    - Logically clean.  This is similar to the guest_protected case.
>>>    Cons
>>>    - Needs to identify the call sites.
>>>
>>> - Revert the change at the hooks after TSC adjustment
>>>    x86 KVM defines the vendor hooks when the TSC offset/multiplier are
>>>    changed.  The callback can revert the change.
>>>    Pros
>>>    - We don't need to care about the logic to change the TSC offset/multiplier.
>>>    Cons:
>>>    - Hacky to revert the KVM x86 common code logic.
>>>
>>> Choose the first one.  With this patch series, SEV-SNP secure TSC can be
>>> supported.
>>
>> I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and
>> GUEST_TSC_SCALE are only available to the guest.
> 
> Nikunj,
> 
> FYI:
> 
> SEV-SNP processors (at least the one below) do not seem affected by this problem.

Did you apply Secure TSC patches of (guest kernel, KVM and QEMU) 
manualy? because none of them are merged. Otherwise, I think SNP guest 
is still using KVM emulated TSC.

> At least this one:
> 
> vendor_id	: AuthenticAMD
> cpu family	: 25
> model		: 17
> model name	: AMD EPYC 9124 16-Core Processor
> 
>
Nikunj A. Dadhania Oct. 28, 2024, 12:48 p.m. UTC | #4
Hi Marcelo,

On 10/25/2024 9:54 PM, Marcelo Tosatti wrote:
> On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
>> On 10/12/2024 1:25 PM, Isaku Yamahata wrote:

>>> Problem
>>> -------
>>> The current x86 KVM implementation conflicts with protected TSC because the
>>> VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
>>> logic to change/adjust the TSC offset/multiplier somehow.
>>>
>>> Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
>>> offset/multiplier, the TSC timer interrupts are injected to the guest at the
>>> wrong time if the KVM TSC offset is different from what the TDX module
>>> determined.
>>>
>>> Originally the issue was found by cyclic test of rt-test [1] as the latency in
>>> TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
>>> the KVM TSC offset is different from what the TDX module determines.
>>
>> Can you provide what is the exact command line to reproduce this problem ? 
> 
> Nikunj,
> 
> Run cyclictest, on an isolated CPU, in a VM. For the maximum latency
> metric, rather than 50us, one gets 500us at times.

I tried out the cyclictest after referring to the documentation[1]. Here are the
results of the run on an isolated CPU in the Secure TSC-enabled SEV-SNP VM (CPUs
16-31 are isolated in the VM):

$ sudo taskset -c 16-31 ./cyclictest --mlockall --priority=80 --interval=200 --distance=0 -q -D 5m
T: 0 ( 1226) P:80 I:200 C:1500000 Min:      6 Act:   10 Avg:   16 Max:     150
$

VM detail: 32 vCPUs VM, guest kernel v6.12-rc3 compiled with CONFIG_PREEMPT_RT=y

> 
> FYI:
> 
> SEV-SNP processors (at least the one below) do not seem affected by this problem.

Thanks for testing on SEV-SNP.

Regards,
Nikunj

1. https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/cyclictest/start
Marcelo Tosatti Oct. 28, 2024, 4:42 p.m. UTC | #5
On Sun, Oct 27, 2024 at 10:06:17PM +0800, Xiaoyao Li wrote:
> On 10/26/2024 12:24 AM, Marcelo Tosatti wrote:
> > On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
> > > Hi Isaku,
> > > 
> > > On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
> > > > This patch series is for the kvm-coco-queue branch.  The change for TDX KVM is
> > > > included at the last.  The test is done by create TDX vCPU and run, get TSC
> > > > offset via vCPU device attributes and compare it with the TDX TSC OFFSET
> > > > metadata.  Because the test requires the TDX KVM and TDX KVM kselftests, don't
> > > > include it in this patch series.
> > > > 
> > > > 
> > > > Background
> > > > ----------
> > > > X86 confidential computing technology defines protected guest TSC so that the
> > > > VMM can't change the TSC offset/multiplier once vCPU is initialized and the
> > > > guest can trust TSC.  The SEV-SNP defines Secure TSC as optional.  TDX mandates
> > > > it.  The TDX module determines the TSC offset/multiplier.  The VMM has to
> > > > retrieve them.
> > > > 
> > > > On the other hand, the x86 KVM common logic tries to guess or adjust the TSC
> > > > offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU
> > > > creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU
> > > > (kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and
> > > > guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()).
> > > > 
> > > > 
> > > > Problem
> > > > -------
> > > > The current x86 KVM implementation conflicts with protected TSC because the
> > > > VMM can't change the TSC offset/multiplier.  Disable or ignore the KVM
> > > > logic to change/adjust the TSC offset/multiplier somehow.
> > > > 
> > > > Because KVM emulates the TSC timer or the TSC deadline timer with the TSC
> > > > offset/multiplier, the TSC timer interrupts are injected to the guest at the
> > > > wrong time if the KVM TSC offset is different from what the TDX module
> > > > determined.
> > > > 
> > > > Originally the issue was found by cyclic test of rt-test [1] as the latency in
> > > > TDX case is worse than VMX value + TDX SEAMCALL overhead.  It turned out that
> > > > the KVM TSC offset is different from what the TDX module determines.
> > > 
> > > Can you provide what is the exact command line to reproduce this problem ?
> > 
> > Nikunj,
> > 
> > Run cyclictest, on an isolated CPU, in a VM. For the maximum latency
> > metric, rather than 50us, one gets 500us at times.
> > 
> > > Any links to this reported issue ?
> > 
> > This was not posted publically. But its not hard to reproduce.
> > 
> > > > Solution
> > > > --------
> > > > The solution is to keep the KVM TSC offset/multiplier the same as the value of
> > > > the TDX module somehow.  Possible solutions are as follows.
> > > > - Skip the logic
> > > >    Ignore (or don't call related functions) the request to change the TSC
> > > >    offset/multiplier.
> > > >    Pros
> > > >    - Logically clean.  This is similar to the guest_protected case.
> > > >    Cons
> > > >    - Needs to identify the call sites.
> > > > 
> > > > - Revert the change at the hooks after TSC adjustment
> > > >    x86 KVM defines the vendor hooks when the TSC offset/multiplier are
> > > >    changed.  The callback can revert the change.
> > > >    Pros
> > > >    - We don't need to care about the logic to change the TSC offset/multiplier.
> > > >    Cons:
> > > >    - Hacky to revert the KVM x86 common code logic.
> > > > 
> > > > Choose the first one.  With this patch series, SEV-SNP secure TSC can be
> > > > supported.
> > > 
> > > I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and
> > > GUEST_TSC_SCALE are only available to the guest.
> > 
> > Nikunj,
> > 
> > FYI:
> > 
> > SEV-SNP processors (at least the one below) do not seem affected by this problem.
> 
> Did you apply Secure TSC patches of (guest kernel, KVM and QEMU) manualy?
> because none of them are merged. 

Yes. cyclictest latency, on a system configured with tuned
realtime-virtual-host/realtime-virtual-guest tuned profiles,
goes from 30us to 50us.

> Otherwise, I think SNP guest is still using
> KVM emulated TSC.

Not in the case the test was made.
Nikunj A. Dadhania Oct. 29, 2024, 4:04 a.m. UTC | #6
Hello Marcelo

On 10/28/2024 10:12 PM, Marcelo Tosatti wrote:
> On Sun, Oct 27, 2024 at 10:06:17PM +0800, Xiaoyao Li wrote:
>> On 10/26/2024 12:24 AM, Marcelo Tosatti wrote:
>>> On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
>>>> Hi Isaku,
>>>>
>>>> On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
>>>>> Choose the first one.  With this patch series, SEV-SNP secure TSC can be
>>>>> supported.
>>>>
>>>> I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and
>>>> GUEST_TSC_SCALE are only available to the guest.
>>>
>>> Nikunj,
>>>
>>> FYI:
>>>
>>> SEV-SNP processors (at least the one below) do not seem affected by this problem.
>>
>> Did you apply Secure TSC patches of (guest kernel, KVM and QEMU) manualy?
>> because none of them are merged. 
> 
> Yes. cyclictest latency, on a system configured with tuned
> realtime-virtual-host/realtime-virtual-guest tuned profiles,
> goes from 30us to 50us.

Would you be ok if I include your Tested-by in the next version of my Secure TSC patches?

https://lore.kernel.org/lkml/20241028053431.3439593-1-nikunj@amd.com/

>> Otherwise, I think SNP guest is still using
>> KVM emulated TSC.
> 
> Not in the case the test was made.
> 

Regards,
Nikunj
Marcelo Tosatti Oct. 29, 2024, 1:44 p.m. UTC | #7
On Tue, Oct 29, 2024 at 09:34:58AM +0530, Nikunj A. Dadhania wrote:
> Hello Marcelo
> 
> On 10/28/2024 10:12 PM, Marcelo Tosatti wrote:
> > On Sun, Oct 27, 2024 at 10:06:17PM +0800, Xiaoyao Li wrote:
> >> On 10/26/2024 12:24 AM, Marcelo Tosatti wrote:
> >>> On Mon, Oct 14, 2024 at 08:17:19PM +0530, Nikunj A. Dadhania wrote:
> >>>> Hi Isaku,
> >>>>
> >>>> On 10/12/2024 1:25 PM, Isaku Yamahata wrote:
> >>>>> Choose the first one.  With this patch series, SEV-SNP secure TSC can be
> >>>>> supported.
> >>>>
> >>>> I am not sure how will this help SNP Secure TSC, as the GUEST_TSC_OFFSET and
> >>>> GUEST_TSC_SCALE are only available to the guest.
> >>>
> >>> Nikunj,
> >>>
> >>> FYI:
> >>>
> >>> SEV-SNP processors (at least the one below) do not seem affected by this problem.
> >>
> >> Did you apply Secure TSC patches of (guest kernel, KVM and QEMU) manualy?
> >> because none of them are merged. 
> > 
> > Yes. cyclictest latency, on a system configured with tuned
> > realtime-virtual-host/realtime-virtual-guest tuned profiles,
> > goes from 30us to 50us.
> 
> Would you be ok if I include your Tested-by in the next version of my Secure TSC patches?
> 
> https://lore.kernel.org/lkml/20241028053431.3439593-1-nikunj@amd.com/

Please don't, haven't tested specifically the patches above.

> >> Otherwise, I think SNP guest is still using
> >> KVM emulated TSC.
> > 
> > Not in the case the test was made.
> > 
> 
> Regards,
> Nikunj
> 
>
diff mbox

Patch

diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 8785309ccb46..969da729d89f 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -694,8 +712,6 @@  int tdx_vcpu_create(struct kvm_vcpu *vcpu)
 	vcpu->arch.cr0_guest_owned_bits = -1ul;
 	vcpu->arch.cr4_guest_owned_bits = -1ul;
 
-	vcpu->arch.tsc_offset = kvm_tdx->tsc_offset;
-	vcpu->arch.l1_tsc_offset = vcpu->arch.tsc_offset;
 	/*
 	 * TODO: support off-TD debug.  If TD DEBUG is enabled, guest state
 	 * can be accessed. guest_state_protected = false. and kvm ioctl to
@@ -706,6 +722,13 @@  int tdx_vcpu_create(struct kvm_vcpu *vcpu)
 	 */
 	vcpu->arch.guest_state_protected = true;
 
+	/* VMM can't change TSC offset/multiplier as TDX module manages them. */
+	vcpu->arch.guest_tsc_protected = true;
+	vcpu->arch.tsc_offset = kvm_tdx->tsc_offset;
+	vcpu->arch.l1_tsc_offset = vcpu->arch.tsc_offset;
+	vcpu->arch.tsc_scaling_ratio = kvm_tdx->tsc_multiplier;
+	vcpu->arch.l1_tsc_scaling_ratio = kvm_tdx->tsc_multiplier;
+
 	if ((kvm_tdx->xfam & XFEATURE_MASK_XTILE) == XFEATURE_MASK_XTILE)
 		vcpu->arch.xfd_no_write_intercept = true;
 
@@ -2674,6 +2697,7 @@  static int tdx_td_init(struct kvm *kvm, struct kvm_tdx_cmd *cmd)
 		goto out;
 
 	kvm_tdx->tsc_offset = td_tdcs_exec_read64(kvm_tdx, TD_TDCS_EXEC_TSC_OFFSET);
+	kvm_tdx->tsc_multiplier = td_tdcs_exec_read64(kvm_tdx, TD_TDCS_EXEC_TSC_MULTIPLIER);
 	kvm_tdx->attributes = td_params->attributes;
 	kvm_tdx->xfam = td_params->xfam;
 
diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h
index 614b1c3b8483..c0e4fa61cab1 100644
--- a/arch/x86/kvm/vmx/tdx.h
+++ b/arch/x86/kvm/vmx/tdx.h
@@ -42,6 +42,7 @@  struct kvm_tdx {
 	bool tsx_supported;
 
 	u64 tsc_offset;
+	u64 tsc_multiplier;
 
 	enum kvm_tdx_state state;
 
diff --git a/arch/x86/kvm/vmx/tdx_arch.h b/arch/x86/kvm/vmx/tdx_arch.h
index 861c0f649b69..be4cf65c90a8 100644
--- a/arch/x86/kvm/vmx/tdx_arch.h
+++ b/arch/x86/kvm/vmx/tdx_arch.h
@@ -69,6 +69,7 @@ 
 
 enum tdx_tdcs_execution_control {
 	TD_TDCS_EXEC_TSC_OFFSET = 10,
+	TD_TDCS_EXEC_TSC_MULTIPLIER = 11,
 };
 
 enum tdx_vcpu_guest_other_state {