RISC-V SiFive U64内核——HPM硬件性能监视器

简介: RISC-V SiFive U64内核——HPM硬件性能监视器

对于性能分析,通常我们会使用Perf工具。而perf中的硬件事件,则需要硬件的支持——性能监视单元PMU。RISC-V u64内核支持PMU,使得我们可以通过perf来统计程序运行所产生的cycle、cache hit、cache miss等事件的次数,从而进一步分析、优化性能。

在SiFive U64内核中,把PMU称作HPM,实际是一个东西。另外,u64内核的hpm增加了一个新的特性——hpm计数溢出中断。

下面详细介绍SiFive U64的HPM。

HPM简介

HPM:Hardware Performance Monitor。U6 处理器内核支持基本的硬件性能监控 (HPM) 设施。性能监视工具分为两类计数器:固定功能计数器和事件可编程计数器。这些类包括一组固定计数器及其计数器使能寄存器,以及一组事件可编程计数器及其事件选择器寄存器。寄存器可用于控制计数器的行为。性能监控可用于多种用途,从优化到调试。

性能监控计数器重置行为

instret 和循环计数器在系统复位时被初始化为零。硬件性能监视器事件计数器不会在系统重置时初始化,因此具有任意值。用户可以将所需值写入计数器控制和状态寄存器 (CSR),以在给定的已知值开始计数。

固定功能性能监控计数器

一个固定功能的性能监视器计数器是硬件连接的,只计算一种特定的事件类型。也就是说,它们不能根据它们计数的事件类型进行重新配置。唯一的可以对固定功能性能监控计数器进行的修改是启用或禁用计数,并写入计数器值本身。

U6 处理器内核包含两个固定功能的性能监控计数器

Fixed-Function Cycle Counter (mcycle)

固定功能性能监控计数器 mcycle 保存自过去某个任意时间以来 hart 执行的时钟周期数的计数。mcycle 计数器是可读写的,64 位宽。读取 mcycle 返回 mcycle CSR 的所有 64 位。

Fixed-Function Instructions-Retired Counter (minstret)

固定功能性能监控计数器 minstret 保存 hart 自过去某个任意时间以来退役的指令数。minstret 计数器是可读写的并且是 64 位宽的。读取 minstret 返回 minstret CSR 的所有 64 位。

事件可编程性能监控计数器

一组可编程事件计数器与固定功能计数器相辅相成。U6 HPM 包括两个额外的事件计数器,mhpmcounter3mhpmcounter4。这些可编程事件计数器是可读写的,宽度为 64 位。硬件计数器本身在 U6 内核系列上实现为 40 位计数器。可以写入这些硬件计数器以初始化计数器值。

事件选择器寄存器

为了控制要计数的事件类型,事件选择器 CSR mhpmevent3 和 mhpmevent4 用于对相应的事件计数器进行编程。这些事件选择器 CSR 是 64 位 WARL 寄存器。

事件选择器分为三个字段;低 8 位选择一个事件类别,中间的一组位形成该类别中事件的掩码,高 8 位用于计数器溢出和事件过滤。

如果对应于任何设置掩码位的事件发生,则计数器递增。例如,如果 mhpmevent3 设置为 0x4200,则 mhpmcounter3 将在任一加载指令时递增或者条件分支指令退出。事件选择器 0 意味着“什么都不考虑”。

Counter Overflow and Event Filters

mhmpevent 寄存器的高 8 位用于控制计数器溢出中断,以及基于模式的事件过滤。位布局如下图所示:

Performance Counter Overflow Operation

当内核处于特权模式 x 时,五个 xINH 位中的每一个都禁止事件计数。这些字段中的所有零导致所有模式下的事件计数。

当相应的 hpmcounterX 溢出时,OF 位由硬件设置,并保持设置状态,直到被软件写入。由于 hpmcounter 值是无符号的,溢出被定义为从全一递增到全零。请注意,溢出后不会丢失信息,因为计数器环绕并继续计数,同时粘性 OF 位保持设置。

如果 hpmcounter 溢出而关联的 OF 位为零,则会生成计数溢出中断请求。如果 hpmcounter 溢出而关联的 OF 位为 1,则不会生成中断。因此,OF 位还用作相关 hpmcounter 的计数溢出中断禁用。

写入 mhpmcounterX 或 mhpmeventX 寄存器不会导致计数溢出。仅当事件导致计数器递增时才会发生溢出。

计数器溢出中断是一个标准的本地中断,对应于 mipmie 寄存器中的第 13。mip LCOFIP 位是这个中断和 mie 的中断挂起位LCOFIE 位是该中断的中断使能位。LCOFI 表示本地计数溢出中断。如果存在 S 模式,则 sip 和 sie 包括用于管理程序中断控制和状态的相应位。

hpmcounter 生成计数溢出中断请求会设置 mip 寄存器中的 LCOFIP 位并设置相关的 OF 位。如果存在 S 模式,则 mideleg 寄存器控制将此中断委托给 S 模式,这会设置 sip 寄存器中的 LCOFIP 位。在处理计数溢出中断后,LCOFIP 位由软件清零。

发往相同特权模式的多个同时中断按以下优先级递减顺序处理:MEI、MSI、MTI、SEI、SSI、STI、LCOFI。

请注意,没有单独的溢出状态和溢出中断使能位。实际上,通过清除 OF 位来启用溢出中断生成是与将计数器初始化为起始值一起完成的。一旦计数器溢出,它和 OF 位必须在产生另一个溢出中断之前重新初始化。

软件可以区分尚未被溢出中断处理程序服务的新溢出计数器和已经被服务的溢出计数器(或者通过维护反映哪些计数器处于活动状态和到期的位掩码配置为不在溢出时生成中断的计数器) 最终溢出。

Scountovf 寄存器

scountovf CSR 是一个 32 位只读寄存器,包含 29mhpmevent CSR 中 OF 位的影子副本。scountovf 中的位 X 对应于 mhpmeventX 中的 OF 位。该寄存器使主管级溢出中断处理程序软件能够快速确定哪些计数器已经溢出,而无需对 M 模式进行环境调用。 CSR 地址为 0xDA0。

对 scountovf 位 X 的读取访问受制于调解 S 模式软件对 hpmcounterX 访问的相同 mcounteren CSR。在 S 模式下,当设置 mcounteren 位 X 时,scountovf 位 X 是可读的,否则读为零。

Disabling Counters in Debug Mode

设置后,dcsr.stopcount 位会在调试模式下停止计数器。这对于 mcycle 和 minstret 计数器尤其重要,因为在调试模式下,核心在紧密循环中执行 ROM 指令。Freedom Studio Performance Monitor View 自动设置dcsr.stopcount 位。

事件选择器编码

表 20 描述了可用的事件选择器编码。根据 mhpmeventX[7:0] 中编码的事件类字段,将事件分类为类。可以通过为给定事件类别设置相应的事件掩码位来对一个或多个事件进行编程。事件选择器编码为 0 表示“无意义”。任何选定事件发生时,多个事件都会导致计数器递增。

对任何事件类可写的事件掩码位对所有类都是可写的。设置与表 20 中定义的事件不对应的事件掩码位对当前实现没有影响。但是,未来的实现可能会在该编码空间中定义新事件,因此不建议将不受支持的值编程到 mhpmevent 寄存器中。

Combining Events

直接计算每个事件是常见的用法。此外,可以使用这些事件的组合来计算新的、独特的事件。例如,要确定来自数据存储器子系统的每次加载的平均周期数,可以对一个计数器进行编程以计算“数据高速缓存/DTIM 繁忙”,并对另一个计数器进行编程以计算“已退出的整数加载指令”。然后,简单地将“数据高速缓存/DTIM 繁忙”周期计数除以“整数加载指令退休”指令计数,结果就是每条指令加载周期的平均周期时间。

了解组合的事件类型很重要;具体来说,事件类型计算发生次数,事件类型计算周期。

计数使能寄存器

32 位计数器使能寄存器 mcounterenscounteren 控制硬件性能监控计数器在下一个最低特权模式下的可用性。

这些寄存器中的设置仅控制可访问性。读取或写入这些启用寄存器的行为不会影响底层计数器,这些计数器在不可访问时会继续递增。

mcounteren 寄存器中的任何位清零时,在 S 模式下执行时尝试读取周期、时间、指令退出或 hpmcounterX 寄存器将导致非法指令异常。当这些位中的一个被设置时,在下一个实现的特权模式 S 模式下允许访问相应的寄存器。

在 U 模式下执行时,scounteren 寄存器中的相同位位置类似地控制对这些寄存器的访问。如果允许 S-mode 访问计数器寄存器并且在 scounteren 中设置了相应的位,则也允许 U-mode 访问该寄存器。

mcounterenscounteren 是 WARL 寄存器。任何位都可能包含硬连线值零,表示在低特权模式下执行时,读取相应计数器将导致非法指令异常。

end

猜你喜欢

RISC-V SiFive U64内核——L2 Prefetcher预取器

RISC-V SiFive U54内核——PMP物理内存保护

RISC-V SiFive U54内核——PLIC平台级中断控制器

RISC-V SiFive U54内核——CLINT中断控制器

RISC-V SiFive U54内核——中断和异常详解

系统明明有很多内存,却无法分配出一片大块内存?

实战 | RISC-V Linux入口地址2M预留内存优化

RISC-V Linux启动之页表创建分析

RISC-V Linux汇编启动过程分析

RISC-V 入门笔记(新手必看!)

教你在QEMU上运行RISC-V Linux

OpenSBI三种固件的区别

写给新手的MMU工作原理

内核调试之devmem直接读写寄存器

相关文章
|
6月前
|
缓存 Linux 调度
操作系统-CPU粘合
操作系统-CPU粘合
68 0
|
Linux 索引 Perl
zynq操作系统: Linux驱动开发Bram篇
zynq操作系统: Linux驱动开发Bram篇
1100 0
|
6天前
|
算法 调度 C语言
探索操作系统的心脏:内核与用户空间的交互
【10月更文挑战第36天】本文将深入探讨操作系统的核心组件—内核,以及它如何与用户空间进行交互。我们将通过浅显易懂的语言和生动的例子来揭示这一复杂主题的面纱。文章不仅涉及理论知识,还会展示具体的代码示例,帮助读者更好地理解内核机制。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供新的视角和深入的理解。
|
19天前
|
存储 Linux 调度
探索操作系统的心脏:内核设计与实现
【10月更文挑战第23天】在这篇文章中,我们将深入探讨现代操作系统的核心—内核。通过浅显易懂的语言和实例,本文旨在揭示操作系统内核的设计哲学、关键组件以及它们如何协同工作以支持复杂的系统功能。无论你是初学者还是有一定基础的开发者,本篇文章将为你打开一扇了解操作系统深层工作原理的大门。
36 8
|
3月前
|
算法 调度 Python
探索操作系统核心:一个简单的进程调度模拟器
【8月更文挑战第31天】在这篇文章中,我们将通过构建一个简单的进程调度模拟器来揭开操作系统调度算法的神秘面纱。通过模拟FIFO(先进先出)、RR(轮转)和优先级调度算法,我们将理解它们如何影响系统性能。文章将使用Python代码示例来展示这些概念,旨在让读者通过动手实践获得深刻的认识,而不仅仅是理论学习。
|
2月前
|
存储 安全 算法
探索操作系统的心脏:内核技术与架构
本文深入探讨了现代操作系统中至关重要的部分——内核。通过分析其功能、架构以及在系统性能和稳定性中的作用,揭示了内核技术背后的复杂性及其对操作系统整体表现的影响。我们将从基本概念入手,逐步深入到内核的具体实现细节,旨在为读者提供一个全面而清晰的理解框架。
|
5月前
|
存储 算法 网络安全
操作系统的心脏:内核
本文深入探讨了操作系统中最为关键的组成部分——内核。我们将通过一个独特的视角,即内核作为操作系统的“心脏”,来分析其功能、结构以及它如何与系统的其他部分协同工作。不同于常规的技术文章摘要,我们不列出关键点或总结,而是邀请读者跟随我们的思考脉络,一起揭开内核的神秘面纱。
|
6月前
|
Linux 存储控制器
微处理器移植Linxu
微处理器移植Linxu
25 0
|
缓存 监控 Linux
RISC-V SiFive U64内核——L2 Prefetcher预取器
RISC-V SiFive U64内核——L2 Prefetcher预取器
|
存储 Linux 内存技术