coherent memory在TF-A中应该怎么用?

前面应该知道了coherent memory是什么东西。不知道的看看下面两个链接:

https://wwwblogs/pdev/p/12004697.html

https://zhuanlan.zhihu/p/21387258

当多个CPU访问具有不匹配的可共享性、可缓存性和内存属性的物理内存时,可能会失去一致性(有关更多详细信息,请参阅Arm Arm的B2.9节)。

当一致性、MMU和缓存以增量方式打开/关闭时,TF-A在加电/断电序列中会出现这种可能性。
TF-A将相干存储器定义为转换表中具有设备nnRE属性的存储器区域。TF-A中的翻译颗粒大小为4KB。这是相干存储区域的最小可能大小。

默认情况下,所有易受来自不同CPU的属性不匹配访问的数据结构都分配在一个一致的内存区域中(请参阅移植指南第2.1节)。相干内存区域访问是外部可共享的、不可缓存的,当MMU打开时,可以使用Device nnRE属性访问它们。因此,TF-A能够以至少一页额外内存为代价解决由于内存属性不匹配而导致的相干问题。

上述方法的另一种选择是在Normal WriteBack WriteAllocate内部可共享内存中分配易受影响的数据结构。这种方法要求设计数据结构,以便通过对其执行软件缓存维护来解决内存属性不匹配的问题。

1、禁止在TF-A中使用coherent memory(一致性内存)

可能需要避免在内存受限的平台上分配一致内存的成本。

TF-A允许通过构建标志USE_coherent_MEM在固件映像中包含coherent memory。默认情况下启用此标志。可以禁用选择上述第二种方法。

以下各节分析了在coherent memory区域中分配的数据结构以及在正常存储器中分配数据结构所需的更改。

2、PSCI实现中的一致内存使用

psci_non_cpu_pd_nodes数据结构存储平台的电源域树信息,用于电源域的状态管理。

默认情况下,此数据结构分配在TF-A中的coherent memory区域中,因为它可以由多个CPU访问,无论是启用还是禁用缓存。


为了将此数据结构移动到正常内存,必须分析其每个字段的使用情况。cpu_start_idx、ncpus、parent_node-level和lock_index等字段在冷启动期间只写入一次。因此,从相干内存中删除它们只需要在写入这些字段后对缓存行进行清理和使其无效。

local_state字段可以由处于不同缓存状态的多个CPU同时访问。Lamport’s Bakery锁psci_locks用于确保该字段的互斥性,并且在写入该字段后需要进行清理并使其无效。

2、互斥锁数据

互斥锁数据结构baker_lock_t分配在一致内存中,并由多个属性不匹配的CPU访问。baker_lock_t的定义如下:


Lamport的Bakery算法的一个特点是,每CPU的易失性字段可以被所有CPU读取,但只能被拥有的CPU写入。

根据数据缓存行大小,多个CPU的baker_lock_t结构的每CPU字段可能存在于单个缓存行上。这些每CPU字段可以在锁争用期间由具有不匹配内存属性的多个CPU读取和写入。

由于这些字段是锁实现的一部分,因此它们不能访问任何其他锁原语来防止由此产生的一致性问题。因此,简单的软件缓存维护不足以将它们分配到一致性内存中。考虑以下示例。

CPU0在启用数据缓存的情况下更新其perCPU字段。此写操作将更新本地缓存行,其中还包含其他CPU的字段副本。现在CPU1在禁用数据缓存的情况下更新baker_lock_t结构的perCPU字段。CPU1随后发出DCIVAC操作,以使系统中任何其他高速缓存行中其字段的任何过时副本无效。此操作也将使CPU0所做的更新无效。

要在禁用USE_COHERENT_MEM时使用互斥锁,已重新设计了锁数据结构。这些变化利用了前面提到的Lamport的Bakery算法的特点。baker_lock结构仅为单个CPU分配内存。宏DEFINE_BAKERY_LOCK将CPU所需的所有互斥锁锁分配到另一个互斥锁中。链接器通过使用为baker_lock部分分配的总大小并将其乘以(PLATFORM_CORE_COUNT-1)来为其他内核分配内存。这使得软件能够在锁数据结构上执行软件缓存维护,而不会遇到与不匹配属性相关的一致性问题。

互斥锁数据结构baker_info_t定义为在禁用USE_COHERENT_MEM时使用,如下所示:

baker_info_t表示一个锁的单个perCPU字段,系统中所有CPU的相应baker_info _t结构的组合表示完整的互斥锁。具有n个互斥锁的系统的内存视图如下:



考虑一个由2个CPU和“N”个互斥锁组成的系统,如上所示。对于Lock_N上的操作,需要获取CPU0和CPU1 bakery_Lock部分中对应的baker_info_t,并且需要为每次访问执行适当的缓存操作。

在Arm平台上,psci(psci_lock)和电源控制器驱动程序(Arm_lock)中使用互斥锁。

3、移除一致性内存的非功能影响

一致性内存区域的移除导致对受影响的数据结构执行缓存维护的额外软件开销。

然而,由于分配数据结构的内存是可缓存的,因此性能的提高主要减轻了开销。

然而,由于以下原因,互斥锁的性能会受到影响:

  • •额外的缓存维护操作,以及

  • •每个锁操作有多个缓存线读取,因为每个CPU的互斥锁分布在不同的缓存线上。

已对实现进行了优化,以最大限度地减少这一额外开销。测量表明,当互斥锁分配到普通内存中时,获取锁的最小延迟平均为3-4微秒,而在设备内存中,这一延迟为2微秒。测量是在Juno Arm开发平台上完成的。

如前所述,通过禁用USE_COHERENT_MEM,几乎可以节省一页内存。每个平台都需要考虑这些权衡,以决定是否应该使用一致性。如果平台禁用USE_COHERENT_MEM,并且需要在移植层中使用互斥锁,则可以选择定义宏PLAT_PERCPU_bakery_LOCK_SIZE(请参阅移植指南)。有关示例,请参阅参考平台代码。

更多推荐

ATF官方文档翻译(十三):ATF固件设计(Firmware Design)-coherent memory在TF-A中的应用