VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

How is RPL in the TR and LDTR register handled?
What happens when they're non-zero? Or non-zero in the Task Gate? What is loaded into the TR register's visible side (RPL and table bits, ie the lower 3 bits)?

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

Reply 1 of 5, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

LLDT and LTR are privileged instructions - you need to be in CPL 0 to execute them. So they don't do any privilege checks on the selectors or descriptors that they load. Similarly, no privilege level tests are performed on the TR load or LDTR load that happen during a task switch - the privilege check is just on the task gate itself. There are some other tests that are performed (Is it a non-null selector? Does it point into the GDT?) just not privilege level. I'm not sure if the TI and RPL bits of TR and LDTR physically exist on the chip (they might just have been omitted since they aren't used) but if the RPL bits do exist the microcode just passes them along unchanged.

Reply 2 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

Ok. So basically just when a TSS is loaded into CS it has it's privilege level checked (either on the gate descriptor or not gated). And a LDT doesn't ever check for privilege?

Also, what happens when a task switch is executed while TR is in the reset state (Access Rights byte 82h, although my emulator loads 0x8B on 386+ and 0x83 on the 80286)? Does it just blindly store the old task state at linear address 0 where TR is pointing to?
Since AR 82h means 'present LDT' that'd be invalid for task switches, but does the CPU check for that condition on the outgoing task?

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

Reply 3 of 5, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

CS is never loaded with a TSS segment (TSS holds register values, CS holds code). Correct, loading LDTR doesn't check for privilege.

You can only do a jump or call into a TSS (a task switch) if it's available (AR byte 0x81 for 286 or 0x89 for 386). You can't switch to a busy (0x83/0x8b) TSS or an LDT (0x82). You also can't load TR with a busy TSS (you get a #GP if you try).

Reply 4 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, performing a JMP or CALL to a TSS segment actually performs the task switch. But before the task switch is done, normal checks are done, just like 'loading' the TSS into CS (all the same steps like privilege level checks that the JMP TSSselector triggers). Only the final parsing of the TSS (before loading it into CS) actually triggers the task switch mechanism instead of loading it into the CS descriptor cache.
The CS loading mechanism only deviates after checking the privilege levels of the TSS descriptor (or task gate) in this case. Since before getting to this point, it's unknown whether it's a task gate, TSS or just a normal code segment that's being jumped to or called.

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

Reply 5 of 5, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

Right - the destination descriptor is loaded first (into internal CPU registers) so that the CPU can tell what kind of destination it is. If the destination is a TSS (or a task gate, or a call gate) then those internal registers are not copied into CS (and the CS descriptor cache) - instead they are used to find the final CS and EIP values.