Adding a skeleton for the memory management code

Moved the PMM away from being object orientated as it is just plain annoying
renamed src folder to source
Set timeout to 5 seconds in the grub config
This commit is contained in:
2022-08-21 21:18:53 +02:00
parent e70f56a005
commit 0f0fc9f252
70 changed files with 308 additions and 404 deletions

View File

@ -0,0 +1,19 @@
.global LoadGlobalDescriptorTable
LoadGlobalDescriptorTable:
lgdt gdtDescriptor
movw $16, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
jmp $8,$flush
flush:
ret

View File

@ -0,0 +1,58 @@
#include "gdtc.h"
#include "../../Terminal/kterm.h"
#define NULL_SEGMENT 0
#define KERNEL_CODE_SEGMENT 1
#define KERNEL_DATA_SEGMENT 2
#define USER_CODE_SEGMENT 3
#define USER_DATA_SEGMENT 4
SegmentDescriptor GlobalDescriptorTable[5];
GlobalDescriptorTableDescriptor gdtDescriptor;
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity ){
GlobalDescriptorTable[which].base_low = (base & 0xFFFF );
GlobalDescriptorTable[which].base_middle = (base >> 6) & 0xFF;
GlobalDescriptorTable[which].base_high = (base >> 24) & 0xFF;
GlobalDescriptorTable[which].limit_low = (limit & 0xFFFF);
GlobalDescriptorTable[which].granularity = ((limit >> 16) & 0x0F);
GlobalDescriptorTable[which].granularity |= (granularity & 0xF0);
GlobalDescriptorTable[which].access = access;
}
void initGDT(){
#ifdef __VERBOSE__
printf("Init GDT!\n");
#endif
// NULL segment
add_descriptor(NULL_SEGMENT, 0,0,0,0);
// Kernel Code Segment
add_descriptor(KERNEL_CODE_SEGMENT, 0, 0xFFFFFFFF, 0x9A, 0xCF);
// Kernel Data Segment
add_descriptor(KERNEL_DATA_SEGMENT, 0, 0xFFFFFFFF, 0x92, 0xCF);
// User Code Segment
// TODO:
// User Data Segement
// TODO:
// init Gdt Descriptor
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1);
gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable;
LoadGlobalDescriptorTable();
}

View File

@ -0,0 +1,27 @@
#include <stdint.h>
struct SegmentDescriptor {
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
}__attribute__((packed));
struct GlobalDescriptorTableDescriptor{
unsigned short limit;
unsigned int base;
}__attribute__((packed));
extern SegmentDescriptor GlobalDescriptorTable[];
extern GlobalDescriptorTableDescriptor gdtDescriptor;
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity );
extern "C" void LoadGlobalDescriptorTable();
void initGDT();

View File

@ -0,0 +1,51 @@
#include "KernelHeap.h"
// Size of heap meta data is 5 bytes
struct heap_block{
uint8_t Used;
uint32_t Size;
}
uint32_t heap_size;
heap_block* start ;
void* malloc(size_t size)
{
printf("Received request for %d bytes of memory", size);
heap_block* current = start;
while(current < start + heap_size)
{
if(current->size >= size && current->Used == false )
{
// We found a spot
// Set the spot to in-use
current->Used = false;
// return the free address
// NOTE: added an offset from the initial address to accomodate for
// meta-data.
return current + sizeof(heap_block);
}
current += current->Size + sizeof(heap_block);
}
// If we are here we need more memory so we should
// probably ask the VMM for more
// TODO: ask for more memory
}
void free(void* addr)
{
// clear the free boolean that corresponds to this adddress
// This should be fairly simple
heap_block* allocatedBlock = addr - sizeof(heap_block);
allocate_block->Used = false;
}
void initHeap()
{
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
void initHeap();
void* malloc (size_t size );
void free(void* addr);

View File

@ -0,0 +1,43 @@
#include "MBI_MMap.h"
void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt) {
printf("mmap_addr = 0x%x, mmap_length = 0x%x\n", (unsigned) mbt->mmap_addr , (unsigned) mbt->mmap_length );
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) mbt->mmap_addr;
for (; (unsigned long) mmap < mbt->mmap_addr + mbt->mmap_length; mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size))){
if ( mmap->type == MULTIBOOT_MEMORY_AVAILABLE){
memInfo->TotalMemory += mmap->len;
} else {
memInfo->ReservedMemory += mmap->len;
}
print_Multiboot_memory_Map(mmap);
}
}
/**
* @brief Debug Verbose functions
*
* @param mmap
*/
void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap) {
printf(
"size = 0x%x, base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n",
(unsigned) mmap->size,
(unsigned) (mmap->addr >> 32),
(unsigned) (mmap->addr & 0xffffffff),
(unsigned) (mmap->len >> 32),
(unsigned) (mmap->len & 0xffffffff),
(unsigned) mmap->type
);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <stddef.h>
#include "../../multiboot.h"
#include "../memoryinfo.h"
void initialise_available_regions(uint32_t memoryMapAddr, uint32_t memoryMapLastAddr, uint32_t* memoryBitMap, int* used_blocks);
void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt);
/**
* @brief Debug Verbose Functions
*
* @param mmap
*/
void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap);

View File

@ -0,0 +1,102 @@
#include "./PhysicalMemoryManager.h"
PhysicalMemoryManagerInfoBlock* PMMInfoBlock;
void initPMM( MemoryInfo* memory) {
// NOTE: Lets for now puts the Physical memoryManagerBlock at a random address
// We'll think of a more proper solution a bit later
PMMInfoBlock = (PhysicalMemoryManagerInfoBlock*) 0xCC900000;
// calculate the maximum number of blocks
PMMInfoBlock->max_blocks = KB_TO_BLOCKS(memory->TotalMemory);
PMMInfoBlock->used_blocks = 0;
PMMInfoBlock->memoryBitMap = (uint32_t*) 0xCCA00000;
printf("Maximum Number of blocks: 0x%x, Number of bytes for memMap: 0x%x\n", PMMInfoBlock->max_blocks , (PMMInfoBlock->max_blocks/8));
//Size of memory map
uint32_t memMap_size = (PMMInfoBlock->max_blocks / 8 ) ;
printf("Memory Map size: 0x%x\n", memMap_size );
printf("size of int in bytes: 0x%x \n" , sizeof(int));
// Set all places in memory as free
memset(PMMInfoBlock->memoryBitMap, 0xFF, memMap_size );
}
// NOTE: this can only give blocks of 4kb at a time!
void* allocate_block() {
uint8_t blocks_available = PMMInfoBlock->max_blocks - PMMInfoBlock->used_blocks;
// Are there any blocks available?
if( blocks_available <= 0)
{
printf("No blocks available. Blocks Delta: 0x%x\n", blocks_available);
return 0;
}
// Find 1 free block somewhere
int free_block_index = bitmap_first_unset(PMMInfoBlock->memoryBitMap, (PMMInfoBlock->max_blocks /8) /*memMap Size*/ );
if(free_block_index == -1)
{
printf("Could not find a good block!\n");
// Could not find a block
return (void*)0xFFFF;
}
if(free_block_index == 0)
printf("Somethings wrong!!!\n");
// Set the block to be used!
bitmap_unset(PMMInfoBlock->memoryBitMap, free_block_index);
// Increase the used_block count!
PMMInfoBlock->used_blocks++;
printf("used blocks: 0x%x\n", PMMInfoBlock->used_blocks);
// return the pointer to the physical address
return (void*) (BLOCK_SIZE * free_block_index);
}
void free_block(void* p) {
// If it is a null pointer we don't need to do anything.
if(p==0) {
return;
}
// calculate the index into the bitmap
int index = ((uint32_t) p) / BLOCK_SIZE;
// set the block to be free
bitmap_set(PMMInfoBlock->memoryBitMap, index);
PMMInfoBlock->used_blocks--;
printf("used blocks: 0x%x, after free\n", PMMInfoBlock->used_blocks);
}
void allocate_region(uint32_t startAddress, uint32_t size) {
// every bit should be 4KiB
// every byte is 8*4KiB = 32KiB
int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1;
int startBlock = (startAddress / 1024) / 4 / 8 ;
// printf("NumberOfBlocksToAllocate: 0x%x\n", NumberOfBlocksToAllocate);
//printf( "start block: 0x%x\n" , startBlock);
for( int i = 0; i < NumberOfBlocksToAllocate; i++)
{
//printf("ALLOCATE BLOCK: 0x%x\n" , startBlock + i );
bitmap_unset(PMMInfoBlock->memoryBitMap, startBlock+ i);
PMMInfoBlock->used_blocks++;
}
}
void deallocate_region(uint32_t StartAddress , uint32_t size ) {
// NOT IMPLEMENTED YET
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <stddef.h>
#include "memoryinfo.h"
#include "../Terminal/kterm.h"
#include "../Lib/mem.h"
#include "../bitmap.h"
// Asumming 32 bit x86 for now!
#define BLOCK_SIZE 4092
#define WORD_SIZE 2
#define BLOCKS_PER_WORD 32
#define KB_TO_BLOCKS(x) (x / BLOCK_SIZE)
#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1))
#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align))
struct PhysicalMemoryManagerInfoBlock
{
uint32_t* memoryBitMap;
size_t pmmap_size;
size_t max_blocks;
int used_blocks;
};
void initPMM(MemoryInfo* memory);
void free_block(void* ptr);
void* allocate_block();
void allocate_region(uint32_t, uint32_t);
void deallocate_region(uint32_t , uint32_t );

View File

@ -0,0 +1,24 @@
#include "VirtualMemoryManager.h"
extern "C" void loadPageDirectory (uint32_t* addr );
extern "C" void enablePaging();
void AllocatePage(uint32_t vaddr)
{
}
void FreePage(uint32_t vaddr )
{
}
void Map ( uint32_t vaddr, uint32_t paddr)
{
}
void Unmap(uint32_t vaddr)
{
// NOTE: I will implement lazy unmapping for now
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "PhysicalMemoryManager.h"
#include "../Terminal/kterm.h"
#include "../cpu.h"
void AllocatePage(uint32_t v_addr );
void FreePage(uint32_t v_addr);
void Map(uint32_t p_addr, uint32_t v_addr);
void Unmap (uint32_t v_addr);

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
struct MemoryArea{
void* StartAddress;
size_t Size;
unsigned int type;
MemoryArea* Next;
}__attribute__((packed));
struct MemoryInfo {
uint32_t TotalMemory;
uint32_t ReservedMemory;
MemoryArea* MemoryRegionList;
}__attribute__((packed));

View File

@ -0,0 +1,56 @@
#pragma once
#include <stdint.h>
/*
This file contains some handy definitions for different types
that have to do with paging in atleast 32 bit and maybe sometime in the future
also 64 bit mode.
*/
#define MAX_DIRECTORY_ENTRIES 1024
#define MAX_PAGE_TABLE_ENTRIES 1024
#define MAX_PAGES 1024
#define PHYSICAL_ADDRESS uint32_t
#define VIRTUAL_ADDRESS uint32_t
#define PageDirectoryEntry uint32_t
#define PageTableEntry uint32_t
#define KERNEL_VRT_MEMORY_BEGIN 0xC0000000
#define KERNEL_VRT_MEMORY_END 0xCFFFFFFF
#define PAGE_SIZE 4096;
// NOTE: FIXME: I am fairly certain these masks are off by one!
#define PD32_PRESENT_MASK (0x1 << 0)
#define PD32_READ_WRITE_MASK (0x1 << 1)
#define PD32_SUPERVISOR_MASK (0x1 << 2)
#define PD32_WRITE_THROUGH_MASK (0x1 << 3)
#define PD32_CACHE_DISABLE_MASK (0x1 << 4)
#define PD32_ACCESSED_MASK (0x1 << 5)
#define PD32_AVAILABLE_1_4KB_MASK (0x1 << 6)
#define PD32_DISABLE_4MB_MASK (0x1 << 6)
#define PD32_PAGE_SIZE_MASK (0x1 << 7)
#define PD32_GLOBAL_4MB_MASK (0x1 << 8)
#define PD32_AVAILABLE_2_4MB_MASK ( 14 << 9)
#define PD32_AVAILABLE_2_4KB_MASK ( 15 << 8)
#define PD32_ADDRESS_4KB_MASK (0x8FFFF << 12)
#define PD32_PAGE_ATTRIBUTE_TABLE_4MB_MASK (0x1 << 12)
#define PD32_HIGH_HALF_ADDRESS_4MB_MASK (0x7F<< 13)
#define PD32_RESERVED_4MB_MASK (0x1 << 21)
#define PD32_LOWER_HALF_ADDRESS_4MB_MASK (0x1FF << 22)
#define PT32_PRESENT_MASK (0x1 << 0)
#define PT32_READ_WRITE_MASK (0x1 << 1)
#define PT32_SUPERVISOR_MASK (0x1 << 2)
#define PT32_WRITE_THROUGH_MASK (0x1 << 3)
#define PT32_CACHE_DISABLE_MASK (0x1 << 4)
#define PT32_ACCESSED_MASK (0x1 << 5)
#define PT32_DIRTY_MASK (0x1 << 6)
#define PT32_PAGE_ATTRIBUTE_TABLE_MASK (0x1 << 7)
#define PT32_GLOBAL_MASK (0x1 << 8)
#define PT32_AVAILABLE_MASK (0x7 << 9)
#define PT32_CACHE_DISABLE_MASK (0x7FFFF << 12)

View File

@ -0,0 +1,44 @@
# NOTE: I wish this wasn't AT&T Syntax its horrible
# REMINDER: INSTRUCTION FROM_REGISTER, TO_REGISTER
.globl enablePaging
enablePaging:
# Create a new call frame
push %ebp
mov %esp, %ebp
# Set the PG bit of CR0
mov %cr0, %eax
or $0x80000000, %eax
mov %eax, %cr0
# Restore to the previous call frame
mov %ebp, %esp
pop %ebp
ret
.globl loadPageDirectory
loadPageDirectory:
push %ebp
mov %esp, %ebp
/* NOTE: We should probably check if paging is already enabled.
Changing the CR3 register whilst paging is enabled might
result in unwanted behaviour (in the worst case) or cause a
fault (in the best case).
*/
mov 8(%esp), %eax # Move the first argument in the eax register
mov %eax, %cr3 # Move the value of eax into the CR3 register
/*
Moving the value of the argument passed to this function
into the CR3 register will allow the MMU to access the paging
structure we setup in memory once we enable paging
*/
mov %ebp, %esp
pop %ebp
ret