1

我对 linux 中的 GDT 有一些疑问。我尝试在内核空间(Ring0)中获取 GDT 信息,并在系统调用上下文中调用我的测试代码。在测试代​​码中,我尝试打印 ss 寄存器(Segment Selector),并通过 GDTR 和 ss-segment-selector 获取 ss 段描述符。

 77 void printGDTInfo(void) {
 78         struct desc_ptr pgdt, *pss_desc;
 79         unsigned long ssr;
 80         struct desc_struct *ss_desc;
 81 
 82         // Get GDTR
 83         native_store_gdt(&pgdt);
 84         unsigned long gdt_addr = pgdt.address;
 85         unsigned long gdt_size = pgdt.size;
 86         printk("[GDT] Addr:%lu |Size:%lu\n", gdt_addr, gdt_size);
 87 
 88         // Get SS Register
 89         asm("mov %%ss, %%eax"
 90                 :"=a"(ssr));
 91         printk("SSR In Kernel:%lu\n", ssr);
 92         unsigned long desc_index = ssr >> 3;    // SHIFT for Descriptor Index
 93         printk("SSR Shift:%lu\n", desc_index);
 94         ss_desc = (struct desc_struct*)(gdt_addr + desc_index * sizeof(struct desc_struct));
 95         printk("SSR:Base0:%lu, Base1:%lu,Base2:%lu\n", ss_desc->base0, ss_desc->base1, ss_desc->base2);
 96 }

最让我困惑的是 ss-descriptor 中的“基本”字段都是零(line95 打印)。我尝试打印 __USER_DS 段描述符,“基本”字段也为零。

真的吗?Linux中的所有段都使用相同的基地址(零)?我想检查 Linux 源代码中的 GDT 初始化,但我不确定 Linux 何时何地设置 GDT?

我在“arch/x86/kernel/cpu/common.c”中找到这样的代码,GDT_ENTRY_INIT 的第二个参数(零)为零,这意味着段描述符中的 base0/base1/base2 字段都为零。

 125         [GDT_ENTRY_KERNEL32_CS]         = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
 126         [GDT_ENTRY_KERNEL_CS]           = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
 127         [GDT_ENTRY_KERNEL_DS]           = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),

如果是这样,则所有段都具有相同的基地址(零)。这样一来,Ring0 和 Ring1 中的相同虚拟地址会映射到相同的线性地址吗?

我很感激你的帮助:)

4

0 回答 0