How does this OSDEV Identity map work for PAE Paging?

0

I'm trying to understand as best I can what this OSDEV tutorial is on about. I have read the AMD64 programmers manaul (vol.2) chapters 4 and 5 as suggested, but I do not understand what happens when he goes through this loop:

    mov ebx, 0x00000003          ; Set the B-register to 0x00000003.
    mov ecx, 512                 ; Set the C-register to 512.

.SetEntry:
    mov DWORD [edi], ebx         ; Set the uint32_t at the destination index to the B-register.
    add ebx, 0x1000              ; Add 0x1000 to the B-register.
    add edi, 8                   ; Add eight to the destination index.
    loop .SetEntry               ; Set the next entry.

I get why he sets ebx to 3, but beyond that, I don't see what he is doing to ID map 2 MB.

memory
mapping
virtual
paging
osdev
asked on Stack Overflow Aug 13, 2017 by Mike

1 Answer

1

mov ebx, 0x00000003          ; Set the B-register to 0x00000003.

The code uses ebx to hold the value to be written to the next page table entry. It initializes it to 3 to set the present and writable bits (bit 0 and 1). From here on, it adds 0x1000 to it at each loop iteration, which does not affect those two bits. The physical address field is zero, so this makes the first entry map to physical address zero.


mov ecx, 512                 ; Set the C-register to 512.

The loop runs for 512 iterations, one iteration per page table entry. Each entry is 64 bits (8 bytes). One page table in long mode can hold 512 entries. 512 is 4096 / 8.


.SetEntry:
mov DWORD [edi], ebx         ; Set the uint32_t at the destination index to the B-register.

Write one page table entry.


add ebx, 0x1000              ; Add 0x1000 to the B-register.

Advance the physical address to be written into the next page table entry by 4KB. Each page table entry maps 4KB.


add edi, 8                   ; Add eight to the destination index.

Write the next page table entry into the next entry of the page table. Each page table entry is 8 bytes.


loop .SetEntry               ; Set the next entry.

The loop instruction means ecx = ecx - 1 jnz .SetEntry. It runs another iteration of the loop if ecx is not zero after reducing ecx by 1. Since ecx was initialized to 512 before the loop, this makes the above instructions repeat 512 times.


Since the first entry uses physical address zero, and each subsequent entries' physical address is 4KB higher, and each entry maps 4KB, and there are 512 of them, this code fills the page table entries for virtual address 0 (inclusive) through 2MB (exclusive) with entries that identity map the first 2MB of physical memory. "Identity" mapping means mapping it so the physical address is equal to the linear address. Each page table in long mode maps 2MB of address space. Since this code fills one page table, it maps 2MB.

Note that this code alone is not sufficient to set up paging. This code only fills the page table entries. This code would work for 32-bit PAE paging or long mode paging.

In PAE paging, you would need to set up two other pages as well. For long mode, you would need to set up three other pages. PAE paging uses a 3-level translation, where the top level maps 1GB regions, the middle level maps 2MB regions, and the page table level maps 4KB regions.

Long mode paging uses a 4-level (or on the latest processors, it can be 5-level) paging. In long mode the top level maps 512GB regions, the second level maps 1GB regions, the third level maps 2MB regions, and the outermost level maps 4KB regions.

Code that sets up identity mapping would need to set up the pages described above, in addition to the setup shown in the code in your question.

answered on Stack Overflow Aug 21, 2018 by doug65536

User contributions licensed under CC BY-SA 3.0