c - 如何正确使用startup-ipi来启动应用处理器?

标签 c linux-kernel x86 intel smp

我的目标是让我自己的内核启动一个应用程序cpu。它使用与linux kernel相同的机制。 :

  • 发送断言和电平触发的 init-IPI
  • 等等...
  • 发送取消断言和电平触发的 init-IPI
  • 等等...
  • 发送最多两个启动 IPI, vector 编号为 (0x40000 >> 12)(应用处理器的入口代码位于此处)

目前我只是想让它与 QEMU 一起工作。不幸的是,应用程序 CPU 没有跳转到 0x40000,而是跳转到 0x0,并将 cs 寄存器设置为 0x4000。 (我用 gdb 检查过)。

Intel MultiProcessor Specification (B.4.2) 解释了如果目标处理器在 RESET 或 INIT 之后立即停止,我注意到的行为是有效的。但这不应该也适用于linux内核的代码吗?它在 init-IPI 之后发送startup-IPI。或者我误解了规范?

如何才能使应用处理器跳转到 0x000VV000 而不是 0x0,并将 cs 寄存器设置为 0xVV00 ?我真的看不出 linux 在哪里做了一些改变行为的事情。

最佳答案

看来我真的误解了规范:由于应用程序cpu是以实模式启动的,0x000VV000相当于0xVV00:0x0000。仅用 16 位 ip 寄存器来表示地址是不可能的。因此需要代码段的段偏移量。

此外,使用 gdb 调试实模式代码相当复杂,因为它不考虑段偏移量。当需要查看当前位置蹦床的反汇编代码时,需要计算物理位置:

x/20i $eip+0xVV000

这使得 gdb 在 0xVV00:$eip 打印接下来的 20 条指令。

关于c - 如何正确使用startup-ipi来启动应用处理器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23962839/

相关文章:

c - 为什么我的程序跳过 for 循环? C

c - 如何为内核和设备驱动程序开发设置 YouCompleteMe?

c - 环回模式下的 ip_rcv(在 ip_input.c 中用于 ipv4)行为

x86 - 从寄存器移动到有效地址

c++ - 将静态 C 库与 C++ 代码链接时出现 "undefined reference to"错误

c - c 中声明和定义的内存分配

linux - 如何在没有 sysfs 的 linux 中查看时钟源?

c - 如何更改处理器堆栈?

visual-studio - 编译器在设置调用堆栈时生成了意外的 `IN AL, DX`(操作码 `EC`)

c - 使用 GDI 将 HBITMAP 保存为 PNG 图像?