Segmentation in long mode and LMLE in EFER

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
Post Reply
lopidas
Member
Member
Posts: 65
Joined: Sun May 26, 2013 10:12 am

Segmentation in long mode and LMLE in EFER

Post by lopidas »

In 32-bit mode I can use segment registers ds and ss to separate stack from heap.
Is it possible to use DS, SS and ES registers in 64-bit mode with LMLE enabled?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Segmentation in long mode and LMLE in EFER

Post by Combuster »

Oh, look what I found in Intel 1 Chapter 3.3.4 :D *ahem* [-X
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
lopidas
Member
Member
Posts: 65
Joined: Sun May 26, 2013 10:12 am

Re: Segmentation in long mode and LMLE in EFER

Post by lopidas »

Courious again :)
So reffering here Intel segmentation in long mode

In 64-bit mode, segmentation is generally (but not completely) disabled, creating a flat 64-bit linear-address
space. The processor treats the segment base of CS, DS, ES, SS as zero, creating a linear address that is equal to
the effective address. The exceptions are the FS and GS segments, whose segment registers (which hold the
segment base) can be used as additional base registers in some linear address calculations.

and here amd

In 64-bit mode, data reads and writes are not normally checked for segment-limit violations. When
EFER.LMSLE = 1, reads and writes in 64-bit mode at CPL > 0, using the DS, ES, FS, or SS segments,
have a segment-limit check applied.

So how do we generate instruction using DS,ES or SS, if the segmentation is disabled? Are the access checks applied?

P.S. I found that even SYSCALL refers SS
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Segmentation in long mode and LMLE in EFER

Post by Brendan »

Hi,
lopidas wrote:In 32-bit mode I can use segment registers ds and ss to separate stack from heap.
In theory you can do this in 32-bit protected mode. In practice functions that accept pointers would have to know if the pointers point to something on the stack or on the heap (or somewhere else); and you end up having to use "fat pointers" everywhere ("48-bit pointers" consisting of a 16-bit segment and a 32-bit offset) and doing very slow segment register loads very often; which creates more code (e.g. segment register loads), more bloat (e.g. pointers take up twice the space due to alignment) and more bugs (e.g. right offset but wrong segment). Basically, there's no benefit that anyone cares about, and no sane person would consider crippling performance for no benefit.

Instead; for 32-bit protected mode sane people set DS, ES and SS to "read/write, base is zero, limit is 4 GiB" so that segmentation is effectively disabled (and then use paging for protection).
lopidas wrote:So how do we generate instruction using DS,ES or SS, if the segmentation is disabled? Are the access checks applied?
You generate instructions in the same way you always have; except that you can just use the default segment register and forget about segment override prefixes (because it makes no difference if the instruction uses DS, ES or SS). Basically; it's the same as what sane people have always done in 32-bit protected mode.

I can't remember which access checks are done when. Typically in 64-bit mode you'd load a "read/write data" descriptor into DS, ES and SS; and after that it's impossible to do anything that any "segmentation access check" won't allow anyway. Of course you'd use paging for the actual/useful access checks.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
rdos
Member
Member
Posts: 3276
Joined: Wed Oct 01, 2008 1:55 pm

Re: Segmentation in long mode and LMLE in EFER

Post by rdos »

Brendan wrote: In theory you can do this in 32-bit protected mode. In practice functions that accept pointers would have to know if the pointers point to something on the stack or on the heap (or somewhere else); and you end up having to use "fat pointers" everywhere ("48-bit pointers" consisting of a 16-bit segment and a 32-bit offset) and doing very slow segment register loads very often; which creates more code (e.g. segment register loads), more bloat (e.g. pointers take up twice the space due to alignment) and more bugs (e.g. right offset but wrong segment). Basically, there's no benefit that anyone cares about, and no sane person would consider crippling performance for no benefit.
More bugs? You cannot be serious. Most bugs are pointer overwrites (usually in heap which will corrupt memory of something else or the memory allocation chain). These are bugs that flat kernels usually are full of and which in combination with multicore multitasking creates bugs that never are fixed.

Besides, smart C compilers will have callings conventions and code generation that avoids most of the segment register reloads. By having a single code segment, you also can omit far calls and can treat all function pointers as near.

But this is impossible to do in long mode, due to long mode having crippled the logic of descriptors and use a zero base regardless of the actual base in the descriptor cache (except for FS and GS). I don't thinlk the limit checking works for FS and GS in long mode, only the base is used. You will have to use legacy mode or protected mode in order to use segmentation as it was meant to be used.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Segmentation in long mode and LMLE in EFER

Post by Combuster »

rdos wrote:More bugs? You cannot be serious.
Yes, more bugs. Running with the whole load of instrumentation enabled also reveals more bugs.

Not that either has any demonstrated effect on the quality of the coder.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Segmentation in long mode and LMLE in EFER

Post by Brendan »

Hi,
rdos wrote:
Brendan wrote: In theory you can do this in 32-bit protected mode. In practice functions that accept pointers would have to know if the pointers point to something on the stack or on the heap (or somewhere else); and you end up having to use "fat pointers" everywhere ("48-bit pointers" consisting of a 16-bit segment and a 32-bit offset) and doing very slow segment register loads very often; which creates more code (e.g. segment register loads), more bloat (e.g. pointers take up twice the space due to alignment) and more bugs (e.g. right offset but wrong segment). Basically, there's no benefit that anyone cares about, and no sane person would consider crippling performance for no benefit.
More bugs? You cannot be serious.
I'm sure I can be serious if I try hard enough!

Without segmentation, only the "offset" can be wrong. With segmentation, the offset can be wrong, the segment can be wrong, or both can be wrong. Obviously there are 3 times as many possible bugs with segmentation.

The theoretical benefit of segmentation is that it's more able to catch some bugs; so (in theory) even though there are more possible bugs to catch less of them are meant to find their way into the final executable. Of course in practice it doesn't work like that and if you really care about catching bugs then segmentation is extremely inferior to (e.g.) managed code (for both "ability to catch bugs" and performance).

Fortunately, AMD were smart enough to close off this particular "detour to the land of nonsense" by removing support for segmentation. We should all thank AMD for this.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: Segmentation in long mode and LMLE in EFER

Post by linguofreak »

Brendan wrote:Hi,
lopidas wrote:In 32-bit mode I can use segment registers ds and ss to separate stack from heap.
In theory you can do this in 32-bit protected mode. In practice functions that accept pointers would have to know if the pointers point to something on the stack or on the heap (or somewhere else); and you end up having to use "fat pointers" everywhere ("48-bit pointers" consisting of a 16-bit segment and a 32-bit offset) and doing very slow segment register loads very often; which creates more code (e.g. segment register loads), more bloat (e.g. pointers take up twice the space due to alignment) and more bugs (e.g. right offset but wrong segment).
I can imagine some architectural features that would alleviate some of the fat pointer issues, but they would completely break compatibility with any existing member of the x86 family. I think that a properly designed MMU architecture could make segmentation extremely useful, but I've not seen anything that quite fits the bill (the access register mechanism on IBM mainframes probably comes closest, from what I've seen).
rdos
Member
Member
Posts: 3276
Joined: Wed Oct 01, 2008 1:55 pm

Re: Segmentation in long mode and LMLE in EFER

Post by rdos »

The "fat" 48-bit pointers in long mode could work almost as well as segment + offset protection, if used in a sane way. However, compilers (GCC) still have serious bugs with their medium and large memory model, which means that popular code for long mode doesn't use this feature either, rather pack all their data structures and use 32-bit relative addressing. That, of course, is just as bad as typical 32-bit flat code that typically is full of bugs.

And it is easy to understand that proper segmentation with base + limit checking should be possible to implement much more efficiently than the 4-level page structure in long mode. If it wasn't for all this "portable" bloat code floating around, Intel and AMD could actually have done this properly.
Post Reply