【发布时间】:2020-06-10 19:25:43
【问题描述】:
我正在开发一个用于学习目的的微型操作系统(此处代码:https://github.com/davidedellagiustina/ScratchOS)。
我有一个 higher half kernel 在 0xc0004000 运行,映射到物理 0x4000。默认页面目录正确映射了这个区域,然后有一个用于标识映射前1MB RAM(需要跳转到上半部分)的条目。进入上半部分后,我删除了页面目录的第一个条目,使TLB无效,一切正常(如果我尝试访问地址0x4000会出现页面错误,因此页面目录更新成功)。
之后我为时间和键盘设置了一个中断向量和中断处理函数,最终我尝试创建一个新的更完整的页面目录并替换启动目录,但是在替换旧的时出现三重错误一个。
目前我可以避免三重错误的唯一方法是加载一个标识映射前 1MB RAM 的新页面目录,甚至在加载后尝试删除页面目录的第一个条目(就像我在启动期间所做的那样过程)导致三重故障(因此身份映射必须保留在那里)。
我能够发现在切换页表之前禁用中断(甚至在切换到保护模式后从未重新启用它们,在启动早期[注释指令asm volatile("sti"); 函数@987654326 @ 在文件src/cpu/isr.c 的底部进行测试])可防止 CPU 发生三重故障。所以,我想我的 IDT(文件 src/cpu/idt.* 和 src/cpu/isr.*)或 GDT(切换到保护模式时在引导过程中加载回文件 src/boot/bootsect.asm 和 src/boot/gdt.asm)可能有一些问题。我已经仔细检查了这两个结构中加载的所有地址。我错过了什么?在我看来它是三重故障,因为在某些时候,没有第一页的身份映射,它无法找到整个中断向量(它加载到内核内部的虚拟内存中,因此映射到物理第一页),但是奇怪的行为是(见第一段)如果没有标识映射前 1MB 的页面目录是引导目录,它不会抱怨。
谁能帮忙找出我的错误?
【问题讨论】:
标签: paging virtual-memory interrupt-handling osdev fault