Messages in this thread | | | Date | Fri, 20 Jun 1997 14:17:40 +0200 | From | Thomas Pornin <> | Subject | Re: Call Gates |
| |
In article <199706201139.HAA19029@jade.cs.binghamton.edu> you write: > I am trying to understand how call gates work and as usual the Intel >documentation sucks. Can someone tell me or point me to a reference that >says EXACTLY what happens when a call gate is used, eg: from the moment >the CALL 0007:00000000 (for example) is executed to the time it is >handled. I was looking through another OS's source code and they use >0x07 as the designated call gate for system calls, however when looking >at how they initted the LDT, the table entry was the first line in the >descriptor array initialization. Is 0x07 an index into the LDT or is it >some other number (I dont think it is realted to the type, though). I >would think that once executed, the CALL makes the processor goto LDT[7] >and pull out that call gate then do the funky address computation and >stack change and do the other code...
I once played with these. I hope I have not forgotten too much.
In Intel architecture, under protected mode, segment registers contain an index to a segment descriptor in the GDT or the LDT. The descriptors are 8 bytes long, so the indexes should be multiples of 8. The last three bits are used to indicate whether the LDT or the GDT should be used, and some trickery about privilege levels. There are four such levels (ring 0 to ring 3) and call gates are meant to allow calls from some unpriviledged code (ring 3 for instance) to a priviledged code (ring 0). Here, the 0007 indicates the first (0) entry in the LDT, and something like "calling from ring 3 but I want to become ring 0". The offset part is irrelevant, as the real target address is hardcoded in the call gate descriptor.
Just after the call, the execution continues from the point targeted by the call gate descriptor, with the priviledge level stored in this descriptor. This is indeed a way of implementing system calls.
The way chosen for linux is a bit more hacky, but it has some advantages. Linux uses a user-triggered interrupt; the system call is an "int $80". I think it might be a bit slower, but it saves the flags automatically, allow all types of travels between rings, and this opcode is much smaller than the "call 0007:00000000" one (2 bytes vs 7). It also has the great characteristic of switching to a kernel stack, as it would be really BAD is the kernel had to rely on the user-level stack.
When I saw your message, I first thought it came from some Microsoft fan... :)
--Thomas Pornin
| |