【问题标题】:There is any way to trigger a legacy mode for RDTSC?有什么方法可以触发 RDTSC 的传统模式?
【发布时间】:2016-05-10 07:58:36
【问题描述】:

我重写了整个问题,人们显然不理解它。

RDTSC 用于计算 CPU 周期,它随 CPU 节流而变化。

目前,RDTSC 不会随 CPU 节流而变化。

一些旧的应用程序,预计 RDTSC 会随着 CPU 节流而变化。

我如何让 RDTSC 满足他们的期望?

我不想分析代码,我不想重写大量代码,我不想强​​迫用户弄乱 BIOS 或内核权限,我只想让遗留应用程序像他们应该。

【问题讨论】:

  • 我以前看过这两个,这有助于理解问题,但不要修复它。我不是在写一个新的应用程序,我是在尝试让遗留应用程序工作而不会对它们进行过多的修改......我不能只是到处替换他们的大部分代码。
  • 人们一定很讨厌我,每次我问一个问题,我都会立即被否决,没有人解释原因。
  • 如果我对您的理解正确,您已经拥有使用 RDTSC 的旧应用程序,并且您确实在寻找一种方法来运行现有的二进制文件,只需极少或无需修改,以便它们像在旧硬件上一样工作。我只能希望你不要雇佣那些为新项目编写原始代码的人。
  • @PeterCordes:自 1995 年以来,我一直在为 SMP x86 构建并行编程工具。我们一直使用 TSC 作为时序源。是的,在过去糟糕的日子里,有时线程从一个 CPU 切换到另一个 CPU 会给我们带来不一致的 TSC 计数。这不是不可用的。您只需要多次运行计时并抛出无意义的答案。是的,即使在 16 个核心系统上,它现在也好多了。

标签: assembly rdtsc


【解决方案1】:

简单地说,你不能通过轻按开关来做到这一点

英特尔开发人员手册 3B第 17 章,明确阅读

不变的 TSC 将在所有 ACPI P-、C- 中以恒定速率运行。和 T 状态。这是向前发展的架构行为。

这是告诉您无法切换回之前的行为的另一种方式。


但是,如果您真的喜欢,可以尝试一下。

rdtsc 的值来自 IA32_TIME_STAMP_COUNTER,它是可写的。
所以你可以在不改变任何程序的情况下“伪造”rdtsc 的读取,但你需要一个驱动程序。
更改 IA32_TIME_STAMP_COUNTER 以调整内部时钟计数可能不是那么容易。

我不记得自复位后是否有计算内部时钟的性能事件,如果有,那么理论上您只需读取该值并写入 IA32_TIME_STAMP_COUNTER
较新的 CPU 还支持 IA32_TSC_ADJUST,可用于以相对方式调整 TSC:从 IA32_TSC_ADJUST 中添加/减去的任何内容都会被添加/减去来自IA32_TIME_STAMP_COUNTER。因此,您可以减慢或加快计数器的速度。

无论您需要哪种方式:

  • 创建驱动程序以交付给您的用户。可能没有安装它的权限。
  • 要知道 CPU 的确切节流,与 gudok answer 的投票计数相反,性能计数器寄存器是唯一的方法。除非您想挂钩操作系统电源管理器功能/事件并进行有根据的猜测。
  • 将该限制映射到 TSC 值。
  • 选择更新 TSC 的频率(非常重要)。

【讨论】:

  • 如果您正在编写驱动程序,性能计数器可能是最简单的方法。您可以获得自上次调整 TSC 以来的核心时钟数,这正是您需要的数字。即使您处于内核模式,您可以在其中以低开销访问操作系统对当前时钟速度的想法,但这并不能平均过去的 turbo up/down 事件历史。无论如何,当操作系统将 CPU 频率决策权交给内核时,Skylake 的效果最好,因此它可以比操作系统检查频率更频繁地调整频率。
  • 请记住,您的 Windows 驱动程序或 Linux 内核模块应该告诉操作系统它不能再使用 TSC 作为时间源。每个核心只有一个 TSC,而不是每个进程或每个线程,因此弄乱它会破坏例如 Linux 上的gettimeofday()。将带有gettimeofday 实现的代码页映射到每个进程的地址空间。在没有constant_tsc 功能的系统上,它从不使用syscall 或任何东西,并与rdtsc 保持在用户空间中。因此,在 Linux 上,从 TSC 到非 TSC 的启动后更改可能会出现问题。 IDK。
  • @PeterCordes :她确实说与他回答的投票数相反。我认为她基本上是在说 Gudok 是对的,但这并没有反映在投票中。
  • @MichaelPetch:啊,我明白了。我想我曾经想通了这一点,但是当我写完我的其他 cmets 时就忘记了。 >.
【解决方案2】:

我最近因为不相关的原因偶然发现了这个:

AMD Bulldozer 系列 (15h) CPU 具有新的 MSR:时间戳计数器比率 (TscRateMsr)、as mentioned in AMD's optimization manual。他们建议 VMM“使用时间戳计数器比率功能来调整来宾虚拟机的 TSC 频率”(第 12.16 节),但您也可以使用它来根据当前的频率缩放设置更改比率。

有关时间戳计数器比率 MSR 的更多信息,请参阅第 3.12 节“MSR - BIOS 和内核开发人员指南 (BKDG) 中的 MSRC000_0xxx”,适用于 AMD 系列 15h 型号 00h-0Fh 处理器.

IDK 如果英特尔有类似的东西;没看过。

【讨论】:

  • 哇,好消息!我会对此进行更多研究,因为到目前为止我发现的信息很模糊,但它可能是正确的轨道。也许你会以接受的答案结束:)
  • 是的,英特尔应该have something similar。但是,如果我在快速阅读后没有错的话,它只会影响 VMM 客人。所以我不确定它是否能解决 OP 问题。
  • 我没有检查,AMD 的 MSR 也可能只影响来宾虚拟机。这个想法已经需要连接到操作系统的频率缩放调节器,现在它可能需要在来宾 VM 中运行您的代码......感谢您指出这一点,@Margaret。几乎可以肯定的是,禁用 turbo 并强制 CPU 达到正常的最大速度更容易。
  • 是的,它仅适用于访客 VM :( 至于禁用 turbo:这并不能解决问题,因为现代 RDTSC 标准不强制它返回与时钟远程相关的值,一个 CPU如果它想要的话,可以有一个 100mhz... 或 10000000ghz... 等等,所以任何使用 RDTSC 计算时钟周期的软件都将获得定时器周期,而不是 CPU,即使禁用了 turbo。
  • @speeder:这在实践中会发生吗?据我了解,英特尔 CPU 以“额定”时钟速度运行其 TSC。关于 AMD 的 IDK。无论如何,只要 TSC 与实际内核时钟周期的比率恒定,您就可以轻松转换。
【解决方案3】:

使用 CPU 性能计数器。在 Linux 中可以使用 perf_event_open 系统调用来使用它们。或者,您也可以通过运行 perf 实用程序来全局测量您的程序需要多少 CPU 周期。

【讨论】:

  • 在我测量之后,我如何将信息反馈给程序?编辑:同样,在 Windows 上。
  • perf_event_open 旨在衡量代码的细粒度和平。不幸的是,我无法为 Windows 推荐任何类似的工具(很可能您需要使用编译器内部函数来设置 CPU 计数器)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 2019-12-16
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多