4

假设我正在修改内存映射 I/O 寄存器中的一些位,并且另一个进程或 ISR 可能正在修改同一寄存器中的其他位。

ldrex 和 strex 可以用来防止这种情况吗?我的意思是,他们原则上可以,因为您可以 ldrex,然后更改位,然后将其返回,如果 strex 失败,则意味着另一个操作可能已经更改了 reg,您必须重新开始。但是 strex/ldrex 机制可以用在不可缓存的区域吗?

我在树莓派上试过这个,I/O 寄存器映射到用户空间,ldrex 操作给了我一个总线错误。如果我将 ldrex/strex 更改为简单的 ldr/str,它可以正常工作(但不再是原子的......)此外,ldrex/strex 例程在普通 RAM 上也可以正常工作。指针是 32 位对齐的。

那么这是 strex/ldrex 机制的限制吗?还是 BCM2708 实现的问题,或者内核设置它的方式?(或者别的什么——也许我把它映射错了)?

4

4 回答 4

4

谢谢你提到我...

您不要在资源本身上使用 ldrex/strex 对。像 swp 或 test and set 或您的指令集支持的任何东西(对于 arm,它是 swp,最近是 strex/ldrex)。您在 ram 上使用这些说明,这是所有相关方都同意的一些 ram 位置。共享资源的进程使用内存位置来争夺对资源的控制权,无论谁获胜,然后才能实际寻址资源。您永远不会在外围设备本身上使用 swp 或 ldrex/strex,这是没有意义的。我可以看到内存系统没有给你一个专有的好的响应(EXOKAY),这是你摆脱 ldrex/strex 无限循环所需要的。

您有两种共享资源的基本方法(也许更多,但这里有两种)。一个是你使用这个共享内存位置和共享资源的每个用户,争夺对内存位置的控制权。当您获胜时,您可以直接与资源交谈。完成后放弃对共享内存位置的控制。

另一种方法是您只允许一个软件与外围设备通信,其他任何软件都不允许与外围设备通信。任何希望在外围设备上做某事的人都要求一个资源为他们做这件事。就像每个人都可以共享汽水机,而汽水机在柜台后面,只有汽水机员工才能使用汽水机。然后你需要一个计划,要么让人们排队,要么让人们拿一个号码并被叫来装满他们的饮料。除了与外围设备通信的单一资源外,您还必须提出一个方案,例如 fifo,以本质上使请求串行化。

这些都在荣誉系统上。您期望没有其他人与不应该与外围设备交谈的外围设备交谈,或者没有赢得与外围设备交谈的权利的人。如果您正在寻找硬件解决方案来阻止人们与之交谈,那么,使用 mmu,但现在您需要管理谁赢得了锁以及他们如何让 mmu 畅通无阻(不使用荣誉系统)并重新阻止以某种方式

在您可能有一个中断处理程序和一个共享资源的前台任务的情况下,您有一个或另一个可以接触资源,而另一个请求请求。例如,资源可能是中断驱动的(例如串行端口),并且您让中断处理程序直接与串行端口硬件对话,如果应用程序/前台任务想要完成某些事情,它会填写请求(将某些内容放入fifo/buffer) 中断然后查看请求队列中是否有任何内容,如果有,则对其进行操作。

当然有,禁用中断和重新启用关键部分,但如果你想让你的中断有一些时间/延迟的概念,这些是可怕的......了解你在做什么,它们可以用来解决这个应用程序+ isr 两个用户问题。

非缓存内存空间上的 ldrex/strex:

我的 extest 可能有更多关于何时可以使用和不能使用 ldrex/strex 的文本,不幸的是,arm 文档在这方面并不是那么好。他们告诉你停止使用 swp,这意味着你应该使用 strex/ldrex。但是然后切换到硬件手册,它说您不必支持单处理器系统上的独占操作。这说明了两件事,ldrex/strex 用于多处理器系统,并用于在多处理器系统上的处理器之间共享资源。这也意味着单处理器系统不一定支持 ldrex/strex。然后它变得更糟。ARM 逻辑通常停在处理器内核的边缘,L1 高速缓存包含在此边界内,它不在 axi/amba 总线上。或者,如果您购买/使用 L2 缓存,则 ARM 逻辑会在该层的边缘停止。然后你进入芯片供应商特定的逻辑。这就是您阅读硬件手册的逻辑,因为它说您不需要支持单处理器系统上的独占访问。所以问题是特定于供应商的。更糟的是,到目前为止,我发现 ARM 的 L1 和 L2 缓存确实支持 ldrex/strex,所以如果你有缓存,那么 ldrex/strex 将在供应商代码不支持它们的系统上工作。如果您没有缓存,那么当您在这些系统上遇到麻烦时(那是我写的最重要的东西)。所以如果你有缓存,那么 ldrex/strex 将在供应商代码不支持它们的系统上工作。如果您没有缓存,那么当您在这些系统上遇到麻烦时(那是我写的最重要的东西)。所以如果你有缓存,那么 ldrex/strex 将在供应商代码不支持它们的系统上工作。如果您没有缓存,那么当您在这些系统上遇到麻烦时(那是我写的最重要的东西)。

具有 ldrex/strex 的处理器足够新,可以通过 copressor 读取访问大量配置寄存器。埋在里面有一个“支持swp指令”位来确定你是否有交换。cortex-m3的人没有遇到没有swap和没有ldrex/strex的情况吗?

linux内核中的错误(还有许多其他对arm硬件和文档的误解)是在支持ldrex / strex的处理器上选择ldrex / strex解决方案而不确定它是否是多处理器,所以你可以(我知道两个实例)进入一个无限的 ldrex/strex 循环。如果您修改 linux 代码以使其使用 swp 解决方案(两种解决方案都有代码),它们 linux 将工作。为什么我所知道的互联网上只有两个人谈论过这个问题,因为你必须关闭缓存才能让它发生(据我所知),谁会关闭两个缓存并尝试运行 linux?成功关闭缓存实际上需要相当多的工作,需要对 linux 进行修改才能使其正常工作而不会崩溃。

不,我不能告诉你系统,不,我现在不知道,也从未为 ARM 工作过。如果您知道在哪里查找以及如何解释这些内容,那么这些内容都在 arm 文档中。

于 2013-04-14T05:36:58.727 回答
4

与之前的答案状态一样,ldrex/strex不是用于访问资源本身,而是用于实现保护它所需的同步原语。

但是,我觉得有必要在架构方面进行一些扩展:

  1. ldrex/ strex(读作 load-exclusive/store-exclusive)所有ARM 架构版本 6 及更高版本的处理器都支持,但不包括 M0/M1 微控制器 (ARMv6-M)。
  2. 在架构上不能保证 load-exclusive/store-exclusive 将在“Normal”以外的内存类型上工作 - 因此在外围设备上对它们的任何巧妙使用都不会是可移植的。
  3. 不建议反对该SWP指令,因为它的本质在多核系统中会适得其反——它在 ARMv6 中已被弃用,并且在某些 ARMv7-A 修订版中是“可选”实现的,并且大多数 ARMv7-A 处理器已经需要它在 cp15 中明确启用SCTLR。Linux 默认情况下不会,而是通过 undef 处理程序使用 ... load-exclusive 和 store-exclusive 模拟操作(@dwelch 在上面提到的内容)。因此,如果您希望代码可跨 ARMv7-A 平台移植,请不要推荐 SWP 作为有效的替代方案。

与不在内部共享域(您的缓存一致性岛)中的总线主控器同步需要额外的外部硬件 - 称为全局监视器- 以跟踪哪些主控器已请求独占访问哪些区域。

“在单处理器系统上不需要”位听起来像是 ARM 术语的阻碍。四核 Cortex-A15 被认为是一个处理器......因此在 Linux 中测试“单处理器”不会有任何区别 - 架构和互连规范保持不变,SWP 仍然是可选的,可能不会在场。

Cortex-M3 支持 ldrex/strex,但它的互连 (AHB-lite) 不支持传播它,因此它不能使用它与外部主设备同步。它不支持 SWP,从未在 Thumb 指令集中引入,其互连也无法传播。

于 2013-04-16T08:20:40.467 回答
3

通常,ldrex需要strex来自内存系统的支持。您可能希望参考dwelch的一些答案以及他的文本应用程序。我相信您不能对内存映射 I/O执行此操作。 并且更多地用于正常内存中的无锁算法。ldrexstrex

通常只有一个驱动程序应该负责一组I/O寄存器。软件将通过信号量等向驱动程序发出请求,这些信号量可以在普通 SDRAMldrex中实现。strex因此,您可以互锁这些I/O寄存器,但不是直接意义上的。

通常,I/O 寄存器将通过写一清除多路复用访问和其他方案来支持原子访问。

  1. 写一清除- 通常与硬件事件一起使用。如果代码处理该事件,则它只写入该位。这样,多个例程可以处理同一寄存器中的不同位。
  2. 多路复用访问- 通常中断启用/禁用将具有寄存器位图。但是,也有备用寄存器,您可以写入启用禁用特定寄存器的中断号。例如,intmask可能是两个 32 位寄存器。要启用int3,您可以屏蔽或仅写入1<<3寄存器。它们通过硬件连接到相同的位。intmask3intenableintmaskintenable

因此,您可以模拟与驱动程序的互锁,或者硬件本身可以通过正常的寄存器写入来支持原子操作。在人们开始谈论无锁和无等待算法之前,这些方案已经很好地服务了系统一段时间。

于 2013-04-14T03:51:11.777 回答
0

如果有问题的芯片有一个切换寄存器(在写入时基本上与输出锁存器进行异或运算),则可以解决。

  • 装载端口闩锁
  • 屏蔽不相关的位
  • xor 与所需的输出
  • 写入切换寄存器

只要两个进程不修改相同的引脚(而不是“相同的端口”),就没有竞争条件。

对于 bcm2708,您可以选择一个输出引脚,其相邻引脚要么未使用,要么从未更改,并以字节模式写入 GPFSELn。但是,这只会确保您不会腐蚀他人。如果其他人正在以 32 位模式写入并且您打断他们,他们仍然会破坏您。所以这是一种黑客行为。

希望这可以帮助

于 2015-07-27T20:01:44.750 回答