'How to update GDT entries after initial loading?
Once I initialize and load my GDT into the GDTR using lgdt
, how can I update the GDT later?
Am I correct if I use the sgdt
command to get the base address and then update or add entries followed by reloading it again with the lgdt
? Is there some other way to do it?
Or am I missing something and the GDT is never "meant" to be updated once initialized and loaded?
Solution 1:[1]
I understand that this question is old however I want to highlight some things that the comments didn't mention, that is what the CPU caches and what does not.
- Some terminology:
- The GDT's entries are called descriptors, for this answer we are interested only for segment descriptors
- Segment registers (
cs
,ds
,es
,fs
,gs
,ss
,ldtr
,tr
) get assigned with segment selectors witch specify a segment descriptors. A segment selector is always 16 bits and consists of:- 13 bits: descriptor entry index
- 1 bit: 0 for GDT 1 for LDT
- 2 bits: Requested Privilege Level (RPL)
- The CPU does not cache the GDT, loading a value to
gdtr
does nothing more than loading a value togdtr
(which consist of the GDT's base address and its size) - The CPU caches the GDT descriptors that each segment register uses, when that segment is loaded with a new segment selector:
- Each segment register has 2 parts:
- The "Visible Part", containing the segment selector
- The "Hidden Part" contained a cached copy of segment descriptor
- When you execute
mov es, ax
, withax
having the value 0x0010 for example:- The "Visible Part" gets the value 0x0010
- The "Hidden Part" receives a copy of the information stored in the 3rd entry of the GDT (because 0x0010 means 3rd entry)
- When using the segment register, only the "Hidden Part" dictates its characteristics (base, limit, access information).
- The GDT segment descriptor that was used to load the segment register may be modified or not be present at all
- The
gdtr
may point to a different location, even an invalid one, and may have any size, again, even an invalid one - the CPU does not care.
- The "Visible Part" does absolute nothing expect holding the segment selector used to load the segment register, that value can be then retrieved by a
mov ax, es
. (ax
becomes 0x0010, even thought that GDT segment descriptor may contain anything or may not even exist at the present time) - So, in order to load a new segment descriptor to a segment register, you need to load another (or even the same) selector, that will update-reload the "Hidden Part" - cache
- Each segment register has 2 parts:
- That being said, there are a lot of reasons to keep the used entries in the GDT fixed, a simple one is that when moving from kernel-mode to user-mode (and vice versa) you change segments; those descriptors must thus be present in GDT. (The CPU also automatically loads new segments in other circumstances such as far calls, interrupts, task gates, call gates, ...). In sort, only remove a descriptor if your OS does not use it anymore. It is also harder to mess up something
- Finally, to answer your question, if you want to add a segment descriptor (or any other descriptor), you add it in your current GDT, you just place the appropriate values into a free descriptor entry and then you load the new selector to a segment (You may change the size of the GDT if needed at this point). If you want to update a segment descriptor, you update it in the GDT and then you reload all the segments that use it, if you don't do that, the segments will just use the old cached values.
Source: Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3: System Programming Guide CHAPTER 3: PROTECTED-MODE MEMORY MANAGEMENT
I suggest you to also take a look at wiki.osdev.org, specifically:
- https://wiki.osdev.org/GDT
- https://wiki.osdev.org/GDT_Tutorial
- https://wiki.osdev.org/Descriptors
- https://wiki.osdev.org/Descriptor_Cache
Please ask for any clarifications
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |