2

在 x86 平台上运行的 Linux 中,实模式地址空间在受保护内核模式下映射到哪里?在内核模式下,线程可以直接访问内核地址空间。内核在较低的 8MB,页表在某个位置,等等(如此处所述。但是实模式地址空间到哪里去了?可以直接访问吗?例如 BIOS 和 BIOS 插件(参见此处)?

4

2 回答 2

3

For Linux x86 32 bits, the first 896MB of physical RAM is mapped to a contiguous block of virtual memory starting at virtual address 0xC0000000 to 0xF7FFFFFF. Virtual addresses from 0xF8000000 to 0xFFFFFFFF are assigned dynamically to various parts of the physical memory, so the kernel can have a window of 128MB mapped into any part of physical memory beyond the 896MB limit.

The kernel itself loads at physical address 1MB and up, leaving the first MB free. This first MB is used, for instance, to have DMA buffers that ISA devices needs to be there, because they use the 8237 DMA controller, which can only be mapped to such addresses.

So, reading from virtual memory address 0xC0000000 is actually reading from physical address 0x00000000 (provided the kernel has flagged that page as present)

于 2015-03-29T17:42:33.610 回答
3

(我的 x86-fu 有点弱。我会添加一些标签,以便其他人可以(希望)纠正我,如果我在任何地方说谎。)

物理地址在实模式和保护模式下是相同的。唯一的区别在于您如何从指令中指定的地址(偏移量)到物理地址:

  • 在实模式下,物理地址基本上是(segment_reg << 4) + offset.

  • 在保护模式下,物理地址是translate_via_page_table([segment_reg] + offset).

我的意思是段的基地址,在全局或本地描述符表中的偏移量处[segment_reg]查找。表示通过分页完成的地址转换(如果启用)。segment_regtranslate_via_page_table()

这里,BIOS ROM 似乎出现在物理地址 0x000F0000-0x000FFFFF。要通过分页以保护模式获取该内存,您必须通过设置正确的页表条目将其映射到某处的虚拟地址空间。假设 4 KB 页面(通常情况下),映射整个范围应该需要 16 个((0xFFFFF-0xF0000+1)/4096)个条目。

要了解 Linux 内核是如何工作的,您可以查看/dev/mem允许读取任意物理地址的 eg 是如何实现的。实现在drivers/char/mem.c中。

以下命令(来自例如this answer)将转储内存范围0xC0000-0xFFFFF(这意味着它也包括视频BIOS,根据上面链接的内存映射):

$ dd if=/dev/mem bs=1k skip=768 count=256 > bios

1024*768 = 0xC0000 和 1024*(768+256) - 1 = 0xFFFFF,这给出了预期的物理内存范围。

read_mem()drivers/char/mem.c调用中稍微跟踪一下,它在arch/x86/mm/ioremap.cxlate_dev_mem_ptr()中有一个特定于 x86 的实现。如果需要,该函数中的调用似乎负责在页面中进行映射。ioremap_cache()

请注意,顺便说一下,BIOS 例程无法在保护模式下工作。他们假设 CPU 在实模式下运行。

于 2015-03-29T14:10:26.530 回答