我一直在阅读Android的内核,看看如何动态管理CPU核心(即DVFS,DCVS)。我找到的代码here调用了以下函数(已定义here),后者又调用了SMC汇编指令。
ARM有一个解释SMC calling convention的文档,但我还没有能够用它来理解以下功能。如何根据其输入操作数进一步查看SMC指令以查看它实际执行的操作?
s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
{
int ret;
int context_id;
register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4);
register u32 r1 asm("r1") = (u32)&context_id;
register u32 r2 asm("r2") = arg1;
register u32 r3 asm("r3") = arg2;
register u32 r4 asm("r4") = arg3;
register u32 r5 asm("r5") = arg4;
asm volatile(
__asmeq("%0", "r0")
__asmeq("%1", "r1")
__asmeq("%2", "r2")
__asmeq("%3", "r0")
__asmeq("%4", "r1")
__asmeq("%5", "r2")
__asmeq("%6", "r3")
#ifdef REQUIRES_SEC
".arch_extension sec\n"
#endif
"smc #0 @ switch to secure world\n"
: "=r" (r0), "=r" (r1), "=r" (r2)
: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5));
ret = r0;
if (ret1)
*ret1 = r1;
if (ret2)
*ret2 = r2;
return r0;
}
EXPORT_SYMBOL(scm_call_atomic4_3);
答案 0 :(得分:2)
SMC calling conventions是ARM关于如何实现跨世界 API的建议,因此多个供应商可以在任何一个世界中编写代码并以最小的不兼容性共存。至少那是意图。供应商(在您的情况下为Android / Linux)不必执行此操作,如果安全世界不遵循它,则可能无法执行此操作。
但我还没能用它来理解以下功能
SMC
指令是从正常世界到安全监视器的受控变更。监视器具有自己的向量表,svc
的条目是SMC调用。寄存器是共享的'世界之间的信息。通常在世界开关上,监视器可以将所有寄存器换出到某个上下文存储器。在SMC
情况下,寄存器可以传输参数并返回结果。这就是这个功能所做的一切。
register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4);
SMC调用约定文档中的类表2-1。它是从普通的Linux到安全的监视器来告诉哪个函数(以及编组/保持4个参数的数量)。
register u32 r2 asm("r2") = arg1;
register u32 r3 asm("r3") = arg2;
register u32 r4 asm("r4") = arg3;
register u32 r5 asm("r5") = arg4;
如果ARM ABI是偶然的,参数arg1-arg4将已经在这些寄存器中,因此不会生成任何代码。全局context_id
(到Linux / Android内核)也通过了。
如何根据其输入操作数进一步查看SMC指令以查看它实际执行的操作?
要做到这一点,您需要安全世界的代码。我的猜测是,这是一些手机和基带等在安全的世界,代码不可用。如果您拥有安全的世界代码,则监视器向量表将具有SMC
条目。这将有一个基于r0
或' cmd'的切换(或if / then)。选择特定smc
函数的值。通用smc
处理程序可以恢复安全世界寄存器/上下文,但保留r0
位字段中指定的四个参数。
所以答案可能是你无法追踪它的作用。您必须依赖供应商文档或者有幸为安全世界提供代码。