Octocontrabass wrote:
rdos wrote:
You cannot use a protected mode call gate [...] when the processor is in long mode.
Correct. You can only use long mode call gates in long mode.
Which is quite useless when the kernel is running in compatibility mode.
Still, when I tried to implement long mode applications, I used SYSCALL. The kernel side of SYSCALL needs to load a kernel stack, and to make this at least somewhat efficient I had to use a flat kernel stack with guard pages. I could load the linear address of the kernel stack through the thread control block. I also had to optimize the dispatch of the server routine by mapping the syscall table to a fixed location and using that location from long mode. Then I needed to alias pointers using paging. All of these things to some degree compromised the integrity of my kernel. The flat kernel stack is only enabled if the long mode loader is present to avoid the integrity issue of a flat stack that can reference anything.
Octocontrabass wrote:
rdos wrote:
This method requires two segment register loads on entry, [...] and two for returning to user mode.
SYSCALL, SYSENTER, SYSRET, and SYSEXIT do not perform segment register loads. That's part of the reason why they're so fast!
That's also the reason why they suck when used with segmentation.
Octocontrabass wrote:
rdos wrote:
Needing twice as many segment register loads and a dozen or so additional operations cannot be faster, even if syscall / sysenter has some optimizations.
Perhaps you should prove it with some benchmarks.
I think this should be obvious. At the caller side, a far call must be done to save cs. You must save ss too on the user mode stack. With call gates, this context is saved on the kernel stack. At the kernel side, another far call must be done to reach the server routine. Additionally, sysenter uses a fixed kernel stack and disables interrupts, and so a thread-stack must be loaded before interrupts can be enabled again. Each CPU core will need it's own sysenter kernel stack. Call gates automatically loads the kernel stack from the TSS.
Octocontrabass wrote:
rdos wrote:
SYSENTER setup a flat CS & SS in kernel, and won't save neither the user mode cs nor the user mode ss. This means that the caller must save CS & SS on the user mode stack and on return these must be restored.
SYSCALL/SYSENTER/SYSRET/SYSEXIT are designed for a flat address space.
Sure, but I don't use a flat kernel and I have two sets of user mode flat selectors. One for normal applications and one for servers. The application flat selectors have a 3GB limit and the server flat selectors have a 2GB limit. SYSEXIT will return to user mode with a 4GB limit, which will compromise kernel integrity (as well as the kernel part of servers). In fact, there is no selector with a 4GB limit that user mode can load, and so it can't reference kernel memory, neither directly nor indirectly by passing bad pointers.
Additionally, the user mode flat selectors can have a non-zero base. This will complicate things even more.
I also support segmented applications, and those work just as well with call gates, but not at all with SYSENTER.