Import backup from 2004-03-08

This commit is contained in:
josh committed 2017-07-25 22:23:46 -04:00
1 parent 0b9d7fde22
commit 8d0e6de040
45 files changed
+243 -219

No files matched your search

+132
View File
@@ -0,0 +1,132 @@
// mm.c
// Author: Josh Holtrop
// Created: 09/01/03
// Modified: 03/08/04
#include "hos_defines.h"
#include "mm.h"
//The total amount of physical memory available (bytes, 1 bit per page)
#define BITMAP_SIZE 0x20000
dword mm_totalmem = 0;
dword mm_megabytes = 0;
byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
//This function initializes the memory manager's linked list, filling it with the
// memory areas returned by bios interrupt 0x8E20
void mm_init()
{
dword memmap_entries = *(dword *)BOOT_MEMMAP_ENTRIES;
memmap_entry *maps = (memmap_entry *) BOOT_FIRST_MEMMAP;
dword a;
for (a = 0; a < BITMAP_SIZE; a++)
{
page_bitmap[a] = 0xFF; //all pages used
}
for (a = 0; a < memmap_entries; a++)
{
if (maps[a].attributes == 1) // (1) mem free to OS
{
mm_totalmem += maps[a].limit.lowdword;
if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
{
if (maps[a].base.lowdword < FREERAM_START)
{
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
}
else
{
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
}
}
}
}
if (mm_totalmem % 0x100000)
mm_megabytes = (mm_totalmem >> 20) + 1;
else
mm_megabytes = mm_totalmem >> 20;
}
// This function frees a certain number of pages starting at the address
// specified in base for a length of pages pages
void mm_pfreen(dword base, dword pages)
{
dword a;
dword max = base + (pages << 12);
for (a = base; a < max; a += 4096)
{
mm_pfree(a);
}
}
// This function frees a single page
void mm_pfree(dword base)
{
// dword pageNumber = base >> 12; // >>12 == /4096
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
}
// This function allocates a single page, returning its physical address
void *mm_palloc()
{
dword bite;
for (bite = 0; bite < BITMAP_SIZE; bite++)
{
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
{
int bit;
for (bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
{
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
return (void *)((bite << 15) | (bit << 12));
}
}
}
}
return 0; //no free page
}
// This function reports the number of bytes of free physical memory
dword mm_freemem()
{
dword a;
dword pages = 0;
for (a = 0; a < BITMAP_SIZE; a++)
{
int bit;
for (bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[a] & (1 << bit)))
pages++;
}
}
return pages << 12;
}
dword mm_getTotalMem()
{
return mm_totalmem;
}
dword mm_getTotalMegs()
{
return mm_megabytes;
}
+28
View File
@@ -0,0 +1,28 @@
// mm.c
// Author: Josh Holtrop
// Created: 09/01/03
// Modified: 03/08/04
#ifndef __HOS_MM__
#define __HOS_MM__ __HOS_MM__
#include "hos_defines.h"
typedef struct {
qword base;
qword limit;
dword attributes;
} __attribute__((packed)) memmap_entry;
void mm_init();
void mm_pfreen(dword base, dword pages);
void mm_pfree(dword base);
void *mm_palloc();
dword mm_freemem();
dword mm_getTotalMem();
dword mm_getTotalMegs();
#endif
+358
View File
@@ -0,0 +1,358 @@
// vmm.c
// Author: Josh Holtrop
// Date: 09/30/03
// Rewritten from scratch: 12/23/03
// Modified: 03/02/04
#include "hos_defines.h"
#include "vmm.h"
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000; //this is where heap memory starts
// This is the initialization procedure for the Virtual Memory Manager
// It sets up the final page directory/page table setup and maps video memory, if present
void vmm_init()
{
unsigned int *pageTables = (unsigned int *)0xC0104000; //this is the location of the page directory
pageTables[0x3FF] = 0x104000|0x03; //the last page directory entry points to the page directory itself
pageTables[0] = 0;
invlpg(0);
if (videoMode) //we are in a graphical mode
{
unsigned int vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
if (vidPages % 4096)
vidPages = (vidPages >> 12) + 1;
else
vidPages = (vidPages >> 12);
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
}
unsigned int firstHeapEntryBlock = (unsigned int)mm_palloc();
vmm_map1((unsigned int)firstHeapEntry, firstHeapEntryBlock);
HeapEntryBlock *heb = (HeapEntryBlock *)firstHeapEntry;
vmm_heb_init(heb);
heb->entry[0].base = (unsigned int)firstHeapEntry; //start of kernel's heap memory
heb->entry[0].size = 4096; //the first HeapEntryBlock is 1 page long
heb->entry[0].attributes = VMM_HE_HEB; //this is a HeapEntryBlock
heb->entry[1].base = (unsigned int)firstHeapEntry+4096; //this is the start of the rest of the kernel's heap memory
heb->entry[1].size = 0x10000000-4096; //the rest of the kernel's heap memory: 256mb - 4kb
heb->entry[1].attributes = VMM_HE_HOLE; //this is a hold - an unmapped section of heap memory
}
// This function initialzes a Heap Entry Block to unused entries linked together
void vmm_heb_init(HeapEntryBlock *heb)
{
int a;
for (a = 0; a < 256; a++)
{
heb->entry[a].base = 0;
heb->entry[a].size = 0;
heb->entry[a].attributes = VMM_HE_UNUSED;
heb->entry[a].link = (unsigned int)&(heb->entry[a+1]);
}
heb->entry[255].link = 0;
}
// This function maps a virtual address to a physical address using the page directory / page table
void vmm_map1(unsigned int virt, unsigned int physical)
{
unsigned int pde = virt >> 22;
unsigned int pte = (virt & 0x003FF000) >> 12;
unsigned int *pageTables = (unsigned int *)0xC0104000; //this is the location of the page directory
if (!(pageTables[pde] & 0x01)) //the page directory entry does not exist, we must allocate a page for it
{
unsigned int *newpagetable = mm_palloc();
pageTables[pde] = ((unsigned int)newpagetable) | 0x03;
invlpg(virt);
unsigned int *newpteptr = (unsigned int *)(0xFFC00000 | (pde << 12)); //points to first unsigned int of newly allocated page table
int a;
for (a = 0; a < 1024; a++)
{
newpteptr[a] = 0;
}
}
unsigned int *pteptr = (unsigned int *)(0xFFC00000 | (pde << 12) | (pte << 2));
*pteptr = physical | 0x03;
invlpg(virt);
}
// This function maps a variable number of pages in a row
void vmm_mapn(unsigned int virt, unsigned int physical, unsigned int n)
{
for (; n > 0; n--)
{
vmm_map1(virt, physical);
virt += 4096;
physical += 4096;
}
}
// This function removes the virtual address's entry in the page directory / page table
void vmm_unmap1(unsigned int virt)
{
unsigned int *pteptr = (unsigned int *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
*pteptr = 0;
invlpg(virt);
}
// This function removes multiple pages' entries
void vmm_unmapn(unsigned int virt, unsigned int n)
{
for (; n > 0; n--)
{
vmm_unmap1(virt);
virt += 4096;
}
}
// Virtual Memory allocator function
void *malloc(unsigned int bytes)
{
if (bytes % VMM_MALLOC_GRANULARITY)
bytes = bytes + VMM_MALLOC_GRANULARITY - (bytes % VMM_MALLOC_GRANULARITY);
void *attempt = vmm_getFreeChunk(bytes);
if (attempt)
return attempt;
if(vmm_moreCore(bytes))
return 0; //we could not get any more heap memory
return vmm_getFreeChunk(bytes);
}
// This function returns a pointer if a free chunk of memory exists
void *vmm_getFreeChunk(unsigned int bytes)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->attributes == VMM_HE_FREE)
{
if (he->size > bytes)
{
HeapEntry *nhe = vmm_nextHeapEntry();
nhe->base = he->base;
nhe->size = bytes;
nhe->attributes = VMM_HE_USED;
he->base += bytes;
he->size -= bytes;
return (void *)(nhe->base);
}
if (he->size == bytes)
{
he->attributes = VMM_HE_USED;
return (void *)(he->base);
}
}
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function coalesces any two adjacent heap entries into one entry
void vmm_coalesceHeapEntry(HeapEntry *he)
{
if (!(he->attributes == VMM_HE_FREE || he->attributes == VMM_HE_HOLE))
return;
if (he->size == 0)
{
he->attributes = VMM_HE_UNUSED;
return;
}
HeapEntry *hec = firstHeapEntry;
for (;;)
{
if (hec->attributes == he->attributes)
{
if ((hec->base + hec->size) == he->base) //hec ends where he begins
{
he->base = hec->base;
he->size += hec->size;
hec->attributes = VMM_HE_UNUSED;
}
if ((he->base + he->size) == hec->base) //he ends where hec begins
{
he->size += hec->size;
hec->attributes = VMM_HE_UNUSED;
}
}
hec = (HeapEntry *)hec->link;
if (!hec)
break;
}
}
// This function retrieves more physical memory for the heap
int vmm_moreCore(unsigned int bytes)
{
unsigned int pages = (bytes >> 12) + 1;
bytes = pages << 12;
HeapEntry *he = vmm_getFirstHoleHeapEntry(bytes);
unsigned int virt = he->base;
for (; pages > 0; pages--)
{
unsigned int phys = (unsigned int)mm_palloc();
if (!phys)
return 1;
vmm_map1(virt, phys);
virt += 4096;
}
if (he->size == bytes)
{
he->attributes = VMM_HE_FREE;
vmm_coalesceHeapEntry(he);
}
else
{
HeapEntry *nhe = vmm_nextHeapEntry();
nhe->base = he->base;
nhe->size = bytes;
nhe->attributes = VMM_HE_FREE;
he->base += bytes;
he->size -= bytes;
vmm_coalesceHeapEntry(nhe);
}
return 0;
}
// This function returns the next available heap entry, creates more entries if we are running low
HeapEntry *vmm_nextHeapEntry()
{
if (vmm_heapEntriesLeft() < 10)
vmm_addHeapEntryBlock();
return vmm_getFirstUnusedHeapEntry();
}
// This function creates a new block (page) of heap entries (256)
void vmm_addHeapEntryBlock()
{
HeapEntry *he = vmm_getFirstHoleHeapEntry(4096);
HeapEntry *newBlock = vmm_getFirstUnusedHeapEntry();
unsigned int heb = (unsigned int)mm_palloc();
vmm_map1(he->base, heb);
vmm_heb_init((HeapEntryBlock *)he->base);
HeapEntry *lhe = vmm_getLastHeapEntry();
if (he->size == 4096)
{
he->attributes = VMM_HE_HEB;
lhe->link = (unsigned int)he->base;
}
else
{
newBlock->base = he->base;
newBlock->size = 4096;
newBlock->attributes = VMM_HE_HEB;
he->base += 4096;
he->size -= 4096;
lhe->link = (unsigned int)newBlock->base;
}
return;
}
// This function returns the last heap entry in the linked list, useful for setting
// its link field to point to the first entry of a newly allocated list
HeapEntry *vmm_getLastHeapEntry()
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->link == 0)
return he;
he = (HeapEntry *)he->link;
}
}
// This function returns the first heap entry corresponding to a memory "hole"
HeapEntry *vmm_getFirstHoleHeapEntry(unsigned int minBytes)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if ((he->attributes == VMM_HE_HOLE) && (he->size >= minBytes))
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function returns the first heap entry that is not being used
HeapEntry *vmm_getFirstUnusedHeapEntry()
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->attributes == VMM_HE_UNUSED)
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function returns the number of heap entries available for use
unsigned int vmm_heapEntriesLeft()
{
HeapEntry *he = firstHeapEntry;
unsigned int entries = 0;
for (;;)
{
if (he->attributes == VMM_HE_UNUSED)
entries++;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return entries;
}
// This function "frees" an area of memory previously allocated with malloc()
int free(void *ptr)
{
HeapEntry *he = vmm_getHeapEntryByBase((unsigned int)ptr);
if (!he)
return 1; //a heap entry starting at the given address was not found
he->attributes = VMM_HE_FREE;
vmm_coalesceHeapEntry(he);
return 0;
}
// This function scans the heap entry linked list for an entry that begins at the given address
HeapEntry *vmm_getHeapEntryByBase(unsigned int base)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->base == base)
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
+54
View File
@@ -0,0 +1,54 @@
// vmm.h
// Author: Josh Holtrop
// Date: 09/30/03
// Rewritten from scratch: 12/23/03
// Modified: 03/02/04
#include "hos_defines.h"
#ifndef __HOS_VMM__
#define __HOS_VMM__ __HOS_VMM__
#define VMM_HE_UNUSED 0 //available entry
#define VMM_HE_FREE 1 //free section of memory
#define VMM_HE_USED 2 //used section of memory
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
#define VMM_HE_HEB 4 //HeapEntryBlock
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
typedef struct {
unsigned int base; //virtual base address
unsigned int size; //size in bytes
unsigned int attributes; //free/used/hole
unsigned int link; //link to next HeapEntry
} __attribute__((packed)) HeapEntry;
typedef struct {
HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
} __attribute__((packed)) HeapEntryBlock;
void vmm_init();
void *malloc(unsigned int bytes);
int free(void *ptr);
void vmm_map1(unsigned int virt, unsigned int physical);
void vmm_mapn(unsigned int virt, unsigned int physical, unsigned int n);
void vmm_unmap1(unsigned int virt);
void vmm_unmapn(unsigned int virt, unsigned int n);
void vmm_heb_init(HeapEntryBlock *heb);
void *vmm_getFreeChunk(unsigned int bytes);
HeapEntry *vmm_nextHeapEntry();
unsigned int vmm_heapEntriesLeft();
HeapEntry *vmm_getLastHeapEntry();
HeapEntry *vmm_getFirstUnusedHeapEntry();
HeapEntry *vmm_getFirstHoleHeapEntry(unsigned int minBytes);
void vmm_addHeapEntryBlock();
int vmm_moreCore(unsigned int bytes);
void vmm_coalesceHeapEntry(HeapEntry *he);
HeapEntry *vmm_getHeapEntryByBase(unsigned int base);
#endif