|
|
|
#include "memory.h"
|
|
|
|
#include "../drivers/vga.h"
|
|
|
|
#include "../lib/conv.h"
|
|
|
|
|
|
|
|
// https://wiki.osdev.org/Page_Frame_Allocation
|
|
|
|
// page = block
|
|
|
|
|
|
|
|
// MAX_BLOCK_SIZE_IN_BITS/8 bytes
|
|
|
|
// i.e. : bit i of byte n define status of block 8n+i
|
|
|
|
// block = 8n+i
|
|
|
|
|
|
|
|
// in 32-bit mode, we have access to 2^32 blocks
|
|
|
|
// which is (2^32)*BLOCK_SIZE blocks
|
|
|
|
// and with a blocksize of 1024, we git around 4.3 trillion blocks
|
|
|
|
// which is more than enough
|
|
|
|
|
|
|
|
#define CHECK_BITMAP(map, idx) ((map) & (1<<(idx)))
|
|
|
|
|
|
|
|
#define BLOCK_TO_MEMP(idx) (pointer)(PM_MEM_START + (idx*BLOCK_SIZE))
|
|
|
|
|
|
|
|
#define MEMP_TO_BLOCK(memp) (uint)((memp - PM_MEM_START)/BLOCK_SIZE)
|
|
|
|
|
|
|
|
static int bitmap = 0;
|
|
|
|
static uint last_block;
|
|
|
|
void mod_bitmap(uint bit, uint bflag) {
|
|
|
|
// create a bitmask that will be applied to the bitmap
|
|
|
|
int bitmask = 1 << bit;
|
|
|
|
|
|
|
|
// apply the bitmask, resulting in the bit:n bit will set
|
|
|
|
// set to bflag
|
|
|
|
bitmap = (((bitmap & ~bitmask)) | (bflag << bit));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pointer block_alloc(uint blockidx) {
|
|
|
|
int block_bflag;
|
|
|
|
block_bflag = CHECK_BITMAP(bitmap, blockidx);
|
|
|
|
|
|
|
|
if( block_bflag == BM_FREE ) { // check if block is free
|
|
|
|
println("Allocating block...", DEFAULT_COLOR);
|
|
|
|
|
|
|
|
mod_bitmap(blockidx, 1);
|
|
|
|
last_block = blockidx;
|
|
|
|
|
|
|
|
return BLOCK_TO_MEMP(blockidx);
|
|
|
|
} else {
|
|
|
|
println("[ERROR] Attemped to allocate non-free block.", 0x0c);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void block_free(uint blockidx) {
|
|
|
|
println("Dealloc block...", DEFAULT_COLOR);
|
|
|
|
mod_bitmap(blockidx, BM_FREE);
|
|
|
|
last_block = blockidx;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool check_block_range(uint start, uint end) {
|
|
|
|
bool allowed = true;
|
|
|
|
|
|
|
|
uint idx;
|
|
|
|
for(idx = start; idx <= end; idx++) {
|
|
|
|
if( CHECK_BITMAP(bitmap, idx) != BM_FREE ) {
|
|
|
|
allowed = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return allowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
int find_free(uint block_count) {
|
|
|
|
// Loop through bitmap starting at last_block
|
|
|
|
for( uint lower = 0; lower < MAX_BLOCK_COUNT - block_count; lower++ ) {
|
|
|
|
bool range_is_free = check_block_range(lower, lower + block_count);
|
|
|
|
|
|
|
|
if(range_is_free == true) { // if range is free
|
|
|
|
return lower;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1; // return the lower block index
|
|
|
|
}
|
|
|
|
|
|
|
|
void pm_malloc_range(ulong start, ulong end, bool force) {
|
|
|
|
uint idx_start;
|
|
|
|
uint idx_end;
|
|
|
|
|
|
|
|
ulong d_addr = end - start; // memory size
|
|
|
|
uint num_blocks = (d_addr/BLOCK_SIZE) + 1; // amount of blocks to be allocated
|
|
|
|
|
|
|
|
uint start_block = MEMP_TO_BLOCK(start); // start idx, end = start_block + num_blocks - 1
|
|
|
|
bool allowed = true && check_block_range(start_block, start_block + num_blocks - 1);
|
|
|
|
|
|
|
|
// allocate (if permitted)
|
|
|
|
if( allowed ) {
|
|
|
|
uint idx;
|
|
|
|
for(idx=start_block; idx <= start_block + num_blocks - 1; idx++)
|
|
|
|
block_alloc(idx);
|
|
|
|
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
println("[ERROR] Tried to allocate memory range without permission!", URGENT_COLOR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pointer pm_malloc(uint block_count) {
|
|
|
|
// find free block range and get lower offset
|
|
|
|
int lower;
|
|
|
|
lower = find_free(block_count);
|
|
|
|
println("lower: ", DEFAULT_COLOR);
|
|
|
|
println((lower+46), 0xfc);
|
|
|
|
|
|
|
|
if( lower < 0 ) {
|
|
|
|
println("malloc: OUT OF MEMORY :(", URGENT_COLOR);
|
|
|
|
// do some out-of-memory interupt
|
|
|
|
return 0x0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// allocate those blocks
|
|
|
|
uint i;
|
|
|
|
for( i = lower; i <= lower + block_count - 1; i++ )
|
|
|
|
block_alloc(i);
|
|
|
|
|
|
|
|
// return pointer to start of first block
|
|
|
|
return BLOCK_TO_MEMP(lower);
|
|
|
|
}
|