我有一些汇编代码封装在我的驱动程序代码的静态函数中。我的代码就像
static int _ARMVAtoPA(void *pvAddr)
{
__asm__ __volatile__(
/* ; INTERRUPTS_OFF" */
" mrs r2, CPSR;\n" /* r2 saves current status */
"CPSID iaf;\n" /* Disable interrupts */
/*In order to handle PAGE OUT scenario, we need do the same operation
twice. In the first time, if PAGE OUT happens for the input address,
translation abort will happen and OS will do PAGE IN operation
Then the second time will succeed.
*/
"mcr p15, 0, r0, c7, c8, 0;\n "
/* ; get VA = <Rn> and run nonsecure translation
; with nonsecure privileged read permission.
; if the selected translation table has privileged
; read permission, the PA is loaded in the PA
; Register, otherwise abort information is loaded
; in the PA Register.
*/
/* read in <Rd> the PA value */
"mrc p15, 0, r1, c7, c4, 0;\n"
/* get VA = <Rn> and run nonsecure translation */
" mcr p15, 0, r0, c7, c8, 0;\n"
/* ; with nonsecure privileged read permission.
; if the selected translation table has privileged
; read permission, the PA is loaded in the PA
; Register, otherwise abort information is loaded
; in the PA Register.
*/
"mrc p15, 0, r0, c7, c4, 0;\n" /* read in <Rd> the PA value */
/* restore INTERRUPTS_ON/OFF status*/
"msr cpsr, r2;\n" /* re-enable interrupts */
"tst r0, #0x1;\n"
"ldr r2, =0xffffffff;\n"
/* if error happens,return INVALID_PHYSICAL_ADDRESS */
"movne r0, r2;\n"
"biceq r0, r0, #0xff;\n"
"biceq r0, r0, #0xf00;" /* if ok, clear the flag bits */
);
}
static unsigned long CpuUmAddrToCpuPAddr(void *pvCpuUmAddr)
{
int phyAdrs;
int mask = 0xFFF; /* low 12bit */
int offset = (int)pvCpuUmAddr & mask;
int phyAdrsReg = _ARMVAtoPA((void *)pvCpuUmAddr);
if (INVALID_PHYSICAL_ADDRESS != phyAdrsReg)
phyAdrs = (phyAdrsReg & (~mask)) + offset;
else
phyAdrs = INVALID_PHYSICAL_ADDRESS;
return phyAdrs;
}
如您所见,我尝试将虚拟地址从用户空间转换为物理地址。我从另一个项目移植此代码,除了我将_ARMVAtoPA
函数修改为静态函数。
当我使用static int _ARMVAtoPA(void *pvAddr)
时:
当我使用int _ARMVAtoPA(void *pvAddr)
时:
任何人都可以向我解释,为什么当我使用静态和非静态功能时结果会有所不同。
由于
答案 0 :(得分:6)
ASM代码没有定义哪个寄存器包含函数参数pvAddr
以及哪个寄存器保存返回值。只是假定编译器遵循mips ABI。
但如果函数是内联的(可能static
可能),寄存器分配可能会改变,因此asm代码可能完全错误。
为了解决这个问题,你应该使用gcc扩展来为函数参数分配寄存器并返回值。并且还声明它将使用哪些寄存器进行无恢复,因此编译器可以在调用之后恢复寄存器,以防内联函数。