How to setup x86 paging? Getting triple fault error
I have a toy kernel that I'm working with running under x86 on bochs. When I enable paging, bochs resets with a triple fault error. It seems that it is every and any memory access which triggers the error. So, I'm assuming that I have an error with setting up paging, and the issue is not with my interrupt handler. Here is the code.
paging.c
#include "paging.h"
#include "lib.h"
#include "screen.h"
#include "descriptor_tables.h"
typedef struct page_dir_entry_s{
bool present:1;
bool writeable:1;
bool user_access:1;
bool write_through:1;
bool cache_disabled:1;
bool accessed:1;
bool unused0:1;
bool use_mb:1;//makes pages 4MB not 4KB
bool unused1:4;
u32 frame:20;
} page_dir_entry_t;
typedef struct page_table_entry_s{
bool present:1;
bool writeable:1;
bool user_access:1;
bool write_through:1;
bool cache_disabled:1;
bool accessed:1;
bool dirty:1;
bool unused0:1;
bool global:1;
bool unused1:3;
u32 phys_page_addr:20;
} page_table_entry_t;
extern u32 end;//as declared in the linker script
static u32 next_addr=0;
static page_dir_entry_t* page_dir=NULL;
static page_table_entry_t* page_table=NULL;
extern void enable_paging(u32);
void InitPaging(){
next_addr=end;
while((next_addr%4096)!=0)
++next_addr;
page_dir=(void*)next_addr;
next_addr+=4*1024;
memset(page_dir,0,4*1024);
page_table=(void*)next开发者_运维问答_addr;
next_addr+=4;
u32 addr=0;
u32 i=0;
*(((u32*)page_table)+i)=0;//zero it out
while(addr<next_addr){
page_table[i].present=true;
page_table[i].writeable=true;
page_table[i].phys_page_addr=addr;
++i;
*(((u32*)page_table)+i)=0;//zero it out
addr+=(1024*4);//4KB
next_addr+=4;
}
page_dir[0].writeable=true;
page_dir[0].present=true;
page_dir[0].frame=(u32)page_table;
enable_paging((u32)page_dir);
}
paging_asm.s
[global enable_paging]
enable_paging:
mov eax,[esp+4]
mov cr3,eax
mov eax,cr0
or eax,0x80000000
mov cr0,eax
ret
The "frame" and "phys_page_addr" fields are bits 32 through 12 (in this paging mode) of the physical address.
Paging doesn't do anything with the offset (0 - 4K).
At the least, you need:
page_table[i].phys_page_addr=addr >> 12;
and
page_dir[0].frame=((u32)page_table) >> 12;
Since both 'addr' and 'page_table' are aligned to 4096, this just removes the extra zeros.
精彩评论