OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 4:41 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4
Author Message
 Post subject: Re: Higher Half in C?
PostPosted: Mon Jul 16, 2018 1:01 am 
Offline
Member
Member

Joined: Fri Aug 19, 2016 10:28 pm
Posts: 360
Octacone wrote:
simeonz wrote:
Octacone wrote:
Success!!!
I managed to enable PSE 4 MB paging in assembly and identity map 1 MB to 1 MB and 3 GB to 1 MB. Everything seems to be working fine. My kernel is officially in higher half.
Now I'm having a problem because it crashes when I try to re-enable paging, more specially turning off PSE and turning on PAE and resetting CR3. How to solve that?
When you turn off PSE, the current code page (being large 4MB page) will be immediately discarded from the TLB, then resolved again, but since PSE is off, the PS bit will be ignored, and the PDE will be interpreted as a pointer to a page table. This is sufficient for a crash. If you turn on the PAE, the paging structures immediately switch to 3-level with PDPTEs at the top. I don't think that there is a way to do that safely without disabling paging first, in which case you are back to square one. I would advise you to keep PSE. Or don't map the kernel with large pages. If you want PAE, you better start with PAE on. There will be one more level of indirection, and you will have to set the first directory entry of the first and fourth page directories.


I definitely don't want to keep PSE. This never gets easy, doesn't it?
This is going to get really messy and complicated. Making PAE work in assembly, great, just great. Shouldn't take more than like 5 weeks, but OK.
To think of it, there might be a contrived way of enabling PAE on the fly. You could rewrite the first 8 PDEs into PDPTEs, make them point to page directories, etc, and then enable PAE. Assuming that the IDT, GDT and TSS are pointed at higher half memory at this point, you shouldn't fault yet. Turning on PAE should serialize the execution, flush the pipeline and discard the TLB entries, and hopefully just reload the paging structures. Of course, starting with PAE will be more conventional, but it is your decision.


Top
 Profile  
 
 Post subject: Re: Higher Half in C?
PostPosted: Mon Jul 16, 2018 2:50 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
simeonz wrote:
To think of it, there might be a contrived way of enabling PAE on the fly. You could rewrite the first 8 PDEs into PDPTEs, make them point to page directories, etc, and then enable PAE. Assuming that the IDT, GDT and TSS are pointed at higher half memory at this point, you shouldn't fault yet. Turning on PAE should serialize the execution, flush the pipeline and discard the TLB entries, and hopefully just reload the paging structures. Of course, starting with PAE will be more conventional, but it is your decision.


I'll go for PAE from the beginning.
Uhmm, how exactly am I supposed to access 64-bit bitfields in assembly while in 32-bit mode? Never had to do something like this.
Like how to move data from one register to some_data + 40 bits? That is why is love higher languages so much and that is why programming abstractions in assembly is hard.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Higher Half in C?
PostPosted: Mon Jul 16, 2018 5:35 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
Initializing PAE is not much more complicated than non-PAE. Here is what I do:


Code:
    ; Initialize the PDPT
    mov edi, _BootPDPT - KERNEL_VIRTUAL_BASE
    mov eax, (_BootPageDirectory - KERNEL_VIRTUAL_BASE) + PAGE_PRESENT
    mov [edi], eax                                      ; Identity map the first 4 MB
    mov [edi + 3 * 8], eax                              ; Map the same 4 MB to high memory

    ; Initialize the page directory (2 MB per entry)
    mov edi, _BootPageDirectory - KERNEL_VIRTUAL_BASE
    mov eax, (_BootPageTables - KERNEL_VIRTUAL_BASE) + PAGE_WRITE + PAGE_PRESENT
    mov [edi], eax                                      ; First page table (First 2 MB)
    add eax, 0x1000
    mov [edi + 8], eax                                  ; Second page table (Next 2 MB)

    ; Initialize the page tables
    mov edi, _BootPageTables - KERNEL_VIRTUAL_BASE
    mov eax, 0x00000000 | PAGE_WRITE | PAGE_PRESENT     ; Start at physical address 0
    mov ecx, 1024                                       ; 1024 entries
.fill_page_table:
    mov [edi], eax
    add eax, 0x1000
    add edi, 8
    loop .fill_page_table


You can see the whole implementation here:
https://github.com/kiznit/kiznix/blob/f ... ot_pae.asm

Hope this helps...

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Higher Half in C?
PostPosted: Wed Jul 18, 2018 1:46 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
kzinti wrote:
Initializing PAE is not much more complicated than non-PAE. Here is what I do:
Code:
---snip---


You can see the whole implementation here:
https://github.com/kiznit/kiznix/blob/f ... ot_pae.asm

Hope this helps...


Easy for you to say, my pages are 4 KB not 2 MB. :) Thanks anyways!



Btw, I found a solution to my problem, that doesn't work, yet.
What I did is basically inspected the paging structures in memory (C++ generated) and then I figured out where to put stuff at and what bytes are flags and what bytes are address bytes. That made my job a lot easier.
After all the pain I created 6 page tables filled them accordingly did all the math, interconnected everything and yet Bochs is not happy:
Code:
SetCR0(): PDPTR check failed !

Emulation stops at mov cr0, eax and I can't inspect my page tables (via Bochs GUI debugger) and no "physical address not available" errors were thrown. Any ideas?
Anyways here are chunks of my code:
Code:
//Do so for all 4, make sure that page directory pointer table has 4 page directories
mov eax, (first_page_directory - 0xC0000000)
shr eax, 12
mov dword [page_directory_pointer_table.first_page_directory_pointer_table_entry - 0xC0000000 + 1], eax
mov byte [page_directory_pointer_table.first_page_directory_pointer_table_entry - 0xC0000000], 1

//Inserting page table address and flags into page directory entry, do so for all six of them
mov eax, (first_page_table - 0xC0000000)
shr eax, 12
mov dword [first_page_directory.first_page_directory_entry - 0xC0000000 + 1], eax
mov dword [third_page_directory.first_page_directory_entry - 0xC0000000 + 1], eax
mov byte [first_page_directory.first_page_directory_entry - 0xC0000000], 3
mov byte [third_page_directory.first_page_directory_entry - 0xC0000000], 3

//The way I fill my page tables, only showing the first 3
  mov ecx, 512
  xor eax, eax
  xor edx, edx
.Fill_First_Page_Table:
    cmp ecx, 0
    je .Done_Filling_First_Page_Table
    shr eax, 12
    mov dword [first_page_table - 0xC0000000 + 1 + edx], eax
    shl eax, 12
    mov byte [first_page_table - 0xC0000000 + edx], 3
    add eax, 0x1000
    dec ecx
    add edx, 8
    jmp .Fill_First_Page_Table
.Done_Filling_First_Page_Table:
    mov ecx, 512
    mov eax, 0x200000
    xor edx, edx
.Fill_Second_Page_Table:
    cmp ecx, 0
    je .Done_Filling_Second_Page_Table
    shr eax, 12
    mov dword [second_page_table - 0xC0000000 + 1 + edx], eax
    shl eax, 12
    mov byte [second_page_table - 0xC0000000 + edx], 3
    add eax, 0x1000
    dec ecx
    add edx, 8
    jmp .Fill_Second_Page_Table
.Done_Filling_Second_Page_Table:
    mov ecx, 512
    mov eax, 0x400000
    xor edx, edx
.Fill_Third_Page_Table:
    cmp ecx, 0
    je .Done_Filling_Third_Page_Table
    shr eax, 12
    mov dword [third_page_table - 0xC0000000 + 1 + edx], eax
    shl eax, 12
    mov byte [third_page_table - 0xC0000000 + edx], 3
    add eax, 0x1000
    dec ecx
    add edx, 8
    jmp .Fill_Third_Page_Table
.....etc


//Last chunk
mov eax, (page_directory_pointer_table - 0xC0000000)
    mov cr3, eax
    mov eax, cr4
    or eax, 00000000000000000000000000100000b
    mov cr4, eax
    mov eax, cr0
    or eax, 10000000000000000000000000000000b
    mov cr0, eax


I know this thread is getting long, sorry for that.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Higher Half in C?
PostPosted: Wed Jul 18, 2018 1:58 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
Octacone wrote:
Easy for you to say, my pages are 4 KB not 2 MB. :) Thanks anyways!


My pages are 4 KB.

There are 512 entries in one page table. 512 x 4 KB = 2 MB per page directory entry.

I use 2 page tables for a total of 4 MB.

That 4 MB is identity-mapped and mapped to 3 GB using the first an last entries of the PDPT.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Higher Half in C?
PostPosted: Wed Jul 18, 2018 2:08 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
kzinti wrote:
Octacone wrote:
Easy for you to say, my pages are 4 KB not 2 MB. :) Thanks anyways!


My pages are 4 KB.

There are 512 entries in one page table. 512 x 4 KB = 2 MB per page directory entry.

I use 2 page tables for a total of 4 MB.

That 4 MB is identity-mapped and also mapped to 3 GB.


Why did I assume they were 2 MB? :oops:
I'll definitely have a look to see if anything stands out.
I need like 12 MB but I'll figure it out.
Edit: So you are using like 1 page directory for the whole thing, just pointing to it twice inside the page directory pointer table. That is smart, it could save a lot of space when I think of it.
Edit: Wait, I don't see you shifting any addresses to the right by 12. Isn't that like mandatory, or it only applies to pages?
Reply to edit above: since it's page aligned it doesn't matter..., only matters for pages looks like.

Okay, I did some bug fixing and now I am getting physical address not available, which is better than not getting it. But why can't I see my page tables in Bochs? How am I supposed to fix them without seeing them?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Fixed: Higher Half in C?
PostPosted: Wed Jul 18, 2018 3:55 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
VICTORY!
It is done, it is over, finally! :-"
Boooooy that took a while, but it was worth it.
Attachment:
Success.png
Success.png [ 23.93 KiB | Viewed 1073 times ]


So how did I fix it?
While looking through @kzinti's code I noticed that he was adding flags directly to the address value, while I was doing it separately and accidentally offsetting it by 1 byte.
Many many thanks to @kzinti he appeared exactly when I needed him.
Now I just need to figure out how to load a new page directory pointer table with different values while removing 0xC000000 offset from all the values so they are physical. I will probably have to switch from static to dynamic allocation, but that is a problem for later for me to figure out.
Again, thanks to everybody who showed interest in helping.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4

All times are UTC - 6 hours


Who is online

Users browsing this forum: Amazonbot [bot], SemrushBot [Bot] and 48 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