ChronOS: The beginning.

To get from Ring 0 to Ring 3, you'll have to change the virtual address space (if you use one), ALL the registers used by the running process, instruction pointer, and privilege level. If you are using protected mode x86, then you can use the automatic task switching feature to do all these things at once.

Recall that all of this information, and more, can be stored in Task State Segments.

So what you should do:
1. Create a new Task State Segment and fill it with the information that the new process needs: all general purpose registers set to their starting values, stack pointer pointing to the stack space you have allocated for the new process, instruction pointer pointing to the entry point of the process, privilege level of the process, and so on.

  1. Create an entry for the new Task State Segment in your Global Descriptor Table.

  2. Create another new Task State Segment in the global descriptor table, but make this one point to some free space that you have allocated. The reason you need this will become apparent later, but you won't have to keep it forever.

  3. Execute the LTR instruction (Load Task Register) with the selector pointing to the empty Task State Segment.

  4. Execute an inter-segment JMP with the selector of the new process's Task State Segment that you just created. The processor will now initiate the automatic task switching feature. It will first perform privilege level checks, then it will save the current task's state into the current Task State Segment pointed to by the Task Register. If you had not loaded the task register in step 4, this step would have failed. Finally the processor will load all of the information from the target Task State Segment, and begin executing code again. The transition is now complete, and you are running your first process at privilege level 3.

Of course if you aren't using x86 protected mode, then none of this will work, but there are still other methods to use.

/r/osdev Thread