réplica de
https://github.com/Arnau478/quark.git
synced 2024-05-19 20:36:31 +02:00
153 líneas
3,7 KiB
C
153 líneas
3,7 KiB
C
#include <stdint.h>
|
|
#include "pmm.h"
|
|
#include "../lib/memory.h"
|
|
|
|
static uint32_t g_pmm_memory_size = 0;
|
|
static uint32_t g_pmm_used_blocks = 0;
|
|
static uint32_t g_pmm_max_blocks = 0;
|
|
static uint32_t *g_pmm_memory_map = 0;
|
|
|
|
static inline void pmm_map_set(int bit){
|
|
g_pmm_memory_map[bit / 32] |= (1 << (bit % 32));
|
|
}
|
|
|
|
static inline void pmm_map_unset(int bit){
|
|
g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32));
|
|
}
|
|
|
|
static inline bool pmm_map_get(int bit){
|
|
return g_pmm_memory_map[bit / 32] & (1 << (bit % 32));
|
|
}
|
|
|
|
int pmm_map_first_free(){
|
|
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
|
for(int j = 0; j < 32; j++){
|
|
if(!(g_pmm_memory_map[i] & (1 << j))){
|
|
return i*4*8+j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int pmm_map_first_free_s(size_t size){
|
|
if(size == 0) return -1;
|
|
if(size == 1) return pmm_map_first_free();
|
|
|
|
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
|
for(int j = 0; j < 32; j++){
|
|
int bit = 1 << j;
|
|
if(!(g_pmm_memory_map[i] & bit)){
|
|
int start_bit = i*32;
|
|
start_bit+=bit;
|
|
|
|
uint32_t free = 0;
|
|
for(uint32_t count = 0; count <= size; count++){
|
|
if(!pmm_map_get(start_bit+count)) free++;
|
|
if(free == size) return i*4*8+j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void pmm_initialize(size_t mem_size, phys_addr bitmap){
|
|
g_pmm_memory_size = mem_size;
|
|
g_pmm_memory_map = (uint32_t *)bitmap;
|
|
g_pmm_max_blocks = (pmm_get_memory_size()*1024) / PMM_BLOCK_SIZE;
|
|
g_pmm_used_blocks = g_pmm_max_blocks;
|
|
|
|
memset(g_pmm_memory_map, 0xFF, pmm_get_block_count() / PMM_BLOCKS_PER_BYTE);
|
|
}
|
|
|
|
void pmm_init_region(phys_addr base, size_t size){
|
|
int align = base / PMM_BLOCK_SIZE;
|
|
int blocks = size / PMM_BLOCK_SIZE;
|
|
|
|
for(; blocks >= 0; blocks--){
|
|
pmm_map_unset(align++);
|
|
g_pmm_used_blocks--;
|
|
}
|
|
|
|
pmm_map_set(0); // First block always set
|
|
}
|
|
|
|
void pmm_deinit_region(phys_addr base, size_t size){
|
|
int align = base / PMM_BLOCK_SIZE;
|
|
int blocks = size / PMM_BLOCK_SIZE;
|
|
|
|
for(; blocks >= 0; blocks--){
|
|
pmm_map_set(align++);
|
|
g_pmm_used_blocks++;
|
|
}
|
|
|
|
pmm_map_set(0); // First block always set
|
|
}
|
|
|
|
void *pmm_alloc_block(){
|
|
if(pmm_get_free_block_count() <= 0) return 0; // Out of memory
|
|
|
|
int frame = pmm_map_first_free();
|
|
if(frame == -1) return 0; // Out of memory
|
|
|
|
pmm_map_set(frame);
|
|
|
|
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
|
g_pmm_used_blocks++;
|
|
|
|
return (void *)addr;
|
|
}
|
|
|
|
void pmm_free_block(void *p){
|
|
phys_addr addr = (phys_addr)p;
|
|
int frame = addr / PMM_BLOCK_SIZE;
|
|
|
|
pmm_map_unset(frame);
|
|
|
|
g_pmm_used_blocks--;
|
|
}
|
|
|
|
void *pmm_alloc_blocks(size_t size){
|
|
if(pmm_get_free_block_count() <= size) return 0; // Out of memory
|
|
|
|
int frame = pmm_map_first_free_s(size);
|
|
if(frame == -1) return 0; // Out of memory
|
|
|
|
for(uint32_t i = 0; i < size; i++) pmm_map_set(frame+i);
|
|
|
|
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
|
g_pmm_used_blocks += size;
|
|
|
|
return (void *)addr;
|
|
}
|
|
|
|
void pmm_free_blocks(void *p, size_t size){
|
|
phys_addr addr = (phys_addr)p;
|
|
int frame = addr / PMM_BLOCK_SIZE;
|
|
|
|
for(uint32_t i = 0; i < size; i++) pmm_map_unset(frame+i);
|
|
|
|
g_pmm_used_blocks -= size;
|
|
}
|
|
|
|
size_t pmm_get_memory_size(){
|
|
return g_pmm_memory_size;
|
|
}
|
|
|
|
uint32_t pmm_get_block_count(){
|
|
return g_pmm_max_blocks;
|
|
}
|
|
|
|
uint32_t pmm_get_used_block_count(){
|
|
return g_pmm_used_blocks;
|
|
}
|
|
|
|
uint32_t pmm_get_free_block_count(){
|
|
return g_pmm_max_blocks - g_pmm_used_blocks;
|
|
}
|