Search code examples
cassemblyoperating-systemxv6

How to understand the following code in xv6 bootstrap code?


Code:

#define SEG(type,base,lim)                  \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff);  \
.byte (((base) >> 16) & 0xff), (0x90 | (type)),     \
    (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)

I know it's a segment descriptor structure.

But i don't understand the code : ((lim) >> 12 & 0xffff)

Why need right shift 12 bit?

I need help.


Solution

  • The reason is archaic. The descriptors were 8 bytes in 286, and limit used to be coded in 16 bits in 286 16-bit protected mode. When 386 came, the descriptors were not widened - each entry being still 8 bytes. However there wouldn't be enough space to code both the segment base and the segment limit using 32 bits - so the limits are now coded using 20 bits.

    There are 2 options for how the 20-bit limit is interpreted - either as multiple of 4K or as bytes - this is called granularity. The 4K mode is a good compromise and works rather well together with the 4K page size of 386 - when you're using more than 1M limits you very probably are using virtual memory as well and then you'd lose an entire page on the edge anyway.

    The limit given to the macro is expressed in bytes and it is divided by 4096 (>> 12) to get the page-granular limit.