Import backup from 2003-12-30
This commit is contained in:
parent
e83408ce83
commit
76398df125
6
kernel.c
6
kernel.c
@ -2,7 +2,7 @@
|
|||||||
//08/13/03 Josh Holtrop
|
//08/13/03 Josh Holtrop
|
||||||
//Holtrop's Operating System
|
//Holtrop's Operating System
|
||||||
//Version: 0.12
|
//Version: 0.12
|
||||||
//Modified: 11/12/03
|
//Modified: 12/30/03
|
||||||
|
|
||||||
#include "k_defines.h" //#DEFINE's for kernel
|
#include "k_defines.h" //#DEFINE's for kernel
|
||||||
|
|
||||||
@ -68,8 +68,8 @@ void k_init()
|
|||||||
video_drawConsole();
|
video_drawConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("HOS 0.13 - Kernel Size: %u kb\n", kernel_size()>>10);
|
printf("HOS 0.13 - Kernel File Size: %u kb\tData Size: %u bytes\n", kernel_size()>>10, (dword)(&_end)-(dword)(&_code));
|
||||||
printf("Memory available to OS: %u MB (Bytes: %u)\n", mm_megabytes, mm_totalmem);
|
printf("Memory available to OS: %u MB (%u bytes)\n", mm_megabytes, mm_totalmem);
|
||||||
printf("Free memory: %u bytes (%u pages)\n", mm_freemem(), mm_freemem()>>12);
|
printf("Free memory: %u bytes (%u pages)\n", mm_freemem(), mm_freemem()>>12);
|
||||||
|
|
||||||
dword key = 0;
|
dword key = 0;
|
||||||
|
245
vmm.c
245
vmm.c
@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
// vmm.c
|
// vmm.c
|
||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
// Rewritten from scratch: 12/23/03
|
// Rewritten from scratch: 12/23/03
|
||||||
|
// Modified: 12/30/03
|
||||||
|
|
||||||
|
|
||||||
|
// 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()
|
void vmm_init()
|
||||||
{
|
{
|
||||||
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
|
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
|
||||||
@ -31,6 +33,7 @@ void vmm_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function initialzes a Heap Entry Block to unused entries linked together
|
||||||
void vmm_heb_init(HeapEntryBlock *heb)
|
void vmm_heb_init(HeapEntryBlock *heb)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
@ -45,7 +48,7 @@ void vmm_heb_init(HeapEntryBlock *heb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function maps a virtual address to a physical address using the page directory / page table
|
||||||
void vmm_map1(dword virt, dword physical)
|
void vmm_map1(dword virt, dword physical)
|
||||||
{
|
{
|
||||||
dword pde = virt >> 22;
|
dword pde = virt >> 22;
|
||||||
@ -69,6 +72,7 @@ void vmm_map1(dword virt, dword physical)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function maps a variable number of pages in a row
|
||||||
void vmm_mapn(dword virt, dword physical, dword n)
|
void vmm_mapn(dword virt, dword physical, dword n)
|
||||||
{
|
{
|
||||||
for (; n > 0; n--)
|
for (; n > 0; n--)
|
||||||
@ -80,6 +84,7 @@ void vmm_mapn(dword virt, dword physical, dword n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function removes the virtual address's entry in the page directory / page table
|
||||||
void vmm_unmap1(dword virt)
|
void vmm_unmap1(dword virt)
|
||||||
{
|
{
|
||||||
dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
|
dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
|
||||||
@ -88,6 +93,7 @@ void vmm_unmap1(dword virt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function removes multiple pages' entries
|
||||||
void vmm_unmapn(dword virt, dword n)
|
void vmm_unmapn(dword virt, dword n)
|
||||||
{
|
{
|
||||||
for (; n > 0; n--)
|
for (; n > 0; n--)
|
||||||
@ -98,39 +104,248 @@ void vmm_unmapn(dword virt, dword n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Virtual Memory allocator function
|
||||||
void *malloc(dword bytes)
|
void *malloc(dword 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(dword bytes)
|
||||||
{
|
{
|
||||||
HeapEntry *he = firstHeapEntry;
|
HeapEntry *he = firstHeapEntry;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if ((he->size >= bytes) && (he->attributes = VMM_HE_FREE))
|
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)
|
if (he->size == bytes)
|
||||||
{
|
{
|
||||||
he->attributes = VMM_HE_USED;
|
he->attributes = VMM_HE_USED;
|
||||||
return (void *)(he->base);
|
return (void *)(he->base);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
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
|
||||||
{
|
{
|
||||||
//get the next HeapEntry, save in it the free mem, save in this entry the used mem...
|
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(dword bytes)
|
||||||
|
{
|
||||||
|
dword pages = (bytes >> 12) + 1;
|
||||||
|
bytes = pages << 12;
|
||||||
|
HeapEntry *he = vmm_getFirstHoleHeapEntry(bytes);
|
||||||
|
dword virt = he->base;
|
||||||
|
for (; pages > 0; pages--)
|
||||||
|
{
|
||||||
|
dword phys = (dword)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();
|
||||||
|
dword heb = (dword)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 = (dword)he->base;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newBlock->base = he->base;
|
||||||
|
newBlock->size = 4096;
|
||||||
|
newBlock->attributes = VMM_HE_HEB;
|
||||||
|
he->base += 4096;
|
||||||
|
he->size -= 4096;
|
||||||
|
lhe->link = (dword)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(dword 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
|
||||||
|
dword vmm_heapEntriesLeft()
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
dword 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((dword)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(dword base)
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->base == base)
|
||||||
|
return he;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int free(void *ptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
15
vmm.h
15
vmm.h
@ -2,7 +2,7 @@
|
|||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
// Rewritten from scratch: 12/23/03
|
// Rewritten from scratch: 12/23/03
|
||||||
// Modified: 12/29/03
|
// Modified: 12/30/03
|
||||||
|
|
||||||
|
|
||||||
#define VMM_HE_UNUSED 0 //available entry
|
#define VMM_HE_UNUSED 0 //available entry
|
||||||
@ -11,6 +11,7 @@
|
|||||||
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
|
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
|
||||||
#define VMM_HE_HEB 4 //HeapEntryBlock
|
#define VMM_HE_HEB 4 //HeapEntryBlock
|
||||||
|
|
||||||
|
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
dword base; //virtual base address
|
dword base; //virtual base address
|
||||||
@ -33,9 +34,19 @@ void vmm_mapn(dword virt, dword physical, dword n);
|
|||||||
void vmm_unmap1(dword virt);
|
void vmm_unmap1(dword virt);
|
||||||
void vmm_unmapn(dword virt, dword n);
|
void vmm_unmapn(dword virt, dword n);
|
||||||
void vmm_heb_init(HeapEntryBlock *heb);
|
void vmm_heb_init(HeapEntryBlock *heb);
|
||||||
|
void *vmm_getFreeChunk(dword bytes);
|
||||||
|
HeapEntry *vmm_nextHeapEntry();
|
||||||
|
dword vmm_heapEntriesLeft();
|
||||||
|
HeapEntry *vmm_getLastHeapEntry();
|
||||||
|
HeapEntry *vmm_getFirstUnusedHeapEntry();
|
||||||
|
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes);
|
||||||
|
void vmm_addHeapEntryBlock();
|
||||||
|
int vmm_moreCore(dword bytes);
|
||||||
|
void vmm_coalesceHeapEntry(HeapEntry *he);
|
||||||
|
HeapEntry *vmm_getHeapEntryByBase(dword base);
|
||||||
|
|
||||||
|
|
||||||
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000;
|
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000; //this is where heap memory starts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user