有人在瑞芯微的 RK35xx 平台上遇到过缓存一致性问题吗?

22 天前
villivateur  villivateur

最近我一个项目涉及这个平台的内核开发。内核有两个线程,使用 wait_event 进行通讯,有大约万分之一的概率,事件发送方设置事件后,接收方获取不到状态。

类似这个问题: https://stackoverflow.com/questions/23262893/wait-event-timeout-exits-on-timeout-with-condition-set

如果我把两个线程绑定到同一个 CPU 核心上,问题就消失了。

之前我搞这个平台的 AMP 架构的时候,也出现过裸机核心与 Linux 核心缓存不一致的问题。

945 次点击
所在节点   问与答  问与答
14 条回复
cnnblike
cnnblike
22 天前
https://developer.arm.com/documentation/100941/0101/Memory-attributes
内存一致性看这个,一般说来是不在一个 cluster 的时候容易遇到这个

做 amp 的话,内核态 解决方案 https://developer.arm.com/documentation/ddi0500/e/system-control/aarch32-register-summary/c7-system-operations?lang=en

做进程通信的话,整个 core affinity ,或者弄个 memory-barrier 应该也行
cnnblike
cnnblike
22 天前
villivateur
villivateur
22 天前
@cnnblike 不在一个 cluster 的情况,按我的理解,应该非常容易出现缓存不一致,而不是极低的概率出现。AMP 的方案我现在也不干了,只是提一嘴。另外 wait_event 相关的内核 API 是自带内存屏障的,理论上不需要手动加。
cnnblike
cnnblike
22 天前
@villivateur 不在一个 cluster 的情况不大可能说实话,你直接说 rk 什么型号吧
https://linaro-dev.linaro.narkive.com/f2kFnMmW/why-is-the-the-smp-mb-in-arm64-s-barrier-h-dmb-ish
”In Arm V8 Architecture Reference Manual£¬there is an example (see beblow) to explain the shareability attribute of clusters. It is easy to know: each cluster is corresponding to a Inner shareable domain; the two cluster comprise a Outer shareable domain.“
cnnblike
cnnblike
22 天前
如果是 rk3568 或者是 rk3566 上的核间通信,因为内存不一致触发问题说实话可能性很低,按 arm 的定义(和推荐实现),单一一个 cluster 的所有核都在同一个 innershareable 上,理论上 cluster 内所有核能看到的,都是一样的。
如果是 rk3588 ,那是有可能的,我猜你把一个小核分出来跑 amp ,或者干脆是在 cortex-m 核上跑 amp 通信,那就触发缓存不一致了
villivateur
villivateur
22 天前
@cnnblike 目前这个问题,出在 RK3588 上,是 SMP 架构,全部 8 个核心都是 Linux 。但你这么一说我开始怀疑是大小核的问题,我要去验证下看看如果两个线程都跑在小核或者都跑大核,看看还有没有问题。

另外,之前我在 RK3568 上面跑 AMP ,是 core 3 裸核,开了一块内存,core3 往里面写数据,Linux 核心(另外三个核)读不到,必须 Linux 先写一下这块内存才能读到
ivan_wl
ivan_wl
22 天前
看下反汇编是不是有内存屏障指令,触发 event 前应该是 dmb ishst ,另外一个 cpu 在被唤醒后应该先做 dmb ishld
cnnblike
cnnblike
22 天前
@villivateur
内存段和 shareable 的设置和 tlb 有关系,在内核的 mm 那块的逻辑里,具体说是 The arch/arm64/mm/cache-*.S 和 arch/arm64/mm/proc-*.S
还有一个可能性,我不知道你是用 mem=xxx MB 设置的内存还是用 reversed_memory 设置的内存,所以可能行为会有不同。

如果你用的 jailhouse 的话,他那个实现对大小 cluster 的支持可能是不对的,看此处注释:
https://github.com/siemens/jailhouse/blob/master/hypervisor/arch/arm64/entry.S#L453-L458
cnnblike
cnnblike
22 天前
@villivateur 我最近也在研究这块,有兴趣的话,记得把结论也发我一下
cnnblike
cnnblike
22 天前
我仔细分析了一下你遇到的问题,感觉像是这样:
1. rk3588 这个问题是应该是因为那个页面被设置成了 write-back 而不是 write-through ,由于是闲时写,所以在你系统的内存总线空闲的时候会写入,然后叠加 wb 会在写入的时候刷 L1 ,更新另一个 cluster 的 L2 ,所以显得触发概率低,所以我建议你跑一个高内存总线开销的用户态程序,应该能让任务出问题

2. rk3568 的场合,你的页表上对这个页面可能没设置 SH ,看这里 https://zhuanlan.zhihu.com/p/532838098
villivateur
villivateur
22 天前
@cnnblike 嗯,有道理,对于内存管理我也还没入门,目前正在复现不同核心的现象,复现很耗时,我有进展了 @你
villivateur
villivateur
20 天前
@cnnblike 这两天验证了一下该问题与大小核的关系。复现情况是:两个线程都在大核或者都在小核,暂时没有复现问题。如果一个大核一个小核,就可以复现。
cnnblike
cnnblike
20 天前
@villivateur https://docs.kernel.org/driver-api/device-io.html
看一下这个,你需要的可能是 ioremap 或者 ioremap_nc
cnnblike
cnnblike
20 天前
正确的做法可能是用 memremap ,用 dts+memremap 这样的形式会比较好点:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841683/Linux+Reserved+Memory

memremap(r.start, resource_size(&r), MEMREMAP_WT);

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1115385

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX