CPU在访问全局变量时重置自定义C内核的执行
希望你在面试中表现良好 作为一个简短的介绍:我写这个问题并不是作为特里特,而是作为来自西班牙的计算机科学学生协会ASOC的成员。我们试图通过自己开发一个内核来学习内核是如何工作的。我们已经将所有代码(与问题相关)发布在 由于我们是大约30名学生,我们已经将工作分为:文件系统、内存、用户空间软件(仅仅是shell)、进程管理和引导加载程序 当我们开发一个月后,我们在最后一部分遇到了一些真正的麻烦,所以在这里我请求您对这个主题提供一些帮助 从BIOS将我们设置为CPU在访问全局变量时重置自定义C内核的执行,c,assembly,kernel,x86-64,bootloader,C,Assembly,Kernel,X86 64,Bootloader,希望你在面试中表现良好 作为一个简短的介绍:我写这个问题并不是作为特里特,而是作为来自西班牙的计算机科学学生协会ASOC的成员。我们试图通过自己开发一个内核来学习内核是如何工作的。我们已经将所有代码(与问题相关)发布在 由于我们是大约30名学生,我们已经将工作分为:文件系统、内存、用户空间软件(仅仅是shell)、进程管理和引导加载程序 当我们开发一个月后,我们在最后一部分遇到了一些真正的麻烦,所以在这里我请求您对这个主题提供一些帮助 从BIOS将我们设置为0x7c00开始,我们遵循的步骤是:
0x7c00
开始,我们遵循的步骤是:
- 通过跳远设置CS(谢谢佩奇先生!)
- 保存主磁盘
- 设置16位堆栈
- 从磁盘加载8个扇区(第二阶段)
- 加载32位GDT
- 负载IDT
- 启用保护模式(CR0)
- 执行跳远以冲洗管道并设置CS
- 将所有分段设置为相同(平面分段)
- 将新堆栈设置为
0x90000
- 通过CPUID检测LM是否存在
- 禁用旧分页(我们没有在PM中设置分页)
- 设置页面表
- 激活PAE
- 激活LM
- 启用分页
- 加载GDT(与32位相同,可能在兼容模式下?)
- 跳远的原因与上述相同
- 更新段
- 重置堆栈
- 通过
extern kmain Call kmain调用C kmain
OUTPUT_FORMAT("binary");
ENTRY(boot);
SECTIONS
{
. = 0x7C00;
.text : {
*(.boot);
*(.text);
}
.rodata : SUBALIGN(4) {
*(.rodata);
}
.data : SUBALIGN(4) {
*(.data);
}
.bss : SUBALIGN(4) {
*(.bss)
}
/DISCARD/ : {
*(.eh_frame);
*(.comment);
*(.note.gnu.build-id);
}
}
我们使用以下工具进行编译:
nasm -f elf64 boot.asm -o boot.o
gcc -ffreestanding -nostdlib -mno-red-zone -fno-exceptions -m64 kernel.c boot.o -o kernel.bin -T link.ld
并通过以下方式进行测试:
qemu-system-x86_64 -fda kernel.bin
如果我们像这样设置函数,我们的kmain会写入VGA:
void kmain() {
char * vga_ptr = (char*)0xb8000;
*(vga_ptr++) = 0x0f;
*(vga_ptr++) = 'H';
while (1){}
}
但是,如果我声明vga_ptr
超出kmain
边界,cpu将重置执行
我在这里所做的假设是,鉴于IDT不完整的事实,CPU是三重故障(对此的任何帮助都将不胜感激)。问题更多的是,是什么触发了导致双故障、三故障、复位底座的异常。我只是猜测,但可能与不正确的分页或构建过程有关(friendlink.ld过去给我们带来了很多麻烦)
任何关于这个问题的说明,或者指出我们代码中检测到的任何混乱,都将不胜感激。如果问题太长或不准确,我很抱歉。记住,我们确实是学生
祝你度过愉快的一天,保持安全
另外,引导加载程序的完整代码链接在github的上面,分支引导测试中。我试图让问题尽可能简短,但根据请求,我可以编辑文本以包含您需要的任何代码片段
[编辑]另一个失败,可能与此无关,就是当我分解.bin文件时,它显示了.data
部分下的所有内容。试着做一个修改,该repo中有很多文件(有些模棱两可:boot.asm
vsboot2.asm
并且没有反映您发布的代码),以及大量的意大利面编码。您的CPU显然存在三重故障,bochs在调试此问题方面优于qemu,因为它可以输出一个非常详细的日志,其中包括导致TF的原因。如果您盲目地从OSDEV复制代码,那么它可能无法工作。我会仔细检查PML4设置,特别是您使用的映射是什么?为什么您是否重新加载了与PM中使用的完全相同的GDT(即,没有设置L位,然后执行64位代码)?如果您将目标分解为:1)从启动时输入PM,并检查一切是否正常(执行32位代码,设置了段),可能会更好。2) 启用PAE并检查每个页面是否可正确访问(访问页面的预期地址)3)启用LM并检查64位汇编代码是否正确运行(包括访问上述页面)。4) 编译内核,检查链接器脚本是否正常工作,访问的地址是否正确。检查内核是否加载到正确的地址并执行它。非常感谢@MargaretBloom。给我一些时间来整理一下分支机构的混乱,(你说得绝对正确)并在第二条评论中遵循你的建议,我将编辑这个问题。祝你有一个愉快的一天。试着做一个简单的回复,回复中有很多文件(有些模棱两可:boot.asm
vsboot2.asm
,没有反映你发布的代码),还有很多意大利面编码。您的CPU显然是三重故障,bochs在调试这个问题上比qemu更好,因为它可以输出一个非常详细的日志,其中包括导致TF的原因。如果您盲目地从OSDEV复制代码,那么它可能不会工作。我会仔细检查PML4设置,特别是您使用的映射是什么?为什么您要重新加载与PM中使用的完全相同的GDT(即,没有设置L位,然后执行64位代码)?也可能更好的是,您可以分解您的目标:1)从启动时输入PM,并检查一切是否正常(执行32位代码,设置段)。2) 启用PAE并检查每个页面是否可正确访问(访问页面的预期地址)3)启用LM并检查64位汇编代码是否正确运行(包括访问上述页面)。4) 编译内核,检查链接器脚本是否正常工作,访问的地址是否正确。检查内核是否加载到正确的地址并执行它。非常感谢@MargaretBloom。给我一些时间来整理一下分支机构的混乱,(你说得绝对正确)并在第二条评论中遵循你的建议,我将编辑这个问题。祝您有个美好的一天。