diff --git a/include/Tier0/heap.h b/include/Tier0/heap.h new file mode 100644 index 0000000..f38ca2f --- /dev/null +++ b/include/Tier0/heap.h @@ -0,0 +1,51 @@ +#ifndef __HEAP_H__ +#define __HEAP_H__ + +#include "types.h" + +#define HEAP_HEADER_MAGIC 0x8A4DF92E +#define HEAP_FOOTER_MAGIC 0x9AFE352B + +#define HEAP_START 0xD0000000 +#define HEAP_INITIAL_SIZE 0x00400000 +#define HEAP_MIN_SIZE 0x00400000 + +#define HEAP_INDEX_SIZE 0x00020000 + +typedef struct { + u32 Magic; + u8 Hole; + u32 Size; +} T_HEAP_HEADER; + +typedef struct { + u32 Magic; + T_HEAP_HEADER *Header; +} T_HEAP_FOOTER; + +typedef struct { + void **Array; + u32 Size; + u32 MaxSize; +} T_HEAP_INDEX; + +T_HEAP_INDEX heap_index_initialize(void *Address, u32 MaxSize); +void heap_index_insert(T_HEAP_INDEX *Index, void *Value); +u8 heap_index_smaller(void *A, void *B); + +typedef struct { + T_HEAP_INDEX Index; + u32 Start; + u32 End; + u32 Max; +} T_HEAP; + +T_HEAP *heap_create(u32 Start, u32 End, u32 Max); +void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned); +void heap_free(T_HEAP *Heap, void *Address); + +void heap_init_simple(void); +void *kmalloc(u32 Size); +void kfree(void *Data); + +#endif diff --git a/include/Tier0/paging.h b/include/Tier0/paging.h index c0490fd..402e1e8 100644 --- a/include/Tier0/paging.h +++ b/include/Tier0/paging.h @@ -5,5 +5,6 @@ void paging_init_simple(void); u8 paging_get_physical(u32 Virtual, u32 *Physical); -void paging_allocate_page(u32 Virtual); +void paging_map_kernel_page(u32 Virtual, u32 Physical); +void paging_map_kernel_table(u32 Virtual, u32 Physical); #endif diff --git a/src/Tier0/.heap.c.swp b/src/Tier0/.heap.c.swp new file mode 100644 index 0000000..d9c354c Binary files /dev/null and b/src/Tier0/.heap.c.swp differ diff --git a/src/Tier0/.kmain.c.swp b/src/Tier0/.kmain.c.swp new file mode 100644 index 0000000..74cc322 Binary files /dev/null and b/src/Tier0/.kmain.c.swp differ diff --git a/src/Tier0/heap.c b/src/Tier0/heap.c new file mode 100644 index 0000000..38b0af2 --- /dev/null +++ b/src/Tier0/heap.c @@ -0,0 +1,381 @@ +#include "Tier0/heap.h" +#include "Tier0/kstdlib.h" +#include "Tier0/kstdio.h" +#include "Tier0/physical_alloc.h" +#include "Tier0/paging.h" + +T_HEAP *g_heap; + +T_HEAP_INDEX heap_index_initialize(void *Address, u32 MaxSize) +{ + T_HEAP_INDEX Index; + Index.Array = (void**)Address; + Index.MaxSize = MaxSize; + Index.Size = 0; + + kmemset(Address, 0, MaxSize * 4); + + return Index; +} + +void heap_index_insert(T_HEAP_INDEX *Index, void *Value) +{ + u32 i = 0; + while (i < Index->Size && heap_index_smaller(Index->Array[i], Value)) + i++; + + if (i == Index->Size) + Index->Array[Index->Size++] = Value; + else + { + void *Temporary = Index->Array[i]; + Index->Array[i] = Value; + while (i < Index->Size) + { + i++; + void *Temporary2 = Index->Array[i]; + Index->Array[i] = Temporary; + Temporary = Temporary2; + } + Index->Size++; + } +} + +u8 heap_index_smaller(void *A, void *B) +{ + return (((T_HEAP_HEADER *)A)->Size < ((T_HEAP_HEADER *)B)->Size)>0 ?1:0; +} + +void *heap_index_get(T_HEAP_INDEX *Index, u32 Position) +{ + return Index->Array[Position]; +} + +void heap_index_remove(T_HEAP_INDEX *Index, u32 Position) +{ + while (Position < Index->Size) + { Index->Array[Position] = Index->Array[Position + 1]; + Position++; + } + Index->Size--; +} + +T_HEAP *heap_create(u32 Start, u32 End, u32 Max) +{ + u16 NumSuperPages = (End - Start ) / (1024 * 1024 * 4); + if ((End - Start) % (1024 * 1024 * 4) != 0) + NumSuperPages++; + + kprintf("[i] Allocating %i superpages (%i MB) for heap.\n", + NumSuperPages, (End - Start) / 0x100000); + for (int i = 0; i < NumSuperPages; i++) + { + u32 Physical = physmem_superpage_to_physical( + physmem_allocate_superpage() + ); + + paging_map_kernel_table(Start + i * 1024 * 1024 * 4, Physical); + } + + T_HEAP* Heap = (T_HEAP *)Start; + Start += sizeof(T_HEAP); + + Heap->Index = heap_index_initialize((void*)Start, HEAP_INDEX_SIZE); + Start += HEAP_INDEX_SIZE * sizeof(void*); + + Heap->Start = Start; + Heap->End = Start + NumSuperPages * 4 * 1024 * 1024; + Heap->Max = Max; + + T_HEAP_HEADER *Hole = (T_HEAP_HEADER *)Start; + Hole->Size = End - Start; + Hole->Magic = HEAP_HEADER_MAGIC; + Hole->Hole = 1; + heap_index_insert(&Heap->Index, (void*)Hole); + + return Heap; +} + +s32 _heap_find_smallest_hole(T_HEAP *Heap, u32 Size, u8 Aligned) +{ + u32 Iterator = 0; + while (Iterator < Heap->Index.Size) + { + T_HEAP_HEADER *Header = heap_index_get(&Heap->Index, Iterator); + if (Aligned > 0) + { + u32 Location = (u32)Header; + u32 Offset = 0; + + if (((Location + sizeof(T_HEAP_HEADER)) & 0xFFFFF000) != 0) + Offset = 0x1000 - (Location + sizeof(T_HEAP_HEADER)) % 0x1000; + + u32 HoleSize = (u32)Header->Size - Offset; + + if (HoleSize >= Size) + break; + } + else if (Header->Size >= Size) + break; + Iterator++; + } + + if (Iterator == Heap->Index.Size) + return -1; + else + return Iterator; +} + +void _heap_expand(T_HEAP *Heap, u32 Size) +{ + u16 NumSuperPages = Size / 0x400000; + if (Size % 0x400000 != 0) + NumSuperPages++; + + for (int i = 0; i < NumSuperPages; i++) + { + u16 SuperPage = physmem_allocate_superpage(); + u32 Physical = physmem_superpage_to_physical(SuperPage); + paging_map_kernel_table(Heap->End + i * 0x400000, Physical); + } +} + +u32 _heap_contract(T_HEAP *Heap, u32 Size) +{ + if (Size & 0x400000) + { + Size &= 0x400000; + Size += 0x400000; + } + + if (Size < HEAP_MIN_SIZE) + Size = HEAP_MIN_SIZE; + + u32 OldSize = Heap->End - Heap->Start; + u32 NumberToDelete = (OldSize - Size) / 0x400000; + + for (int i = 0; i < NumberToDelete; i++) + { + u32 Virtual = Heap->End + i * 0x400000; + u32 Physical; + paging_get_physical(Virtual, &Physical); + u16 SuperPage = Physical / 0x400000; + physmem_free_superpage(SuperPage); + } + + Heap->End -= NumberToDelete * 0x400000; + + return (Heap->End - Heap->Start); +} + +void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned) +{ + u32 RealSize = Size + sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER); + s32 Iterator = _heap_find_smallest_hole(Heap, RealSize, Aligned); + + if (Iterator == -1) + { + u32 OldSize = Heap->End - Heap->Start; + u32 OldEnd = Heap->End; + + _heap_expand(Heap, RealSize); + u32 NewSize = Heap->End - Heap->Start; + + Iterator = 0; + u32 Last = 0; + s32 LastIndex = -1; + + while (Iterator < Heap->Index.Size) + { + u32 Location = (u32)heap_index_get(&Heap->Index, Iterator); + if (Location > Last) + { + Last = Location; + LastIndex = Iterator; + } + Iterator++; + } + + if (LastIndex == -1) + { + T_HEAP_HEADER *Header = (T_HEAP_HEADER *)OldEnd; + Header->Magic = HEAP_HEADER_MAGIC; + Header->Size = NewSize - OldSize; + Header->Hole = 1; + + T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)(OldEnd + Header->Size + - sizeof(T_HEAP_FOOTER)); + Footer->Magic = HEAP_FOOTER_MAGIC; + Footer->Header = Header; + + heap_index_insert(&Heap->Index, (void*)Header); + } + else + { + T_HEAP_HEADER *Header = (T_HEAP_HEADER *)Last; + Header->Size += NewSize - OldSize; + + T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header + + Header->Size - sizeof(T_HEAP_FOOTER)); + Footer->Header = Header; + Footer->Magic = HEAP_FOOTER_MAGIC; + } + + return heap_alloc(Heap, Size, Aligned); + } + + T_HEAP_HEADER *Header = (T_HEAP_HEADER*)heap_index_get(&Heap->Index, + Iterator); + u32 HoleStart = (u32)Header; + u32 HoleSize = Header->Size; + + if (HoleSize - RealSize < sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER)) + { + Size += (HoleSize - RealSize); + RealSize = HoleSize; + } + + if (Aligned && HoleStart & 0xFFFFF000) + { + u32 NewLocation = HoleStart + 0x1000 - (HoleStart & 0xFFF) + - sizeof(T_HEAP_HEADER); + Header->Size = 0x1000 - (HoleStart & 0xFFF) - sizeof(T_HEAP_HEADER); + Header->Magic = HEAP_HEADER_MAGIC; + Header->Hole = 1; + + T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER*)(NewLocation + - sizeof(T_HEAP_FOOTER)); + Footer->Magic = HEAP_FOOTER_MAGIC; + Footer->Header = Header; + + HoleStart = NewLocation; + HoleSize -= Header->Size; + } + else + heap_index_remove(&Heap->Index, Iterator); + + T_HEAP_HEADER *BlockHeader = (T_HEAP_HEADER *)HoleStart; + BlockHeader->Magic = HEAP_HEADER_MAGIC; + BlockHeader->Size = RealSize; + BlockHeader->Hole = 0; + + + T_HEAP_FOOTER *BlockFooter = (T_HEAP_FOOTER *)(HoleStart + RealSize + - sizeof(T_HEAP_FOOTER)); + BlockFooter->Magic = HEAP_FOOTER_MAGIC; + BlockFooter->Header = BlockHeader; + + if (HoleSize - RealSize > 0) + { + T_HEAP_HEADER *NewHoleHeader = (T_HEAP_HEADER*)(HoleStart + RealSize); + NewHoleHeader->Magic = HEAP_HEADER_MAGIC; + NewHoleHeader->Size = HoleSize - RealSize; + NewHoleHeader->Hole = 1; + + T_HEAP_FOOTER *NewHoleFooter = (T_HEAP_FOOTER*)((u32)NewHoleHeader + + NewHoleHeader->Size - sizeof(T_HEAP_FOOTER)); + + if ((u32)NewHoleFooter < Heap->End) + { + NewHoleFooter->Magic = HEAP_FOOTER_MAGIC; + NewHoleFooter->Header = NewHoleHeader; + } + + heap_index_insert(&Heap->Index, (void*)NewHoleHeader); + } + + return (void *)((u32)BlockHeader + sizeof(T_HEAP_HEADER)); +} + +void heap_free(T_HEAP *Heap, void *Data) +{ + if (Data == 0) return; + T_HEAP_HEADER *Header = (T_HEAP_HEADER *)((u32)Data + - sizeof(T_HEAP_HEADER)); + T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size + - sizeof(T_HEAP_FOOTER)); + + if (Header->Magic != HEAP_HEADER_MAGIC) + return; + if (Footer->Magic != HEAP_FOOTER_MAGIC) + return; + Header->Hole = 1; + + u8 ShouldAdd = 1; + + T_HEAP_FOOTER *FooterLeft = (T_HEAP_FOOTER *)((u32)Data + - sizeof(T_HEAP_FOOTER)); + if (FooterLeft->Magic == HEAP_FOOTER_MAGIC && FooterLeft->Header->Hole) + { + u32 OurSize = Header->Size; + Header = FooterLeft->Header; + Footer->Header = Header; + Header->Size += OurSize; + ShouldAdd = 0; + } + + T_HEAP_HEADER *HeaderRight = (T_HEAP_HEADER *)((u32)Footer + + sizeof(T_HEAP_FOOTER)); + if (HeaderRight->Magic == HEAP_HEADER_MAGIC && HeaderRight->Hole) + { + Header->Size += HeaderRight->Size; + Footer = (T_HEAP_FOOTER *)((u32)HeaderRight + HeaderRight->Size + - sizeof(T_HEAP_FOOTER)); + Footer->Header = Header; + + u32 Iterator = 0; + while (Iterator < Heap->Index.Size && + heap_index_get(&Heap->Index, Iterator) != (void *)HeaderRight) + Iterator++; + + if (Iterator != -1) + heap_index_remove(&Heap->Index, Iterator); + } + + if ((u32)Footer + sizeof(T_HEAP_FOOTER) == Heap->End) + { + u32 OldSize = Heap->End - Heap->Start; + u32 NewSize = _heap_contract(Heap, (u32)Header - Heap->Start); + + if (Header->Size > (OldSize - NewSize)) + { + Header->Size -= (OldSize - NewSize); + Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size + - sizeof(T_HEAP_FOOTER)); + Footer->Magic = HEAP_FOOTER_MAGIC; + Footer->Header = Header; + } + else + { + u32 Iterator = 0; + while (Iterator < Heap->Index.Size && + heap_index_get(&Heap->Index, Iterator) != (void *)Header) + Iterator++; + + if (Iterator < Heap->Index.Size) + { + heap_index_remove(&Heap->Index, Iterator); + ShouldAdd = 0; + } + } + } + + if (ShouldAdd) + heap_index_insert(&Heap->Index, (void *)Header); +} + +void heap_init_simple(void) +{ + g_heap = heap_create(HEAP_START, HEAP_START + HEAP_INITIAL_SIZE, + HEAP_START + 0x0FFFF000); +} + +void *kmalloc(u32 Size) +{ + return heap_alloc(g_heap, Size, 0); +} + +void kfree(void *Data) +{ + heap_free(g_heap, Data); +} diff --git a/src/Tier0/kmain.c b/src/Tier0/kmain.c index e00e754..7396f03 100644 --- a/src/Tier0/kmain.c +++ b/src/Tier0/kmain.c @@ -9,6 +9,7 @@ #include "Tier0/pic.h" #include "Tier0/kbd_layout.h" #include "Tier0/physical_alloc.h" +#include "Tier0/heap.h" void interrupts_irq_sample(void); @@ -64,13 +65,7 @@ void kmain(void *MultibootHeader, u32 Magic) kprintf("[i] Hardware interrupts are now enabled.\n"); - /*while(1) - { - s8 c = ps2_getc(); - kprintf("%c", c); - }*/ - - physmem_dump_map(); - + heap_init_simple(); + LOOPFOREVER; } diff --git a/src/Tier0/paging.c b/src/Tier0/paging.c index e789796..9aa8821 100644 --- a/src/Tier0/paging.c +++ b/src/Tier0/paging.c @@ -3,14 +3,9 @@ #include "Tier0/kstdio.h" #include "types.h" -// 10 megabytes is safe guess, I guess. -#define PAGING_FREEFORALL_START 0x00F00000 - u32 g_kernel_page_directory[1024] __attribute__ ((aligned (4096))); u32 g_kernel_page_tables[1024][1024] __attribute__ ((aligned (4096))); -u32 g_paging_current_offset = PAGING_FREEFORALL_START; - u8 paging_get_physical(u32 Virtual, u32 *Physical) { u16 DirectoryIndex = (Virtual >> 22) & 0x3FF; @@ -112,20 +107,3 @@ void paging_init_simple(void) "mov %%eax, %%cr0\n" :: "m" (PhysicalDirectory)); } -// This allocates a 4kb page for whatever reason -void paging_allocate_page(u32 Virtual) -{ - u32 MaximumAddress = system_get_memory_upper(); - while (!system_memory_available(g_paging_current_offset, 0x1000)) - { - g_paging_current_offset += 0x1000; - if (g_paging_current_offset > MaximumAddress) - { - kprintf("[e] Fatal error: out of memory!\n"); - for (;;) {} - } - } - - paging_map_kernel_page(Virtual, g_paging_current_offset); - g_paging_current_offset += 0x1000; -}