Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Presumably you are running in an emulator. Which one? What does its log tell you about the triple fault? As you know exactly where it is you have presumably done a register dump; this would be useful information.
And you say that the paging is set up correctly. What evidence do you have for that statement?
The simple answer is, use a debugger to single-step through the code in your emulator and see exactly what is happening. Also, it would be useful to implement very rudimentary exception handlers so that you can stop the code at the first exception and then inspect registers and memory contents.
In short - you really need to do a little debugging before posting code here and just saying "what's the problem?".
I of course did some debugging on my own.
I have just pasted jmp $ until it wasn't crashing and stepped as far as possible
in the code.
Triple faults both on Qemu and Bochs.
Evidence for correct paging setup is simple i think, I checked in bochs GUI debugger the address at 0x9000 and i can
see the address of paging layer 3 or'ed by 1 and 10b.
Also, when i do memory drop of the address i also see it is correct (filled with zeroes as it should be).
0x9000 is divisible by 4096 and i have checked other operations like ten times before i posted here. I also did
page 0x9000 in bochs dbg and it points to 0x9000
Also i have to mention that the code pasted before is loaded by stage1, which relocates itself to 0x7a00 and loads new code
at 0x7c00 so i can start again from that address with more memory.
Also when i do
lea eax, [PAGING_LAYER4] before i mov cr0, eax it somehow doesn't tripple fault but it should as well i guess. <-strange
I really did a lot of debugging, around 4 hours now I guess and i simply have no idea
(0).[168181647] ??? (physical address not available)
(0).[168181648] ??? (physical address not available)
bx_dbg_read_linear: physical address not available for linear 0x000000000000824c
PML4: 0x000000000000a002 ps a pcd pwt S W p
physical address not available for linear 0x0000000000009000
bx_dbg_read_linear: physical address not available for linear 0x000000000000824c
The first entry in your PML4 (PAGING_LAYER4) doesn't have the present bit set, causing a pagefault.
Also, your PDPT (PAGING_LAYER3) is filled with 0, which will also cause a pagefault.
Both of these will result in a triplefault, as you don't have an IDT setup.
So you'll have to set the present bit in your first PML4E and properly initialize your PDPT.
You haven't set the write-protect bit in CR0. This leads to a GP fault when you enable paging, which leads to a triple fault as you have no handler for the exception.
iansjack wrote:You haven't set the write-protect bit in CR0. This leads to a GP fault when you enable paging, which leads to a triple fault as you have no handler for the exception.
The WP bit in CR0 merely enforces write protect on pages with the R/W bit cleared. It will only generate a GP if the WP bit is set, the R/W bit cleared and whenever that page is being written to. However, this only applies in kernel mode, it will always cause a GP in usermode.
Last edited by DropDemBits on Sun Mar 26, 2017 11:21 am, edited 1 time in total.
I'm sure that you are correct, in which case the Wiki is incorrect.
Anyway, what the OP needs to do is to implement rudimentary exception handlers (all they have to do is halt the processor) so that they can see what the first exception is and can inspect any error code associated with it.
if screen gets green - we are in real mode!
;;setting up paging
;;We have to set address of page directory to first page dir ptr tab, and or it with 1
lea eax, [PageDir]
or eax, 1b
mov [PageDirPtrTab+4], eax
;;now we set address of page tab to page dir and or it by 3
lea eax, [PageTab]
or eax, 3
mov [PageDir+4], eax
;;lets map 100MiB of memory
mov ecx, 0;counter
mov ebx, 0;address
.map:
lea eax, [PageTab + 4 + ecx*8]
mov [eax], ebx
or dword [eax], 3
add ebx, 0x1000
inc ecx
cmp ecx, 25600
jl .map
;; 100MiB should be mapped now
;; let's set PAE bit and load page directory pointer
lea eax, [PageTab]
mov eax, cr4
bts eax, 5
mov cr4, eax
lea eax, [PageDirPtrTab+4]
mov cr3, eax
;;now lets activate paging
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
jmp $
;;<<------triple fault here
call gdt64_install
;;TODO: paging
;;not working yet
;;-------------
jmp dword 0x8:longmode
align 0x20
PageDirPtrTab: dq 4 dup(0)
align 0x1000
PageDir: dq 512 dup(0)
align 0x1000
PageTab: dq 512 dup(0)
You're on the right track, but I see a few problems.
1) I don't see a PML4, those are required in long mode paging.
2) Your PDPT isn't page aligned (0x1000).
3) CR3 points to the base address of your PML4.