I'm working on own OS, it's a lot of fun but i'm stucked with paging, I had wrote simple(very simple) pagination code, but when I turn pagination on, there is page fault. Some details: I'm using C for kernel I'm using qemu as VM I had own crosscompiler I don't use any external libs After loading and jumping into kernel code I setup interrupts and remap PIC, It's working and i reckon it's not the issue, after that I'm trying to enable paging Here is paging.h
#ifndef PAGING_H
#define PAGING_H
#include "../cpu/types.h"
#include "../cpu/isr.h"
#define PAGE_SIZE 4096
typedef struct page{
u32 present :1;
u32 rw :1;
u32 kernel_space :1;
u32 accessed :1;
u32 dirty :1;
u32 unused :7;
u32 frame :20;
} page_t;
typedef struct page_table{
page_t pages[1024];
} page_table_t;
typedef struct page_directory{
u32 page_tables[1024];
} page_dir_t;
typedef struct page_directory_interface{
page_dir_t dir;
page_table_t* page_tables;
u32 page_dir_ph_address;
} page_dir_interface_t;
void init_paging();
void switch_page_dir(page_dir_t* new_dir);
page_t* get_page(u32 addres, page_dir_t* dir, u8 make);
void page_fault(registers_t regs);
#endif
I'm using page_t struct from some tutorial, because I reckon it's quite convinent, other parts, I've writed on my own twice, on both cases code results with PageFault. Here's paging.c:
#include "./paging.h"
#include "../util/panic.h"
#include "./memory.h"
#include "../drivers/screen.h"
page_dir_t* kernel_dir, cur_dir;
//helper function for convinient printing
void pint(u32 a){
char * tmp;
itoa(a, tmp);
kprint(tmp);
kprint("\n");
}
void init_paging(){
kernel_dir = kmalloc(sizeof(page_dir_t));
memset(kernel_dir, 0, 4096);
pint(sizeof(page_dir_t));
pint(&kernel_dir->page_tables[0]);
pint(kernel_dir);
int i;
for(i=0; i<1024; i++){ //setting up page directories for kernel
// read and write and kernel_mode and not present
kernel_dir->page_tables[i] = (u32)kmalloc(sizeof(page_table_t)) | 0x2;
}
map_page_table(kernel_dir->page_tables[0], 1, 1); //map ram to pages;
kernel_dir->page_tables[0] |= 0x3; //set as present
enable_paging();
}
void map_page_table(page_table_t* p_table, int kernel, int rw){
int i;
page_t tmp_page;
tmp_page.present = 1;
tmp_page.rw = (rw) ? 1 : 0;
tmp_page.kernel_space = (kernel) ? 1: 0;
for(i=0; i<1024; i++){
tmp_page.frame |= kmalloc(PAGE_SIZE);
p_table->pages[i] = tmp_page;
}
}
void enable_paging(){
u32 cr0_temp_value;
__asm__ __volatile__("mov %0, %%cr3":: "r"(&kernel_dir->page_tables));
__asm__ ("mov %%cr0, %0": "=r"(cr0_temp_value));
cr0_temp_value |= 0x80000000;
__asm__ __volatile__("mov %0, %%cr0":: "r"(cr0_temp_value));
}
And here is memory.c:
#include "./memory.h"
#include "../cpu/types.h"
#include "../../cathesimc/def.h"
u32 placement_addr = 0x10000;
void memcpy(char* src, char* dst, unsigned int bytes){
int i=0;
for (i=0; i< bytes; i++){
dst[i] = src[i];
}
}
void memset(u8* dest, u8 val, u32 len){
u8* tmp = (u8*)dest;
for(;len != 0; len--) *tmp++ = val;
}
//@TODO poprawic tego biedackiego malloca
u32 kmalloc_intrnl(size_t size, short int align, u32 *phys_addr){
if(align != 0 && (placement_addr & 0xFFFFF000)){
placement_addr &= 0xFFFFF000;
placement_addr += 0x1000;
}
if(phys_addr) *phys_addr = placement_addr;
u32 ret = placement_addr;
placement_addr += size;
return ret;
}
u32 kmalloc(size_t size){
return kmalloc_intrnl(size, 0, NULL);
}
u32 kmalloc_a(size_t size){
return kmalloc_intrnl(size, 1, NULL);
}
u32 kmalloc_p(size_t size, u32* phys_addr){
return kmalloc_intrnl(size, 0, phys_addr);
}
u32 kmalloc_ap(size_t size, u32* phys_addr){
return kmalloc_intrnl(size, 1, phys_addr);
}
My kernel is below 0x10000, it has about 16kb so 0x10000 is safe start of mapped space and memory from that address is definetely not used, I only set up one page table because I want to make paging barebones, and then take care about allocation and freeing, so my only goal for now is to find out what mistake I has making.
============EDIT==============
I have made intensive investigation, and I found that malloc has strange bahaviour, below are snippets of code with explaination
//as we can se from kmalloc() code above, kmalloc starts with
//placement_addr == 0x10000 when kernel starts
void init_paging(){
kernel_dir = kmalloc(sizeof(page_dir_t)); //page_dir_t has size 4096 and that is first malloc in kernel code
memset(kernel_dir, 0, 4096);
pint(sizeof(page_dir_t));
phex(sizeof(page_dir_t));
pint(&kernel_dir->page_tables[0]);
phex(&kernel_dir->page_tables[0]); //prints 0x10000 as expected
int i;
for(i=0; i<1024; i++){ //setting up page directories for kernel
// read and write and kernel_mode and not present
kernel_dir->page_tables[i] = (u32)kmalloc(sizeof(page_table_t)) | 0x2;
}
phex(kernel_dir->page_tables[0]); //0x11002 as expected
phex(kernel_dir->page_tables[1023]); //0x410002 as expected
kprint("pages\n");
map_page_table(kernel_dir->page_tables[0], 1, 1); //map ram to pages;
kernel_dir->page_tables[0] |= 0x3; //set as present
kprint("lol");
enable_paging();
}
void map_page_table(page_table_t* p_table, int kernel, int rw){
int i;
page_t tmp_page;
tmp_page.present = 1;
tmp_page.rw = (rw) ? 1 : 0;
tmp_page.kernel_space = (kernel) ? 1: 0;
//since now troubles starts this forloop below prints adresses:
// iteration0 0x11000
// iteration1 0x12000
// iteration2 0x13000
// iteration3 0x14000
// iteration4 0x15000
// iteration5 0x16000
// iteration6 0x17000
// iteration7 0x18000
for(i=0; i<8; i++){
tmp_page.frame = kmalloc(PAGE_SIZE);
phex(tmp_page.frame);
p_table->pages[i] = tmp_page;
}
}
I think that's definetly might be source of problems but I have no idea why placement_addr changes when i call another function, and why then it changes to 0x11000
User contributions licensed under CC BY-SA 3.0