Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
global loadGDT64
global GDT64
loadGDT64:
lgdt [GDT64.Pointer] ; Load the new GDT pointer
ret
GDT64: ; Global Descriptor Table (64-bit).
.Null: equ $ - GDT64 ; The null descriptor.
dw 0xFFFF ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 1 ; Granularity.
db 0 ; Base (high).
.Code: equ $ - GDT64 ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011010b ; Access (exec/read).
db 10101111b ; Granularity, 64 bits flag, limit19:16.
db 0 ; Base (high).
.Data: equ $ - GDT64 ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access (read/write).
db 00000000b ; Granularity.
db 0 ; Base (high).
.Pointer: ; The GDT-pointer.
dw $ - GDT64 - 1 ; Limit.
dq GDT64 ; Base.
AMD APM Volume 2, section 4.5.1 wrote:
Segment selectors are pointers to specific entries in the global and local descriptor tables. Figure 4-3 shows the segment selector format.Figure 4-3. Segment SelectorThe selector format consists of the following fields:
Selector Index Field.
Bits 15:3.
The selector-index field specifies an entry in the descriptor table. Descriptor-table entries are eight bytes long, so the selector index is scaled by 8 to form a byte offset into the descriptor table. The offset is then added to either the global or local descriptor-table base address (as indicated by the table-index bit) to form the descriptor-entry address in virtual-address space.
Some descriptor entries in long mode are 16 bytes long rather than 8 bytes (see “Legacy Segment Descriptors” on page 84 for more information on long-mode descriptor-table entries). These expanded descriptors consume two entries in the descriptor table. Long mode, however, continues to scale the selector index by eight to form the descriptor-table offset. It is the responsibility of system software to assign selectors such that they correctly point to the start of an expanded.
Table Indicator (TI) Bit.
Bit 2.
The TI bit indicates which table holds the descriptor referenced by the selector index. When TI=0 the GDT is used and when TI=1 the LDT is used. The descriptor-table base address is read from the appropriate descriptor-table register and added to the scaled selector index as described above.
Requestor Privilege-Level (RPL) Field.
Bits 1:0.
The RPL represents the privilege level (CPL) the processor is operating under at the time the selector is created.
RPL is used in segment privilege-checks to prevent software running at lesser privilege levels from accessing privileged data. See “Data-Access Privilege Checks” on page 101 and “Control-Transfer Privilege Checks” on page 104 for more information on segment privilege-checks.
Null Selector.
Null selectors have a selector index of 0 and TI=0, corresponding to the first entry in the GDT. However, null selectors do not reference the first GDT entry but are instead used to invalidate unused segment registers. A general-protection exception (#GP) occurs if a reference is made to use a segment register containing a null selector in non-64-bit mode. By initializing unused segment registers with null selectors software can trap references to unused segments.Null selectors can only be loaded into the DS, ES, FS and GS data-segment registers, and into the LDTR descriptor-table register. A #GP occurs if software attempts to load the CS register with a null selector or if software attempts to load the SS register with a null selector in non 64-bit mode or at CPL 3.
Well, the values stored in the segment registers, but yes. Those need to be updated to point to the correct descriptors in your GDT, otherwise the value you save and restore during an interrupt won't be valid, and you'll get an exception after handling the interrupt.
Aight so, what you are saying is that when I saved the data selector, and pushed it to the stack, I might have popped the incorrect value of the stack?
EDIT: No, you are saying the values were invalid to begin with. After reading the AMD manuals, I might have a fix for it...
So, I assume I am supposed to load the GDT64.Code descriptor into the cs register, and GDT64.Data descriptor into the ds register? If so, I don't know how. Loading the contents throws a triple fault and loading the pointer doesn't even assemble.
In the AMD manuals it says the offset is 8 bits long. This is obviously not enough to fit a memory address, what am I supposed to put in there to make it point to my descriptors?