0

I've searched up on a lot on the net and every time I can only find the sizes of GDT, LDT and IDT.

Here I'm not asking for the size of the table, but I'm asking about the sizes of the registers

I know that GDTR is a 64 bit register, but clueless about the others.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Marc Al
  • 27
  • 1
  • 6

2 Answers2

1

IDTR and GDTR appear to be 10 bytes each.

IDTR can also point anywhere in virtual address space, so obviously its base has to be 64-bit as well. lidt and lgdt take the same limit / base structure format, and the pseudocode shows that in 64-bit mode they do:

                    GDTR(Limit) ← SRC[0:15];
                    GDTR(Base) ← SRC[16:79];

The limit (max byte offset) should be considered part of GDTR / IDTR. The documentation for sidt also says "store IDTR", and what it stores is the same 2 + 8 byte struct that has limit + base. (The GDTR internally uses the limit to check segment selectors before looking them up in the GDT, so memory within 64k of the address you used with lgdt can be used for other things, if it's past the limit.)

It seems lidt / lgdt don't check for the GDT/IDT base being a canonical address. The documentation says they #GP(0) If the memory address is in a non-canonical form. but I think that's talking about the addressing mode to reach the 10-byte memory operand, not the base address.

(If it isn't possible to get a non-canonical address into the GDTR or IDTR, the CPU could internally store only the significant 48 bits (or 57 with PML5), bringing the size down to 6 + 2 = 8 bytes. And do the sign extension back to 64-bit as part of sidt / sgdt. But probably it is possible to round-trip an arbitrary 64-bit value through GDTR, just make sure the CPU doesn't need to use the GDT for anything before you put in a valid address!)


LDTR holds a segment selector and a whole descriptor

The documentation for lldt indicates that if there's no error:

    LDTR(SegmentSelector) ← SRC;
    LDTR(SegmentDescriptor) ← GDTSegmentDescriptor;

This indicates that the internal LDTR keeps the 16-bit segment selector (the actual operand to ldtr, e.g. ldtr ax), as well as loading the selected GDT entry and keeping that. A GDT entry is 8 bytes, but it may decode that entry into some internal format. (Perhaps not including the type field, which was already checked and required to be of type == LDT)

This implies that like segment registers such as DS or SS, if you change the GDT contents after running lldt, the base/limit of the selected entry at the time you ran lldt will continue to apply.

TR appears similar to LDTR

Again, the documentation shows:

TaskRegister(SegmentSelector) ← SRC;
TaskRegister(SegmentDescriptor) ← TSSSegmentDescriptor;

As with LDTR, you can only retrieve the segment selector, not the actual descriptor it was storing. str r/m16 and sldt r/m16 only write a 16-bit destination operand.

But the actual internal register needs to hold onto the whole segment descriptor, not re-index the current GDT with the selector.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Perfectly understood TR and LDTR, just had one last question about the GDTR and IDTR. If its 10 bytes (80 bits) each, are all 10 bytes accessible while programming? As i understand, and i may be completely wrong, we can only access the 8 bytes of gdtr as you mentioned. So what are the remaining 2 bytes used for? Are they wasted or just not visible? – Marc Al Jun 11 '21 at 20:36
  • @MarcAl: As my answer says, you can get both the base and limit out again with `sidt` or `sgtd`. This is a total of 2 + 8 = 10 bytes. So yes, all 10 bytes are accessible in that sense. Only the low 6 bytes of the base address are truly usable, though, as an actual address. (Or the low 57 bits with PML5 for 57-bit virtual addresses.) So yes, the top bits of the base address are effectively useless. The limit isn't, though. – Peter Cordes Jun 11 '21 at 23:04
1

You can always check what the CPU manufacturer says, Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 Chapter 2.4, in sort:

GDT and IDT:

  • Base address 32 or 64 bits (in protected and long mode respectively)
  • Limit: 16 bits
  • Total size: 48 or 80 bits (4+2=6 Bytes or 8+2=10 Bytes)
LDT and TR: 16 bits, as every other segment register.

You can also take a look at wiki.osdev.org, it is a wiki about Operating System development. It has, among others, pages for GDT, IDT and LDT.
Coconut9
  • 123
  • 2
  • 7