Exceptions directly in userspace?
Posted: Sat Jan 29, 2005 7:51 pm
I just figured that on x86 it seems to be possible to have some of the interrupt vectors point to CPL3 segments. So in theory, CPU exceptions that are safe to handle in userspace could be handled without trapping into kernel at all.
Now, I'm wondering whether this has been used, and whether there are some things to watch out. Basicly, what I'm thinking would be to have piece of the kernel code readable to userspace and trap into that code keeping CPL as 3, then dispatch to the real user-settable exception handler from there. The only real purpose of having predefined userspace "kernel" code would be to avoid tweaking IDT on process switches, but one could ofcourse have a pre-process IDT too, since IDT's referenced with a linear address. Either method would work.
At least exceptions 0 (divide), 4 (overflow), 5 (bound), 16 (math), 17 (align check) and 19 (simd) could be dispatched safely in userspace.
Additionally, if we had debugger support in userspace (and communicated with debugger using IPC, or self debugged), we could have 1 (debug), 3 (break) and 6 (inv op) in userspace just as well.
Of the remaining exceptions 2 (NMI), 8 (double fault) and 18 (machine check) are probably fatal. 10 (tss), 11 (segment not present) and 12 (stack) normally won't happen with your typical no-segments setup. Copro overrun 9 won't happen with modern processors.
So 7 (fpu not available), 13 (general protection) and 14 (page fault, see below) seem like the only ones that kernel should actually do something about.
What would be avoided would be an extra stack switch and moving data from kernel to userspace when there is an userspace signal handler. Additionally, the userspace "stub" could skip reloading CS on return, which could save a few more cycles. (?)
Anyway, the main motivation would be that more of the exception handling could be directly accounted to the faulting process.
Page faults unfortunately can't be handled in userspace even in self-paging case, because the trap must disable interrupts and kernel read CR2 so that we can get the address. I wonder why the page isn't pushed with the error-code (there would be space for it just fine and one usually doesn't need to whole address).
Now, am I missing something?
Now, I'm wondering whether this has been used, and whether there are some things to watch out. Basicly, what I'm thinking would be to have piece of the kernel code readable to userspace and trap into that code keeping CPL as 3, then dispatch to the real user-settable exception handler from there. The only real purpose of having predefined userspace "kernel" code would be to avoid tweaking IDT on process switches, but one could ofcourse have a pre-process IDT too, since IDT's referenced with a linear address. Either method would work.
At least exceptions 0 (divide), 4 (overflow), 5 (bound), 16 (math), 17 (align check) and 19 (simd) could be dispatched safely in userspace.
Additionally, if we had debugger support in userspace (and communicated with debugger using IPC, or self debugged), we could have 1 (debug), 3 (break) and 6 (inv op) in userspace just as well.
Of the remaining exceptions 2 (NMI), 8 (double fault) and 18 (machine check) are probably fatal. 10 (tss), 11 (segment not present) and 12 (stack) normally won't happen with your typical no-segments setup. Copro overrun 9 won't happen with modern processors.
So 7 (fpu not available), 13 (general protection) and 14 (page fault, see below) seem like the only ones that kernel should actually do something about.
What would be avoided would be an extra stack switch and moving data from kernel to userspace when there is an userspace signal handler. Additionally, the userspace "stub" could skip reloading CS on return, which could save a few more cycles. (?)
Anyway, the main motivation would be that more of the exception handling could be directly accounted to the faulting process.
Page faults unfortunately can't be handled in userspace even in self-paging case, because the trap must disable interrupts and kernel read CR2 so that we can get the address. I wonder why the page isn't pushed with the error-code (there would be space for it just fine and one usually doesn't need to whole address).
Now, am I missing something?