Intel Processor Trace(一)

发布时间:2024年01月16日

前言

参考Intel vo3 Chapter 32 Intel Processor Trace

Intel? Processor Trace(Intel PT)是Intel?架构的扩展,利用专用的硬件设施捕获有关软件执行的信息,对被追踪的软件性能干扰非常小。这些信息被收集在数据包中。最初的Intel PT实现提供了控制流追踪,生成各种数据包供软件解码器处理。这些数据包包括计时信息、程序流信息(例如分支目标、分支是否被执行)、程序引发的模式相关信息(例如Intel TSX状态转换、CR3更改)。这些数据包在发送到内存子系统或平台上的其他输出机制之前,可以在内部进行缓冲。调试软件可以处理跟踪数据并重构程序流程。

Intel Processor Trace首次引入于基于Broadwell微架构的Intel?处理器和基于Goldmont微架构的Intel Atom?处理器。后续的代数还包括其他追踪源,包括使用PTWRITE进行的软件追踪仪器化和功耗事件追踪。

一、Features and Capabilities

Intel PT的控制流追踪生成多种数据包,当与程序的二进制代码结合使用时,可以通过后处理工具生成精确的执行跟踪。这些数据包记录了诸如指令指针(IP)、间接分支目标以及连续代码区域(基本块)中条件分支的方向等流程信息。

Intel PT还可以配置为使用PTWRITE记录软件生成的数据包,以及描述处理器功耗管理事件的数据包。此外,可以配置精确事件基础采样(PEBS)以在Intel PT跟踪中记录PEBS记录;详见Intel vol3第19.5.5.2节。

此外,这些数据包还记录了其他上下文、计时和记账(bookkeeping)信息,可用于应用程序的功能和性能调试。Intel PT具有多种控制和过滤功能,可用于自定义所收集的跟踪信息,并附加其他处理器状态和计时信息以进行调试。例如,可以基于当前特权级(CPL)或CR3的值对数据包进行过滤的模式。

数据包生成和过滤功能的配置是通过一组MSR(Model Specific Register)进行编程的。这些MSR通常遵循IA32_RTIT_*的命名约定。这些配置MSR提供的功能由CPUID进行枚举,详见第32.3节。有关配置Intel PT的MSR的详细信息,请参阅第32.2.8节。

1.1 Packet Summary

在追踪工具启用和配置适当的MSR之后,处理器将按以下数据包类别收集和生成跟踪信息(有关数据包的更多详细信息,请参阅第32.4节):

关于程序执行的基本信息的数据包,包括:
(1)Packet Stream Boundary(PSB)数据包:PSB数据包作为“心跳”定期生成(例如,每4K跟踪数据包字节)。这些数据包允许数据包解码器在输出数据流中找到数据包的边界;当解码跟踪时,解码器应该首先寻找PSB数据包。
(2)Paging Information Packet(PIP):PIP记录对CR3寄存器的修改。这些信息以及操作系统关于每个进程CR3值的信息,允许调试器将线性地址归属到正确的应用源。
(3)Time-Stamp Counter(TSC)数据包:TSC数据包有助于跟踪墙钟时间,并包含一部分软件可见的时间戳计数器。
(4)Core Bus Ratio(CBR)数据包:CBR数据包包含核心:总线时钟比率。
(5)Mini Time Counter(MTC)数据包:MTC数据包定期指示墙钟时间的流逝。
(6)Cycle Count(CYC)数据包:CYC数据包指示数据包之间经过的处理器核心时钟周期数。
(7)Overflow(OVF)数据包:当处理器发生内部缓冲区溢出并丢弃数据包时,会发送OVF数据包。该数据包通知解码器数据丢失的情况,有助于解码器应对此情况。

控制流信息数据包用于动态二进制分析和跟踪,用于追踪和理解程序的执行流程。它们提供有关程序行为的重要信息,包括分支的方向、目标地址和执行模式。通过分析这些数据包,开发人员和研究人员可以深入了解程序的运行方式,并识别潜在的问题或优化机会。
以下是常见的控制流信息数据包类型:
(1)Taken Not-Taken (TNT) 数据包:TNT 数据包用于跟踪直接条件分支的“方向”(是否被执行)。
(2)Target IP (TIP) 数据包:TIP 数据包记录间接分支、异常、中断和其他分支或事件的目标地址。这些数据包可以包含指令指针(IP),尽管该地址可能被压缩,去掉与上一个 IP 匹配的高位字节。TIP 数据包有多种类型,在第32.4.2.2节中有更详细的介绍。
(3)Flow Update Packets (FUP):FUP 数据包提供异步事件(中断和异常)的源地址,以及其他无法通过二进制文件确定源地址的情况。
(4)MODE 数据包:这些数据包提供解码器重要的处理器执行信息,以便正确解释反汇编的二进制和跟踪日志。MODE 数据包包含有关处理器执行模式的信息,例如16位模式、32位模式或64位模式。

软件插入的数据包:
软件插入的数据包包括PTWRITE (PTW) 数据包,其中包含传递给PTWRITE指令的操作数的值。PTWRITE指令用于将数据写入处理器跟踪数据包。
在这里插入图片描述
该指令读取源操作数中的数据,并将其发送到Intel处理器跟踪硬件以编码到PTW数据包中,前提是TriggerEn、ContextEn、FilterEn和PTWEn都设置为1。如果在64位模式下使用了REX.W前缀,数据大小为64位,否则从源操作数中复制32位数据。
注意:如果使用了66H前缀,该指令将引发#UD异常。

处理器功耗管理事件的数据包包括:
(1)MWAIT 数据包:指示成功完成一个比C0.0更深的C状态的MWAIT操作。
(2)Power State Entry (PWRE) 数据包:指示进入一个比C0.0更深的C状态。
(3)Power State Exit (PWRX) 数据包:指示从一个比C0.0更深的C状态退出,返回到C0。
(4)Execution Stopped (EXSTOP) 数据包:指示由于诸如P状态更改、C状态更改或热限制等事件而导致软件执行停止。
这些数据包用于跟踪和记录处理器的功耗管理事件。通过分析这些数据包,可以了解处理器进入和退出不同的C状态,以及软件执行停止的原因。这对于分析和优化功耗管理以及检测潜在的性能问题非常有用。

包含处理器状态值组的数据包包括:
(1)Block Begin Packets (BBP):指示以下组中保存的状态类型。
(2)Block Item Packets (BIP):指示组中保存的状态值。
(3)Block End Packets (BEP):指示当前组的结束。

这些数据包用于将一组处理器状态值进行分组和表示。Block Begin Packets(BBP)标识了以下组中保存的状态类型,Block Item Packets(BIP)包含了实际的状态值,而Block End Packets(BEP)表示当前组的结束。

通过这些数据包,可以将相关的处理器状态值组织在一起,并进行更好的跟踪和分析。这对于了解处理器在不同时间点的状态变化以及对性能和功耗的影响非常有帮助。

二、Intel Processor Trace Operational Model

2.1 Change of Flow Instruction (COFI) Tracing

基本程序块是指在代码中没有跳转或分支的部分。在这个代码块中,指令指针(IP)无需被追踪,因为处理器会按顺序从头到尾执行它们,不会改变代码流程。但是,诸如分支指令、异常或中断等指令和事件可以改变程序的执行流程。这些改变程序流程的指令和事件被称为流程改变指令(COFI)。COFI分为三个类别:

直接转移COFI:这个类别包括直接将控制流转移到代码中的新位置的指令。直接转移COFI指令的例子包括无条件跳转(如JMP)或根据条件改变执行路径的条件分支(如JNZ,JNE)。

间接转移COFI:这个类别涉及根据寄存器或内存位置中的值来间接转移控制流的指令。间接转移COFI的例子包括CALL指令,它根据寄存器或内存中存储的地址转移到一个子程序。

远跳转COFI:远跳转COFI指的是改变执行流程到不同的代码段或代码选择器的指令。这些指令通常在分段内存模型中使用。远跳转COFI的例子包括FAR JMP指令,它将代码段和指令指针更改为不同的位置。

以下小节描述了导致生成跟踪数据包的COFI事件。表32-1按COFI类型列出了分支指令。
在这里插入图片描述

2.1.1 Direct Transfer COFI

直接转移COFI是指相对分支。这意味着它们的目标是当前指令指针的偏移量嵌入在指令字节中。在跟踪输出中不需要指示这些指令的目标,因为可以通过源代码反汇编获得。条件分支只需要指示分支是否被执行。无条件分支不需要在跟踪输出中记录任何信息。直接转移COFI有两个子类别:

(1)条件分支(Jcc,JCXZ)和LOOP:为了跟踪这种类型的指令,处理器编码了一个单独的位(taken或not taken)来指示指令执行后的程序流程。Jcc,JCXZ和LOOP可以使用TNT(Taken/Not Taken)位进行跟踪。为了提高跟踪数据包的输出效率,处理器会将多个TNT位压缩为一个单独的数据包。

(2)无条件直接跳转:对于直接无条件跳转(如相对近跳转JMP或CALL指令),不需要跟踪输出,因为可以直接从应用程序的汇编代码中推断出来。直接无条件跳转不会生成TNT位或目标指令指针(Target IP)数据包,但是无条件直接跳转可能会生成切换Intel PT启用的TIP.PGD和TIP.PGE数据包(详见第32.2.6节)。

2.1.2 Indirect Transfer COFI

间接转移COFI涉及从寄存器或内存位置更新指令指针(IP)。由于寄存器或内存内容在执行过程中可以随时变化,因此在读取寄存器或内存内容之前无法知道间接转移的目标。因此,仅凭反汇编代码无法确定这种类型的COFI的目标。因此,跟踪硬件必须在跟踪数据包中发送目标指令指针,以便调试软件确定COFI的目标地址。请注意,此目标指令指针可以是线性地址或有效地址(详见第32.3.1.1节)。

间接转移指令生成一个目标指令指针数据包(Target IP Packet,TIP),其中包含分支的目标地址。有两个子类别:

(1)Near JMP Indirect and Near Call Indirect:如前所述,间接COFI的目标位于寄存器或内存位置的内容中。因此,处理器必须生成一个包含此目标地址的数据包,以供解码器确定程序流程。

(2)Near RET:当执行CALL指令时,它将CALL指令后面的指令地址压入栈中。在调用过程完成后,通常使用RET指令从调用栈中弹出返回地址,并将代码流程重定向回CALL指令后面的指令。

RET指令简单地将程序流程转移到从栈中弹出的地址处。由于被调用的过程可能在执行RET指令之前更改返回地址,如果假设代码流程将返回到最后一个CALL指令后面的指令,调试软件可能会被误导。因此,即使对于近RET,也可能发送一个目标指令指针数据包。

RET Compression:如果RET的目标与跟踪CALL栈的预期一致,将应用一种特殊情况。如果确保解码器已经看到了对应的CALL(“对应"定义为具有匹配堆栈深度的CALL),并且RET的目标是该CALL指令后的指令,那么RET的目标可以进行"压缩”。在这种情况下,只生成一个"taken"的TNT位,而不是目标指令指针数据包。为确保解码器在RET压缩的情况下不会混淆,只有自上一个PSB数据包以来已经看到的CALL的RET才能在给定的逻辑处理器中进行压缩。有关详细信息,请参阅第32.4.2.2节中的"Indirect Transfer Compression for Returns(RET)"。

2.1.3 Far Transfer COFI

所有改变指令指针且不属于近跳转的操作都被称为"远跳转"(Far Transfer)。这包括异常、中断、陷阱、TSX异常以及执行远跳转的指令。

所有远跳转都会生成一个目标指令指针数据包(Target IP Packet,TIP),其中包含目标指令指针的地址。对于那些无法从二进制源代码中推断出的远跳转(例如异步事件,如异常和中断),TIP之前会有一个流程更新数据包(Flow Update Packet,FUP),其中提供了事件发生时的源指令指针地址。第32.23表明了由远跳转生成的FUP中将包含哪个指令指针。

简而言之,所有改变指令指针且不是近跳转的操作都属于远跳转。远跳转会生成目标指令指针数据包(TIP),其中包含目标地址。对于无法从二进制源代码中推断出的远跳转,会在TIP之前生成流程更新数据包(FUP),其中提供了事件发生时的源指令指针地址。

2.2 Software Trace Instrumentation with PTWRITE

PTWRITE是一种软件工具,可以用来对Intel PT跟踪进行插装。PTWRITE是一个可在Ring 3访问的指令,可以传递给一个寄存器或内存变量,详见《Intel? 64和IA-32体系结构软件开发人员手册第2B卷》中的"PTWRITE - 将数据写入处理器跟踪数据包"。该变量的内容将作为PTW数据包的有效负载使用(参见第32.40表中的"PTW数据包定义"),并在PTWRITE指令退役时插入,前提是启用了PTWRITE并满足所有其他过滤条件。解码和分析软件可以根据关联的PTWRITE指令的指令指针(IP)确定PTWRITE数据包的含义。
在这里插入图片描述

可以通过IA32_RTIT_CTL.PTWEn[12](参见第32.6表)来启用PTWRITE。用户还可以使用IA32_RTIT_CTL.FUPonPTW[5]来启用在PTW数据包之后跟随包含关联PTWRITE指令的IP的FUP数据包。对PTWRITE的支持首次引入了基于Goldmont Plus微架构的Intel Atom处理器。

2.3 Power Event Tracing

Power Event Trace(PET)是一种功能,用于提供核心级别和线程级别的睡眠状态和电源关闭转换信息。当启用此功能时,跟踪将提供有关以下信息的信息:

(1)软件执行停止的场景。
由于进入睡眠状态、频率变化或其他电源关闭。
包括在跟踪上下文中的指令指针(IP)。
(2)请求和实现的硬件线程C状态。
包括硬件自主进入C状态的指示。
(3)在睡眠会话期间实现的最后和最深的核心C状态。
(4)C状态唤醒的原因。
此信息是在任何电源关闭后默认提供的总线比率(CBR)信息以及在电源关闭状态期间或之后提供的定时信息(TSC、TMA、MTC、CYC)之外的信息。

可以通过IA32_RTIT_CTL.PwrEvtEn[4]来启用Power Event Trace。对Power Event Tracing的支持首次引入了基于Goldmont Plus微架构的Intel Atom处理器。

2.4 Event Tracing

Event Trace是一种功能,用于暴露有关异步事件的详细信息,包括它们生成的时间以及相应的软件事件处理程序完成执行的时间。这些事件包括:

(1)中断,包括NMI和SMI,当定义时包括中断向量。
(2)故障和异常,包括故障向量。
页面故障还包括在上下文中的页面故障地址。
(3)事件处理程序返回,包括IRET和RSM指令。
(4)虚拟机退出和虚拟机进入。
虚拟机退出包括写入"退出原因"和"退出限定"VMCS字段的值。
(5)INIT和SIPI事件。
(6)TSX异常,包括RTM指令返回的异常状态。
(7)关机。
此外,它还提供了中断标志(IF)的状态指示,以指示中断是否被屏蔽。可以通过IA32_RTIT_CTL.EventEn[31]来启用Event Trace。事件跟踪信息包含在控制流事件(CFE)和事件数据(EVD)数据包以及传统的MODE.Exec数据包中。有关数据包详细信息,请参阅第32.4.2节。对Event Trace的支持首次引入了基于Gracemont微架构的Intel?处理器。

2.5 Trace Filtering

“英特尔处理器跟踪”提供过滤功能,调试/配置文件工具可以通过该功能控制跟踪哪些代码。

2.5.1 Filtering by Current Privilege Level (CPL)

在Intel PT中,可以配置逻辑处理器仅在当前特权级(CPL)等于0时、CPL大于0时或不考虑CPL时生成跟踪数据包。

CPL过滤确保在日志中无法看到与被过滤CPL相关的指令指针(IP)或其他体系结构状态信息。例如,如果处理器配置为仅在CPL大于0时进行跟踪,并且软件执行SYSCALL(将CPL更改为0),则生成的数据包将不会包含SYSCALL的目标IP(参见第32.4.2.5节中关于TIP.PGD的讨论)。

需要注意的是,在实地址模式下,CPL始终为0,在虚拟-8086模式下,CPL始终为3。要跟踪这些模式下的代码,应相应地配置过滤设置。

当软件在未启用的CPL下执行时,ContextEn将被清除。详细信息请参见第32.2.6.1节。

源码分析:

simple-pt/sptcmd

--no-kernel -K disable kernel trace (default on) (only use with --comm ...)
--no-user   -U disable user trace (default on)


	K) KERNEL=0 ;;
	U) USERMODE=0 ;;

C=/sys/module/simple_pt/parameters

	echo $KERNEL > $C/kernel
	echo $USERMODE > $C/user

IA32_RTIT_CTL MSR寄存器:

PositionBit NameAt ResetBit Description
0TraceEn0If 1, enables tracing; else tracing is disabled.
2OS00: Packet generation is disabled when CPL = 0.
1: Packet generation may be enabled when CPL = 0.
3User00: Packet generation is disabled when CPL > 0.
1: Packet generation may be enabled when CPL > 0
simple-pt/simple-pt.c

#define MSR_IA32_RTIT_CTL		0x00000570
#define TRACE_EN	BIT_ULL(0)
#define CTL_OS		BIT_ULL(2)
#define CTL_USER	BIT_ULL(3)

static int user = 1;
module_param_cb(user, &resync_ops, &user, 0644);
MODULE_PARM_DESC(user, "Set to 0 to not trace user space");
static int kernel = 1;
module_param_cb(kernel, &resync_ops, &kernel, 0644);
MODULE_PARM_DESC(kernel, "Set to 0 to not trace kernel space");

simple_pt_init()
	-->restart()
		-->do_start_pt()
			-->start_pt()
static int start_pt(void)
{
	pt_rdmsrl_safe(MSR_IA32_RTIT_CTL, &val);

	if (val & TRACE_EN)
		pt_wrmsrl_safe(MSR_IA32_RTIT_CTL, val & ~TRACE_EN);

	if (kernel)
		val |= CTL_OS;
	if (user)
		val |= CTL_USER;

	pt_wrmsrl_safe(MSR_IA32_RTIT_CTL, val);

	__this_cpu_write(pt_running, true);
	return 0;
}

2.5.2 Filtering by CR3

Intel PT支持CR3过滤机制,通过该机制可以基于CR3的值启用或禁用包含体系结构状态的数据包生成。调试器可以使用CR3过滤来仅跟踪单个应用程序,而无需上下文切换RTIT MSRs的状态。对于从具有多个线程的软件中重构跟踪,调试软件可能希望上下文切换RTIT MSRs的状态(如果操作系统不提供上下文切换支持),以便将输出分离为不同的线程(详见第32.3.5节中的"上下文切换考虑")。

要仅跟踪单个CR3值,软件可以将该值写入IA32_RTIT_CR3_MATCH MSR,并设置IA32_RTIT_CTL.CR3Filter。当CR3值与IA32_RTIT_CR3_MATCH不匹配且IA32_RTIT_CTL.CR3Filter为1时,ContextEn被强制为0,将不会生成包含体系结构状态的数据包。当ContextEn为0时,可能会生成其他一些数据包;详见第32.2.6.3节。

当CR3与IA32_RTIT_CR3_MATCH匹配(或IA32_RTIT_CTL.CR3Filter为0时),CR3过滤不会强制将ContextEn设置为0(尽管由于其他过滤器或模式的原因,ContextEn可能为0)。

CR3与IA32_RTIT_CR3_MATCH匹配的条件是,对于位63:12(在非PAE分页模式下)或位63:5(在PAE分页模式下),两个寄存器的值完全相同;CR3和IA32_RTIT_CR3_MATCH的低5位将被忽略。CR3过滤与CR0.PG的值无关。

当使用CR3过滤时,如果处理器配置为在CPL = 0(IA32_RTIT_CTL.OS = 1)时进行跟踪,日志中仍可能看到PIP数据包。否则,将不会看到任何PIP数据包。

2.5.3 Filtering by IP

(1)
如果CPUID.(EAX=14H, ECX=0):EBX[bit 2] = 1,则支持通过可配置的IP过滤来生成跟踪数据包。可以配置Intel PT仅在处理器执行特定IP范围内的代码时生成包含体系结构状态的数据包。如果IP在这些范围之外,将阻止某些数据包的生成。

使用IA32_RTIT_CTL MSR中的ADDRn_CFG字段启用IP过滤(详见第32.2.8.2节),其中数字’n’是从零开始的数字,选择要配置的地址范围。每个ADDRn_CFG字段配置使用寄存器对IA32_RTIT_ADDRn_A和IA32_RTIT_ADDRn_B(详见第32.2.8.5节)。IA32_RTIT_ADDRn_A定义了基地址,而IA32_RTIT_ADDRn_B指定了启用跟踪的范围的上限。因此,每个范围(称为ADDRn范围)由[IA32_RTIT_ADDRn_A,IA32_RTIT_ADDRn_B]定义。可以存在多个这样的范围,软件可以查询CPUID(第32.3.1节)以获取处理器支持的范围数量。

默认行为(ADDRn_CFG=0)不定义IP过滤范围,意味着FilterEn始终设置。在这种情况下,可以跟踪任何IP处的代码,尽管其他过滤器(如CR3或CPL)可能限制跟踪。当ADDRn_CFG设置为启用IP过滤时(参见第32.3.1节),只有当看到目标地址在ADDRn范围内的分支或事件时,跟踪才会开始。

在跟踪区域内且FilterEn已设置的情况下,只有当已执行的目标地址在范围之外的分支或事件退役时,才能检测到离开跟踪区域。如果通过执行下一个连续指令而不是控制流转移来进入或退出ADDRn范围,则FilterEn可能不会立即切换。详见第32.2.6.5节中有关FilterEn的更多详细信息。

请注意,这些地址范围的基地址和限制值是包含的,因此范围包括第一条指令和最后一条指令,其第一个指令字节位于ADDRn范围内。

根据处理器实现的不同,IP过滤可能基于线性地址或有效地址。如果CSbase不等于零或处于实模式下,这可能导致实现之间的不同行为。详见第32.3.1.1节了解详细信息。软件可以查询CPUID以确定过滤器是基于线性地址还是有效地址(第32.3.1节)。

请注意,某些数据包(如MTC(第32.3.7节)和其他计时数据包)不依赖于FilterEn。有关依赖于FilterEn的数据包以及受IP过滤影响的数据包的详细信息,请参见第32.4.1节。

(2)TraceStop
ADDRn范围也可以配置为在进入指定区域时禁用跟踪。这适用于执行意外代码的情况,用户希望立即停止生成数据包以避免覆盖先前写入的数据包。

TraceStop机制的工作方式与IP过滤非常相似,并且使用相同的地址比较逻辑。TraceStop区域的基地址和限制值被编程到一个或多个ADDRn范围中,但是IA32_RTIT_CTL.ADDRn_CFG被配置为TraceStop编码。与FilterEn类似,当一个分支或事件落在TraceStop区域内时,TraceStop被检测到。

此外,TraceStop要求在分支/事件开始时TriggerEn=1,并在分支/事件完成时ContextEn=1。当发生这种情况时,CPU将设置IA32_RTIT_STATUS.Stopped,从而清除TriggerEn并禁用数据包生成。这可能会生成一个带有进入TraceStop区域的分支或事件的目标IP的TIP.PGD数据包。最后,将插入一个TraceStop数据包,指示命中了条件。

如果在缓冲区溢出(第32.3.8节)期间遇到TraceStop条件,则不会丢弃该条件,而是在溢出解决后发出信号。

请注意,TraceStop事件并不保证所有内部缓冲区的数据包都被刷新出内部缓冲区。为确保这一点,用户应该清除TraceEn。

要在TraceStop事件后恢复跟踪,用户必须首先通过清除IA32_RTIT_CTL.TraceEn来禁用Intel PT,然后才能清除IA32_RTIT_STATUS.Stopped位。在此时刻,可以重新配置Intel PT,并恢复跟踪。

请注意,IA32_RTIT_STATUS.Stopped位还可以使用ToPA STOP位设置。详见第32.2.7.2节。

(3)IP Filtering Example
下表给出了IP筛选行为的示例。假设IA32_RTIT_ADDRn_A=RangeBase的IP,IA32_TIT_ADDRn_B=RangeLimit的IP,而IA32_RIT_CTL。ADDRn_CFG=0x1(启用ADDRn范围作为FilterEn范围)。
在这里插入图片描述
(4)IP Filtering and TraceStop
用户可以配置重叠的IP过滤范围和TraceStop范围。在这种情况下,位于任一范围的非重叠部分执行的代码将按照该范围的预期行为进行。而位于重叠范围内执行的代码将获得TraceStop行为。

2.6 Packet Generation Enable Controls

Intel Processor Trace(Intel 处理器跟踪)包括多种控制机制,用于确定是否生成数据包。通常情况下,只有在设置了数据包使能(PacketEn)时才会发送数据包。PacketEn是一个在硬件中根据可配置的软件使能控制而维护的内部状态,PacketEn对软件来说不是直接可见的。PacketEn与配置寄存器中的软件可见控制之间的关系在本节中进行了描述。

2.6.1 Packet Enable (PacketEn)

当设置了PacketEn时,处理器处于Intel PT监控模式。PacketEn由以下关系中的其他状态组成:

PacketEn := TriggerEn AND ContextEn AND FilterEn AND BranchEn

这些组成控制在下面的子章节中进行了详细说明。

PacketEn最终确定处理器何时进行跟踪。当设置了PacketEn时,所有的控制流数据包都被启用。当PacketEn被清除时,不会生成任何控制流数据包,尽管其他数据包(如时间和记录数据包)仍然可以被发送。有关PacketEn和数据包生成的详细信息,请参阅第32.2.7节。

请注意,在不支持IP过滤的处理器上(即CPUID.(EAX=14H, ECX=0):EBX[bit 2] = 0),FilterEn被视为始终设置。

2.6.2 Trigger Enable (TriggerEn)

触发使能(TriggerEn)是指示跟踪数据包生成活动的主要指示器。当设置了IA32_RTIT_CTL.TraceEn时,TriggerEn被设置,而通过以下任何一种情况之一来清除:
? 软件清除了TraceEn。
? 遇到了TraceStop条件并且设置了IA32_RTIT_STATUS.Stopped。
? 由于操作错误而设置了IA32_RTIT_STATUS.Error(请参阅第32.3.10节)。

软件可以通过读取IA32_RTIT_STATUS.TriggerEn位来了解当前的TriggerEn值。当TriggerEn被清除时,跟踪处于非活动状态,不会生成任何数据包。

2.6.3 Context Enable (ContextEn)

上下文使能(ContextEn)指示处理器是否处于软件配置的跟踪状态或模式。例如,如果不跟踪CPL = 0代码执行(IA32_RTIT_CTL.OS = 0),那么当处理器处于CPL0时,ContextEn将为0。

软件可以通过读取IA32_RTIT_STATUS.ContextEn位来了解当前的ContextEn值。ContextEn定义如下:

ContextEn = !((IA32_RTIT_CTL.OS = 0 AND CPL = 0) OR
(IA32_RTIT_CTL.USER = 0 AND CPL > 0) OR (IS_IN_A_PRODUCTION_ENCLAVE1) OR
(IA32_RTIT_CTL.CR3Filter = 1 AND IA32_RTIT_CR3_MATCH does not match CR3)

如果清除ContextEn导致PacketEn被清除,则会生成一个数据包生成禁用(TIP.PGD)数据包,但其IP有效载荷将被抑制。如果设置ContextEn导致PacketEn被设置,则会生成一个数据包生成使能(TIP.PGE)数据包。

当ContextEn为0时,不会生成控制流数据包(TNT、FUP、TIP.、MODE.),也不会暴露线性指令指针(LIP)。但是,在ContextEn为0时仍然可能生成一些数据包,如MTC和PSB(参见第32.4.2.16节和第32.4.2.17节)。关于只在设置ContextEn时生成哪些数据包的详细信息,请参阅第32.4.1节。

当TriggerEn = 0时,处理器不会更新ContextEn的值。

只有当TriggerEn = 1时,ContextEn的值才会切换。

2.6.4 Branch Enable (BranchEn)

分支使能(BranchEn)的值完全基于IA32_RTIT_CTL.BranchEn的值。如果未设置BranchEn,则相关的COFI数据包(TNT、TIP*、FUP、MODE.*)将被抑制。其他与计时相关的数据包(TSC、TMA、MTC、CYC)以及PSB将会正常生成。此外,作为软件运行指示器,PIP和VMCS仍将生成。

2.6.5 Filter Enable (FilterEn)

过滤器使能(FilterEn)指示指令指针(IP)是否在Intel PT配置为监视的IP范围内。软件可以通过对IA32_RTIT_STATUS.FilterEn进行RDMSR操作来获取FilterEn的状态。有关IP过滤的配置和使用的详细信息,请参阅第32.2.5.3节。

在清除同时清除PacketEn的FilterEn时,将生成一个数据包生成禁用(TIP.PGD),但与ContextEn情况不同,IP有效载荷可能不会被抑制。对于直接的、无条件的分支以及间接分支(包括RET指令),离开跟踪区域并清除FilterEn时生成的PGD将包含目标IP。这意味着,只要这些IP在上下文范围内,来自配置范围之外的IP可以在跟踪中被暴露。

当FilterEn为0时,不会生成控制流数据包(例如TNT、TIP)。然而,在FilterEn被清除时,仍然可能生成一些数据包,如PIP、MTC和PSB。有关数据包使能的依赖关系的详细信息,请参阅第32.4.1节。

在设置了TraceEn之后,如果没有由软件配置的IP过滤器范围(对于所有n,IA32_RTIT_CTL.ADDRn_CFG != 1),或者处理器不支持IP过滤(即CPUID.(EAX=14H, ECX=0):EBX[bit 2] = 0),则FilterEn始终设置为1。只有当TraceEn=1和ContextEn=1,并且至少配置了一个IP过滤器范围时,FilterEn才会切换。

2.7 Trace Output

Intel PT的输出应独立于跟踪内容和过滤机制进行查看。可用于跟踪输出的选项可能因处理器世代和平台而异。

跟踪输出使用以下输出方案之一进行写出,由IA32_RTIT_CTL的ToPA和FabricEn位字段进行配置(参见第32.2.8.2节):
? 物理地址空间的单个连续区域。
? 变大小的物理内存区域集合。这些区域通过指向这些区域的指针表进行链接,称为物理地址表(ToPA)。跟踪输出绕过缓存和TLB,但不进行序列化。这旨在最小化输出的性能影响。
? 平台特定的跟踪传输子系统。

无论选择哪种输出方案,Intel PT存储默认绕过处理器缓存。这确保它们不会占用宝贵的缓存空间,但它们没有与不可缓存(UC)存储相关的序列化方面。软件应避免使用MTRRs将Intel PT输出区域的任何部分标记为UC,因为这可能覆盖上述描述的行为,并强制使Intel PT存储为UC,从而产生严重的性能影响。

不能保证数据包在生成数据包的指令执行后的固定周期后会被写入内存或其他跟踪终点。确保所有生成的数据包已到达其终点的唯一方法是清除TraceEn,并进行存储、屏障或序列化指令;这样做可以确保所有缓冲的数据包都被刷新出处理器。

2.7.1 Single Range Output

(1)
当IA32_RTIT_CTL.ToPA和IA32_RTIT_CTL.FabricEn位清除时,跟踪数据包输出被发送到由IA32_RTIT_OUTPUT_BASE(第32.2.8.7节)中的基地址和IA32_RTIT_OUTPUT_MASK_PTRS(第32.2.8.8节)中的掩码值定义的单个连续内存区域(如果DRAM不可用,则发送到MMIO)。此范围内的当前写指针也存储在IA32_RTIT_OUTPUT_MASK_PTRS中。这个输出范围是循环的,意味着当写入超过缓冲区的末尾时,它们会从基地址重新开始。

这种输出方法最适用于以下情况:
? 配置为将Intel PT输出定向到足够大的连续DRAM区域。
? 配置为发送到MMIO调试端口,以便将Intel PT输出路由到特定于平台的跟踪终点(例如JTAG)。在这种情况下,特定范围的地址以循环方式写入,并且SoC将拦截这些写入并将其定向到正确的设备。对同一地址的重复写入不会相互覆盖,而是由调试程序累积,因此缓冲区的循环性质不会导致数据丢失。

处理器将根据以下方式确定下一个跟踪数据包输出字节的写入地址:

OutputBase[63:0] := IA32_RTIT_OUTPUT_BASE[63:0]
OutputMask[63:0] := ZeroExtend64(IA32_RTIT_OUTPUT_MASK_PTRS[31:0])
OutputOffset[63:0] := ZeroExtend64(IA32_RTIT_OUTPUT_MASK_PTRS[63:32])
trace_store_phys_addr := (OutputBase & ~OutputMask) + (OutputOffset & OutputMask)

(2)Single-Range Output Errors
如果输出基地址和掩码未被软件正确配置,将会发生操作错误(参见第32.3.10节),并禁用跟踪。单一范围输出的错误情况包括:

? 掩码值非连续。
IA32_RTIT_OUTPUT_MASK_PTRS.MaskOrTablePointer值中,在比包含1的最高有效位更低的位位置上有一个0。

? 基地址和掩码对齐错误,并且设置了重叠的位。
IA32_RTIT_OUTPUT_BASE && IA32_RTIT_OUTPUT_MASK_PTRS[31:0] > 0。

? 非法的输出偏移量。
IA32_RTIT_OUTPUT_MASK_PTRS.OutputOffset大于掩码值IA32_RTIT_OUTPUT_MASK_PTRS[31:0]。

此外,请注意,由于跟踪数据包输出与受限内存重叠,可能会导致错误,参见第32.2.7.4节。

2.7.2 Table of Physical Addresses (ToPA)

当设置了IA32_RTIT_CTL.ToPA并清除了IA32_RTIT_CTL.FabricEn时,将使用ToPA输出机制。ToPA机制使用一个表的链表;请参见图32-1,以了解一个示例。表中的每个条目包含一些属性位、指向输出区域的指针和区域的大小。表中的最后一个条目可以保存指向下一个表的指针。该指针可以指向当前表的顶部(用于循环数组),也可以指向另一个表的基地址。表的大小不固定,因为下一个表的链接可以存在于任何条目中。

处理器将由ToPA表引用的各个输出区域视为一个统一的缓冲区。这意味着单个数据包可以跨越一个输出区域和下一个输出区域之间的边界。

ToPA机制由处理器维护的三个值控制:

(1)proc_trace_table_base:
这是当前ToPA表基地址的物理地址。当启用跟踪时,处理器从IA32_RTIT_OUTPUT_BASE MSR加载该值。在跟踪启用期间,处理器使用proc_trace_table_base的更改更新IA32_RTIT_OUTPUT_BASE MSR,但这些更新可能不与软件执行同步。当禁用跟踪时,处理器确保MSR包含proc_trace_table_base的最新值。

(2)proc_trace_table_offset:
这指示当前正在使用的表的条目(该条目包含当前输出区域的地址)。当启用跟踪时,处理器将IA32_RTIT_OUTPUT_MASK_PTRS的31:7位(MaskOrTableOffset)的值加载到proc_trace_table_offset的27:3位。在启用跟踪期间,处理器使用proc_trace_table_offset的更改更新IA32_RTIT_OUTPUT_MASK_PTRS.MaskOrTableOffset,但这些更新可能不与软件执行同步。当禁用跟踪时,处理器确保MSR包含proc_trace_table_offset的最新值。

(3)proc_trace_output_offset:
这是当前输出区域中的指针,指示下一个写入的位置。当启用跟踪时,处理器从IA32_RTIT_OUTPUT_MASK_PTRS的63:32位(OutputOffset)加载该值。在启用跟踪期间,处理器使用proc_trace_output_offset的更改更新IA32_RTIT_OUTPUT_MASK_PTRS.OutputOffset,但这些更新可能不与软件执行同步。当禁用跟踪时,处理器确保MSR包含proc_trace_output_offset的最新值。
在这里插入图片描述
使用ToPA机制,处理器将数据包写入当前输出区域(由proc_trace_table_base和proc_trace_table_offset标识)。下一个字节将被写入的区域偏移由proc_trace_output_offset确定。当该区域被数据包输出填满(即proc_trace_output_offset = RegionSize–1)时,proc_trace_table_offset移动到下一个ToPA条目,proc_trace_output_offset设置为0,并开始将数据包写入由proc_trace_table_offset指定的新输出区域。

随着数据包的写入,每个存储的物理地址如下计算:

trace_store_phys_addr := 当前ToPA表条目的基地址 + proc_trace_output_offset

最终,表中所有条目所代表的区域可能会变满,并且到达表的最后一个条目。可以通过具有END或STOP属性来识别条目为最后一个条目。END属性表示条目中的地址不指向另一个输出区域,而是指向另一个ToPA表。STOP属性表示一旦相应的区域填满,将禁用跟踪。有关STOP的详细信息,请参见表32-3和后续章节。

当到达END条目时,处理器从此END条目中的基地址加载到proc_trace_table_base,从而将当前表指针移动到这个新表。proc_trace_table_offset被重置为0,proc_trace_output_offset也被重置为0,数据包写入将在第一个条目中指示的基地址处恢复。

如果表中没有STOP或END条目,并且跟踪数据包生成仍然启用,最终将达到最大表大小(proc_trace_table_offset = 0FFFFFF8H)。在这种情况下,当最后一个输出区域被填满时,proc_trace_table_offset和proc_trace_output_offset将被重置为0(回到当前表的开头)。

重要的是要注意,处理器对IA32_RTIT_OUTPUT_BASE和IA32_RTIT_OUTPUT_MASK_PTRS MSRs的更新与指令执行异步进行。因此,在启用Intel PT的情况下读取这些MSR可能会返回过时的值。与所有IA32_RTIT_* MSRs一样,除非通过清除IA32_RTIT_CTL.TraceEn来首先禁用跟踪数据包生成,否则不应信任或保存这些MSRs的值。这确保输出MSR的值考虑到该点生成的所有数据包,之后处理器将停止更新输出MSR的值,直到跟踪恢复。

处理器可以在内部缓存来自当前表或其引用的表(直接或间接)的任意数量的条目。如果启用了跟踪,处理器可能会忽略或延迟对这些表的修改的检测。为了确保处理器可预测地检测到表的更改,软件应在修改当前表(或其引用的表)之前清除TraceEn,然后重新启用数据包生成。

省略

2.7.3 Trace Transport Subsystem

当设置IA32_RTIT_CTL.FabricEn时,将忽略IA32_RTIT_CTL.ToPA位,并将跟踪输出写入跟踪传输子系统。此传输的端点是特定于平台的,有关配置选项的详细信息应参考特定平台的文档。如果CPUID(EAX=14H, ECX=0):EBX[位 3] = 1,则可以设置FabricEn位。

2.7.4 Restricted Memory Access

(1)
数据包输出不能定向到平台限制的内存区域。特别是,为了数据包输出而进行的所有内存访问都会与SMRR(System Management Range Register)区域进行检查。如果与这些区域有任何重叠,跟踪数据收集将无法正常工作。具体的处理器行为取决于实现;表32-5总结了几种情况。
在这里插入图片描述
还应注意,数据包输出不应路由到由IA32_APIC_BASE MSR定义的4KB APIC MMIO区域。有关APIC的详细信息。对于这种情况,不会发出错误信号。

(2)Modifications to Restricted Memory Regions
建议在修改SMRR以更改SMRR区域范围之前,软件禁用数据包生成。这是因为处理器在检查ToPA表条目与受限内存范围冲突后,保留了在内部缓存任意数量的条目的权利。一旦缓存,这些条目将不再进行检查,这意味着数据包输出可能会被路由到新的受限区域。软件可以通过清除IA32_RTIT_CTL.TraceEn来确保所有缓存的条目被写入内存。

2.8 Enabling and Configuration MSRs

2.8.1 General Considerations

数据包生成由一组特定于模型的寄存器(MSRs)启用和配置,以下是这些寄存器的详细信息。关于配置MSR行为的一些注意事项:
(1)如果处理器不支持Intel Processor Trace(请参阅第32.3.1节),对IA32_RTIT_* MSRs的RDMSR或WRMSR将引发#GP异常。
(2)在启用数据包生成(IA32_RTIT_CTL.TraceEn=1)的情况下,对任何IA32_RTIT_*配置MSR的WRMSR将生成#GP异常。在更改配置MSR之前,必须禁用数据包生成。
注意:即使TraceEn=1,软件也可以将相同的值写回IA32_RTIT_CTL而不会引发#GP异常。
(3)Intel PT的所有配置MSR对于每个逻辑处理器都是重复的。
(4)对于每个配置MSR,任何尝试更改标记为保留位或使用标记为保留编码的MSR写操作都会导致#GP故障。
(5)在热复位或冷复位时,清除所有Intel PT的配置MSR。

如果CPUID.(EAX=14H, ECX=0):EBX[位 2] = 1,则热复位仅清除TraceEn位;尽管这可能会清除IA32_RTIT_STATUS中的其他位。在热复位时,跟踪配置MSR的其他MSR值将被保留。
(6)在本章中,对跟踪配置MSR的MSR写操作的语义通常适用于对这些寄存器的显式WRMSR操作,使用VMexit或VM entry MSR加载列表到这些MSR,带有包括state_8的请求功能位图的XRSTORS(对应于IA32_XSS[位 8]),以及通过XSAVES对IA32_RTIT_CTL.TraceEn的写入(第32.3.5.2节)。

2.8.2 IA32_RTIT_CTL MSR

IA32_RTIT_CTL(位于地址570H)是用于数据包生成的主要启用和控制MSR。
表格省略

2.8.3 Enabling and Disabling Packet Generation with TraceEn

(1)
当TraceEn从0过渡到1时,将启用Intel Processor Trace,并可能生成一系列数据包。这些数据包有助于确保解码器在跟踪开始时了解处理器的状态,并能够跟踪在禁用数据包生成期间可能发生的任何时间或状态变化。如果IA32_RTIT_STATUS.PacketByteCnt=0,则会生成一个完整的PSB+(参见第32.4.2.17节),在其他情况下也可能生成PSB+。否则,将生成时间数据包,包括TSC、TMA和CBR(参见第32.4.1.1节)。

IA32_RTIT_CTL MSR寄存器:

PositionBit NameAt ResetBit Description
0TraceEn0If 1, enables tracing; else tracing is disabled.

除了上述讨论的数据包之外,如果PacketEn(第32.2.6.1节)从0过渡到1(根据过滤设置的不同可能会立即发生),将生成一个TIP.PGE数据包(第32.4.2.3节)。当设置TraceEn时,处理器可能会从内存中读取ToPA条目并将其在内部缓存。因此,软件在对ToPA表进行修改之前(或更改受限内存区域的配置)应禁用数据包生成。有关修改TraceEn时可能生成的其他数据包的详细信息,请参阅第32.7节。

(2)Disabling Packet Generation
清除TraceEn会导致逻辑处理器内部缓冲的任何数据包数据被刷新,此后输出MSRs(IA32_RTIT_OUTPUT_BASE和IA32_RTIT_OUTPUT_MASK_PTRS)将具有稳定的值。当输出定向到内存时,可能需要进行存储、屏障或架构序列化指令,以确保数据包数据在全局上被观察到。禁用数据包生成不会生成特殊的数据包,但如果在禁用时PacketEn=1,则可能会生成一个TIP.PGD数据包。

(3)Other Writes to IA32_RTIT_CTL
如果TraceEn已设置,则任何尝试修改IA32_RTIT_CTL的操作都会导致通用保护故障(#GP),除非相同的写操作也清除了TraceEn。然而,对于不修改任何位的IA32_RTIT_CTL的写操作不会引发#GP,即使TraceEn仍然设置。

2.8.4 IA32_RTIT_STATUS MSR

IA32_RTIT_STATUS MSR可以被软件读取和写入,尽管某些字段不能被软件修改。详见表格32-7。在WRMSR指令中,源操作数中的这些位将被忽略(尝试修改这些位将被忽略,不会导致WRMSR引发故障)。

只有在IA32_RTIT_CTL.TraceEn为0时才能写入此MSR;否则,WRMSR会引发通用保护故障(#GP)。在TraceEn为0时,处理器不会修改此MSR的值(软件可以使用WRMSR进行修改)。

表格省略

2.8.5 IA32_RTIT_ADDRn_A and IA32_RTIT_ADDRn_B MSRs

IA32_RTIT_ADDRn_A/B寄存器对应于IA32_RTIT_CTL中的相应ADDRn_CFG字段(参见第32.2.8.2节),其作用由这些字段决定。这些寄存器对的数量由CPUID.(EAX=14H, ECX=1):EAX.RANGECNT[2:0]枚举。

(1)支持1个范围的处理器支持:
IA32_RTIT_ADDR0_A, IA32_RTIT_ADDR0_B

(2)支持2个范围的处理器支持:
IA32_RTIT_ADDR0_A, IA32_RTIT_ADDR0_B
IA32_RTIT_ADDR1_A, IA32_RTIT_ADDR1_B

(3)支持3个范围的处理器支持:
IA32_RTIT_ADDR0_A, IA32_RTIT_ADDR0_B
IA32_RTIT_ADDR1_A, IA32_RTIT_ADDR1_B
IA32_RTIT_ADDR2_A, IA32_RTIT_ADDR2_B

(4)支持4个范围的处理器支持:
IA32_RTIT_ADDR0_A, IA32_RTIT_ADDR0_B
IA32_RTIT_ADDR1_A, IA32_RTIT_ADDR1_B
IA32_RTIT_ADDR2_A, IA32_RTIT_ADDR2_B
IA32_RTIT_ADDR3_A, IA32_RTIT_ADDR3_B
每个寄存器都有一个单独的64位字段,用于存储线性地址值。写操作必须确保地址处于规范形式,否则会引发通用保护故障(#GP)。

每个MSR只能在IA32_RTIT_CTL.TraceEn为0时写入;否则,WRMSR会引发通用保护故障(#GP)。

2.8.6 IA32_RTIT_CR3_MATCH MSR

当IA32_RTIT_CTL.CR3Filter为1时,IA32_RTIT_CR3_MATCH寄存器与CR3进行比较。位63:5存储要匹配的CR3地址值,位4:0保留为0。有关CR3过滤和此寄存器的处理的更多详细信息,请参见第32.2.5.2节。

如果CPUID.(EAX=14H, ECX=0):EBX[bit 0],“CR3 Filtering Support”为1,则可以访问此MSR。只有当IA32_RTIT_CTL.TraceEn为0时,才能写入此MSR;否则,WRMSR会引发通用保护故障(#GP)。IA32_RTIT_CR3_MATCH[4:0]是保留位,必须为0;尝试使用WRMSR设置这些位会引发#GP。

2.8.7 IA32_RTIT_OUTPUT_BASE MSR

此MSR用于配置跟踪输出目的地,当输出定向到内存时(IA32_RTIT_CTL.FabricEn = 0)。地址字段的大小由CPUID.80000008H:EAX[7:0]报告的最大物理地址宽度(MAXPHYADDR)确定。

当使用ToPA输出方案时,处理器在启用数据包生成时可能会更新此MSR,并且这些更新与指令执行是异步的。因此,除非禁用数据包生成(IA32_RTIT_CTL.TraceEn = 0),否则此MSR中的值应被视为不可靠。

只有在支持将Intel PT输出到内存时才支持访问此MSR,即当CPUID.(EAX=14H, ECX=0):ECX[bit 0]或CPUID.(EAX=14H, ECX=0):ECX[bit 2]设置时。否则,WRMSR或RDMSR会引发通用保护故障(#GP)。如果支持,只能在IA32_RTIT_CTL.TraceEn为0时写入此MSR;否则,WRMSR会引发通用保护故障(#GP)。

表格省略

2.8.8 IA32_RTIT_OUTPUT_MASK_PTRS MSR

此MSR保存了指示下一个跟踪输出字节应写入的任何掩码或指针值。此MSR中保存的值的含义取决于是否使用ToPA输出机制。请参见第32.2.7.2节获取详细信息。

处理器在启用数据包生成时更新此MSR,这些更新与指令执行是异步的。因此,除非禁用数据包生成(IA32_RTIT_CTL.TraceEn = 0),否则此MSR中的值应被视为不可靠。

只有在支持将Intel PT输出到内存时才支持访问此MSR,即当CPUID.(EAX=14H, ECX=0):ECX[bit 0]或CPUID.(EAX=14H, ECX=0):ECX[bit 2]设置时。否则,WRMSR或RDMSR会引发通用保护故障(#GP)。如果支持,只能在IA32_RTIT_CTL.TraceEn为0时写入此MSR;否则,WRMSR会引发通用保护故障(#GP)。

文章来源:https://blog.csdn.net/weixin_45030965/article/details/135596894
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。