第三级页面表间接源代码与x86 Linux内核中的汇编不同
我正在使用4个级别的页面表(禁用LA57),并试图了解获取第三级页面虚拟地址的实现。但是源代码和拆卸之间遇到了差异。
source code
static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
{
return p4d_pgtable(*p4d) + pud_index(address);
}
source code > p4d_pgtable
和pud_index
呼叫在结果组件中置于 (以下)。这是他们的源代码。
static inline pud_t *p4d_pgtable(p4d_t p4d)
{
return (pud_t *)__va(p4d_val(p4d) & p4d_pfn_mask(p4d));
}
static inline unsigned long pud_index(unsigned long address)
{
return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
}
href =“ https://elixir.bootlin.com/linux/v5.19-rc2/source/include/include/linux/pgtable.h#l77” rel =“ nofollow noreferrer ” href =“ https://elixir.bootlin.com/linux/v5.19-rc2/source/arch/x86/include/asm/pgtable_64_types.h#l80”代码>和ptrs_per_pud
/*
* 3rd level page
*/
#define PUD_SHIFT 30
#define PTRS_PER_PUD 512
问题:根据pud_index
源代码,我期望将其用0x1e
(pud_shift
)进行编译,然后和0x1ff
(ptrs_per_pud -1
)和和anded。但是拆卸
pud_offset
显示不同的值。
拆卸:
(gdb) disas pud_offset
Dump of assembler code for function pud_offset:
0xffffffff812bfc40 <+0>: push rbp
0xffffffff812bfc41 <+1>: mov rbp,rsp
0xffffffff812bfc44 <+4>: mov rax,rdi
0xffffffff812bfc47 <+7>: nop DWORD PTR [rax]
0xffffffff812bfc4a <+10>: and rax,QWORD PTR [rip+0x142936f] # 0xffffffff826e8fc0 <physical_mask>
0xffffffff812bfc51 <+17>: shr rsi,0x1b # <---- 0x1b is 27, but 3rd level starts at bit 30
0xffffffff812bfc55 <+21>: pop rbp
0xffffffff812bfc56 <+22>: and rax,0xfffffffffffff000
0xffffffff812bfc5c <+28>: and esi,0xff8 # <---- 4088, but there are 512 entries at the 3rd level
0xffffffff812bfc62 <+34>: add rax,QWORD PTR [rip+0x14122df] # 0xffffffff826d1f48 <page_offset_base>
0xffffffff812bfc69 <+41>: lea rax,[rax+rsi*1]
0xffffffff812bfc6d <+45>: ret
End of assembler dump.
我们在拆卸输出中所拥有的是地址
通过0x1b
(27),然后使用0xff8 (4088或511&lt;&lt; 3)。
您是否知道为什么会发生这种情况?
I'm using 4 levels page table (LA57 disabled) and tried to understand the implementation of getting virtual address of the 3rd level page. But encountered difference between source code and it's disassemble.
static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
{
return p4d_pgtable(*p4d) + pud_index(address);
}
Both p4d_pgtable
and pud_index
calls were inlined in the resulting assembly (below). Here are their source code.
static inline pud_t *p4d_pgtable(p4d_t p4d)
{
return (pud_t *)__va(p4d_val(p4d) & p4d_pfn_mask(p4d));
}
static inline unsigned long pud_index(unsigned long address)
{
return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
}
/*
* 3rd level page
*/
#define PUD_SHIFT 30
#define PTRS_PER_PUD 512
The problem: According to the pud_index
source code I expected it to be compiled with the shift right by 0x1e
(PUD_SHIFT
) and then anded with 0x1ff
(PTRS_PER_PUD - 1
). But disassembling pud_offset
shows different values.
Disassemble:
(gdb) disas pud_offset
Dump of assembler code for function pud_offset:
0xffffffff812bfc40 <+0>: push rbp
0xffffffff812bfc41 <+1>: mov rbp,rsp
0xffffffff812bfc44 <+4>: mov rax,rdi
0xffffffff812bfc47 <+7>: nop DWORD PTR [rax]
0xffffffff812bfc4a <+10>: and rax,QWORD PTR [rip+0x142936f] # 0xffffffff826e8fc0 <physical_mask>
0xffffffff812bfc51 <+17>: shr rsi,0x1b # <---- 0x1b is 27, but 3rd level starts at bit 30
0xffffffff812bfc55 <+21>: pop rbp
0xffffffff812bfc56 <+22>: and rax,0xfffffffffffff000
0xffffffff812bfc5c <+28>: and esi,0xff8 # <---- 4088, but there are 512 entries at the 3rd level
0xffffffff812bfc62 <+34>: add rax,QWORD PTR [rip+0x14122df] # 0xffffffff826d1f48 <page_offset_base>
0xffffffff812bfc69 <+41>: lea rax,[rax+rsi*1]
0xffffffff812bfc6d <+45>: ret
End of assembler dump.
What we have in the disassemble output is the address
shifted right by 0x1b
(27) and then anded with 0xff8
(4088 or 511 << 3).
Do you have any idea of why it might happen?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论