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.
Hello, in bochs I get now his message "exception(): 3rd (14) exception with no resolution". What does this mean? I checked it in "AMD64 Programming Guide Version 2" and found out "Page Fault (Vector 14)". The problem appearted just after adding a new function, and the kernel image changed from 4616 to 5016 bytes.
When some failure occures in your exception handler, CPU tries to execute so-called double-fault handler. If this also leads to exception then we have triple-fault (3rd exception) and CPU resets. This is a really basic thing.
That's assuming you have an exception handler. What's the new function do? Is it trying to access a page that doesn't exist/is marked not writable? Does your kernel now overlap a page that is not marked executable? Is your kernel accidentally jumping somewhere that meets one of these conditions (maybe via stack clobbering before a function return)? Just random thoughts off the top of my head.
EDIT:
In fact, I just noticed that RSP is 0x10. That's probably getting clobbered somewhere and the root of your problem (or at least a strong pointer to your root problem).
Well my os is loaded after the loaded MBR at 0x7e00, and the stack pointer is set to 0x7e00. The paging tables PML4, PDP, PD and PT are loaded from 0x0 to 0x4000. Only one PT is made for the 512 first 4KB. How do I steup the stack anyway? I don't know the basic concepts of the sack, just the that it grows down...
.code64
# Setup the stack
movq $0x07e0, %rsp
# Set arg0
# Set arg1
# Set arg2
# Set arg3
# Set arg4
# Set arg5
# Enter into the kernel
clrq %rdi
clrq %rsi
clrq %rdx
clrq %rcx
clrq %r8
clrq %r9
call kmain
# Disable Interrupts before Halt
cli
Hang:
# Halt the CPU
# Infinit loop if Halt doesn't work
hlt
jmp Hang
maybe the problem is in your paging
check it and correct it
and some exceptions push an error code inside the error itself
for example, double fault push's an error code
if it doesn't coded, it will push's a triple fault (third exception)
page fault (exception number 14) actually push's an error code
if it doesn't coded, it give's a double fault and again, it give's a triple fault
testing the operating system is very hard when your eyes can't see well
like me and many others
The paging tables should be correct. The kernel is loaded at 0x7e00 and is 5592 bytes long (the MBR loads 0x10 sectors of 0x200 bytes at 0x7e00). The first part of the kernel enters 32 bits Protected Mode, then sets up Paging, before entering 64 bits Long Mode. The GDT and IDT are located in the .rodata part of the kernel. Hardware interrupts are relocated to 0x20 t0 0x2f. All went well until the kernel grow from 4650 bytes to 5592.
# Clear memory (0x0000 - 0x4000) for the Paging Tables
# Set A Register to 0x0000
# Set C Register to 0x1000
# Set Destination Index to 0x0000
# Store 4 bytes 0x1000 times
clrl %eax
movl $0x1000, %ecx
clrl %edi
rep stosl
# Set Destination Index to the PML4 address
# Create reference to PDP entry in PML4
# Set Destination Index to the PDP address
# Create reference to PD entry in PDP
# Set Destination Index to the PD address
# Create reference to PT entry in PD
# Set Destination Index to the PT address
movl $0x0000, %edi
movl $0x1003, (%edi)
addl $0x1000, %edi
movl $0x2003, (%edi)
addl $0x1000, %edi
movl $0x3003, (%edi)
addl $0x1000, %edi
# Set B Register to Page Table Flags
# Set C Register to the number of entries
# Create Page Tables Entry
# Add 0x1000 to B Register
# Add 0x0008 to Destination Index
# Set next entry while C Register is different from zero
movl $0x0003, %ebx
movl $0x0200, %ecx
SetPtEntry:
movl %ebx, (%edi)
addl $0x1000, %ebx
addl $0x0008, %edi
loop SetPtEntry
Wait, are you saying that you're clobbering linear 0x0000 to 0x4000? As in where the BIOS/initial IVT data lives (0x0 - 0x500)? Or do you have a GDT that has 0x10 pointing to something above that?
IVT is not needed in 64 bits Long Mode, because it serves only in 16 bits Real Mode as interrupt handler. I am speaking of linear addresses. My kernel is at most 8KB long and is loaded to 0x7e00, the GDT and IDT are in my .rodata part of the kernel. The kernel goes over to Protected Mode without paging, then sets up PML4, PDP, PD and PT from 0x0 to 0x4000. Everything was run correctly until the kernel growed in size. Could it be that the Bochs BIOS does not load more than 4KB via the extended LBA read? I heard that some BIOSes can 'only' read 0x7f sectors using LBA.
Ok found out something: What is the difference between 'C switch' and 'C if else if'? Using switch causes 'exception(): 3rd (14) exception with no resolution', where if else if works perfectly. I am using gcc-4.8.1.
teodori wrote:What is the difference between 'C switch' and 'C if else if'?
the former causes people to forget scope rules and break statements...
At any rate, I would know from such an observation not to trust anything anymore. You will have to singlestep and find the exact instruction and circumstances that cause the problem, then relate it to what the code is supposed to do.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]