I read a tutorial on GDT (Global Descriptor Table) which defines GDT as " the one that defines base access privileges for certain parts of memory ". That means GDT is used for memory protection.
Does it perform any other tasks other than the above?
Is it a must to implement a GDT in an Operating System?
In short it would be better if anyone could elaborate on GDT in a way easy to understand.
Thanks
All the images have been taken from Intel Manual 3A, §5.1.
For further details the OP should read that manual, here I will expose just some concepts simplified for the sake of brevity and to avoid a link-only answer.
As the name suggests the Global Descriptor Table is an array of descriptors available to specify and define system wide resources (hence describe those resources).
More often than not the resource is an area of continuous memory but there are other kinds of very important resources too.
The taxonomy of the descriptors is
Descriptors
Non system descriptors
Code segment descriptor
Data segment descriptor
Stack segment descriptor (Alias of the previous)
System descriptors
System segment descriptors
LDT segment descriptor
TSS segment descriptor
Gate descriptors
Call gate descriptor
Interrupt gate descriptor
Trap gate descriptor
Task gate descriptor
Other than the GDT there is another table, the Local Descriptor Table that describes resources made available by the OS to specific contexts only.
A descriptor is identified by its table (either GDT or LDT) and its position on the table, its index.
Such index is written into specific registers, called selector registers (previously known as segment registers).
Every instruction that accesses memory implicitly or explicitly uses one of the selectors.
xor eax, eax ;eax is zero
xor esp, esp ;esp is zero
xor ebx, ebx ;ebx is zero
mov ecx, DWORD [eax] ;Use DS selector (implicit)
mov ecx, DWORD [esp] ;Use SS selector (implicit)
mov ecx, DWORD [fs:ebx] ;Use FS selector (explicit)
All these instructions read the logical address 0 but the CPU uses the descriptor to compute a new address, called linear address and perform security checks.
So those three instructions may end up reading totally different addresses.
Each selector also specifies the privilege which should be used when carrying out an operation.
The cs
selector is special because it cannot be longer changed (it has been a while actually) with a mov
but only with a branch instruction (jmp
, ret
, call
, ...).
Its purpose is not only to be used when fetching code, it also holds the code privilege level.
This privilege level is used by the CPU to check if a resource can be accessed (with the requested privilege), checks are not always trivial.
As you will see, every descriptor has a DPL field to set its privilege level.
So they are a form of protection.
Non system descriptors are used to define regions of memory intended to store code or data along with their attributes.
As you can see, the purpose of this kind of descriptors is to designate an area of memory and attach some attributes to it.
In particular the base address, the limit (size), the privilege needed to access it (the DPL field, checks are actually more involved than this), the size of the code (code only), if read/write is allowed and so on.
Long mode (64 bits) changed how the attributes are interpreted, beware of that.
System descriptors are used by the OS to control user mode programs.
These descriptors define the memory area used for storing the LDT and another structure called Task State Segment (a mechanism Intel provided for easing task switching).
There can be more than one of these structures on the system, the selected ones are indicated by the ldtr (LDT register) and tsr (TS register) registers.
These are used to transfer control to other (more or less privileged) code.
Call gates
If you look at the picture you can see that a call gate is essentially a meta descriptor, it specifies a selector and an offset into the area designated by that descriptor along with privileges.
It is used to pass control to privileged routines.
call fs:0badbabeh
Assuming fs
holds a gate's index, the CPU won't use the immediate address 0badbabeh at all, it will instead use the information on the gate itself.
Interrupt and Trap gates
These are used with interrupts, the difference between the two is that the former clear the if flag, the latter doesn't.
They are very similar to call gates.
These descriptors are actually placed into another table, the Interrupt Descriptor Table usually.
This other table is not indexed with selectors but with interrupt numbers.
If I recall correctly they can also be placed in the GDT/LDT and used like other gates.
A Task gate can be used to perform a task switch.
Task gates
These are like the call gates but transfer control to a new task (task switching).
Some resources are not simple memory area, they can be gates