OSDev.org
https://forum.osdev.org/

Cottontail Mem Management/Implementation
https://forum.osdev.org/viewtopic.php?f=1&t=10350
Page 1 of 1

Author:  Cjmovie [ Fri Mar 25, 2005 11:17 am ]
Post subject:  Cottontail Mem Management/Implementation

Hows this look? Just for note, I am in protected mode with GDT set up and A20 enabled. Memory map set to 0 already.

Cottontail Mem Management tutorial as found at http://osdever.net/tutorials/cottontailmm.php?the_id=47.

Heres code (Alloc only, I commented it tediously):

Code:
#define MAP_BASE  0x10000000 //Start at 256mb mark
#define PAGE_BASE 0x10020000 //Start page map
#define MEM_BASE  0x10020400 //There are 2^20 pages, starting here

#define MICRO_PAGES 0x00100000 //Micro Pages/Mem Base (4kb/each)
#define SUPER_PAGES 0x00000400 //Super Pages/Start of each page (4mb/each)

unsigned long *MicroMap = MAP_BASE;
unsigned long *PageMap = PAGE_BASE;

const int CheckAND[] = { //So we can & to see what page is used in the longs (set of 32)
2^0, 2^1, 2^2, 2^3, 2^4, 2^5, 2^6, 2^7, 2^8, 2^9, 2^10, 2^11,
2^12, 2^13, 2^14, 2^15, 2^16, 2^17, 2^18, 2^19, 2^20, 2^21,
2^22, 2^23, 2^24, 2^25, 2^26, 2^27, 2^28, 2^29, 2^30, 2^31};

void* AllocPage(){                 //Allocate 4kb block
int i = 0, x = 0, Page = 0;       //i and x are counting vars, Page is superpage to use
void* newpage;                    //so we can return the final pointer
while(PageMap[i] == 0xFFFFFFFF){  //While the Super Page is used in this list 1-32...
  i++;                             //Keep searching
  if(i >= SUPER_PAGES)return NULL; //No more room, abort!
}                                 //We leave 'i' with set of 32 that has free superpage
for(x=0; x<32; x++){              //Now search through set of 32 for that free one
  if( !(PageMap[i] & CheckAND[x]) ){ //if this is a free of the 32 super pages....
   Page = x + i*32;                //make this our page, (rem., 'x' is within 32,
   break;                          // so make it like a two-dim array like [super][mini])
  }
}
i = 0;                            //Reset counter caus' we saved it in Page
while(MicroMap[i+Page*1024] == 0xFFFFFFFF){ //Search for free Micropage set in Superpage
  i++;                                     //Haven't found one yet
  if(i >= MICRO_PAGES/SUPER_PAGES)return NULL; //Should never get her unless weird error
}                                             //Since it said there was 1(or more) free
                                               //up there in the for loop
for(x=0; x<32; x++){                          //Find Page within set of 32 micropages
  if(! (MicroMap[i+Page*1024] & CheckAND[x]) ){ //Found one?
   newpage = (void*)(MEM_BASE+((i+Page*1024)*32+x)*4096); //Make ptr. to the actual mem
   MicroMap[i+Page*1024] |= CheckAND[x];             //Mark it as used....
   return newpage;                                //Return a page of free memory!
  }                                               //(Finally)
}
}

Author:  Pype.Clicker [ Fri Mar 25, 2005 11:41 am ]
Post subject:  Re:Cottontail Mem Management/Implementation

imvho looks rather unreadable (here at least. with proportionnal font, the 'two column' coding style is rather ugly :P)

Author:  Poseidon_away [ Fri Mar 25, 2005 11:49 am ]
Post subject:  Re:Cottontail Mem Management/Implementation

Iself use a stack where the free memory addresses are pushed on. When I alloc a page, I only have to pop off the latest address and there is a page alloced. Cleaner, shorter and faster ;)

Author:  A Guest, of course [ Fri Mar 25, 2005 3:31 pm ]
Post subject:  Re:Cottontail Mem Management/Implementation

Poseidon_away wrote:
Cleaner, shorter and faster


For allocation and deallocation of single inspecific pages. Consider the isAllocated() and AllocateContiguous() functions, which with a stack are dirtier, longer, and slower.

Less used, maybe, but still useful.

isAllocated(), among other things, is useful for checking to make sure you didn't attempt to free a page twice. This should never happen, but no one writes perfect code. So the check finds bugs, and helps you avoid data corruption. Consider what happens to a stack if you accidently push the same address on twice.

AllocateContiguous() you might want for DMA and such things. Pulling contiguous pages off a stack? Ick.

Author:  FlashBurn [ Fri Mar 25, 2005 3:52 pm ]
Post subject:  Re:Cottontail Mem Management/Implementation

Maybe my code will show you a way how to do allocation and deallocation!

Code:
//---------------------------
//   global vars
uint32_t mem_total_4kb= 1024;
uint32_t mem_total_4mb= 0;
uint32_t *bitmap_4kb= (uint32_t *)0xc0001000;
uint32_t *bitmap_4mb_1= (uint32_t *)0xc0021000;
uint32_t *bitmap_4mb_2= (uint32_t *)0xc0021080;
uint32_t free_first_4kb=0x100;
uint32_t free_first_4mb=1;
uint32_t free_4kb=0;
uint32_t free_4mb=0;

#define set_bit_makro(x,bit_nr) x|= (1 << bit_nr)
#define del_bit_makro(x,bit_nr) x&= ~(1 << bit_nr)
#define get_bit_makro(x,bit_nr) x& (1 << bit_nr)

uint32_t alloc_4kb_phys()
{
   register uint32_t x,y;
   uint32_t phys_addr;

   if(free_4kb == 0)
      return 0;

   x= free_first_4kb >> 5;
   y= free_first_4kb & 0x1f;

   del_bit_makro(bitmap_4kb[x],y);

   phys_addr= free_first_4kb << 12;

   free_4kb--;
   if(free_4kb == 0)
      return phys_addr;
   /////////////////////////
   //we need a new free 4MiB page
   if((free_first_4kb >> 10) == free_first_4mb)
   {
      x= free_first_4mb >> 5;
      y= free_first_4mb & 0x1f;
      del_bit_makro(bitmap_4mb_1[x],y);
      while(1)
      {
         if(bitmap_4mb_1[x] != 0)
            break;
         x++;
      }
      asm("bsf %0,%1"
         :"=r"(y)
         :"r"(bitmap_4mb_1[x]));
      free_first_4mb= (x << 5) + y;
      free_4mb--;
   }
   //end search of new 4MiB page
   /////////////////////////
   //we need a new 4KiB page
   x= free_first_4kb >> 5;
   while(1)
   {
      if(bitmap_4kb[x] != 0)
         break;
      x++;
      /////////////////////////
      //the old 4MiB page is full => search a new one with >0 free 4KiB pages
      if((x & 0x1f) == 0)
      {
         x>>= 5;
         x--;
         y= x & 0x1f;
         x>>= 5;
         del_bit_makro(bitmap_4mb_2[x],y);
         while(1)
         {
            if(bitmap_4mb_2[x] != 0)
               break;
            x++;
         }
         asm("bsf %0,%1"
            :"=r"(y)
            :"r"(bitmap_4mb_2[x]));
         x= ((x << 5) + y) << 5;
      }
      //end search for 4MiB page with >0 4KiB pages
      /////////////////////////
   }
   asm("bsf %0,%1"
      :"=r"(y)
      :"r"(bitmap_4kb[x]));
   free_first_4kb= (x << 5) + y;
   //end search of new 4KiB page
   /////////////////////////

   return phys_addr;
}

uint32_t dealloc_4kb_phys(uint32_t addr)
{
   register uint32_t x,y;

   if((addr & 0xfff) != 0)
      return 0;

   x= addr >> 12;
   y= x & 0x1f;
   x>>= 5;

   if(get_bit_makro(bitmap_4kb[x],y))
      return 0;

   set_bit_makro(bitmap_4kb[x],y);

   x>>= 5;
   y= x & 0x1f;
   x>>= 5;
   set_bit_makro(bitmap_4mb_2[x],y);

   free_4kb++;

   if((addr >> 12) < free_first_4kb)
      free_first_4kb= addr >> 12;
   /////////////////////////
   //check if the whole 4MiB page is free now
   x= addr >> 17;
   for(y= 0; y <= 31; y++)
      if(bitmap_4kb[x+y] == 0)
         return 1;
   /////////////////////////
   //set 4MiB page free
   x>>= 5;
   y= x & 0x1f;
   x>>= 5;

   set_bit_makro(bitmap_4mb_1[x],y);

   if(((x << 5) + y) < free_first_4mb)
      free_first_4mb= (x << 5) + y;

   free_4mb++;

   return 1;
}

uint32_t alloc_4mb_phys()
{
   register uint32_t x,y,z;
   uint32_t phys_addr;

   if(free_4mb == 0)
      return 0;

   x= free_first_4mb >> 5;
   y= free_first_4mb & 0x1f;

   del_bit_makro(bitmap_4mb_1[x],y);
   del_bit_makro(bitmap_4mb_2[x],y);

   for(z= 0; z <= 31; z++)
   {
      bitmap_4kb[(((x << 5) + y) << 5) + z]= 0xffffffff;
   }

   phys_addr= ((x << 5) + y) << 22;

   free_4mb--;
   free_4kb-= 1024;
   if(free_4mb == 0)
      return phys_addr;

   if((free_first_4kb >> 10) == free_first_4mb)
   {
      /////////////////////////
      //we need a new free 4KiB page
      x= 0;
      while(1)
      {
         if(bitmap_4mb_2[x] != 0)
            break;
         x++;
      }

      asm("bsf %0,%1"
         :"=r"(y)
         :"r"(bitmap_4mb_2[x]));
      x= ((x << 5) + y) << 5;
      while(1)
      {
         if(bitmap_4kb[x] != 0)
            break;
         x++;
      }
      asm("bsf %0,%1"
         :"=r"(y)
         :"r"(bitmap_4kb[x]));
      free_first_4kb= (x << 5) + y;
      //end search
      /////////////////////////
   }
   /////////////////////////
   //find new free 4MiB page
   x= 0;
   while(1)
   {
      if(bitmap_4mb_1[x] != 0)
         break;
      x++;
   }
   //end search
   /////////////////////////
   asm("bsf %0,%1"
      :"=r"(y)
      :"r"(bitmap_4mb_1[x]));
   free_first_4mb= (x << 5) + y;

   return phys_addr;
}

uint32_t dealloc_4mb_phys(uint32_t addr)
{
   register uint32_t x,y;

   if((addr & 0x3fffff) != 0)
      return 0;

   x= addr >> 17;
   y= (x >> 5) & 0x1f;

   if(get_bit_makro(bitmap_4mb_1[x>>10],y))
      return 0;

   for(y= 0; y <= 31; y++)
      bitmap_4kb[x+y]= 0xffffffff;

   x>>= 5;
   y= x & 0x1f;
   x>>= 5;
   set_bit_makro(bitmap_4mb_1[x],y);
   set_bit_makro(bitmap_4mb_2[x],y);

   free_4mb++;
   free_4kb+= 1024;

   x= addr >> 12;
   if(x < free_first_4kb)
      free_first_4kb= x;

   return 1;
}

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/