【问题标题】:How to interpret ARM's SMC calls?如何解释 ARM 的 SMC 调用?
【发布时间】:2017-10-18 22:42:12
【问题描述】:

我一直在阅读 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);

【问题讨论】:

  • 类似this?
  • @DavidWohlferd 该链接解释了安全模型。我更想知道在 SMC 调用后运行的代码。
  • 关键是 SMC 调用进入安全世界。这可以有一个完全不同的物理内存映射,并且有不同的模型来说明安全世界中的软件如何运行。它绝对不必是(并且可能不是)Linux。这通常是闭源软件,您可能能够访问二进制图像,甚至可能很困难。您可能需要进行逆向工程或与创建安全世界软件的供应商交谈。

标签: arm kernel android-kernel trust-zone


【解决方案1】:

SMC calling conventions 是 ARM 提出的关于如何实现 cross world API 的建议,以便多个供应商可以在任一世界中编写代码并以最小的不兼容性共存。至少这是意图。供应商(在您的情况下为 Android/Linux)不必这样做,如果安全世界不遵循它,则可能无法这样做。

但我无法使用它来理解以下功能

SMC 指令是从正常世界到安全监视器的受控更改。监视器有自己的向量表,svc 的条目是 SMC 调用。寄存器是世界之间的“共享”信息。通常在世界切换上,监视器可能会将所有寄存器交换到某个上下文存储中。在SMC 的情况下,寄存器可以传递参数并返回结果。这就是这个函数所做的一切。

register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4);

这是SMC 调用约定 文档中类似表 2-1 的位字段。它是从普通世界的 Linux 到安全监视器来判断哪个函数(以及编组/保持四个的参数数量)。

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 位字段中指定的四个参数。

所以答案可能是你无法追查它的作用。您必须依赖供应商文档或有幸拥有安全世界的代码。

【讨论】:

  • 你可能很幸运,PSCI 文档可能适用。查看开源ARM Trusted Firmware。我没有看到 MSM SOC,但他们可能在某些 CPU 上使用它(供其他人阅读)。
  • 谢谢,我会调查的。假设实现是封闭源代码,你知道我应该能够在这个源代码树中的哪里找到二进制文件吗? android.googlesource.com/kernel/msm/+/android-5.1.0_r0.6/arch/…
  • 它甚至不在源代码树中。它将在设备中进行编程(如 BIOS 芯片)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 2019-10-20
相关资源
最近更新 更多