I am trying to write a kernel, mostly for entertainment purposes, and I am running into a problem were I believe it is triple faulting. Everything worked before I attempted to enable paging. The code that is breaking is this:
void switch_page_directory(page_directory_t *dir){
current_directory = dir;
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
u32int cr0;
asm volatile("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000;//enable paging
asm volatile("mov %0, %%cr0":: "r"(cr0)); //this line breaks
}//switch page directory
I have been following a variety of tutorials / documents for this but the one I am using to paging is thus http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html . I am not sure what other code will be useful in figuring this out but if there is more I should provide I will be more than happy to do so.
Edit=====
I believe the CS,DS and SS are selecting correct entries here's the code used to set them
global gdt_flush
extern gp
gdt_flush:
lgdt [gp] ; Load the GDT with our 'gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!
and here's the gdt struct itself
struct gdt_entry{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
struct gdt_ptr{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct gdt_entry gdt[5];
struct gdt_ptr gp;
The IDT is very similar to this.
GDT: you don't say what the contents of the GDT entries are, but the stuff you've shown looks fairly similar to the earlier part of the tutorial you linked to and if you've set up the entries in the same way, then all should be well (i.e. flat segment mapping with a ring 0 code segment for CS, ring 0 data segment for everything else, both with a base of 0 and a limit of 4GB).
IDT: probably doesn't matter anyway if interrupts are disabled and you're not (yet) expecting to cause page faults.
Page tables: incorrect page tables do seem like the most likely suspect. Make sure that your identity mapping covers all of the code, data and stack memory that you're using (at least).
The source code linked to at the bottom of http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html definitely builds something that does work correctly with both QEMU and Bochs, so hopefully you can compare what you're doing with what that's doing, and work out what is wrong.
QEMU is good in general, but I would recommend Bochs for developing really low-level stuff - it includes (or can be configured to include) a very handy internal debugger. e.g. set reset_on_triple_fault=0
on the cpu:
line of the config file, set a breakpoint in the switch_page_directory()
code, run to the breakpoint, then single step instructions and see what happens...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With