Skip to content

Add sysenter fast system call support to DragonWare's kernel#2

Draft
tseli0s wants to merge 15 commits into
masterfrom
sysenter-support
Draft

Add sysenter fast system call support to DragonWare's kernel#2
tseli0s wants to merge 15 commits into
masterfrom
sysenter-support

Conversation

@tseli0s
Copy link
Copy Markdown
Owner

@tseli0s tseli0s commented May 10, 2026

sysenter/sysexit are a pair of instructions introducing low overhead ring 0 entries. From https://wiki.osdev.org/SYSENTER:

"Executes a fast call to a level 0 system procedure or routine. SYSENTER is a companion instruction to SYSEXIT.
The instruction is optimized to provide the maximum performance for system calls from user code running at privilege level 3 to
operating system or executive procedures running at privilege level 0." -- Intel IA-32 (64) programming manual, volume 2B.

For a microkernel like DragonWare, where system calls are done for almost every task (Because message passing is done using system calls), using this instruction can be very beneficial to performance, reducing the cycles needed to enter the kernel to about half or even more.

tseli0s added 7 commits May 10, 2026 10:09
Preparation to introduce proper sysenter/sysexit support in DragonWare
and reduce the system call overhead significantly by only pushing what's
necessary and not loading a full InterruptStackFrame.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
From v0.0.2 forwards, the kernel is going to use registers ebx, esi, edi
and ebp for arguments in the exposed system calls, with eax used as the
system call number.

This is in preparation to move into sysenter/sysexit, which need to have
ecx/edx preserved but the kernel uses them for the second and third
arguments of system calls.

Obviously this is a breaking change, so libc's shim handlers to trigger
a system call are also updated to use the appropriate registers.
Five-parameter system call support has been temporarily removed.

Note that temporarily the SYSCALL_TICKS_SINCE_BOOT system call is
broken, and as such, cannot be used. This will be addressed in another
commit.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
No longer defined (The kernel supports up to four parameters per system
call for now). Additionally drop __make_syscall_ia32_5param_reti32()
which is a jump to that function.

Both definitions of these two stubs were removed in 65091ae.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
See commit a886e1d of which this one is a supplement of. System calls do
not need a complete InterruptStackFrame - More than half the state saved
in every interrupt is completely unused.

Additionally, neither DragonWareSyscall nor POSIXSyscall should return
any values - They are ignored entirely, so no point in even returning
anything. That was a remnant from when interrupts were the only way to
switch tasks around.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Update the interrupt handling code to copy the system call registers
returned by DragonWareSyscall to the InterruptStackFrame of the
function. Otherwise no matter what DragonWareSyscall returns in the
registers, it will be completely ignored, like the system call was never
performed.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
…ailable

Check if the sysenter/sysexit instruction pair is supported on the
machine. If so, the kernel has enabled support for it and it can be used
for faster system calls.

If not, then the old, software interrupt path will be used instead. libc
will install the correct gate during early initialization by detecting
the feature support using CPUID.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Update the sysenter code to create a SystemCallFrame by pushing all the
registers expected inside SystemCallFrame on the stack and then passing
the stack pointer as the argument of DragonWareSyscall. This effectively
means that now DragonWare supports sysenter to some extent, although
support is buggy and incomplete.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
@tseli0s tseli0s self-assigned this May 10, 2026
@tseli0s tseli0s added enhancement New feature or request kernel Kernel-related feature or bug user-programs Userland related feature or bug libc C library implementation feature or bug breaking Breaking change (For pull requests only) performance Performance and throughput related bug or feature labels May 10, 2026
tseli0s added 8 commits May 15, 2026 10:36
It was only used for supporting _DWRaiseIOPL in both software interrupts
and the WIP sysenter support, but due to incompatibilities between the
two, the register will no longer be saved and the system call will be
replaced with a proper TSS I/O bitmap instead.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Arithmetic on a NULL pointer (Address 0) is undefined behaviour and we
cannot rely on it. Using __builtin_offsetof() is a better approach that
also allows for some compiler optimizations.

Additionally, clean up some code like the unused foreach() macro and use
parentheses in places where precedence matters.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
They were a remnant from before the kernel used ports for all IPC
communication. They only waste memory and lines of code, so they can be
dropped safely.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
It is no longer used and the functionality is replaced by another system
call that's in the works. See also a2a28d0 for the relevant previous
part.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
This system call replaces _DWRaiseIOPL (From v0.0.1 relying on EFLAGS
state) with a more secure function, that is also fine grained and
technically a little faster. The relevant userland will be updated in
another commit.

Replacing _DWRaiseIOPL was a necessity due to the limitations of
sysenter and its very minimal context saving. Making the kernel work
well with both mechanisms (software interrupts and sysenter) to preserve
hardware compatibility requires some refactoring in this system call.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
…ocess`

It has to be implemented otherwise context switching will break any
process that previously had the right to access a port.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
See commit d0f2f10 for more details. The _DWRaiseIOPL system call has
been dropped and has no effect anymore, and the system call number now
corresponds to _DWRequestPorts.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Per the Intel Developer Manuals:

"RFLAGS.IF := 0;"

Meaning they are automatically cleared when `sysenter` is executed, and
there's no reason to execute cli manually.

Interrupts still have to be manually reenabled before returning from a
system call made using sysenter.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
@tseli0s tseli0s marked this pull request as ready for review May 15, 2026 11:28
@tseli0s tseli0s marked this pull request as draft May 15, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change (For pull requests only) enhancement New feature or request kernel Kernel-related feature or bug libc C library implementation feature or bug performance Performance and throughput related bug or feature user-programs Userland related feature or bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant