assemblyx86operating-systemxv6gdt

Why in xv6 there's sizeof(gdt)-1 in gdtdesc


In bootasm.S

.p2align 2                                # force 4 byte alignment
gdt:
  SEG_NULLASM                             # null seg
  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
  SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg

gdtdesc:
  .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
  .long   gdt                             # address gdt

And this is used in

lgdt gdtdesc

Shouldn't the first word of gdtdesc be the size of gdt in bytes? In this case, it's 3*8=24, which equals to gdtdesc - gdt. Why gdtdesc - gdt - 1 here?


Solution

  • According to the manual, lgdt wants the GDT size in bytes, but also describes it as the "limit". That wording is ambiguous between size vs. address of the last byte. (Which would make sense as a way to allow a higher limit without wrapping the 16-bit limit.)

    But the examples in https://wiki.osdev.org/GDT_Tutorial use sizeof(gdt) so that's either a bug in xv6 or in the osdev tutorial.

    https://wiki.osdev.org/Global_Descriptor_Table agrees with xv6, saying "limit" is size-1, unlike the GDT tutorial. This makes sense:

    The size is the size of the table subtracted by 1. This is because the maximum value of size is 65535, while the GDT can be up to 65536 bytes (a maximum of 8192 entries). Further no GDT can have a size of 0.

    If you want to confirm the details, check Intel or AMD's manuals; they will hopefully clarify this point somewhere in the system development details, separate from the instruction-set reference entry for lgdt.

    Or you'd hope they would. But unfortunately Intel says:

    Section 2.4.1 Global Descriptor Table Register (GDTR)

    "the table limit specifies the number of bytes in the table".

    Which probably just means that whoever wrote it is so caught up in the limit = offset of last byte = size idea that they didn't even realize this isn't clear. Segment limits themselves (in GDT entries) also work this way, using 0xFFFFF (with granularity=page) to specify the limit as the very top of the 4GiB address space, i.e. unlimited.