【问题标题】:Some kernel ARM code一些内核 ARM 代码
【发布时间】:2015-06-01 09:10:29
【问题描述】:

我正在阅读一些 ARM 内核源代码,直到我偶然发现了以下函数:-

314 #define __get_user_asm_byte(x, addr, err)                       \
315         __asm__ __volatile__(                                   \
316         "1:     " TUSER(ldrb) " %1,[%2],#0\n"                   \
317         "2:\n"                                                  \
318         "       .pushsection .fixup,\"ax\"\n"                   \
319         "       .align  2\n"                                    \
320         "3:     mov     %0, %3\n"                               \
321         "       mov     %1, #0\n"                               \
322         "       b       2b\n"                                   \
323         "       .popsection\n"                                  \
324         "       .pushsection __ex_table,\"a\"\n"                \
325         "       .align  3\n"                                    \
326         "       .long   1b, 3b\n"                               \
327         "       .popsection"                                    \
328         : "+r" (err), "=&r" (x)                                 \
329         : "r" (addr), "i" (-EFAULT)                             \
330         : "cc")

调用上下文如下:-

299 #define __get_user_err(x, ptr, err)                                     \
300 do {                                                                    \
301         unsigned long __gu_addr = (unsigned long)(ptr);                 \
302         unsigned long __gu_val;                                         \
303         __chk_user_ptr(ptr);                                            \
304         might_fault();                                                  \
305         switch (sizeof(*(ptr))) {                                       \
306         case 1: __get_user_asm_byte(__gu_val, __gu_addr, err);  break;  \

现在我想澄清一下关于上面的 ARM 程序集的一些疑问。

  1. __get_user_asm_byte 函数在做什么?我可以看到 r3 被复制到 r0 并且值 0 被移动到 r1。之后它会分支到偏移量 0x2b 吗?
  2. 该函数试图做什么?第 328 行以后的 "+r" (err), "=&r" (x) 是什么意思?
  3. 什么是 .pushsection 和 .popsection?
  4. 为什么为内核编写的 ARM 程序集在语法上如此不同(使用的汇编程序是什么?为什么有 %<regno> 而不是 r<regno>?)

【问题讨论】:

  • 至于 4. — 这是一种汇编语法,如果您告诉 GCC 编译但不汇编 (-S 选项)。 即汇编器应用程序是 GAS。
  • %0 不是r02b 不是 0x2b。阅读documentation
  • @CL。谢谢,有帮助!如果您可以将其添加为答案,我可以接受。

标签: linux linux-kernel arm system-calls


【解决方案1】:

首先,正如 cmets 所指出的,语法是标准的 gcc 内联汇编语法(+r=&r%<arg> 部分)。

剩下的就是设计用来处理页面错误的内核魔法。 get_user_asm_byte 的重点是从用户空间中提取一个字节。但是,在从用户空间提取数据时,需要适应两种特殊情况:

  1. 一个完全合法的用户空间地址,目前根本不存在(即通常因为它已被调出)
  2. 非法的用户空间地址。

两者都可能导致页面错误。对于(1),期望的行为是恢复用户页面(从交换空间或其他地方读回),然后重新执行加载指令,最终成功;对于 (2),期望的行为是使操作失败而不重试,向调用者返回 EFAULT 错误。

如果不进行特殊处理,内核模式下页面错误的正常行为是“糟糕”。特殊部分与页面错误处理代码协调并使其可以正确恢复。如果您想了解其工作原理的详细信息,请在内核源代码中搜索__ex_table

另外,请查看内核文档:Documentation/x86/exception-tables.txt

唯一的 ARM 特定项是使用 ldrt 或 MMU 域;这是domain.h 的条件。现代 ARM CPU 支持域。 translated 加载/存储变体对旧 CPU 应用用户模式访问。

【讨论】:

    猜你喜欢
    • 2016-07-03
    • 2012-07-10
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    相关资源
    最近更新 更多