Enabling paging immidiatly causes a Triple Fault

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.
Post Reply
Andrispowq
Posts: 2
Joined: Fri Jul 17, 2020 7:20 am

Enabling paging immidiatly causes a Triple Fault

Post by Andrispowq »

I've followed the tutorials of cfenollosa, on GitHub (link: https://github.com/cfenollosa/os-tutorial), and having finished it, I decided to move on with James Molloy's tutorials, the 6th one, which was about paging. I copied the source code, integrated it with the rest of my code, but I didn't change any line which was about the paging code, only swapped the monitor_write calls to printf calls, because that's what the print command is called in my kernel. Anyways, this line:

Code: Select all

asm volatile("mov %0, %%cr0" :: "r"(cr0));
throws a triple fault for some reason. This is the enabling code:

Code: Select all

current_directory = dir;
    asm volatile("mov %0, %%cr3" :: "r"(dir->tablesPhysical));
    uint32_t cr0;
    asm volatile("mov %%cr0, %0" : "=r"(cr0));
    cr0 |= 0x80000000; // Enable paging!
    asm volatile("mov %0, %%cr0" :: "r"(cr0));
And this is the paging structure:

Code: Select all

typedef struct page
{
   uint32_t present    : 1;   // Page present in memory
   uint32_t rw         : 1;   // Read-only if clear, readwrite if set
   uint32_t user       : 1;   // Supervisor level only if clear
   uint32_t accessed   : 1;   // Has the page been accessed since last refresh?
   uint32_t dirty      : 1;   // Has the page been written to since last refresh?
   uint32_t unused     : 7;   // Amalgamation of unused and reserved bits
   uint32_t frame      : 20;  // Frame address (shifted right 12 bits)
} page_t;

typedef struct page_table
{
   page_t pages[1024];
} page_table_t;


typedef struct page_directory
{
   /**
      Array of pointers to pagetables.
   **/
   page_table_t* tables[1024];
   /**
      Array of pointers to the pagetables above, but gives their *physical*
      location, for loading into the CR3 register.
   **/
   uint32_t tablesPhysical[1024];
   /**
      The physical address of tablesPhysical. This comes into play
      when we get our kernel heap allocated and the directory
      may be in a different location in virtual memory.
   **/
   uint32_t physicalAddr;
} page_directory_t;
Upon triple faulting, I recieved a report of the CPU's state before the triple fault occoured, and the main parts are the CR0, and the CR3 registers:

Code: Select all

CR0=80000011 CR2=0008fc6c CR3=00008000 CR4=00000000
Now, the CR0 looks fine to me, as the PG bit is enabled (bit 31), bit 0 is for protected mode, and I don't know what bit 4 is for, but I don't think it is relevant. CR3 contains the address 0x8000, which is 4K aligned, and I am absolutely sure it is correct, as the page directory is allocated at 0x7000, and the tables member is 4096 bytes long, so the tablesPhysical member starts at 0x8000.
A few things that might help us solve the bug:
Even though I set up the GDT in the bootloader, before jumping into protected mode, I set it up again in C, because the tutorial also does that (I know it's not necessery, but it didn't work so I thought this might be the problem why paging doesn't works, turns out it isn't but it's nice to have it in C too).
Also, it might be important to know that I run the code using QEMU, debug it via GDB (the makefile contains more information, which is on GitHub, see below), and this whole program is written in Ubuntu 20.04, which is installed on VirtualBox, version 6.1.10, and the host OS is Windows 10, the hardware is AMD Ryzen 7 2700x, 16 GB RAM.

The source code is on GitHub, the link: https://github.com/Andrispowq/HackOS

Any help is appreciated, thanks in advice!
Octocontrabass
Member
Member
Posts: 5885
Joined: Mon Mar 25, 2013 7:01 pm

Re: Enabling paging immidiatly causes a Triple Fault

Post by Octocontrabass »

Andrispowq wrote:Upon triple faulting, I recieved a report of the CPU's state before the triple fault occoured, and the main parts are the CR0, and the CR3 registers:
That information is useful, yes, but QEMU can also tell you what kind of fault it was. (Try "-d int" if you aren't already using it.) For example, if the log says it's a page fault - which is pretty likely - you then know that you should check CR2 to determine which page directory entry and page table entry to examine, and the error code in the log will tell you which bits in those entries are incorrect.
Andrispowq wrote:I don't know what bit 4 is for, but I don't think it is relevant.
It's obsolete on most CPUs. (On a 386DX, it selects the FPU interface.)
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Enabling paging immidiatly causes a Triple Fault

Post by nexos »

You may make your kernel however you want, but James Molloy's paging tutorial uses questionable coding practices. I would recommend either reading the Intel manuals and not using a tutorial, or using the tutorial at http://www.brokenthorn.com/Resources/OSDev18.html. But I repeat, you may make your OS however you like.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply