闲话

前段时间过年,忙得有段时间没更新blog了,工作上的待解决的问题看似越堆越多,也没有静下心来整理。Now,新的一年,新的开始,继续努力吧!

这段时间遇到了新的问题:在ARM64环境中的alignment fault,之前没有关注过类似的问题,对ARM架构也没有深入研究过,从前都是在X86上,好像从来没遇到过类似的问题,呵呵,特此做了一下研究。

问题现象

Xorg启动失败,报错:

kernel: Unhandled fault: alignment fault (0x92000061) at 0x0000007f855de000

对齐异常?

看了下相关内核代码,就是发生了alignment fault,也叫对齐异常。

什么是对齐异常?

简单来说,当CPU访问内存地址时,如果发现访问的地址是不对齐的,硬件(部分)就会自动触发对齐异常。

什么叫不对齐?

简单来说,就是被访问的地址没有满足其数据类型的位宽要求,就叫不对齐,比如要访问一个4字节int型的数据,但是提供的地址不是4字节对齐的,那就是不对齐了。也就是说要访问的数据的位宽长度是多少,那么访问的地址就必须是按这个位宽长度对齐的。如果是char类型的,那就没有没有对齐要求了。

X86没有?

为什么X86上没有(极少)见过这种异常呢,因为X86硬件会自动处理这种情况,使其支持不对齐访问,但这肯定是要影响效率的。

是什么引起的?

通常是由于用户编写的代码中,没有进行对齐(padding)处理,比如进行指针类型转换,或者关闭掉了编译器的padding功能。

问题原因

就我遇到的这个问题而言,问题的原因就比较复杂了,这里就不详细描述了。总结来说,是因为我的ARM64环境中内核的TTM模块,在分配内存时,使用了device类型的内存,同时,在用户态的代码中使用了memset接口,memset的glibc实现由于性能需要,使用了DC ZVA指令,而Arm64架构中,DC ZVA指令不能用于device类型的内存,否则就会触发对齐异常。

解决方案

1.修改用户代码,对应device类型的内存,不使用glibc标准的memset接口,而自己实现相应的memset。

2.修改glibc库中的memset实现,不使用DC指令,当然结果是性能损失。

3.修改用户代码,想办法将device类型的内存访问都弄成对齐的。