Newer
Older
ubixos-old / src / sys / mm / memory.c
#include <vmm/vmm.h>
#include <sys/io.h>
#include <ubixos/kpanic.h>
#include <lib/kprintf.h>
#include <lib/kmalloc.h>
#include <ubixos/vitals.h>
#include <ubixos/spinlock.h>
#include <assert.h>

int               numPages = 0;

void
mmFreeTaskPages(kTask_t *task)
{
	/* just move the list to tail of the free page list */
	if(task->FirstPage != NULL)
	{
		vmmFreePages->Last->Next = task->FirstPage;
		task->FirstPage->Previous = vmmFreePages->Last;
		vmmFreePages->Last = task->LastPage;
		memset(emptyKernDesc,0x0,0x4000);
		/* TODO: zero out the memory last used */
		kprintf("mmFreeTaskPages: Memory has been wiped\n");
	}
	else
		kprintf("mmFreeTaskPages: Nothing to free!\n");	
}

void 
mmFreeVirtualPage(kTask_t *task, uInt32 memAddr)
{
	mMap *tmp;

	for(tmp = task->FirstPage ; tmp != NULL ; tmp = tmp->Next)
	{
		if(tmp->pageAddr == memAddr)
		{
			/* remove the page from the task's used list */
			if(tmp == task->FirstPage)
			{
				task->FirstPage = task->FirstPage->Next;
			}
			else
			{
				tmp->Previous->Next = tmp->Next;
				tmp->Next->Previous = tmp->Previous;
				tmp->Next = NULL;
				tmp->Previous = NULL;
			}
			
			/* add the page to the end free pages list */
			vmmFreePages->Last->Next = tmp;
			tmp->Previous = vmmFreePages->Last;
			vmmFreePages->Last = tmp;
			kprintf("vmmFreeVirtualPage: %d has been freed\n", memAddr);
			return;
		}
	}
	kpanic("vmmFreeVirtualPage: attempted to free non-existant page\n");
	return;
}

void *
mmGetFreeVirtualPage(kTask_t *task)
{
	mMap *tmp;

	if(vmmFreePages == NULL)
	{
		kprintf("Out of memory\n");
		return NULL;
	}

	/* remove the first page from the list and return it */
	tmp = vmmFreePages->First;
	vmmFreePages->First = vmmFreePages->First->Next;
	vmmFreePages->First->Previous = NULL;
	return tmp;
}

int
mmMemMapInit()
{
	uInt32 memStart, z;
	mMap *tmpMap;

	/* Count System Memory */
	numPages = countMemory();

	/* calculate the start of memory */
	memStart  = 0x101;
	memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000);

	/* initialize free pages */
	for(z = memStart ; z < numPages; z++)
	{
		if(vmmFreePages == NULL)
		{
			//UBU: replace this with static location
			vmmFreePages = kmalloc(sizeof(mMap));
			vmmFreePages->First = vmmFreePages;
			vmmFreePages->Last = vmmFreePages;
			vmmFreePages->Next = NULL;
			vmmFreePages->Previous = NULL;
			vmmFreePages->pid = vmmID;
			vmmFreePages->pageAddr = z * 4096;
			vmmFreePages->status = memAvail;
		}
		else
		{
			//UBU: replace this with static location
			tmpMap = kmalloc(sizeof(mMap));
			vmmFreePages->Last->Next = tmpMap;
			tmpMap->Previous = vmmFreePages->Last;
			vmmFreePages->Last = tmpMap;
			tmpMap->pid = vmmID;
			tmpMap->pageAddr = z * 4096;
			tmpMap->status = memAvail;
		}
	}

	/* initialize used pages (kernel space) */
	for(z = 0 ; z < memStart; z++)
	{
		if(vmmUsedPages == NULL)
                {
			vmmUsedPages = kmalloc(sizeof(mMap));
                        vmmUsedPages->First = vmmUsedPages;
                        vmmUsedPages->Last = vmmUsedPages;
                        vmmUsedPages->Next = NULL;
                        vmmUsedPages->Previous = NULL;
			vmmUsedPages->pid = vmmID;
			vmmUsedPages->pageAddr = z * 4096;
			vmmUsedPages->status = memNotavail;
		}
		else
		{
                        tmpMap = kmalloc(sizeof(mMap));
                        vmmUsedPages->Last->Next = tmpMap;
                        tmpMap->Previous = vmmUsedPages->Last;
                        vmmUsedPages->Last = tmpMap;
			tmpMap->pid = vmmID;
			tmpMap->pageAddr = z * 4096;
			tmpMap->status = memNotavail;
		}
	}

	/* Print Out Memory Information */
	kprintf("Real Memory:      %iMB\n", ((numPages  * 4096) / 1024) / 1024 );
	kprintf("Available Memory: %iMB\n", ((freePages * 4096) / 1024) / 1024 );
	kprintf("Used Memory:      %iMB\n", ((usedPages * 4096) / 1024) / 1024 );

	/* Return */
	return (0);
}

uInt32 countMemory() {
  register uInt32 *mem = 0x0;
  unsigned long    memCount = -1, tempMemory = 0x0;
  unsigned short   memKb = 0;
  unsigned char    irq1State, irq2State;
  unsigned long    cr0 = 0x0;

  /*
   * Save The States Of Both IRQ 1 And 2 So We Can Turn Them Off And Restore
   * Them Later
   */
  irq1State = inportByte(0x21);
  irq2State = inportByte(0xA1);

  /* Turn Off IRQ 1 And 2 To Prevent Chances Of Faults While Examining Memory */
  outportByte(0x21, 0xFF);
  outportByte(0xA1, 0xFF);

  /* Save The State Of Register CR0 */
  asm volatile (
    "movl %%cr0, %%ebx\n"
    :               "=a" (cr0)
    :
    :               "ebx"
    );

  asm volatile ("wbinvd");
  asm volatile (
    "movl %%ebx, %%cr0\n"
    :
    :               "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000)
    :               "ebx"
    );

  while (memKb < 4096 && memCount != 0) {
    memKb++;
    if (memCount == -1)
      memCount = 0;
    memCount += 1024 * 1024;
    mem = (uInt32 *)memCount;
    tempMemory = *mem;
    *mem = 0x55AA55AA;
    asm("": : :"memory");
    if (*mem != 0x55AA55AA) {
      memCount = 0;
      }
    else {
      *mem = 0xAA55AA55;
      asm("": : :"memory");
      if (*mem != 0xAA55AA55) {
	memCount = 0;
        }
      }
    asm("": : :"memory");
    *mem = tempMemory;
    }

  asm volatile (
    "movl %%ebx, %%cr0\n"
    :
    :               "a" (cr0)
    :               "ebx"
    );

  /* Restore States For Both IRQ 1 And 2 */
  outportByte(0x21, irq1State);
  outportByte(0xA1, irq2State);

  /* Return Amount Of Memory In Pages */
  return ((memKb * 1024 * 1024) / 4096);
  }