Address space segmentation basically means dividing all possible virtual addresses into groups – segments – and applying some properties on those segments, e.g. privilege level required to access them. Segmentation applies to virtual addresses so it comes into play before virtual-to-physical address translation takes place. In x86, segmentation is a relic from past. 286 didn’t have virtual addressing so it divided address space into segments so that processes could keep themselves to addresses in their own segments. Then 386 added virtual addresses but still kept segments.
Different types of addresses
In x86, there are three different types of addresses.
This requires two steps to translate from logical to physical address. Translation from logical to linear is described in this article. Translation from linear to physical is done using page tables and we might cover it in a follow-up article.
Logical address consists of two parts: segment and offset. Segment is basically an index into an array of 8-byte records (discriptors) stored in RAM. This array is called Global Discriptor Table (GDT). There is also a per-process Local Descriptor Table (LDT) but we will ignore it as it doesn’t play a significant role in this discussion.
Each entry inside GDT contains info about a segment that it represents: base address, range (max address), CPU privelege level needed to access it and some other info.
Linear address = base address from segment entry in GDT + offset part of logical address
So to convert a logical address into linear, take base address from segment entry in GDT and add offset to it.
What Linux does with it
Linux prefers to group addresses into sections and manage them during the linear-to-physical transition phase, instead of logical-to-linear transition phase. Therefore, it pretty much nullifies effects of segment part of logical address so that offset just represents linear address. It does create four different segments: two (code and data) for each user space and kernel space. But each segment’s base is zero and max range is 2^32 – 1, thereby nullifying segmentation. It does however use CPU privilege level so that CPU has to be in right privilege level for accessing segments in kernel space – kernel code and kernel data segments.