Category Archives: 体系结构

x32 ABI

kernel 3.4发布了,其中一个更新是加入对x32 ABI的支持。

与此前曾介绍的armel与armhf关系一样,x32并不是intel处理器的一种新架构,而是在intel 64位处理器上(也许将来也会用到ARM上?)的一种二进制程序调用规范。它的主要想法是:

在64位处理器上,所有的指针自然也应该是64位的,但很多应用程序在运行时并不需要超过4GB的内存,因此64位的指针是浪费的。这些浪费体现在程序大小上、程序运行后可执行代码占用的内存上,当然这些都是相对来说不必考虑的,但从CPU cache的角度考虑,64位的指针和32位的指针,对本来容量就很小的cache就意义重大了。从逻辑上,32位指针应该可以让cache缓存更多内容,并且在一致性维护上的开销更小。

但如果在64位CPU上纯粹地以兼容模式跑32位程序,又无法充分利用64位CPU的一些特性,例如更大的寄存器、更快的函数参数传递、更快的浮点运算、更快的syscall等。

因此,出现了x32这种折中。与armhf类似,它的改动也很简单:在x64 ABI基础上,将指针全部改为32位。

一份性能测试结果如下(完整介绍在这里):

On Core i7 2600K 3.40GHz:
Improved SPEC CPU 2K/2006 INT geomean by 7-10% over ia32 and 5-8% over Intel64.
Improved SPEC CPU 2K/2006 FP geomean by 5-11% over ia32.
Very little changes in SPEC CPU 2K/2006 FP geomean, comparing against Intel64.
Comparing against ia32 PIC, x32 PIC:
Improved SPEC CPU 2K INT by another 10%.
Improved SPEC CPU 2K FP by another 3%.
Improved SPEC CPU 2006 INT by another 6%
Improved SPEC CPU 2006 FP by another 2%.

作为一种独立于编译工具和应用程序的通用优化方法,这种改进的效果可以说是非常显著而有价值的。

虽然说起来简单,但实际要做的工作并不少。因为这两种调用约定在二进制级别并不能兼容,从armel到armhf迁移的经验来看,需要的工作应该是:开发工具链、内核支持和迁移、公用代码库迁移、常用软件迁移等。这一次kernel的更新,应该是指第二步已经完成了。

linux社区在armhf和x32这两种新的ABI上的动作,给我两种感觉:从小的来说,随着编译优化的不断前进,以往忽略的ABI可能是性能的瓶颈,在这方面是否还有进一步修改优化的余地?从大的看,ABI这种已经形成实施标准的东西,居然也是可以迁移和并存的,考虑另一些领域,例如网络、例如总线,在广泛应用的事实标准存在的情况下,有没有可能出现新的更优方案?以往总认为代价太大而不值得,但现在这两件事提供了参考。

关于armhf (hard-float ABI for ARM)

armhf是什么

在Ubuntu 12.04和Debian里,除了arm, armel,还出现了一个名为armhf的版本。这个东西是什么?

众所周知,armel是目前主要的ARM ABI。armhf则是armel的一个变种,主要区别在浮点计算上。

在armel中,关于浮点数计算的约定有三种。以gcc为例,对应的-mfloat-abi参数值有三个:soft,softfp,hard。soft是指所有浮点运算全部在软件层实现,效率当然不高,适合于早期没有浮点计算单元的ARM处理器;softfp是目前armel的默认设置,它将浮点计算交给FPU处理,但函数参数的传递使用通用的整型寄存器而不是FPU寄存器;hard则使用FPU浮点寄存器将函数参数传递给FPU处理。

需要注意的是,在兼容性上,soft与后两者是兼容的,但softfp和hard两种模式不兼容。默认情况下,armel使用softfp,因此将hard模式的armel单独作为一个abi,称之为armhf。

价值

使用softfp模式,会存在不必要的浮点到整数、整数到浮点的转换。而使用hard模式,在每次浮点相关函数调用时,平均能节省20个CPU周期[1]。对ARM这样每个周期都很重要的体系结构来说,这样的提升无疑是巨大的。

在完全不改变源码和配置的情况下,在一些应用程序上,使用armhf能得到20——25%的性能提升[2]。对一些严重依赖于浮点运算的程序,更是可以达到300%的性能提升[3]。

使用

armhf的开启需要硬件的支持,在Debian的wiki上要求ARMv7 CPU、Thumb-2指令集以及VFP3D16浮点处理器[4]。

在gcc的编译参数上,使用-mfloat-abi=hard -mfpu=vfp即可。

在工具上,CodeSourcery最早支持hard模式。也可已自己编译工具链[5]。

Continue reading

AAPCS笔记

AAPCS全称Procedure Call Standard for the ARM Architecture,是ARM架构下应用程序例程调用的二进制接口规范。它的前身是著名的ATPCS。

这个规范的目的是使不同程序模块可以分别编译,在二进制级别直接配合使用。目前ARM编译器均采用了这一标准。因此,当在ARM架构进行调试、逆向工程、漏洞分析、病毒分析时,如果对这些调用规范比较熟悉,就能快速识别出函数调用、参数和返回值等,提高效率。

Continue reading