Global Descriptor Table: Difference between revisions

m
fixed reference to TSS Descriptor in Intel SDM
[unchecked revision][unchecked revision]
m (fixed reference to TSS Descriptor in Intel SDM)
 
(24 intermediate revisions by 6 users not shown)
Line 1:
The '''Global Descriptor Table''' ('''GDT''') is a binary data structure specific to the [[IA32_Architecture_Family |IA-32]] and [[X86-64 |x86-64]] architectures. It contains entries telling the CPU about memory [[Segmentation|segments]]. A similar [[Interrupt Descriptor Table]] exists containing [[task]] and [[Interrupts|interrupt]] descriptors.
 
It is recommended to read the [[GDT Tutorial]].
Line 7:
The '''GDT''' is pointed to by the value in the '''GDTR''' register. This is loaded using the '''LGDT''' assembly instruction, whose argument is a pointer to a '''GDT Descriptor''' structure:
 
{| class="wikitable"
<pre>
|+ GDT Descriptor (GDTR):
!style="width: 66%; text-align: left;" |79 (64-bit mode) <br> 48 (32-bit mode)&nbsp;&nbsp;&nbsp;<span style="float: right;">16</span>
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
!style="width: 34%; text-align: left; vertical-align: bottom;" |15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
┃79 (64-bit Mode) / 48 (32-bit Mode) 16│15 0┃
|-
┠───────────────────────────────────────────────────────────────┼───────────────────────────────┨
|'''Offset'''<br>63 (64-bit mode) <br> 31 (32-bit mode)&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
┃Offset │Size ┃
|'''Size'''<br><br>15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
┃63 (64-bit Mode) / 31 (32-bit Mode) 0│15 0┃
|}
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
</pre>
 
* '''Size:''' The size of the table in bytes subtracted by 1. This subtraction occurs because the maximum value of '''Size''' is 65535, while the '''GDT''' can be up to 65536 bytes in length (8192 entries). Further, no '''GDT''' can have a size of 0 bytes.
* '''Offset:''' The linear address of the '''GDT''' (not the physical address, paging applies).
Line 28 ⟶ 26:
The entries in the '''GDT''' are 8 bytes long and form a table like this:
 
{|class="wikitable"
<pre>
|+ Global Descriptor Table
Table: Address:
! Address !! Content
┏━━━━━━━━━━━┓
|-
┃ Null ┃ IDTR Offset + 0
| GDTR Offset + 0 || Null
┠───────────┨
|-
┃ Entry 1 ┃ IDTR Offset + 8
| GDTR Offset + 8 || Entry 1
┠───────────┨
|-
┃ Entry 2 ┃ IDTR Offset + 16
| GDTR Offset + 16 || Entry 2
┠───────────┨
|-
┃ Entry 3 ┃ IDTR Offset + 24
| GDTR Offset + 24 || Entry 3
┠───────────┨
|- style="text-align: center;"
┃ ... ┃ ...
| '''...''' || '''...'''
┠───────────┨
|}
</pre>
 
The first entry in the '''GDT''' (Entry 0) should always be null and subsequent entries should be used instead.
 
Entries in the table are accessed by '''[[Segment Selector|Segment Selectors]]''', which are loaded into '''[[Segmentation]]''' registers either by assembly instructions or by hardware functions such as '''[[Interrupts]]'''.
 
== Segment Descriptor ==
 
Each entry in the table is contains '''Segment Descriptor''' entries which are 8 bytes long. Each entry has a complex structure:
{| class="wikitable"
 
|+ Segment Descriptor
<pre>
!style="width: 20%; text-align: left;"|63&nbsp;&nbsp;&nbsp;<span style="float: right;">56</span>
SEGMENT DESCRIPTOR:
!style="width: 12.5%; text-align: left;"|55&nbsp;&nbsp;&nbsp;<span style="float: right;">52</span>
┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━┓
!style="width: 12.5%; text-align: left;"|51&nbsp;&nbsp;&nbsp;<span style="float: right;">48</span>
┃63 56│55 52│51 48│47 40│39 32┃
!style="width: 25%; text-align: left;"|47&nbsp;&nbsp;&nbsp;<span style="float: right;">40</span>
┠───────────────────────┼───────────┼───────────┼───────────────────────┼───────────────────────┨
!style="width: 25%; text-align: left;"|39&nbsp;&nbsp;&nbsp;<span style="float: right;">32</span>
┃Base │Flags │Limit │Access Byte │Base ┃
|-
┃31 24│4 0│19 16│7 0│23 16┃
|'''Base'''<br>31&nbsp;&nbsp;&nbsp;<span style="float: right;">24</span>
┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┛
|'''Flags'''<br>3&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|'''Limit'''<br>19&nbsp;&nbsp;&nbsp;<span style="float: right;">16</span>
┃31 16│15 0┃
|'''Access Byte'''<br>7&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
┠───────────────────────────────────────────────┼───────────────────────────────────────────────┨
|'''Base'''<br>23&nbsp;&nbsp;&nbsp;<span style="float: right;">16</span>
┃Base │Limit ┃
|-
┃15 0│15 0┃
!colspan=3 style="text-align: left;"|31 &nbsp;&nbsp;<span style="float: right;">16</span>
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
!colspan=2 style="text-align: left;"|15 &nbsp;&nbsp;<span style="float: right;">0</span>
</pre>
|-
|colspan=3|'''Base'''<br>15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|colspan=2|'''Limit'''<br>15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|}
 
* '''Base:''' A 32-bit value containing the linear address where the segment begins.
Line 74 ⟶ 76:
For more information, see '''Section 3.4.5: Segment Descriptors''' and '''Figure 3-8: Segment Descriptor''' of the Intel Software Developer Manual, Volume 3-A.
 
{| class="wikitable"
=== Access Byte ===
|+ Access Byte
|-
!style="width: 12.5%;"|7
!style="width: 12.5%;"|6
!style="width: 12.5%;"|5
!style="width: 12.5%;"|4
!style="width: 12.5%;"|3
!style="width: 12.5%;"|2
!style="width: 12.5%;"|1
!style="width: 12.5%;"|0
|-
|'''P''' ||colspan=2|'''DPL''' || '''S''' || '''E''' || '''DC''' || '''RW''' || '''A'''
|}
 
* '''P:''' Present bit. Allows an entry to refer to a valid segment. Must be set ('''1''') for any valid segment.
The '''Access Byte''' is laid out as follows:
* '''DPL:''' Descriptor privilege level field. Contains the [[Security#Rings|CPU Privilege level]] of the segment. '''0''' = highest privilege (kernel), '''3''' = lowest privilege (user applications).
 
<pre>
ACCESS BYTE:
┏━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┓
┃ 7 │ 6 5 │ 4 │ 3 │ 2 │ 1 │ 0 ┃
┠─────────┼───────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┨
┃Pr │Privl │S │Ex │DC │RW │Ac ┃
┗━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┛
</pre>
 
* '''Pr:''' Present bit. Allows an entry to refer to a valid segment. Must be set ('''1''') for any valid segment.
* '''Privl:''' Descriptor privilege level field. Contains the [[Security#Rings|CPU Privilege level]] of the segment. '''0''' = highest privilege (kernel), '''3''' = lowest privilege (user applications).
* '''S:''' Descriptor type bit. If clear ('''0''') the descriptor defines a system segment (eg. a [[Task_State_Segment|Task State Segment]]). If set ('''1''') it defines a code or data segment.
* '''ExE:''' Executable bit. If clear ('''0''') the descriptor defines a data segment. If set ('''1''') it defines a code segment which can be executed from.
* '''DC:''' Direction bit/Conforming bit.
** For data selectors: Direction bit. If clear ('''0''') the segment grows up. If set ('''1''') the segment [[Expand_Down|grows down]], ie. the '''Offset''' has to be greater than the '''Limit'''.
** For code selectors: Conforming bit.
*** If clear ('''0''') code in this segment can only be executed from the ring set in '''PrivlDPL'''.
*** If set ('''1''') code in this segment can be executed from an equal or lower privilege level. For example, code in ring 3 can far-jump to ''conforming'' code in a ring 2 segment. The '''PrivlDPL''' field represent the highest privilege level that is allowed to execute the segment. For example, code in ring 0 cannot far-jump to a conforming code segment where '''PrivlDPL''' is 2, while code in ring 2 and 3 can. Note that the privilege level remains the same, ie. a far-jump from ring 3 to a segment with a '''PrivlDPL''' of 2 remains in ring 3 after the jump.
* '''RW:''' Readable bit/Writable bit.
** For code segments: Readable bit. If clear ('''0'''), read access for this segment is not allowed. If set ('''1''') read access is allowed. Write access is never allowed for code segments.
** For data segments: Writeable bit. If clear ('''0'''), write access for this segment is not allowed. If set ('''1''') write access is allowed. Read access is always allowed for data segments.
* '''A:''' Accessed bit. The CPU will set it when the segment is accessed unless set to '''1''' in advance. This means that in case the GDT descriptor is stored in read only pages and this bit is set to '''0''', the CPU trying to set this bit will trigger a page fault. Best left set to '''1''' unless otherwise needed.
* '''Ac:''' Accessed bit. Best left clear ('''0'''), the CPU will set it when the segment is accessed.
 
{| class="wikitable"
=== Flags ===
|+ Flags
|-
!style="width: 25%;"|3
!style="width: 25%;"|2
!style="width: 25%;"|1
!style="width: 25%;"|0
|-
|'''G''' || '''DB''' || '''L'''
|Reserved
|}
 
* '''G:''' Granularity flag, indicates the size the '''Limit''' value is scaled by. If clear ('''0'''), the '''Limit''' is in 1 Byte blocks (byte granularity). If set ('''1'''), the '''Limit''' is in 4 KiB blocks (page granularity).
The '''Flags''' are laid out as follows:
* '''DB:''' Size flag. If clear ('''0'''), the descriptor defines a 16-bit protected mode segment. If set ('''1''') it defines a 32-bit protected mode segment. A GDT can have both 16-bit and 32-bit selectors at once.
* '''L:''' Long-mode code flag. If set ('''1'''), the descriptor defines a 64-bit code segment. When set, '''DB''' should always be clear. For any other type of segment (other code types or any data segment), it should be clear ('''0''').
 
== System Segment Descriptor ==
<pre>
FLAGS:
┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┓
┃ 3 │ 2 │ 1 │ 0 ┃
┠─────────┼─────────┼─────────┼─────────┨
┃Gr │Sz │L │Reserved ┃
┗━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┛
</pre>
 
For system segments, such as those defining a '''[[Task State Segment]]''' or '''[[Local Descriptor Table]]''', the format of the '''Access Byte''' differs slightly, in order to define different types of system segments rather than code and data segments.
* '''Gr:''' Granularity flag, indicates the size the '''Limit''' value is scaled by. If clear ('''0'''), the '''Limit''' is in 1 Byte blocks (byte granularity). If set ('''1'''), the '''Limit''' is in 4 KiB blocks (page granularity).
 
* '''Sz:''' Size flag. If clear ('''0'''), the descriptor defines a 16-bit protected mode segment. If set ('''1''') it defines a 32-bit protected mode segment. A GDT can have both 16-bit and 32-bit selectors at once.
For more information, see '''Section 3.5: System Descriptor Types''' and '''Figure 3-2: System-Segment and Gate-Descriptor Types''' of the Intel Software Developer Manual, Volume 3-A.
* '''L:''' Long-mode code flag. If set ('''1'''), the descriptor defines a 64-bit code segment. When set, '''Sz''' should always be clear. For any other type of segment (other code types or any data segment), it should be clear ('''0''').
 
{| class="wikitable"
|+ Access Byte
|-
!style="width: 12.5%;"|7
!style="width: 12.5%;"|6
!style="width: 12.5%;"|5
!style="width: 12.5%;"|4
!style="width: 12.5%;"|3
!style="width: 12.5%;"|2
!style="width: 12.5%;"|1
!style="width: 12.5%;"|0
|-
|'''P'''&nbsp;&nbsp;&nbsp; ||colspan=2|'''DPL''' || '''S''' || colspan=4|'''Type'''
|}
 
* '''Type:''' Type of system segment.
 
Types available in 32-bit protected mode:
* '''0x1:''' 16-bit TSS (Available)
* '''0x2:''' LDT
* '''0x3:''' 16-bit TSS (Busy)
* '''0x9:''' 32-bit TSS (Available)
* '''0xB:''' 32-bit TSS (Busy)
 
Types available in Long Mode:
* '''0x2:''' LDT
* '''0x9:''' 64-bit TSS (Available)
* '''0xB:''' 64-bit TSS (Busy)
 
== Long Mode System Segment Descriptor ==
 
For a '''[[Task State Segment]]''' or '''[[Local Descriptor Table]]''' in '''[[Long Mode]]''', the format of a '''Segment Descriptor''' differs to ensure that the '''Base''' value can contain a 64-bit '''[[Linear Address]]'''. It takes up the space in the table of two usual entries, in a little endian format, such that the lower half of this entry precedes the higher half in the table.
 
For more information, see '''Section 8.2.3: TSS Descriptor in 64-bit Mode''' and '''Figure 8-4: Format of TSS and LDT Descriptors in 64-bit Mode''' of the Intel Software Developer Manual, Volume 3-A.
 
{| class="wikitable" style="display: inline-table;"
|+ 64-bit System Segment Descriptor
|-
!colspan=5 style="text-align: left;"|127 &nbsp;&nbsp;<span style="float: right;">96</span>
|-
|colspan=5|Reserved
|-
!colspan=5 style="text-align: left;"|95 &nbsp;&nbsp;<span style="float: right;">64</span>
|-
|colspan=5|'''Base'''<br>63&nbsp;&nbsp;&nbsp;<span style="float: right;">32</span>
|-
!style="width: 20%; text-align: left;"|63&nbsp;&nbsp;&nbsp;<span style="float: right;">56</span>
!style="width: 12.5%; text-align: left;"|55&nbsp;&nbsp;&nbsp;<span style="float: right;">52</span>
!style="width: 12.5%; text-align: left;"|51&nbsp;&nbsp;&nbsp;<span style="float: right;">48</span>
!style="width: 25%; text-align: left;"|47&nbsp;&nbsp;&nbsp;<span style="float: right;">40</span>
!style="width: 25%; text-align: left;"|39&nbsp;&nbsp;&nbsp;<span style="float: right;">32</span>
|-
|'''Base'''<br>31&nbsp;&nbsp;&nbsp;<span style="float: right;">24</span>
|'''Flags'''<br>3&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|'''Limit'''<br>19&nbsp;&nbsp;&nbsp;<span style="float: right;">16</span>
|'''Access Byte'''<br>7&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|'''Base'''<br>23&nbsp;&nbsp;&nbsp;<span style="float: right;">16</span>
|-
!colspan=3 style="text-align: left;"|31 &nbsp;&nbsp;<span style="float: right;">16</span>
!colspan=2 style="text-align: left;"|15 &nbsp;&nbsp;<span style="float: right;">0</span>
|-
|colspan=3|'''Base'''<br>15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|colspan=2|'''Limit'''<br>15&nbsp;&nbsp;&nbsp;<span style="float: right;">0</span>
|}
 
== See Also ==
Line 128 ⟶ 202:
 
* [http://files.osdev.org/mirrors/geezer/os/pm.htm Protected Mode tutorial]
* [http://www.intel.com/design/processor/manuals/253668.pdf Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A:. System Programming Guide, Part 1 (order number 253668)] chapter 2.4[[Category:X86 CPU]]
 
[[Category:X86 CPU]]
[[Category:Memory Segmentation]]
[[de:Global Descriptor Table]]
Anonymous user