VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

Does CPL only update when a SS descriptor is fetched into the cache?

As far as I can see, whenever the privilege level changes, SS is loaded with a new descriptor(either raising or lowering privilege because of that)? The only exceptions might be during TSS-based task switching and switching processor modes loading CR0?

So the 'CPL = CS.RPL' lines of the x86 manuals (within a real CPU) might not even be there like the manual says? Effectively, it's the load of the SS descriptor into the descriptor cache itself that's doing that instead, when raising(INT,CALL gate) or lowering(RETF,IRET) privilege?

Last edited by superfury on 2019-10-03, 20:16. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 2, by crazyc

User metadata
Rank Member
Rank
Member

You can't depend on CS RPL being the same as CPL. For example when you switch into protected mode CS will be whatever it was before and the lowest 2 bits will probably not be 0 (but the DPL of SS will barring LOADALL or SMM tricks). There is BIOS code that requires this to work properly. I think the 'CPL = CS.RPL' thing means that it should be true for the x86 privilege model to work correctly not that it's always true.

Reply 2 of 2, by superfury

User metadata
Rank l33t++
Rank
l33t++

I made a little mistake in wording my example, the line from the documentation says:

Set CPL to new code segment DPL

Instead of 'CPL = CS.RPL'.

For example, look at https://css.csail.mit.edu/6.858/2014/readings/i386/INT.htm

But, isn't the case rather that the privilege level('CPL') changes because it's loading the SS descriptor cache(SS.DPL changing to be exact) due to the privilege level change actually causes the 'CPL' to change? Since the CPL field actually is the SS descriptor's DPL field itself, privilege changes are only affected by the SS.DPL changing?

So actually the line I'm quoting isn't actually done by a real processor? It's the SS selector being loaded(just before loading the CS descriptor cache) from the GDT/LDT that's actually changing SS.DPL, thus changing the privilege level('CPL', which is actually SS.DPL), not the loading of the CS or it's descriptor DPL(although it's the CS.DPL that makes the CPU actually load the new privilege's SS selector(which in and of itself doesn't change CPL, depending on the new SS descriptor's DPL itself what privilege to end up at), which in turn causes the privilege change due to, once again, SS.DPL changing)? Is that correct? If, for some reason, the CPU wouldn't check the SS.DPL field it's gotten from the table(e.g. LOADALL?), it would actually end up with the privilege level in SS.DPL, not CS.DPL after all?

And of course, everything becomes obviously clear that SS.DPL is actually handled as CPL without CS.DPL influencing it directly(although it might indirectly, due to call gates and interrupt/trap gates). You can see the SS.DPL being CPL always, since it stays the same when a conforming code segment is used(in which case CS.DPL<=CPL and SS.DPL==CPL, thus proving that SS.DPL actually is the descriptor that determines CPL). And of course the ring -1 tricks with SS.DPL changing ring 0-3's CPL by modifying it directly proves it as well.

So, the steps immediately before 'Set CPL to new code segment DPL' doesn't happen at all. It's the line above it ('Load SS descriptor into invisible portion of SS register;') that actually sets 'CPL'(actually SS.DPL descriptor field's bits in the cache) directly.
Of course, that SMM trick with SS.DPL and CPL also applies with LOADALL, which allows to load seperate values into the descriptors(even creating illegal modes, like CS.DPL>SS.DPL(alias 'CPL') with a conforming code segment).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io