OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 8:17 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: [SOLVED] Attempt to labeling paging tables instant reset CPU
PostPosted: Sun Aug 08, 2021 12:19 pm 
Offline
Member
Member

Joined: Sun Aug 01, 2021 5:24 pm
Posts: 51
The code is from https://wiki.osdev.org/Setting_Up_Long_Mode is working

Then I tried to labeling the tables and it instant reboot the OS.

Original code:
Code:
    mov edi, 0x1000    ; Set the destination index to 0x1000.
    mov cr3, edi       ; Set control register 3 to the destination index.
    xor eax, eax       ; Nullify the A-register.
    mov ecx, 4096      ; Set the C-register to 4096.
    rep stosd          ; Clear the memory.
    mov edi, cr3       ; Set the destination index to control register 3.

    mov DWORD [edi], 0x2003      ; Set the uint32_t at the destination index to 0x2003.
    add edi, 0x1000              ; Add 0x1000 to the destination index.
    mov DWORD [edi], 0x3003      ; Set the uint32_t at the destination index to 0x3003.
    add edi, 0x1000              ; Add 0x1000 to the destination index.
    mov DWORD [edi], 0x4003      ; Set the uint32_t at the destination index to 0x4003.
    add edi, 0x1000              ; Add 0x1000 to the destination index.

    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.


My mod:
Code:
; Setup page table
;{
    %define PG_PRESENT    (1 << 0)
    %define PG_WRITE      (1 << 1)
    %define PG_READABLE   (1 << 2)

    mov     DWORD [p4_table], p3_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p3_table], p2_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p2_table], p1_table + (PG_PRESENT + PG_WRITE + PG_READABLE)

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

    mov     edi, p1_table
    .SetEntry:
    ;{
        mov     [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.
    ;}
;}

p5_table: times 0x1000 db 0     ; Page Map Level 5
p4_table: times 0x1000 db 0     ; Page Map Level 4
p3_table: times 0x1000 db 0     ; Page Directory Pointer Table
p2_table: times 0x1000 db 0     ; Page Directory
p1_table: times 0x1000 db 0     ; Page Table


Last edited by Rukog on Mon Aug 09, 2021 7:35 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Attempt to labeling page tables instant reset CPU
PostPosted: Sun Aug 08, 2021 1:23 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Your tables aren't page aligned. They must be.


Top
 Profile  
 
 Post subject: Re: Attempt to labeling page tables instant reset CPU
PostPosted: Mon Aug 09, 2021 3:42 am 
Offline
Member
Member

Joined: Sun Aug 01, 2021 5:24 pm
Posts: 51
iansjack wrote:
Your tables aren't page aligned. They must be.


Code:
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:


Still doesn't work


Top
 Profile  
 
 Post subject: Re: Attempt to labeling page tables instant reset CPU
PostPosted: Mon Aug 09, 2021 4:41 am 
Offline
Member
Member

Joined: Tue Nov 07, 2006 7:37 am
Posts: 514
Location: York, England
Code:
align 4096
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:


Top
 Profile  
 
 Post subject: Re: Attempt to labeling page tables instant reset CPU
PostPosted: Mon Aug 09, 2021 5:08 am 
Offline
Member
Member

Joined: Sun Aug 01, 2021 5:24 pm
Posts: 51
Tyler wrote:
Code:
align 4096
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:


Thanks the code is working now but you are aligning the code above the tables there.

Why aligning the code too.

I assembled a source with only
Code:
align 4096
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:


versus
Code:
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:


And both do have the same bin size. but it's not when I add my code.


Last edited by Rukog on Mon Aug 09, 2021 5:10 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Attempt to labeling paging tables instant reset CPU
PostPosted: Mon Aug 09, 2021 5:09 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
When you compile with just the table data it will be aligned to start with, so no padding is inserted. When you insert your code - unless it just happens to be an exact multiple of the page size - padding will be necessary to ensure that the data is aligned.

Running your code under a debugger would let you inspect memory and the problem would-be apparent immediately.


Top
 Profile  
 
 Post subject: Re: Attempt to labeling paging tables instant reset CPU
PostPosted: Mon Aug 09, 2021 5:21 am 
Offline
Member
Member

Joined: Sun Aug 01, 2021 5:24 pm
Posts: 51
iansjack wrote:
When you compile with just the table data it will be aligned to start with, so no padding is inserted. When you insert your code - unless it just happens to be an exact multiple of the page size - padding will be necessary to ensure that the data is aligned.

Running your code under a debugger would let you inspect memory and the problem would-be apparent immediately.


I see, so the above code is already encapsulated inside my ongoing paging table init, that's why I have to encapsulate it inside one single page.

Else the CPU does a reset since it cannot execute code or read data that share multiple pages.

Thank you :oops:


Top
 Profile  
 
 Post subject: Re: Attempt to labeling paging tables instant reset CPU
PostPosted: Mon Aug 09, 2021 6:01 am 
Offline
Member
Member

Joined: Tue Nov 07, 2006 7:37 am
Posts: 514
Location: York, England
Rukog wrote:
Else the CPU does a reset since it cannot execute code or read data that share multiple pages.


No.

IA-32/x86-64 have weak rules regarding aligment. Any code can cross (linear) page boundaries. Any (application) data can cross page boundaries. At most you will have performance penalties.

It's specifically paging data that was the problem in this example. Any given paging structure must appear entirely on a single physical page of memory. For practical purposes, this needs to be for one reason. CR3 and the paging structures (e.g. page table entries) only have bits available for the Top-20- (32-bit paging) or Top-40- (PAE and Long Mode) -bits of of the paging structures physical address. This means it is impossible for you to reference a page table, page directory etc. with any other alignment.

EDIT: I'd like to harp on about this a little more...

Really think about this code.

Code:
    mov     DWORD [p4_table], p3_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p3_table], p2_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p2_table], p1_table + (PG_PRESENT + PG_WRITE + PG_READABLE)


Imagine your tables are misaligned such that p3_table is 0x8003. Then the first line becomes,

Code:
    mov     DWORD [p4_table], 0x8003 + (PG_PRESENT + PG_WRITE + PG_READABLE)


Ignoring the (intentional) flags for a second. This means you are placing the value 0x0000000000008003 in the first P4 entry. Go to page 132 of https://software.intel.com/content/dam/develop/external/us/en/documents-tps/253668-sdm-vol-3a.pdf and look at the structures. The "Address of page-directory-pointer table " is being set to 0xXXX0000000008XXX (where X is outside the value "Address of page-directory-pointer table " and I put it there to make it it a 64-bit number).

The 0x3 is being places in the lower part of the structure, setting the present and read/write flags.

Worse yet, because you add, rather than or'ing, your flags, you then do the sum 0x8003 + 1 + 2 + 4, giving a value of 0x800A. In this value, you are clearing the Present, Supervisor bits, setting the writable bit, and accidentally setting the page write through caching flag. This lack of present flag is what probably caused the triple fault, as the processor could have never known you intended to use a mis-aligned page.

Incidentally, I'm not sure about,

Code:
    %define PG_READABLE   (1 << 2)


According the my reading of the page I linked above, this sets the User/Supervisor flag, not a flag setting read permissions.


Top
 Profile  
 
 Post subject: Re: Attempt to labeling paging tables instant reset CPU
PostPosted: Mon Aug 09, 2021 8:19 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Rukog wrote:
Else the CPU does a reset since it cannot execute code or read data that share multiple pages.
That would be extremely limiting, and is not the case.

I think you may benefit from reading the Intel or AMD Programmer's Manuals to ensure that you have a thorough understanding of the basic operation of the processor. Pay particular attention to the chapter on memory management.


Top
 Profile  
 
 Post subject: Re: Attempt to labeling paging tables instant reset CPU
PostPosted: Mon Aug 09, 2021 8:28 am 
Offline
Member
Member

Joined: Sun Aug 01, 2021 5:24 pm
Posts: 51
iansjack wrote:
Rukog wrote:
Else the CPU does a reset since it cannot execute code or read data that share multiple pages.

That would be extremely limiting, and is not the case.
I think you may benefit from reading the Intel or AMD Programmer's Manuals to ensure that you have a thorough understanding of the basic operation of the processor. Pay particular attention to the chapter on memory management.


Yep, long reading awaits me oof

Tyler wrote:
Rukog wrote:
Else the CPU does a reset since it cannot execute code or read data that share multiple pages.


No.

IA-32/x86-64 have weak rules regarding aligment. Any code can cross (linear) page boundaries. Any (application) data can cross page boundaries. At most you will have performance penalties.

It's specifically paging data that was the problem in this example. Any given paging structure must appear entirely on a single physical page of memory. For practical purposes, this needs to be for one reason. CR3 and the paging structures (e.g. page table entries) only have bits available for the Top-20- (32-bit paging) or Top-40- (PAE and Long Mode) -bits of of the paging structures physical address. This means it is impossible for you to reference a page table, page directory etc. with any other alignment.

EDIT: I'd like to harp on about this a little more...

Really think about this code.

Code:
    mov     DWORD [p4_table], p3_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p3_table], p2_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
    mov     DWORD [p2_table], p1_table + (PG_PRESENT + PG_WRITE + PG_READABLE)


Imagine your tables are misaligned such that p3_table is 0x8003. Then the first line becomes,

Code:
    mov     DWORD [p4_table], 0x8003 + (PG_PRESENT + PG_WRITE + PG_READABLE)


Ignoring the (intentional) flags for a second. This means you are placing the value 0x0000000000008003 in the first P4 entry. Go to page 132 of https://software.intel.com/content/dam/develop/external/us/en/documents-tps/253668-sdm-vol-3a.pdf and look at the structures. The "Address of page-directory-pointer table " is being set to 0xXXX0000000008XXX (where X is outside the value "Address of page-directory-pointer table " and I put it there to make it it a 64-bit number).

The 0x3 is being places in the lower part of the structure, setting the present and read/write flags.

Worse yet, because you add, rather than or'ing, your flags, you then do the sum 0x8003 + 1 + 2 + 4, giving a value of 0x800A. In this value, you are clearing the Present, Supervisor bits, setting the writable bit, and accidentally setting the page write through caching flag. This lack of present flag is what probably caused the triple fault, as the processor could have never known you intended to use a mis-aligned page.

Incidentally, I'm not sure about,

Code:
    %define PG_READABLE   (1 << 2)


According the my reading of the page I linked above, this sets the User/Supervisor flag, not a flag setting read permissions.


Fixed, thanks

Code:
%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

mov     eax, PG_FLAG_P(1) + PG_FLAG_RW(1) + PG_FLAG_US(0)

; mov     [PagingTable.PML5], dword PagingTable.PML4
; or      [PagingTable.PML5], eax

mov     [PagingTable.PML4], dword PagingTable.PDPT
or      [PagingTable.PML4], eax

mov     [PagingTable.PDPT], dword PagingTable.PD
or      [PagingTable.PDPT], eax

mov     [PagingTable.PD]  , dword PagingTable.PT
or      [PagingTable.PD]  , eax


Top
 Profile  
 
 Post subject: Re: [SOLVED] Attempt to labeling paging tables instant reset
PostPosted: Mon Aug 09, 2021 10:21 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Code:
mov     eax, PG_FLAG_P(1) + PG_FLAG_RW(1) + PG_FLAG_US(0)

Am I missing something here? I feel like these should be ORed and not ADDed together.


Top
 Profile  
 
 Post subject: Re: [SOLVED] Attempt to labeling paging tables instant reset
PostPosted: Mon Aug 09, 2021 11:00 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Strictly speaking, yes, but it makes no difference in this case.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 159 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group