Generic timer

本文深入剖析了Linux在ARM平台上的通用定时器(generictimer)驱动,包括物理计数器和虚拟计数器的概念,以及在不同安全和虚拟化扩展场景下的timer配置。分析了timer的 CompareValue 和 TimerValue 寄存器功能,以及如何通过它们触发中断。此外,还讨论了在系统不支持协处理器访问时如何使用内存映射方式来访问定时器硬件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Reference: Linux时间子系统之(十七):ARM generic timer驱动代码分析 - ArnoldLu - 博客园 (cnblogs.com)


Timer其实就是定时器,它可以定义一段指定的时间,当时间到了,就会assert一个外部的输出信号

溢出时间    至少40年 ??? REF_CLK=25M/100M, 64bit gray code.能有40年?要算一下

  • 处理器可以通过CNTPCT寄存器来获取system counter的当前值,我们称之physical counter。
  • 有physical就有virtual,processor可以通过CNTVCT寄存器访问virtual counter
  • 对于不支持security extension和virtualization extension的系统,virtual counter和physical counter是一样的值。

每个processor都会附着多个timer 处理逻辑

(1)对于不支持security extension的SOC(不支持security extension也就意味着 不支持virtualization extension),timer实际上有两个,一个是physical timer,另外一个是virtual timer。虽然有两个,不过从行为上看,virtual timer和physical timer行为一致

(2)对于支持security extension但不支持virtualization extension的SOC,每个cpu有三个timer:Non-secure physical timer,Secure physical timer和virtual timer

(3)对于支持virtualization extension的SOC,每个cpu有四个timer:Non-secure PL1 physical timer,Secure PL1 physical timer,Non-secure PL2 physical timer和virtual timer

PL1是什么?

"

每个timer都会有三个寄存器(我们用physical timer为例描述):

(1)64-bit CompareValue register。该寄存器配合system counter可以实现一个64 bit unsigned upcounter。如果physical counter - CompareValue >= 0的话,触发中断。也就是说,CompareValue register其实就是一个64比特的upcounter,设定为一个比当前system counter要大的值,随着system counter的不断累加,当system counter value触及CompareValue register设定的值的时候,便会向GIC触发中断。

(2)32-bit TimerValue register。该寄存器配合system counter可以实现一个32 bit signed downcounter(有的时候,使用downcounter会让软件逻辑更容易,看ARM generic timer的设计人员考虑的多么周到)。开始的时候,我们可以设定TimerValue寄存器的值为1000(假设我们想down count 1000,然后触发中断),向该寄存器写入1000实际上也就是设定了CompareValue register的值是system counter值加上1000。随着system counter的值不断累加,TimerValue register的值在递减,当值<=0的时候,便会向GIC触发中断

(3)32-bit控制寄存器。该寄存器主要对timer进行控制,具体包括:enable或是disable该timer,mask或者unmask该timer的output signal(timer interrupt)

各个processor的各个Timer都可以产生中断,因此它和GIC有接口。当然,由于timer的中断是属于各个CPU的,因此使用PPI类型的中断,具体可以参考GIC文档。当然,如果让timer触发中断,当然要确保该timer是enable并且是umask的。

"

此外,有些系统不支持协处理的访问,这种情况下又想给系统增加ARM generic timer的功能,这时候必须使用memory mapped register的方式来访问ARM generic timer的所有硬件block(包括system counter和per cpu的timer)。这时候,在访问timer硬件的时候虽然性能不佳,但总是好过功能丧失。  utility bus?

### 关于Linux内核在ARMv8架构上的定时器实现及其问题 #### 定时器机制概述 Linux内核针对不同平台提供了多种类型的计时设施,对于ARMv8架构而言,其定时器功能依赖于体系结构特有的寄存器以及中断控制器的支持。具体来说,在ARMv8中存在物理定时器和虚拟定时器两种模式[^1]。 #### 物理定时器与虚拟定时器的区别 - **物理定时器**:用于裸机环境或者当CPU运行于非虚拟化状态时提供时间基准服务; - **虚拟定时器**:则是在启用虚拟化扩展的情况下供各客户操作系统使用的独立逻辑定时装置;两者共享相同的控制接口但是相互隔离互不影响[^3]。 #### 实现细节 为了适应不同的应用场景需求,Linux内核实现了通用的时间管理框架(timekeeping subsystem),该子系统能够自动检测并配置最适合当前处理器特性的计时源。对于ARMv8设备,默认情况下会选择使用集成到核心中的Generic Timer作为首选方案之一。 ```c static struct clocksource arm_arch_timer = { .name = "arch_sys_counter", .rating = 400, .read = arch_counter_get_cntvct, .mask = CLOCKSOURCE_MASK(56), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; ``` 这段代码展示了如何定义一个名为`arm_arch_timer`的clocksource对象来表示ARM架构下的系统计数器资源,并将其注册给内核以便后续利用它来进行高精度的时间测量操作。 #### 常见问题及解决方案 有时开发者可能会遇到诸如定时不准、丢失中断等问题。这可能是由于以下几个方面引起: - 配置错误:确保正确设置了相关寄存器位以激活所需的特性; - 中断优先级设置不当:检查IRQ/FIQ分配情况,调整至合理范围以免被其他更高优先生效的任务抢占执行权; - 虚拟化影响:如果是多租户环境下,则需特别注意宿主机与来宾OS间可能存在的干扰因素[^2]。 #### ARM官方文档支持 更详细的关于ARMv8架构下定时器的具体工作原理和技术参数可以在Arm官方网站找到相应的技术手册获取更多信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值