HALICERY

free-time coding, hardware dev, articles

Top
Home 8042 Blogs About
Home IntelEssential The 386: IA-32 Protected Mode IntelEssentialGATE

Last modified: Mon Jun 29 08:08:50 UTC+0200 2026 © A. Tarpai


Automatic Stack Switch with GATE control descriptors

This analysis came from..

I want interrupts run on their own stack - and not on the interrupted program

Maybe I exactly fiddle with SP.. then an interrupt occurs. Not good, CPU starts pushing data.. destroying my memory area. Or in deep recursive call and stack is almost full..

Without CPU hardware support this is not possible (unless we disable interrupts for the whole operation, which is not a good idea either). Intel processors can do this – but only when the interrupted program runs on lesser privilege.

Code Privilege level change

It's possible to CALL to higher privilege level code through a CALL GATE or enter higher privilege level code via exception or interrupt. Matching RETF/IRET will return to lower privilege level:

     CALL GATE             RETF
INTERRUPT GATE             IRET

        --> 0              0 --\
1 ----/---> 1              1 ---\---->   1
2 ---/----> 2              2 ----\--->   2
3 --/                              -->   3

to higher privilege        to lower privilege

It's not possible to CALL to lower privilege level or return to higher privilege level.

Note that JMP and the INT n instruction cannot change privilege level.

These transitions involve automatic stack-switch.

HW Stack Switch

CPU can invoke routines to run on a separate, isolated stack.

                  CALL GATE              RETF
             INTERRUPT GATE              IRET

                      --> 0              0 --\
              1 ----/---> 1              1 ---\----> 1
              2 ---/----> 2              2 ----\---> 2
              3 --/                              --> 3


|            |             |            |             |            |
+------------+             +------------+     TSS     +------------+
|            |             |     SS     | <-- SS:SP   |            |
+------------+             +------------+             +------------+
|            |             |     SP     |             |            |
+------------+             +------------+             +------------+
|            |             |     ..     |             |            |
+------------+                   ..                   +------------+
|            | <-- SP      |     ..     |             |            | <-- SP
+------------+             +------------+             +------------+
|            |             |     CS     |             |            |
                           +------------+
    Lower                  |     IP     |                 Lower
  Privilege                +------------+               Privilege
    STACK                  |            |                 STACK

                               Higher
                             Privilege
                               STACK


.. is copied optional parameters (CALL GATE) or FLAGS (INTERRUPT GATE)

Works only through GATE (INTERRUPT or CALL), when target code is more privileged and non-conforming (C=0). New SS:SP read from the TSS structure – pointed by the Task Register (TR).

The matching RETF/IRET will recognize a lower privilege CS SELECTOR on stack and returns with stack switch by popping SS:SP.

Code transfer through CALL GATE mechanism

CALL GATE-SELECTOR:offset  (offset is ignored)


                                        CALL GATE
   current         SELECTOR             DESCRIPTOR              CODE DESCRIPTOR
   CPU CS          in instr             IN MEMORY               IN MEMORY


                                       +--------------+        +--------------+
15           0   15           0        | idx    |T| * |        |  BASE/LIMIT  |
+------------+   +------------+        +--------------+        +--------------+
| idx  |T|CPL|   | idx  |T|RPL|  --->  |P|DPL|0| ...  |  --->  |P|DPL|1| X  C |
                                       +--------------+        +--------------+
                                       |   OFFSET     |        |              |

                                       1.                      2.
                                       DPL >= CPL              DPL = CPL      --> SAME PRIVILEGE TRANSFER
                                       DPL >= RPL              DPL < CPL C=1  --> SAME PRIVILEGE TRANSFER
                                                               DPL < CPL C=0  --> MORE PRIVILEGE TRANSFER


                                            |                           |
                                            |                           |
                                            |                           |
        ^                                   |                           |
        |                                   | LOAD CS                   |
        |                                   | from GATE                 |
        |                                   |                           |
        |                                   |                           |
        |                                   |                           |
        +-----------------------------------+                           | CACHE
                                                                        | DESCRIPTOR
        ^ Set CPL to DPL                                                |
        | MORE PRIVILEGE TRANSFER                                       |
        |                                                               |
+-------------+------+------+------+------+------+                      |
|P|DPL|S| ... |     BASE 23..0     | LIMIT 15..0 |     <----------------+
+-------------+------+------+------+------+------+


* In GATE DESCRIPTORS the Code Selector RPL is ignored


1. Protection at GATE-LEVEL:
   Cannot access more priv GATE at all.
   Both CPL and RPL checked. Eg. doesn't help to set RPL 0, when CPL is 3.
   But fine to use less priv - like data segment
   else #GP(call gate selector)

2. Protection at CODE TRANSITION
   Cannot enter to less priv at all
   else #GP(code segment selector)
   But allowed to call to MORE PRIV using GATE:
   new SS:SP from TSS.. stack-switch.. copy parameters.. (non-conforming only)
   Conforming is simply CALL TO SAME PRIVILEGE

CALL GATE TO SAME PRIVILEGE:

CALL GATE TO MORE PRIVILEGE:

Code transfer through INTERRUPT GATE mechanism

Similar to CALL and as if Selector from vector number has RPL=0 (shifting by 3).

But software- and hardware interrupts are handled differently:

                                        INTERRUPT GATE
   current         SELECTOR             DESCRIPTOR              CODE DESCRIPTOR
   CPU CS          from vector          IN MEMORY               IN MEMORY


                                       +--------------+        +--------------+
15           0   15           0        | idx    |T| * |        |  BASE/LIMIT  |
+------------+   +------------+        +--------------+        +--------------+
| idx  |T|CPL|   | idx  |0| 0 |  --->  |P|DPL|0| ...  |  --->  |P|DPL|1| X  C |
                                       +--------------+        +--------------+
                                       |   OFFSET     |        |              |

                                        1.                      2.
                 INT n -->              DPL >= CPL              DPL = CPL      --> SAME PRIVILEGE TRANSFER
                                                                DPL < CPL C=1  --> SAME PRIVILEGE TRANSFER


                                        1.                      2.
          EXC and INTR -->              DPL ignored             DPL = CPL      --> SAME PRIVILEGE TRANSFER
                                                                DPL < CPL C=1  --> SAME PRIVILEGE TRANSFER
                                                                DPL < CPL C=0  --> MORE PRIVILEGE TRANSFER

* In GATE DESCRIPTORS the Code Selector RPL is ignored

1. GATE-LEVEL protection

2. CODE TRANSITION protection

Return to lower privilege code with stack switch

The RETF and IRET instructions recognize the lower privilege CS SELECTOR on stack: and will pop SS:SP resulting in stack switch.

RETF N pops N bytes from both stacks. This should match the 0..31 WORD/DWORD number in the 16/32-bit CALL GATE Descriptor.