Page 1 of 1

Paging trouble

Posted: Mon Aug 06, 2007 12:44 pm
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;
}

Posted: Mon Aug 06, 2007 7:27 pm
by Kevin McGuire
Your code has three major problems.

Posted: Mon Aug 06, 2007 10:40 pm
by Tyler
Kevin McGuire wrote:Your code has three major problems.
You're my hero.

Posted: Tue Aug 07, 2007 3:16 am
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)

Posted: Tue Aug 07, 2007 3:30 am
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

Posted: Tue Aug 07, 2007 4:55 am
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

Posted: Wed Aug 08, 2007 10:26 am
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