Hey guys, so I spent all day trying to understand paging. And I finally figured it out, but sadly my code to map from 0x0 to 4mb didn't work. When I tried to set the CR3 register in long mode it raised a page fault which makes no sense but ok. So here is my kernel's intilizer for paging that works and is what is currently active in my long mode:
Code: Select all
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 double word at the destination index to 0x2003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov DWORD [edi], 0x3003 ; Set the double word at the destination index to 0x3003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov DWORD [edi], 0x4003 ; Set the double word at the destination index to 0x4003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov ebx, 0000003 ; Set the B-register to 0x00000003.
mov ecx, 512 ; Set the C-register to 512.
.SetEntry:
mov DWORD [edi], ebx ; Set the double word 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.
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
There's some other part's, but you get the idea. So my issue mainly is that the stupid 32bit paging that is setup above, starts at 4k and runs through my multi boot structure and stuff. So I am tying to create a page setup with the first 4mb paged using variables in nasm. This part runs in 64bit mode, because I want to swap out page tables as a test basically, and for fun. But my paging code isn't working as I said above. Now one thing to consider is that the 'Bit_Set' function simply set the bit of my choice to what I would like in a number. It comes in handy. So here is my Paging code:
Code: Select all
;The root table that contains 512 Page Table Directory Pointer Table's
PML4T: TIMES 4096 db 0
;The first Page Directory Pointer Table that contains 512 Page Directory Table's
PDPT_0: TIMES 4096 db 0
;The first Page Directory Table that contains 512 Page Table's
PDT_0: TIMES 4096 db 0
;The first Page Table that contains 512 Page's
PT_0: TIMES 4096 db 0 ;2Mb mapped
;The seond Page Table that contains 512 Page's
PT_1: TIMES 4096 db 0 ;2Mb mapped
;A total of 20kb of data.
;Each table has 512 64bit value entry's.
;Setups paging in 32bit mode.
Paging_Setup:
;First we want to set the first entry in the PLM4T to PDPT_0
mov rax, PDPT_0
push rax
push 64
push 1 ;On, Present
call Bit_Set
push 63
push 1 ;On, Read/Write
call Bit_Set
pop rax
mov dword[PML4T], eax
;Now set the first entry in PDPT_0 to PDT_0
mov rax, PDT_0
push rax
push 64
push 1 ;On, Present
call Bit_Set
push 63
push 1 ;On, Read/Write
call Bit_Set
pop rax
mov qword[PDPT_0], rax
;Now set the first entry in PDT_0 to PT_0
mov rax, PT_0
push rax
push 64
push 1 ;On, Present
call Bit_Set
push 63
push 1 ;On, Read/Write
call Bit_Set
pop rax
mov qword[PDT_0], rax
;Now the last thing to do is set the last entry in the PDT_0 to itself
mov rax, PDT_0
push rax
push 64
push 1 ;On, Present
call Bit_Set
push 63
push 1 ;On, Read/Write
call Bit_Set
pop rax
mov dword[PDT_0+4088], eax
;Now map all pages from 0 to 2mb
;So PT_0 contains 512 4k entrys which is 512*4096 = 2MB
;So lets start our mapping process.
mov rax, 0 ;Start address
mov rbx, PT_0 ;Start
mov rcx, PT_0 ;End
add rcx, 4096 ;End
;-------------------------------------------------------------------------------
.loop_0:
cmp rbx, rcx
jge .done_0
; Now we want to move the current address
; into the page table, but we first have to set the present and read/write flags.
push rax ;Save the address
push rbx ;Save ths start
push rcx ;Save the end
push rax
push 64
push 1 ;Present
call Bit_Set
push 63
push 1 ;Read/Write
call Bit_Set
pop rdx
pop rcx ;End
pop rbx ;Start
pop rax ;Address
; Now we will move the new address with the flags set into the page table
mov dword[rbx], edx
; Now add 0x1000:4096 to the address
add rax, 0x1000
add rbx, 8 ;Entry size
; Just loop back now
jmp .loop_0
.done_0:
; -------------------------------------------------------------------------------
mov rbx, PT_1 ;Start
mov rcx, PT_1 ;End
add rcx, 4096 ;End
.loop_1:
cmp rbx, rcx
jge .done_1
; Now we want to move the current address
; into the page table, but we first have to set the present and read/write flags.
push rax ;Save the address
push rbx ;Save ths start
push rcx ;Save the end
push rax
push 64
push 1 ;Present
call Bit_Set
push 63
push 1 ;Read/Write
call Bit_Set
pop rdx
pop rcx ;End
pop rbx ;Start
pop rax ;Address
; Now we will move the new address with the flags set into the page table
mov dword[rbx], edx
; Now add 0x1000:4096 to the address
add rax, 0x1000
add rbx, 8 ;Entry size
; Just loop back now
jmp .loop_1
.done_1:
;Now set the PML4T to the CR3 register to swap page tables
;this might kill the whole system...
mov rax, PML4T
mov cr3, rax
jmp os_hang
Now you'll notice that in one part of the code up there I map PDT_0 to itself because this page here:
http://www.rohitab.com/discuss/topic/31 ... directory/
was talking about a issue where you couldn't edit the page directory tables unless you mapped it to itself in the last entry. I tried my code with that done, and without it. I think my logic somewhere is flawed.
Some of that is a eye sore. Anyways, sorry for asking so much of you guys. I commented the code as much as possible when
I was writing it so that if it failed you guys could follow my logic some. Thanks, Matt