32bit user @ 64 bit kernel
ARMv8支持64-bit 和32-bit所规范的层次结构
ARMv8arch overview-generalregister layout
Armv8架构下有31个通用寄存器(R0-R30),每个寄存器有64bit的位宽。访问方式:
当作64-bit寄存器来访问,命名为(X0-X30) 当作32-bit寄存器来访问,命名为(W0-W30) X30用来作为连接寄存器(LR), 用来保存调用子程序的返回地址或者异常返回地址. SP是专用堆栈指针寄存器,位宽64bit,用来保存当前处理器模式的堆栈的栈顶。 PC是程序计数器,位宽64bit,其内容是处理器要取的下一条指令的地址。Armv8软件上不能直接操作PC。 ARMv8arch overview-AddressTranslation l Usecompat_ioctl( ) but not onlyunlock_ioctl() in kernel driver lcompat_ioctl( ) :支持64bit的driver必须要实现的ioctl,当有32bit的userspace application call 64bit kernel的IOCTL的时候,这个callback会被调用到 lioctl参数和结构体一致性1. 数据类型 nILP32数据模型是32bit系统中用的最多的数据模型,在64bit系统中,用的比较多的就有两种LP64与LLP64。 nLP64主要用在linux系统上,而LLP64主要用在windows系统上,移植代码时需要注意数据类型在不同平台上的长度
Programming Type
ILP32
LP64(linux)
LLP64(windows)
char
8-bit
8-bit
8-bit
short
16-bit
16-bit
16-bit
int
32-bit
32-bit
32-bit
long
32-bit
64-bit
32-bit
long long
64-bit
64-bit
64-bit
float
32-bit
32-bit
32-bit
double
64-bit
64-bit
64-bit
size_t
32-bit
64-bit
64-bit
void * (pointer)
32-bit
64-bit
64-bit
intptr_t
32-bit
64-bit
64-bit
ptrdiff_t
32-bit
64-bit
64-bit
2. 类型转化
3. 高位截断
情形一:函数中如果需要精确地控制指针偏移时,有时候需要添加一个偏移量,处理时我们可能会选择先把指针转化为 int 或者 unsigned int 类型,这在 32bit 平台上是 OK 的,但在 64bit 平台上则会发生高位截断。强制类型转换会把高位数据丢 失 . 情形二:在分配一个对齐指针时,可能会先把指针做类型转化,接着再与上一个对齐量,这种做法在64bit平台上也同样存在高位截断问题。 4.移位有效性 32bit 平台允许 bitNum 设置在 0~31 之间,在 64bit 平台可能允许 bitNum 设置在 0~63 之间。 下边函数 SetBitN ( ) 在 32bit 平台上可以正常工作, 但在 64bit 平台,当 bitNum >31 时候,便取不到正确结果。这是因为对于没有加任何后缀的常量或者立即数,编译器会认为它属于最小的那种类型。
longlongSetBitN(longlong value, unsignedbitNum)
{
longlong mask
mask = (longlong) 1 <<bitNum;
return value |msk;
}
或者
{
longlong mask
mask = 1LL<<bitNum;
return value |mask;
}
5.位域操作 32bit平台下由于long与int数据类型长度一样,可以取得正确的结果。 64bit平台下由于long 与int数据类型长度不一致,将会取得错误的结果。 6.函数返回 情形一:这种错误跟函数原型的定义有关系,例如在函数中引用一个子函数,而子函数没有显式定义的话,虽然链接的时候还是可以链接成功,但编译器由于不知道返回值是什么,就会使用缺省的int类型。 例如下边的例子,在 64bit 平台上就不能很好的工作了。 8. 常数有效性 情景一:有时候如果是习惯于32bit的思维,做一些操作时我们会去做一些假设,比如pointer size等于4、0x7FFF FFFF为32bit有符号数最大值等等,或者在32bit环境下常用无符号常量0xFFFF FFFF用来测试是否等于-1。#defineINVALID_POINTER_VALUE 0xFFFFFFFF
在64bit系统中,这个值不是-1, 而是4294967295; 在64bit系统中,-1正确的值应当为0xFFFF FFFFFFFFFFFF。要避免这个问题,在常量声明时,使用const并带上signed或者unsigned。Const signedintINVALID_POINTER_VALUE = 0xFFFF FFFF
上边代码,在32bit或者64bit环境下都可以正常运行。另外,根据需要,适当的使用L后缀或者U后缀来声明整形常量。
代码检查check list
声明
(1)如果变量32bit平台是32位的,64bit平台是32位的,根据需要可以将其类型定义为int
(2)如果变量32bit平台是32位的,64bit平台是64位的,根据需要可以将其类型定义为long
(3)防止符号扩展,需要Check变量是否可以定义成unsigned.
(4)防止符号扩展,需要Check常量是否需要添加“L”或者“U”来约束.
表达式
(1)Check表达式是否存在显示类型转换
(2)注意隐形转化,需要Check表达式操作数是否混合使用不同数据类型.
(3)注意隐形转化,需要Check表达式操作数是否混合使用有符号数与无符号数.
赋值
(1)Check是否存在把指针变量赋值给int
(2)Check是否存在把int赋值给指针变量
(3)Check是否存在左值&&右值数据类型不一致
函数参数相关
(1)Check调用到的函数,是否已经声明。
(2)Check实参数据类型与形参数据类型是否匹配。
字符串格式化
(1)Check地址打印,尽量使用printk("addr=%p\n", addr)格式.
(2)Check整型打印,例如int型用%d或者%x、long型用%ld或者%lx.