Closed hypervisor closed 4 years ago
Hi!
The answer is simple -- those other sources use the selector index (which is kind of odd).
The code in ShvUtilConvertGdtEntry
uses the selector itself. The selector is an offset. So you add the offset to the table base.
I hope this helps!
I'm quite new to segmentation, so please bare with me.
To get a segment descriptor entry from GDT we have to access the GDT like an array. Each entry in the GDT is 8 bytes, according to the Intel SDM. To my understanding we can therefore access the GDT like:
Or, what this is equivalent to:
Now, while learning, I read the source to a bunch of different hypervisors. Specifically - Gbhv. Gbhv gets segment descriptors from GDT using the exact method above. https://github.com/Gbps/gbhv/blob/master/gbhv/vmx.c#L178
The bitshift to the left by 3 is the same as multiplication by 8, so this is basically exactly the same as the code I wrote above. However, you do it completely differently in SimpleVisor, and I'm very confused as to why.
https://github.com/ionescu007/SimpleVisor/blob/master/shvutil.c#L50
I understand the
Selector & ~RPL_MASK
part. You're masking away Rpl & Table bits to extract the index from the selector. But you are not multiplying it by the size of a descriptor (8). Since you're casting GdtBase to a uintptr_t - an integer, this is using integer arithmetic (duh), so it's not accessing the entry in the GDT properly. I'm super confused, because I've personally ran SimpleVisor in the past on both a VMware guest, and on my host system - and it worked. Why? Am I missing something, or is this simply a bug?