linux内核中的虚拟到物理地址转换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核中的虚拟到物理地址转换相关的知识,希望对你有一定的参考价值。

以下用于将Linux内核中的虚拟地址转换为物理地址。但是这是什么意思?

我对装配知识非常有限

163 #define __pv_stub(from,to,instr,type)                   
164         __asm__("@ __pv_stub
"                         
165         "1:     " instr "       %0, %1, %2
"           
166         "       .pushsection .pv_table,"a"
"         
167         "       .long   1b
"                           
168         "       .popsection
"                          
169         : "=r" (to)                                     
170         : "r" (from), "I" (type))
答案

这不是真正的“汇编”,因为这个宏本身没有指令。

它只是一个插入instr(传递给宏的指令)的宏,它有一个输入操作数from,一个立即(常量)输入操作数type和一个输出操作数to

还有pushsectionpopsection之间的部分,它在特定的二进制部分pv_table中记录了该指令的地址。这允许内核在其代码中找到这些位置。

最后一部分是asm约束和操作数。它列出了编译器将用qzxswpoi,%0%1替换的内容。 %2是第一个列出的(%0),它意味着%0将是任何通用寄存器,即输出操作数将存储在宏参数"=r"(to)中。其他2是相似的,除了它们是输入操作数:to是一个寄存器所以得到from"r"是立即所以是type

有关详细信息,请参阅"i"

所以考虑来自内核的这段代码(http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Extended-Asm.html#Extended-Asm

http://lxr.linux.no/linux+v3.9.4/arch/arm/include/asm/memory.h#L172

static inline unsigned long __virt_to_phys(unsigned long x) { unsigned long t; __pv_stub(x, t, "add", __PV_BITS_31_24); return t; } 将相当于__pv_stubt = x + __PV_BITS_31_24 == instradd == fromx == tot == type

所以你可能想知道为什么有人会做这么复杂的事情而不只是在代码中编写__PV_BITS_31_24

原因是我上面提到的pv_table。所有这些陈述的地址都记录在特定的精灵部分。在某些情况下,内核会在运行时修补这些指令(因此需要能够轻松找到所有这些指令),因此需要一个表。

ARM端口就是这样做的:t = x + __PV_BITS_31_24

它仅在使用CONFIG_ARM_PATCH_PHYS_VIRT编译内核时使用:

http://lxr.linux.no/linux+v3.9.4/arch/arm/kernel/head.S#L541

以上是关于linux内核中的虚拟到物理地址转换的主要内容,如果未能解决你的问题,请参考以下文章

在Windows内核地址空间中将虚拟地址转换为物理地址

虚拟地址转换为物理地址

Linux内核——内存管理

Linux的内存管理

在 Linux 中将物理地址转换为虚拟地址并读取其内容

linux 学习一