Paging trouble
Posted: Mon Aug 06, 2007 12:44 pm
I have tried to implement paging in my (fairly new and simple) OS.
I based my code on a paper from osdever.net on paging and implemented my malloc() and free() functions around it. These seem to work however when i try to call the enable_paging() function, i get a popup saying "An Unrecoverable Processor Error has been discovered"
Could this be my emulator (MS virtual PC) or is my code majorly incorrect?
I based my code on a paper from osdever.net on paging and implemented my malloc() and free() functions around it. These seem to work however when i try to call the enable_paging() function, i get a popup saying "An Unrecoverable Processor Error has been discovered"
Could this be my emulator (MS virtual PC) or is my code majorly incorrect?
Code: Select all
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
#define MEMORY 4096000 /* Stack(bytes) (4mb) */
extern void write_cr3(unsigned long *page_directory);
extern void write_cr0(unsigned long page_directory);
extern int read_cr0();
extern int read_cr3();
static char allocbuffer[MEMORY]; /* Array to store all memory locations */
static char *allocp = &allocbuffer[0]; /* Pointer to next free location */
unsigned long *page_directory = (unsigned long *) 0x110000;
unsigned long *page_table = (unsigned long *) 0x111000;
unsigned long address = 0;
/* Pages used... this is used for page_directory array */
unsigned long page_number = 1;
typedef struct
{
int access;
unsigned long start;
int used;
}page_t;
void enable_paging(int memory)
{
int __RAM__= memory/4096; /* convert to amount of pages */
__RAM__ -= 2; /* 8kb stack for OS */
unsigned long *pagedir = (unsigned long *) 0x400000;
unsigned long *pagetable = (unsigned long *) 0x401000;
unsigned long addr = 0, i;
for (i = 0; i < 1024; i++)
{
*(pagetable + i) = addr | 3; /* Supervisor, R/W, Present */
addr += 4096; /* 4kB / page */
}
/* For the first entry */
*(pagedir) = (unsigned long int) pagetable;
*(pagedir) |= 3; /* Set attributes */
/* Set remaining pages to absent */
for (i = 1; i < 1024; i++)
*(pagedir + i) = 0 | 2; /* Not present */
write_cr3 ((unsigned long int) pagedir);
write_cr0 (read_cr0 () | 0x80000000); /* Set paging bit */
}
/* This function sets the amount of needed pages to present and updates the
page_number global variable. It returns the pointer to the memory location */
unsigned long request_pages(int size)
{
unsigned long ret = 0;
if(size > 4096) /* More than one page */
{
int runs = size/4096;
ret = page_directory[page_number+1];
for(int i=0;i<(page_number+1);i++)
page_table[i+1] = address | 3;
page_number += runs;
} else { /* only one */
ret = page_directory[page_number+1];
page_table[page_number+1] = address | 3; /* Set pages to present */
page_number++;
}
return ret; /* Pointer to start of free space */
}
/* Resets unused pages to not present */
unsigned long free_pages(int size)
{
int runs = size/4096;
page_number -= runs;
for(int i = runs;i>0;i--)
page_table[i-1] = address | 2; /* Reset to not present */
return 0;
}
/* Allocates n amount of memory using pages */
char* malloc(unsigned long n) /* Return pointer to n chars */
{
unsigned long page = request_pages(n);
if (page - MEMORY >= n) /* Space available */
{
allocp += n;
return allocp - n; /* Return pointer to start of memory location */
} else {
return 0; /* No space */
}
}
/* Frees memory pointer to by p */
void* free(char *p)
{
int tmp = strlen(p);
free_pages(tmp); /* Free pages */
allocp = p; /* Reset pointer */
return 0;
}