我在xen的内核代码(文件:xen / include / asm-x86 / x86_64 / page.h)中看到一行,但无法理解为什么他们这样做:
/* Extract flags into 24-bit integer, or turn 24-bit flags into a pte mask. */
#define get_pte_flags(x) (((int)((x) >> 40) & ~0xFFF) | ((int)(x) & 0xFFF))
#define put_pte_flags(x) (((intpte_t)((x) & ~0xFFF) << 40) | ((x) & 0xFFF))
至于
#define get_pte_flags(x) (((int)((x) >> 40) & ~0xFFF) | ((int)(x) & 0xFFF))
我理解((int)(x) & 0xFFF)
会提取x的最后24位,但为什么需要第一部分((int)((x) >> 40) & ~0xFFF)
?
至于
#define put_pte_flags(x) (((intpte_t)((x) & ~0xFFF) << 40) | ((x) & 0xFFF))
我迷失在((intpte_t)((x) & ~0xFFF) << 40)
的目的。在我看来它应该是0。那我们为什么需要呢?
谢谢,
答案 0 :(得分:3)
我不得不两次看他们的代码。因为我花了一分钟才意识到0xFFF不是24位,所以它只有12位。因此,请举例64位输入:0xAABBCCDDEEFF1122
。将它向右移动40,你得到0x0000000000AABBCC
。在这种情况下,~0xFFF
是0xFFFFFFFFFFFFF000
的简写。 And
他们在一起,你得到0x0000000000AAB000
。所以基本上,他们抓住前12位并将它们向下移动。然后他们or
底部12位。所以他们最终得到了0x0000000000AAB122
。
另一半则相反,在底部取24位,将它们切成两半,顶部为12,底部为12。
答案 1 :(得分:1)
0xFFF
不是24位,只有12位。
知道了这一点,你会发现get_pte_flags
的目的是将前12位移到12-24位,如下所示:
xxxxxxxx xxxx0000 00000000 00000000 00000000 00000000 0000yyyy yyyyyyyy
变为
00000000 00000000 00000000 00000000 00000000 xxxxxxxx xxxxyyyy yyyyyyyy
当然,put_pte_flags
执行相反的操作,将位移回最重要的位置。
答案 2 :(得分:0)
64位思考。
在32位系统上,结果当然是0。 但是,当你向左移24位40位时,你有
xxxxxxxx yyyyyyyy zzzzzzzz 00000000 00000000 00000000 00000000 00000000
这是一个有效的64位值。