在optee中 arm_va2pa_helper实现了virtual addr转换phys addr,具体实现如下
/*virt transform to phys, regardless of the virt is ddr addr or register addr*/
arm_va2pa_helper((void *)buf_in, &phy_in);
arm_va2pa_helper((void *)buf_out, &phy_out);
#include <linux/module.h>
#define BIT32(nr) ((1 & 0xffffffff) << (nr))
#define BIT64(nr) ((1 & 0xffffffffffffffff) << (nr))
#define PAR_F BIT32(0)
#define PAR_PA_SHIFT 12
#define PAR_PA_MASK (BIT64(36) - 1)
#define DEFINE_REG_READ_FUNC_(reg, type, asmreg) \
static inline type read_##reg(void) \
{ \
type val; \
\
asm volatile("mrs %0, " #asmreg : "=r" (val)); \
return val; \
}
#define DEFINE_U64_REG_READ_FUNC(reg) \
DEFINE_REG_READ_FUNC_(reg, uint64_t, reg)
DEFINE_U64_REG_READ_FUNC(par_el1)
static inline void write_at_s1e1r(uint64_t va)
{
asm volatile ("at S1E1R, %0" : : "r" (va));
}
bool arm_va2pa_helper(void *va, uint64_t *pa)
{
uint64_t par;
uint64_t par_pa_mask;
bool ret = false;
local_irq_disable();
write_at_s1e1r((uint64_t)va);
isb();
par = read_par_el1();
par_pa_mask = PAR_PA_MASK;
if (par & PAR_F)
goto out;
*pa = (par & (par_pa_mask << PAR_PA_SHIFT)) |
((uint64_t)va & ((1 << PAR_PA_SHIFT) - 1));
ret = true;
out:
local_irq_enable();;
return ret;
}
EXPORT_SYMBOL(arm_va2pa_helper);
总结一下arm_va2pa_helper,其实就是将虚拟地址写入MMU寄存器,然后再读取另外一个寄存器获取物理地址