Paging trouble

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
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Paging trouble

Post by lukem95 »

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?

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;
}
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

Your code has three major problems.
Tyler
Member
Member
Posts: 514
Joined: Tue Nov 07, 2006 7:37 am
Location: York, England

Post by Tyler »

Kevin McGuire wrote:Your code has three major problems.
You're my hero.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Hi,
Your code has three major problems.
After a (albeit quick, I'm waiting for a soak run to begin here at work) scan look through that code, no huge errors popped out at me. What are your three major problems? Apart from the fact that the OP hasn't worked out how to printf/for(;;); debug and narrow the problem down?

JamesM (probably speaking in haste, and almost certainly when rereading his code will find those 3 errors)
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Again, I have only scanned quickly, but shouldn't 4MB be 4194304, not 4096000? I would always suggest using hex for this - 0x400000 is so much easier!

Also, are you sure you have paged in the area your current code is running from?

Bochs is your friend!

Cheers,
Adam
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

thankyou all for your quick replys, i will go back through my code,

EDIT Oh and my Kernel loads at 0x1000 so it shouldn't overrun it /EDIT

@ Kevin... Could you enlighten me as to what these are?

Thanks again,

~Lukem
oscoder
Member
Member
Posts: 59
Joined: Mon Mar 27, 2006 12:00 am
Location: UK

Post by oscoder »

I can't see anything wrong with your enable_paging function's code (probably due to the fact I am basically a beginner at OSdev). However, I can see a serious design flaw: the page directory is not mapped into memory, so there will be no way, once paging is enabled, for you to map in any more memory than you already have.

Btw, you might want to try using an emulator, such as bochs, that comes with a debugger, as this will make your osdeving life a lot easier!

Hope that helps,
OScoder
Post Reply