CygnusOlor wrote:
In user mode, the kernel and the processes will have separate page maps.
In a typical OS, the kernel doesn't have its own set of page tables. Instead, each set of user page tables is split between user mappings that are different for each user and kernel mappings that are the same everywhere. For 32-bit x86, there are no limitations on how user and kernel addresses are assigned, but it's common to split the address space at the 2GB or 3GB mark, with all addresses below that point available to the user and the rest available to the kernel. (For 64-bit x86, there are no hardware limitations, but compilers and binary formats are optimized for user mappings in the lower half and kernel mappings in the upper half.)
Some OSes do have separate page tables for the kernel, either to increase the available virtual address space for users (because fewer kernel-only pages will need to be mapped everywhere) or to work around specific CPU vulnerabilities. Most hobby OS developers aren't worried about either of those things.
Examples on the wiki and elsewhere are written on the assumption that the kernel is mapped in every set of page tables, which means it's safe for the kernel to set CR3 at any time. If you're not going to map the kernel in every set of page tables, you'll need to ensure you only set CR3 at kernel entry and exit points, while accessing only the few kernel-only pages that are mapped everywhere.
CygnusOlor wrote:
That means that I'll have to identity map a few critical pages for usage during the task switch.
You don't need to identity-map anything unless you're disabling paging, and you shouldn't be disabling paging.
CygnusOlor wrote:
Return from the interrupt, returning us to user mode.
You might not be returning from an interrupt anymore. The next task could have saved its state somewhere else, like a syscall.
CygnusOlor wrote:
I wanted to ask — is this a good concept?
It sounds unnecessarily complicated.