高半内核初始化
当初始化我的内核时,我需要做一些事情:1)需要启用分页,2)物理内存管理器需要从 grub 解析内存映射,3)各种启动代码需要访问需要的数据留在那里供以后使用(例如 GDT、IDT、内存管理结构)。
这些步骤之间的依赖性让我发疯。对于上半部分,内核在其虚拟地址处链接,因此我提出的选项是 1)在汇编中启用分页,这将涉及跟踪所有多重引导指针(在汇编中),以便它们仍然可以访问到物理内存管理器,然后取消它们全部的映射,2)将启动代码链接到其物理地址,然后执行一些指针操作以访问其物理地址的内核结构,或者3)不使用高半部分核心。
还涉及到在编译时不知道物理内存量的情况下引导物理内存管理器。我很确定我必须在分配第一个结构时小心地避免所有多重引导结构,或者首先使用它们,然后不用担心覆盖它们(尽管我仍然需要处理模块,并且这种方法可能涉及在设置物理内存管理器时将多重引导表复制到我需要的已知位置)。
这些问题是我迄今为止一直避免使用较高半内核的原因。有人有一个好的系统来解决这些依赖关系吗?也许这个 GDT 技巧有一些变化,可以访问链接/虚拟地址的内核和物理地址的多重引导表,或者使用某种预定义的页表来避免上述问题,也许涉及 PSE?
When initializing my kernel, I have a few things that need to happen: 1) paging needs to be enabled, 2) the physical memory manager needs to parse the memory map from grub, and 3) assorted startup code needs to access data that needs to stay there for later (e.g. the GDT, IDT, memory management structures).
The dependencies between these steps are driving me crazy. With higher-half, the kernel is linked at its virtual address and so the options I've come up with are 1) enable paging in assembly, which would involve following all the multiboot pointers (in assembly) so they'll still be accessible to the physical memory manager and then later unmapping them all, 2) link the startup code at its physical address and then do some pointer manipulation to access kernel structures at their physical addresses as well, or 3) don't use a higher-half kernel.
Also involved is bootstrapping the physical memory manager without knowing the amount of physical memory at compile time. I'm pretty sure I have to either carefully avoid all the multiboot structures when allocating the first structures, or use them all first and then don't worry about overwriting them (although I'd still have to deal with modules and this approach probably involves copying the multiboot tables to a known location as I need them while setting up the physical memory manager).
These problems are why I've avoided a higher half kernel up to now. Does anyone have a good system for resolving these dependencies? Maybe some variation on this GDT trick to access both the kernel at its linked/virtual address and the multiboot tables at their physical address, or using some kind of pre-defined page tables that avoid the problems above, maybe involving PSE?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这就是我解决这个问题的方法:
我的内核映像由 GRUB 在(物理)地址 0x01000000(16MB,位于 ISA DMA 区域上方)加载。该映像基本上由两部分组成:
由于早期 init 部分中的代码链接到与其加载位置相同的地址,因此 GRUB 可以毫无问题地跳转到该代码。此早期 init 代码执行以下步骤:
此时,其余的初始化是由上半部分代码完成的。这包括设置 GDT、IDT、内存管理……请注意,MBI 已重新定位到众所周知的位置,因此您不必担心用自己的数据结构覆盖它。
关于物理内存管理器的简短说明:我所做的是计算数据结构所需的页面数量,从内核映像之后的第一页开始分配这些结构,并从这些数据结构之后开始处理页面。
我希望这个解释是清楚的。如果不是,请告诉我。如果您愿意,我还可以为您提供我的内核的副本。
This is how I tackled this problem:
My kernel image is loaded by GRUB at (physical) address 0x01000000 (16MB, just above the ISA DMA region). This image basically consists of two parts:
Since the code in the early init section is linked at the same address as where it is loaded, GRUB can jump into this code without any problems. This early init code performs the following steps:
At this point the rest of the initialization is done from higher half code. This includes setting up the GDT, IDT, memory management,... Note that the MBI is relocated to a well-known location so you shouldn't have to worry about overwriting it with your own data structures.
A small word about the physical memory manager: What I do is calculate the amount of pages needed for my data structures, allocate these structures starting at the first page after the kernel image and start dealing pages starting after these data structures.
I hope this explanation is clear. If it's not, please let me know. I could also provide you with a copy of my kernel if you'd like that.