繁体   English   中英

现代 x86 CPU 中是否有一个计数器,它只计算在中断处理程序中花费的时间(或周期)?

[英]Is there a counter in modern x86 CPUs which only counts the time (or cycles) spent in interrupt handlers?

这不是一个重复的问题。 有人声称这个问题是这个问题的副本。 但是,我没有提到“Linux”或“内核”(标签和文本中都没有)。 因此,声称这是处理 Linux 和 perf 的问题的重复是错误的。

我想知道如何在没有外部程序的情况下测量中断时间。 换句话说,我想自己在代码中进行时间测量,最好使用硬件寄存器。 为了这个问题,我们假设没有操作系统。

说了这么多:

在类似 Pentium-M 处理器上运行的汇编程序中,我想测量某个程序执行所需的时间。 这通常是显而易见的,有很多文章说明并展示了如何做到这一点,而且我也有自己的可靠方法。

但是,在这种情况下,存在一个问题:程序可能随时被中断(通过硬件中断)。 由于我想测量程序本身的纯执行时间,事情变得越来越复杂:

  • 测量整个过程所需的时间(简单)
  • 测量程序运行时中断处理程序所需的时间(不是那么容易)
  • 从整个时间中减去中断时间得到我感兴趣的数字

我一直认为在“现代”英特尔 PC CPU 上有一个计数器,它只在 CPU 执行中断处理程序时计数。 但情况似乎并非如此。 至少,我没有在 Intel 64 和 IA-32 架构软件开发人员手册的“性能监控”一章中找到它。

我已经制定了一个适合我目前需求的解决方案,但是对于未来的情况,它并不像我希望的那样精确,而且它也不是很优雅。

因此,我想知道我是否错过了一个硬件计数器,它可以通过仅在执行中断处理程序时计数(或者仅在执行不在中断处理程序中的代码时计数)来帮助我。

禁用中断来测量纯过程执行时间不是一种选择,因为中断处理程序中发生的事情可能会影响过程的执行。

该过程和中断处理程序在同一个内核上运行。

整个代码(过程和中断处理程序)在环 0 中运行。

不,对此没有硬件支持,仅用于编程计数器以在环 0(内核模式)与环 3(用户空间)中计数。 这就是 Linux perf用来实现perf stat --all-user--all-kernelcycles:u:k修饰符的方法。 (我不确定哪一个环 1 和环 2 被混为一谈)。

x86 ISA 不会将处于“中断处理程序”中的状态区分为特殊状态。 这只是一个软件概念,例如,主流内核中的中断处理程序可能会通过跳转到一个名为schedule()的函数来决定是返回到被中断的任务还是返回某个其他任务。 最终可能会有一个iret (中断返回),但这并不是“特殊”,除了从当前堆栈中弹出 CS:RIP、RSP 和 RFLAGS 之外,这可能很难用其他指令来模拟。

但是,如果内核上下文切换到之前进行了阻塞系统调用的任务,它可能会通过sysret返回用户空间,仅在上下文切换回被中断的任务后很久才运行iret 你不需要做任何特别的事情来告诉 x86 CPU 你已经完成了一个中断处理程序(可能不像其他一些 ISA),所以 CPU 甚至没有什么可以监视的。

APIC(外部中断的中断控制器)可能需要被戳,让它知道我们已经准备好处理这种类型的进一步中断,但 CPU 内核本身可能不会跟踪这一点。

因此,可以想象假设的 x86 硬件使用几种不同的启发式方法来判断中断处理程序何时完成,但我认为实际的 x86 硬件 PMU 不会做任何这些。


对于在用户空间中运行(并且不进行系统调用)的分析代码的正常情况perf stat --all-user (或手动编程它将使用的 PMU 设置)将完全按照您的意愿进行,不计入CPU处于内核模式时的任何内容。 唯一的内核时间将在中断处理程序中。

但是对于您的情况,您要分析的代码在环 0 中运行,硬件无法帮助您。

除非你在你的中断处理程序中做了非常耗时的事情(与其他工作量相比),否则只让它们被计算就足够了。 至少对于像“循环”这样的事件。 如果中断处理程序导致大量 TLB 未命中或缓存未命中或其他原因,则可能会影响您对其他事件的计数。

您的中断处理程序可以在开始/结束时运行rdpmc并可能将每个事件的计数汇总到一些全局(或核心本地)变量中,因此您可以从主要计数中减去一些内容。 但这会给每个中断处理程序增加多个rdpmc指令的开销。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM