OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 18, 2024 6:45 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 10:20 am 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
Hi!

I am currently trying to put my kernel into virtual higher half. When i am trying to jump from the lower half into the higher half, i get a tripple fault exactly after the jump.
The base address for the kernel should be 0xFFFF FF00 0000 0000 (=HVMA). The PML4 is located at 0x7E0 0000 (+ HVMA).
Because i don't want to paste all of the connected code pieces, it is online at https://github.com/MathiLpHD/MOS/ in the folder system/kernel/
The main files are makefile, linker.ld and src/init/boot.asm

Also, what does -mcmodel=kernel do? And how can i change the datamodel to allow 64-Bit addresses? Or would it be better to move ctors and so on into the text section?

The main Codepieces in boot.asm are:

Code:
mov edi, 0x7E00000      ; Set the destination index to 0x7E00000.
    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], 0x7E01003      ; Set the uint32_t at the destination index to 0x7E01003.

   mov ebx, 0x00000083            ; Set the B-register to 0x000000083. 0x83 = PS = 1 (=> 1GiB Page) R/W = 1, P = 1
   add edi, 0x1000               ; Add 0x1000 to the destination index.
   mov DWORD [edi], ebx         ; Set the uint32_t at the destination index to the B-register.

   mov edi, 0x7FFE000            ; Set the destination index to 0x1000.
   mov DWORD [edi], 0x7E01003      ; Set the uint32_t at the destination index to 0x7E01003. This is for HVMA
    add edi, 0x1000               ; Add 0x1000 to the destination index.
   mov DWORD [edi], 0x7E00003      ; Set the uint32_t at the destination index to 0x7E00003. This is for recrusive mapping

and:
Code:
lgdt [GDT64.Pointer]         ; Load the 64-bit global descriptor table.
   mov ax, 0x10
   mov ss, ax
   mov ax, 0x0
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   jmp GDT64.Code:.trampoline      ; Set the code segment and enter 64-bit long mode.

.NoLongMode:
   cli
   hlt

[BITS 64]
.trampoline:
   ; enter the higher half
   mov rax, QWORD .Realm64
   jmp rax

[section .inith]
.Realm64:
   cli      ; Clear the interrupt flag.

   mov rax, [GDT64.Pointer + 2]
   mov rbx, HVMA
   add rax, rbx
   mov [GDT64.Pointer  + 2], rax
   mov rax, GDT64.Pointer + HVMA
   lgdt [rax]


Image


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 11:26 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Quote:
The PML4 is located at 0x7E0 0000 (+ HVMA).
PML4 is located at a physical address. Do you really have that much RAM?


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 11:38 am 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
iansjack wrote:
Quote:
The PML4 is located at 0x7E0 0000 (+ HVMA).
PML4 is located at a physical address. Do you really have that much RAM?

Well that (+ HVMA) is just if you want to access it from HVMA. Then it would be 0xFFFFFF0007E00000.

EDIT: I am not sure if i found the source of my problem:
My current paging structure:
PL4R: Points to 0x7E0 0000
PL4H: Points to PL3 (=0x7E0 1000)
...
PL3 + 3 * 4096: Points to 3 * 1GB
PL3 + 2 * 4096: Points to 2 * 1GB
PL3 + 1 * 4096: Points to 1 * 1GB
PL3 + 0 * 4096: Points to 0 * 1GB = 0x0000
PL4L: Points to PL3 (=0x7E0 1000)

When i try to access 0xFFFFFF0007E00000, which should be PL4L's HVMA, i get a Page Fault. So it seems that i can't make a paging structure like that, or did i make a different mistake?


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 11:59 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
I've looked at your code and I can't see you creating any entries to map pages. Perhaps I am misunderstanding it.

What do your page tables look like after you have created them? Are they reasonable and what you expect?


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 12:07 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
iansjack wrote:
I've looked at your code and I can't see you creating any entries to map pages. Perhaps I am misunderstanding it.

What do your page tables look like after you have created them? Are they reasonable and what you expect?


Code:
mov edi, 0x7E00000      ; Set the destination index to 0x7E00000.
    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], 0x7E01003      ; Set the uint32_t at the destination index to 0x7E01003.

   mov ebx, 0x00000083            ; Set the B-register to 0x000000083. 0x83 = PS = 1 (=> 1GiB Page) R/W = 1, P = 1
   add edi, 0x1000               ; Add 0x1000 to the destination index.
   mov DWORD [edi], ebx         ; Set the uint32_t at the destination index to the B-register.

   mov edi, 0x7FFE000            ; Set the destination index to 0x1000.
   mov DWORD [edi], 0x7E01003      ; Set the uint32_t at the destination index to 0x7E01003. This is for HVMA
    add edi, 0x1000               ; Add 0x1000 to the destination index.
   mov DWORD [edi], 0x7E00003      ; Set the uint32_t at the destination index to 0x7E00003. This is for recrusive mapping


That creates the paging structure. CR3 is set to 0x7E0 0000, which is PML4T[0] and it points to 0x7E0 1000 which is PDPT[0], which then points to 0x0 as a 1GB page.
Then there is 0x7FF E000 which is PML4T[510] and also points to 0x7E 1003. The last one 0x7FF F000 is PML4T[511] and points to 0x7E0 0000 (=PML4T[0]) for recrusive mapping.


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 12:13 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
That code seems to be setting 32-bit values only. Are you sure that the upper 32-bits of each entry are correctly set?

As before, I would recommend that you inspect the tables I'm memory to see that they correspond to what you think they should be.


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 12:20 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
iansjack wrote:
That code seems to be setting 32-bit values only. Are you sure that the upper 32-bits of each entry are correctly set?

As before, I would recommend that you inspect the tables I'm memory to see that they correspond to what you think they should be.


Well how do i do that? Is there an argument i have to give to QEMU so it saves a image of it's memory?


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 12:23 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
You can use qemu's built-in monitor (see the documentation) or gdb in association with qemu. You'll need to put a "jmp ." instruction somewhere to stop things before the triple fault.

I do see where you are apparently clearing the memory used by the page tables but, unless I missed it, I don't see you setting the DF flag before the repeat string instructions. It's possible that you are clearing memory downwards rather than upwards.


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 12:39 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
iansjack wrote:
You can use qemu's built-in monitor (see the documentation) or gdb in association with qemu. You'll need to put a "jmp ." instruction somewhere to stop things before the triple fault.

I do see where you are apparently clearing the memory used by the page tables but, unless I missed it, I don't see you setting the DF flag before the repeat string instructions. It's possible that you are clearing memory downwards rather than upwards.


The addresses all seem to be right:

Image

EDIT: Do i have to set the 'A' (=Bit 5) Bit?
EDIT2: QEMU is also unable to access the HVMA. x/1xg 0xFFFFFF0007E00000 returns Cannot access memory


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 1:12 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Info mem doesn't show any mapping for your higher-half addresses. That would explain the triple-faulting.


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 1:32 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
iansjack wrote:
Info mem doesn't show any mapping for your higher-half addresses. That would explain the triple-faulting.


Do i have to do something special to activate the higher mappings? Do i have to set the other entries between PML4T[0] and PML4T[510]? Because the MMU maybe tries to increment through the PML4T entries?

EDIT: Wait, does each entry in a table (from 0 - 511) has to be 4k aligned? Or does only the first entry have to be 4k aligned?
EDIT2: I don't know why i thought that but only the first entry has to be 4k aligned.
Now i changed the line:
Code:
mov edi, 0x7FFE000
to:
Code:
mov edi, 0x7E00FF0


Here the info mem:
Image

Now it works^^
Thanks for your help!


Top
 Profile  
 
 Post subject: Re: Setting up x86-64 Higher Half Kernel
PostPosted: Fri May 26, 2017 5:05 pm 
Offline
Member
Member

Joined: Thu Aug 13, 2015 4:57 pm
Posts: 384
MathiLpHD wrote:
EDIT: Wait, does each entry in a table (from 0 - 511) has to be 4k aligned? Or does only the first entry have to be 4k aligned?


Just wanted to clarify, _none_ of the entries have to be 4KiB aligned, however _all_ the tables have to be 4KiB aligned. Of course as a consequence of the table being 4KiB aligned the first entry ends up 4KiB aligned as well, but that's just a consequence, it's the table alignment that's relevant here.

Note also that all the entries will need the physical address they refer to be aligned as well, that alignment has to be what ever the "natural" alignment for the entry is, so for 4KiB pages that's 4KiB, for 2MiB pages it's 2MiB, etc.


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], Google [Bot] and 283 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