为什么__io_rmb() __io_wmb()使用的是dsb(ld/st)?dmb?

imx8 驱动中读写寄存器一般使用的api是readl和writel,因为imx8中控制器的寄存器是32bit,根据不同的芯片架构提供的寄存器宽度可以选择不同的api接口。注意笔者当前使用的内核版本是4.14.98。

本文要求读者对内存屏障有一定的了解,并且手边有一份内核代码。这样就可以立马查询文中的内容的真假.

1、readl,writel定义

#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })

#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); })

多核情况下为了保证数据的一致性,即为了让本cpu对寄存器的操作结果能够被其他cpu观察到,使用了对应的读写内存屏障进行同步,然后我们再看下__io_rmb(),__io_wmb()内存屏障的定义.

2、__io_rmb(),__io_wmb()定义

#define __iormb()   rmb()

#define __iowmb()  wmb()

#define rmb() dsb(ld)    //rmb之前的所有加载指令完成

#define wmb() dsb(st)  //wmb之前的所有存储指令完成

what? 层层展开后,使用的是dsb,数据同步指令。ARM V8指令集手册上关于dsb的定义如下:

Data Synchronization Barrier(dsb) acts as a special kind of memory barrier.No instruction in program order after this instruction executes until this instruction completes.This instruction completes when:

• All explicit memory accesses(显示内存访问) before this instruction complete(完成).

• All Cache, Branch predictor and TLB maintenance operations before this instruction complete(完成).

因为readl_relaxed/writel_relaxed内嵌汇编指令ldr,str数据加载和存储指令操作驱动控制器内部寄存器,显然是一个内存操作,应该使用dmb指令才对。

我们再看下手册中对dmb的定义:

Data Memory Barrier(dmb),acts as a memory barrier.It ensures that all explicit memory accesses that appear in program order before the DMB instruction are observed(被观察到) before any explicit memory accesses that appear in program order after the DMB instruction.It does not affect the ordering of any other instructions executing on the processor.(不影响处理上执行的任何其他指令的顺序).

通过对比dmb和dsb,最大的差异是,dsb强调的是complete(完成),内存访问的完成,cache,分支预测,TLB维护操作的完成。而且其范围更广。dmb强调的是对内存的加载/存储操作能够被其他CPU观察到即其他CPU能够看见本cpu内容的提交。

所以,笔者在看这段代码时总感觉不太对,用dsb没有毛病,但是总感觉把影响范围扩大了。

3、最新kernel中又是如何定义的呢?

于是,笔者下载了较新Linux内核版本,linux 6.4.7版本。

最新版本中定义如下:

 

#define __io_bw()        dma_wmb()


/* arm64-specific, don't use in portable drivers */
#define __iormb(v)        __io_ar(v)
#define __iowmb()        __io_bw()

__iormb,__iowmb 定义修改为使用 dma_rmb,dma_wmb.

我们再看下dma_rmb,dma_wmb的定义?

#define dma_rmb()   dmb(oshld)

#define dma_wmb()  dmb(oshst)

层层展开后,可以看见在最新的内核里面,已经将__iormb,__iowmb的内存屏障修改为dmb+osh+ld/st.

这里的oshld/st是什么意思?即使dmb指令的可选参数,我们把dmb的可选参数部分一起贴出来:

DMB:Data Memory Barrier(数据内存屏障).

Syntax:DMB{cond} {option}

where:

cond is an optional condition code.

option is an optional limitation on the operation of the hint. Permitted values are:

SY:Full system DMB operation. This is the default and can be omitted.(默认指令,可以忽略即dmb sy=dmb).

ST:DMB operation that waits only for stores to complete.(存储指令完成)

ISH:DMB operation only to the inner shareable domain.(内部共享域同步完成)

ISHST:DMB operation that waits only for stores to complete, and only to the inner shareable domain.(存储指令完成以及内部共享域同步完成)

NSH:DMB operation only out to the point of unification.

NSHST:DMB operation that waits only for stores to complete and only out to the point of unification.

OSH:DMB operation only to the outer shareable domain.

OSHST:DMB operation that waits only for stores to complete, and only to the outer shareable domain.

ish指的内部共享域,如多个核情况下,其他核能够看到dmb指令的影响。

osh指的外部共享域,如DMA,GPU等控制器也能够看到dmb指令的影响。

在linux6.4.7版本中使用dmb内存屏障指令,并且将其范围指定到osh,让DMA,GPU等SOC内部的控制器也能观察到寄存器的修改,如果它们想去观察的话。

4、总结

希望所有看到本篇文章的童靴能够不断进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值