Jump to userland
Once you’ve loaded the binary into memory, with separate segment for code and data, you should be able to execute the rom code. This code should run in ring3, so it means that it should be unprivileged.
The processor state needed in order to launch an unprivileged program is the following:
|ds||DS_USER | RING3_DPL|
|es||DS_USER | RING3_DPL|
|ss||SS_USER | RING3_DPL|
|esp||SS_USER upper address|
|cs||CS_USER | RING3_DPL|
|eip||Linear rom entry point|
According to the intel manual:
Privilege level checking also occurs when the SS register is loaded with the segment selector for a stack segment. Here all privilege levels related to the stack segment must match the CPL; that is, the CPL, the RPL of the stack- segment selector, and the DPL of the stack-segment descriptor must be the same. If the RPL and DPL are not equal to the CPL, a general-protection exception (#GP) is generated.
It implies that we must change the
ss privilege at the same time.
Therefore, we shall use the
iret instruction to jump to userland.
With a hand-crafted stack,
iret sets every register aforementioned except
es so we must set them beforehand.
Possible bug causes
- Memory mapping
- Event manager
- VGA driver
- Syscall wrapper
So be sure to test every part of your kernel before jumping to userland.