Page 1 of 1

[SOLVED] Paging 1-GByte Page

Posted: Wed Aug 18, 2021 2:24 pm
by Rukog
I don't know what is wrong since this code update isn't working, ive maybe missed something in intel docs.

Image
Image

Code: Select all

    ; Setup paging
    ;{
        ; Linear-Address Translation to a 1-GByte Page using 4-Level Paging
        ;{
            ; Format of a Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page
            ;{
                %define PG_FLAG_P(bit)      (bit << 0)  ; 0: Page not Present           1: Page Present
                %define PG_FLAG_RW(bit)     (bit << 1)  ; 0: Read-only                  1: Read Write
                %define PG_FLAG_US(bit)     (bit << 2)  ; 0: Supervisor Mode            1: User Mode
                %define PG_FLAG_PWT(bit)    (bit << 3)  ; 0: Page-level write-through   1: Page-level write-through
                %define PG_FLAG_PCD(bit)    (bit << 4)  ; 0: Page-level cache disable   1: Page-level cache disable
                %define PG_FLAG_A(bit)      (bit << 5)  ; 0: Accessed                   1: Accessed
                %define PG_FLAG_D(bit)      (bit << 6)  ; 0: Dirty                      1: Dirty
                %define PG_FLAG_PS(bit)     (bit << 7)  ; 0: Refer a Page Directory     1: Refer a 1-GByte Page
                %define PG_FLAG_G(bit)      (bit << 8)  ; 0: Global                     1: Global
                %define PG_FLAG_PAT(bit)    (bit << 12) ; 0: Paging and Memory Typing   1: Paging and Memory Typing
                
                mov     eax, PG_FLAG_P(1) + PG_FLAG_RW(1) + PG_FLAG_US(0) + PG_FLAG_A(1) + PG_FLAG_D(1)+ PG_FLAG_PS(1)
                mov     [PagingTable.PML4], dword PagingTable.PDPT
                or      [PagingTable.PML4], eax
                
                ; Build the Page-Directory-Pointer Table
                mov     ecx, 4     ; 4 GB
                mov     edi, PagingTable.PDPT
                .SetNextEntry:
                ;{
                    mov     [edi], eax          ; Set page entry
                    add     eax, 0x4000_0000    ; Next 1-GB page
                    add     edi, 8              ; Next PDPT entry
                
                    loop    .SetNextEntry
                ;}
            ;}
        ;}
    ;}

Re: Paging 1-GByte Page

Posted: Wed Aug 18, 2021 2:57 pm
by iansjack
You don't say what your problem is. But what you may have missed s that not all processors support 1GB pages.

Re: Paging 1-GByte Page

Posted: Wed Aug 18, 2021 3:00 pm
by Octocontrabass
You're setting the page size bit in your PML4E, not your PDPTEs. The page size bit is not valid in a PML4E.

You're not setting the present bit or the page size bit in your PDPTEs. You need both of those to get 1GB pages. You probably want to set a few other bits too.

The behavior of large pages that cross effective memory type boundaries is undefined. Before using large pages, you must read the MTRRs and verify that the effective memory type will be the same across the entire page. (See Intel SDM 3A 11.11.9 for details.)

And, of course, you have to make sure your CPU supports 1GB pages.

Re: Paging 1-GByte Page

Posted: Wed Aug 18, 2021 3:52 pm
by Rukog
The original code reset the CPU constantly, so I think my CPU does support the 1 GB Page, it does looping with that code.

Code: Select all

    Yes:
        mov     eax, 0x80000001
        cpuid
        mov     eax, edx
        or      eax, 1 << 26
        cmp     edx, eax
    je      Yes
And you are right about the PS thus here's an update of the code.

Code: Select all

    ; Setup paging
    ;{
        ; Paging Structures in the Different Paging Modes
        
        ; Linear-Address Translation to a 1-GByte Page using 4-Level Paging
        ;{
            ; Format of a PML4 Entry (PML4E) that References a Page-Directory-Pointer Table
            ;{
                %define PG_FLAG_P(bit)      (bit << 0)  ; 0: Page not Present           1: Page Present
                %define PG_FLAG_RW(bit)     (bit << 1)  ; 0: Read-only                  1: Read Write
                %define PG_FLAG_US(bit)     (bit << 2)  ; 0: Supervisor Mode            1: User Mode
                %define PG_FLAG_PWT(bit)    (bit << 3)  ; 0: Page-level write-through   1: Page-level write-through
                %define PG_FLAG_PCD(bit)    (bit << 4)  ; 0: Page-level cache disable   1: Page-level cache disable
                %define PG_FLAG_A(bit)      (bit << 5)  ; 0: Accessed                   1: Accessed
                %define PG_FLAG_PS(bit)     (bit << 7)  ; Reserved (must be 0)
                
                mov     eax, PG_FLAG_P(1) + PG_FLAG_RW(1) + PG_FLAG_US(0) + PG_FLAG_A(1) + PG_FLAG_PS(0)
                
                ; Build the PML4 Table
                mov     [PagingTable.PML4], dword PagingTable.PDPT
                or      [PagingTable.PML4], eax
            ;}
            
            ; Format of a Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page
            ;{
                %define PG_FLAG_P(bit)      (bit << 0)  ; 0: Page not Present           1: Page Present
                %define PG_FLAG_RW(bit)     (bit << 1)  ; 0: Read-only                  1: Read Write
                %define PG_FLAG_US(bit)     (bit << 2)  ; 0: Supervisor Mode            1: User Mode
                %define PG_FLAG_PWT(bit)    (bit << 3)  ; 0: Page-level write-through   1: Page-level write-through
                %define PG_FLAG_PCD(bit)    (bit << 4)  ; 0: Page-level cache disable   1: Page-level cache disable
                %define PG_FLAG_A(bit)      (bit << 5)  ; 0: Accessed                   1: Accessed
                %define PG_FLAG_D(bit)      (bit << 6)  ; 0: Dirty                      1: Dirty
                %define PG_FLAG_PS(bit)     (bit << 7)  ; 0: Refer a Page Directory     1: Refer a 1-GByte Page
                %define PG_FLAG_G(bit)      (bit << 8)  ; 0: Global                     1: Global
                %define PG_FLAG_PAT(bit)    (bit << 12) ; 0: Paging and Memory Typing   1: Paging and Memory Typing
                
                mov     eax, PG_FLAG_P(1) + PG_FLAG_RW(1) + PG_FLAG_US(0) + PG_FLAG_A(1) + PG_FLAG_D(1)+ PG_FLAG_PS(1)
                
                ; Build the Page-Directory-Pointer-Table
                mov     ecx, 4     ; 512 entries max
                mov     edi, PagingTable.PDPT
                .SetNextEntry:
                ;{
                    mov     [edi], eax          ; Set new PDPT Entry
                    add     eax, 0x4000_0000    ; Next 1-GB page
                    add     edi, 8              ; Next PDPT Entry
                
                    loop    .SetNextEntry
                ;}
            ;}
        ;}
    ;}

And Qemu does boot this but not my real machine.

Re: Paging 1-GByte Page

Posted: Wed Aug 18, 2021 4:23 pm
by Octocontrabass
It's hard to say what else could be wrong, especially when it only fails on hardware.

You made sure the rest of your PML4 and PDPT is cleared to zero, right?

Re: Paging 1-GByte Page

Posted: Wed Aug 18, 2021 4:52 pm
by Rukog
Octocontrabass wrote:It's hard to say what else could be wrong, especially when it only fails on hardware.

You made sure the rest of your PML4 and PDPT is cleared to zero, right?
Yep, I am using the same paging table of my previous 4 KB pages mapping.

Code: Select all

PagingTable:    ; 512 address of 64-bit
;{
    .PML5: times 512 dq 0  ; Page Map Level 5
    .PML4: times 512 dq 0  ; Page Map Level 4
    .PDPT: times 512 dq 0  ; Page Directory Pointer Table
    .PD:   times 512 dq 0  ; Page Directory
    .PT:   times 512 dq 0  ; Page Table
;}
EndPagingTable:

Re: Paging 1-GByte Page

Posted: Thu Aug 19, 2021 8:44 am
by nexos
Are you trying to use 5 level paging? It looks that way as, you have a PML5 in your code. 5 level paging hasn't been released by Intel yet :) . It only works on QEMU.

Re: Paging 1-GByte Page

Posted: Thu Aug 19, 2021 11:40 am
by Rukog
nexos wrote:Are you trying to use 5 level paging? It looks that way as, you have a PML5 in your code. 5 level paging hasn't been released by Intel yet :) . It only works on QEMU.
I found the bug and it was the enable of PCIDE in cr4 that caused problem.
I thought I needed that flag for the 1 GB page mapping :shock:

Code: Select all

mov     eax, cr4
or      eax, 1 << 5
; or      eax, 1 << 17    ; PCIDE
mov     cr4, eax