kernel - 高半内核初始化

标签 kernel bootstrapping virtual-memory osdev

在初始化我的内核时,我有几件事需要发生:1)需要启用分页,2)物理内存管理器需要从 grub 解析内存映射,以及 3)各种启动代码需要访问需要的数据留在那里供以后使用(例如 GDT、IDT、内存管理结构)。

这些步骤之间的依赖关系让我发疯。对于高半部分,内核链接在其虚拟地址处,因此我提出的选项是 1)在程序集中启用分页,这将涉及跟踪所有多引导指针(在程序集中),因此它们仍然可以访问到物理内存管理器,然后将它们全部取消映射,2)将启动代码链接到其物理地址,然后进行一些指针操作以访问其物理地址的内核结构,或者 3)不使用高半部分核心。

还涉及在编译时不知道物理内存量的情况下引导物理内存管理器。我很确定我必须在分配第一个结构时小心地避免所有多重引导结构,或者首先使用它们然后不要担心覆盖它们(尽管我仍然必须处理模块并且这种方法可能涉及在设置物理内存管理器时将多重引导表复制到我需要的已知位置)。

这些问题是我到目前为止避免使用更高半内核的原因。有没有人有一个很好的系统来解决这些依赖关系? this GDT trick 上可能有一些变化在其链接/虚拟地址处访问内核和在其物理地址处访问多引导表,或者使用某种预定义的页表来避免上述问题,可能涉及 PSE?

最佳答案

这就是我解决这个问题的方法:

我的内核镜像由 GRUB 在(物理)地址 0x01000000(16MB,就在 ISA DMA 区域上方)加载。这张图基本上由两部分组成:

  • “早期初始化”部分。本节包含为准备跳转到高半内核而执行的代码。我还在本节中为准备期间使用的堆栈和堆保留了一些空间。本节中的所有代码都链接到(虚拟)地址 0x01000000。
  • 图像的其余部分包含属于高半内核的代码和数据。这部分中的所有代码都链接到(虚拟)地址 0xc0000000 (3GB)。

  • 由于早期 init 部分中的代码与加载它的地址链接在同一地址,因此 GRUB 可以毫无问题地跳转到该代码。此早期初始化代码执行以下步骤:
  • 重定位 GRUB 传递给内核的 MBI 结构。早期初始化部分内的堆用于此目的。
  • 标识将从物理地址 0x0 开始的所有页面映射到 early init 部分使用的最后一页的物理地址。身份映射意味着虚拟地址与物理地址相同。这确保了在启用分页后,早期 init 部分中的代码仍然可以执行。
  • 将高半内核映射到虚拟地址 0xc0000000。
  • 启用分页。
  • 跳转到上半部分内核。

  • 在这一点上,其余的初始化是从高半代码完成的。这包括设置 GDT、IDT、内存管理……请注意,MBI 已重新定位到众所周知的位置,因此您不必担心用自己的数据结构覆盖它。

    关于物理内存管理器的小话:我所做的是计算我的数据结构所需的页面数量,从内核镜像之后的第一页开始分配这些结构,并从这些数据结构之后开始处理页面。

    我希望这个解释是清楚的。如果不是,请告诉我。如果您愿意,我还可以为您提供我的内核的副本。

    关于kernel - 高半内核初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6222411/

    相关文章:

    linux - 哪个硬件定时器用于 linux 中的 hr 定时器?

    c - Linux 内核链接

    c++ - 虚拟内存或物理内存

    ios - iOS 上的内存交换和虚拟内存

    hibernate - Grails和Hibernate:未知实体:com.mypackage.Role

    linux - 管理程序 guest 操作系统中的内存地址转换

    ubuntu - 更新我的 ubuntu 精确 12.04 后虚拟框错误(未安装内核驱动程序(rc=-1908))

    linux - 如果在folder1中创建了一些新文件夹,为什么我必须重复输入 "sudo chmod -R 0777 folder1"

    zend-framework - 在 Bootstrap 中获取语言环境资源

    data-structures - 引导集合以提高性能