Subject: Which Gates to use?
To: None <port-i386@NetBSD.ORG>
From: Charles M. Hannum <mycroft@gnu.ai.mit.edu>
List: port-i386
Date: 10/25/1994 14:48:58
It seems to me that there are some real limitations to using a call
gate to enter system calls. Basically:
We have to fiddle around shuffling eflags into the frame correctly so
the final iret can restore it. This means that if we get a
single-step trap when entering a syscall, we can't simply have trap()
turn off the trace bit, because it wouldn't be restored correctly on
exit from the syscall; so we also have to fiddle around with the trace
bit in the syscall handler.
This in turn makes it somewhat ugly (at best) to make single-stepping
into a system call with DDB configured *not* cause DDB to be
activated.
To put it as simply as possible, doing it this way sucks.
It seems to me that switching to a trap gate, and using an INT
instruction to enter the kernel, would be easier. This has some
significant advantages:
1) It's faster and simpler. The eflags register is saved by the CPU
automatically on entering a trap gate, and we can just turn off the
trace bit in trap() if we get a single-step interrupt from kernel mode
on the first instruction of the syscall handler.
2) The DDB problem is very simple to fix. See item 1.
3) Programs using VM86 mode (i.e. pcemu or dosemu) can do system calls
directly from 16-bit code, rather than having to switch to a 32-bit
code segment first. Thus they will be faster. (They'll still have to
fiddle with the stack a bit so that the kernel will know where to find
the syscall arguments.)
In addition, it means the glue code for each syscall is 5 bytes
smaller, though this is not really significant.
Obviously, this requires also having the old call gate, for programs
compiled for previous versions of NetBSD, and for 386BSD, BSDI, iBCS2,
and SVR4. Note that Linux currently uses a trap gate, as far as I
know.
Does anyone have serious objections to this?