问题描述
假设我正在修改内存映射 I/O 寄存器中的一些位,并且另一个进程或 ISR 可能正在修改同一寄存器中的其他位.
Suppose I'm modifying a few bits in a memory-mapped I/O register, and it's possible that another process or and ISR could be modifying other bits in the same register.
可以使用 ldrex 和 strex 来防止这种情况吗?我的意思是,他们原则上可以,因为您可以 ldrex,然后更改位,然后将其重新加载,如果 strex 失败,则意味着另一个操作可能更改了 reg,您必须重新开始.但是 strex/ldrex 机制可以用于不可缓存的区域吗?
Can ldrex and strex be used to protect against this? I mean, they can in principle because you can ldrex, and then change the bit(s), and strex it back, and if the strex fails it means another operation may have changed the reg and you have to start again. But can the strex/ldrex mechanism be used on a non-cacheable area?
我在树莓派上试过这个,I/O 寄存器映射到用户空间,ldrex 操作给我一个总线错误.如果我将 ldrex/strex 更改为简单的 ldr/str 它可以正常工作(但不再是原子的......)此外,ldrex/strex 例程在普通 RAM 上也能正常工作.指针是 32 位对齐的.
I have tried this on raspberry pi, with an I/O register mapped into userspace, and the ldrex operation gives me a bus error. If I change the ldrex/strex to a simple ldr/str it works fine (but is not atomic any more...) Also, the ldrex/strex routines work fine on ordinary RAM. Pointer is 32-bit aligned.
那么这是 strex/ldrex 机制的限制吗?或者 BCM2708 实现的问题,或者内核设置它的方式?(或其他东西 - 也许我映射错了)?
So is this a limitation of the strex/ldrex mechanism? or a problem with the BCM2708 implementation, or the way the kernel has set it up? (or somethinge else- maybe I've mapped it wrong)?
推荐答案
感谢你提到我...
不要在资源本身上使用 ldrex/strex 对.像 swp 或 test and set 或任何您的指令集支持的东西(对于 arm,它是 swp 和最近的 strex/ldrex).您在 ram 上使用这些说明,所有相关方都同意某些 ram 位置.共享资源的进程使用 ram 位置来争夺资源的控制权,无论谁获胜,都可以实际处理资源.您永远不会在外围设备本身上使用 swp 或 ldrex/strex,这是没有意义的.我可以看到内存系统没有给你一个专属的 OK 响应 (EXOKAY),这是你摆脱 ldrex/strex 无限循环所需要的.
You do not use ldrex/strex pairs on the resource itself. Like swp or test and set or whatever your instruction set supports (for arm it is swp and more recently strex/ldrex). You use these instructions on ram, some ram location agreed to by all the parties involved. The processes sharing the resource use the ram location to fight over control of the resource, whoever wins, gets to then actually address the resource. You would never use swp or ldrex/strex on a peripheral itself, that makes no sense. and I could see the memory system not giving you an exclusive okay response (EXOKAY) which is what you need to get out of the ldrex/strex infinite loop.
您有两种共享资源的基本方法(也许更多,但这里有两种).一个是你使用这个共享内存位置和共享资源的每个用户,争取对内存位置的控制.当您获胜时,您可以直接与资源交谈.完成后放弃对共享内存位置的控制.
You have two basic methods for sharing a resource (well maybe more, but here are two). One is you use this shared memory location and each user of the shared resource, fights to win control over the memory location. When you win you then talk to the resource directly. When finished give up control over the shared memory location.
另一种方法是您只允许一个软件与外围设备通信,其他人不得与外围设备通信.任何希望在外围设备上做某事的人都要求一个资源为他们做这件事.就像每个人都可以共享软饮料机,而软饮料机在柜台后面,只有软饮料机员工可以使用软饮料机.然后你需要一个计划,要么让人们排队,要么让人们拿一个号码,然后被叫来装满他们的饮料.除了与外围设备通信的单一资源外,您还必须提出一个方案,例如 fifo,以本质上使请求串行化.
The other method is you have only one piece of software allowed to talk to the peripheral, nobody else is allowed to ever talk to the peripheral. Anyone wishing to have something done on the peripheral asks the one resource to do it for them. It is like everyone being able to share the soft drink fountain, vs the soft drink fountain is behind the counter and only the soft drink fountain employee is allowed to use the soft drink fountain. Then you need a scheme either have folks stand in line or have folks take a number and be called to have their drink filled. Along with the single resource talking to the peripheral you have to come up with a scheme, fifo for example, to essentially make the requests serial in nature.
这些都在荣誉系统上.您期望没有其他人与不应该与外围设备交谈的外设交谈,或者没有赢得与外围设备交谈的权利的其他人.如果您正在寻找硬件解决方案来防止人们与它交谈,那么,使用 mmu,但现在您需要管理谁赢得了锁定以及他们如何解锁 mmu(不使用荣誉系统)并重新阻止以某种方式
These are both on the honor system. You expect nobody else to talk to the peripheral who is not supposed to talk to the peripheral, or who has not won the right to talk to the peripheral. If you are looking for hardware solutions to prevent folks from talking to it, well, use the mmu but now you need to manage the who won the lock and how do they get the mmu unblocked (without using the honor system) and re-blocked in a way that
在您可能有一个中断处理程序和一个共享资源的前台任务的情况下,您有一个或另一个可以访问资源,另一个请求请求.例如,资源可能是中断驱动的(例如串行端口),并且您让中断处理程序直接与串行端口硬件通信,如果应用程序/前台任务想要完成某事,它会填写一个请求(将某些内容放入fifo/buffer)中断然后查看请求队列中是否有任何内容,如果有则对其进行操作.
Situations where you might have an interrupt handler and a foreground task sharing a resource, you have one or the other be the one that can touch the resource, and the other asks for requests. for example the resource might be interrupt driven (a serial port for example) and you have the interrupt handlers talk to the serial port hardware directly, if the application/forground task wants to have something done it fills out a request (puts something in a fifo/buffer) the interrupt then looks to see if there is anything in the request queue, and if so operates on it.
当然有,禁用中断和重新启用临界区,但如果你想让你的中断有一些时间/延迟的概念,这些是可怕的......了解你在做什么,它们可以用来解决这个应用+isr 两个用户的问题.
Of course there is the, disable interrupts and re-enable critical sections, but those are scary if you want your interrupts to have some notion of timing/latency...Understand what you are doing and they can be used to solve this app+isr two user problem.
ldrex/strex 在非缓存内存空间上:
ldrex/strex on non-cached memory space:
我的 extest 可能有更多关于何时可以和不能使用 ldrex/strex 的文本,不幸的是 arm 文档在这方面不是很好.他们告诉您停止使用 swp,这意味着您应该使用 strex/ldrex.但是然后切换到硬件手册,它说您不必支持单处理器系统上的独占操作.这说明了两件事,ldrex/strex 用于多处理器系统,用于在多处理器系统上的处理器之间共享资源.这也意味着 ldrex/strex 在单处理器系统上不一定支持.然后情况变得更糟.ARM 逻辑通常停止在处理器内核的边缘,L1 缓存包含在此边界内,而不是在 axi/amba 总线上.或者,如果您购买/使用 L2 缓存,则 ARM 逻辑会在该层的边缘停止.然后你进入芯片供应商特定的逻辑.这就是你阅读硬件手册的逻辑,它说你不需要在单处理器系统上支持独占访问.所以问题是特定于供应商的.更糟糕的是,据我所知,ARM 的 L1 和 L2 缓存确实支持 ldrex/strex,所以如果您有缓存,那么 ldrex/strex 将在供应商代码不支持它们的系统上工作.如果您没有缓存,那么您就会在这些系统上遇到问题(这是我写的最详尽的内容).
My extest perhaps has more text on the when you can and cant use ldrex/strex, unfortunately the arm docs are not that good in this area. They tell you to stop using swp, which implies you should use strex/ldrex. But then switch to the hardware manual which says you dont have to support exclusive operations on a uniprocessor system. Which says two things, ldrex/strex are meant for multiprocessor systems and meant for sharing resources between processors on a multiprocessor system. Also this means that ldrex/strex is not necessarily supported on uniprocessor systems. Then it gets worse. ARM logic generally stops either at the edge of the processor core, the L1 cache is contained within this boundary it is not on the axi/amba bus. Or if you purchased/use the L2 cache then the ARM logic stops at the edge of that layer. Then you get into the chip vendor specific logic. That is the logic that you read the hardware manual for where it says you dont NEED to support exclusive accesses on uniprocessor systems. So the problem is vendor specific. And it gets worse, ARM's L1 and L2 cache so far as I have found do support ldrex/strex, so if you have the caches on then ldrex/strex will work on a system whose vendor code does not support them. If you dont have the cache on that is when you get into trouble on those systems (that is the extest thing I wrote).
具有 ldrex/strex 的处理器足够新,可以通过 copressor 读取访问大量配置寄存器.埋在有一个支持swp指令"位来确定您是否有交换.cortex-m3 的人没有遇到过没有交换和没有 ldrex/strex 的情况吗?
The processors that have ldrex/strex are new enough to have a big bank of config registers accessed through copressor reads. buried in there is a "swp instruction supported" bit to determine if you have a swap. didnt the cortex-m3 folks run into the situation of no swap and no ldrex/strex?
Linux 内核中的错误(还有许多其他错误以及对 arm 硬件和文档的其他误解)是在支持 ldrex/strex 的处理器上选择 ldrex/strex 解决方案时没有确定它是否是多处理器,所以你可以(我知道有两个实例)进入一个无限的 ldrex/strex 循环.如果您修改 linux 代码以使其使用 swp 解决方案(任何一种解决方案都有代码),它们 linux 将可以工作.为什么我所知道的互联网上只有两个人谈论过这个,因为你必须关闭缓存才能让它发生(据我所知),谁会关闭两个缓存并尝试运行 linux?成功关闭缓存实际上需要大量的工作,需要对 linux 进行修改才能使其正常工作而不会崩溃.
The bug in the linux kernel (there are many others as well for other misunderstandings of arm hardware and documentation) is that on a processor that supports ldrex/strex the ldrex/strex solution is chosen without determining if it is multiprocessor, so you can (and I know of two instances) get into an infinite ldrex/strex loop. If you modify the linux code so that it uses the swp solution (there is code there for either solution) they linux will work. why only two people have talked about this on the internet that I know of, is because you have to turn off the caches to have it happen (so far as I know), and who would turn off both caches and try to run linux? It actually takes a fair amount of work to succesfully turn off the caches, modifications to linux are required to get it to work without crashing.
不,我不能告诉你系统,不,我现在也不曾为 ARM 工作过.如果您知道在哪里查看以及如何解释它,那么这些内容都在 arm 文档中.
No, I cant tell you the systems, and no I do not now nor ever have worked for ARM. This stuff is all in the arm documentation if you know where to look and how to interpret it.
这篇关于ARM strex 和 ldrex 中的原子操作 - 它们可以在 I/O 寄存器上工作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!