How to correctly use a startup-ipi to start an application processor?
c, intel, linux-kernel, smp, x86
Solution
It seems that I really misunderstood the specification: Since the application cpu is started in real mode `0x000VV000` is equivalent to `0xVV00:0x0000`. It is not possible to represent the address just in the 16 bit `ip` register. Therefore a segment offset for the code segment is required.
Additionally, debugging real mode code with gdb is comparable complicated because it does not respect the segment offset. When required to see the disassembled code of the trampoline at the current position, it is necessary to calculate the physical location:
x/20i $eip+0xVV000
This makes gdb print the next 20 instructions at `0xVV00:$eip`.
Problem
My goal is to let my own kernel start an application cpu. It uses the same mechanism as the linux kernel: - Send asserting and level triggered init-IPI - Wait... - Send deasserting and level triggered init-IPI - Wait... - Send up to two startup-IPIs with vector number `(0x40000 >> 12)` (the entry code for the application processor lies there) Currently I'm just interested in making it work with QEMU. Unfortunately, instead of jumping to `0x40000`, the application cpu jumps to `0x0` with the `cs` register set to `0x4000`. (I checked with gdb). The Intel MultiProcessor Specification (B.4.2) explains that the behavior that I noticed is valid if the target processor is halted immediately after RESET or INIT. But shouldn't this also apply to the code of the linux kernel? It sends the startup-IPI after the init-IPI. Or do I misunderstand the specification? What can I do to have the application processor jump to `0x000VV000` and not to `0x0` with the `cs` register set to `0xVV00`? I really can't see, where linux does something that changes the behavior.