Implemented Physical Memory Manager
This commit is contained in:
parent
76a7ce2a8a
commit
7bb02930eb
|
@ -43,6 +43,8 @@ SECTIONS {
|
|||
}
|
||||
|
||||
_kernel_bss_end = .;
|
||||
|
||||
. = ALIGN(4K);
|
||||
_kernel_end = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
* pmm_init:
|
||||
* Initializes the Physical Memory Manager.
|
||||
*
|
||||
* @param size - Size of available physical memory
|
||||
* @param mmap_addr - Physical memory address of memory map data structure
|
||||
* @param size - Size of available physical memory in KB
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_init(size_t size, uint32_t mmap_addr);
|
||||
void pmm_init(uint32_t mmap_addr, size_t size);
|
||||
|
||||
/*
|
||||
* pmm_init_region:
|
||||
|
@ -30,6 +30,19 @@ void pmm_init(size_t size, uint32_t mmap_addr);
|
|||
|
||||
void pmm_init_region(uint32_t base, size_t size);
|
||||
|
||||
/*
|
||||
* pmm_init_available_regions:
|
||||
* ---------------------------
|
||||
*
|
||||
* Using multiboot info, initialize the available memory regions.
|
||||
*
|
||||
* @param mmap - Pointer to start of memory map info
|
||||
* @param mmap_end - Pointe rto end of memory map info
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_init_available_regions(uint32_t mmap_, uint32_t mmap_end_);
|
||||
|
||||
/*
|
||||
* pmm_deinit_region:
|
||||
* Deinitializes a memory region of specified size.
|
||||
|
@ -41,6 +54,16 @@ void pmm_init_region(uint32_t base, size_t size);
|
|||
|
||||
void pmm_deinit_region(uint32_t base, size_t size);
|
||||
|
||||
/*
|
||||
* pmm_deinit_kernel:
|
||||
* Deinitializes the memory where the kernel and the memory map data
|
||||
* structure stay. It assumes that the memory map is placed after
|
||||
* the end of kernel.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_deinit_kernel(void);
|
||||
|
||||
/*
|
||||
* pmm_alloc_block:
|
||||
* Allocates a memory block and returns a generic pointer to its physical
|
||||
|
@ -54,6 +77,8 @@ void *pmm_alloc_block(void);
|
|||
* pmm_free_block:
|
||||
* Frees a memory block.
|
||||
*
|
||||
* @param p - Pointer to be free'd
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_free_block(void *p);
|
||||
|
@ -67,7 +92,7 @@ void pmm_free_block(void *p);
|
|||
*
|
||||
*/
|
||||
|
||||
void print_memory_map(multiboot_memory_map_t *mmap, multiboot_memory_map_t *mmap_end);
|
||||
void print_memory_map(uint32_t mmap_, uint32_t mmap_end_);
|
||||
|
||||
/*
|
||||
* print_ksections
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef PMM_INTERNALS_H_
|
||||
#define PMM_INTERNALS_H_
|
||||
|
||||
#define BLOCKS_PER_BYTE 8
|
||||
#define BLOCK_SIZE 4096
|
||||
#define BLOCK_ALIGN BLOCK_SIZE
|
||||
|
||||
/* Macros for testing and aligning memory. */
|
||||
|
||||
#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1))
|
||||
#define ALIGN(addr, align) (((addr) & ~((align) - 1)) + (align))
|
||||
|
||||
/*
|
||||
* Internal variables:
|
||||
*
|
||||
* mem_size - Size of availabe memory in KB
|
||||
* used_blocks - Number of used blocks of size BLOCK_SIZE
|
||||
* max_blocks - Maximum number of blocks of size BLOCK_SIZE
|
||||
* pmmap - pointer to a data structure containing info about the
|
||||
* state of each block (Physical Memory Map)
|
||||
* pmmap_size - Number of double words occupied by pmmap
|
||||
*
|
||||
*/
|
||||
|
||||
static size_t mem_size;
|
||||
static uint32_t used_blocks;
|
||||
static uint32_t max_blocks;
|
||||
static uint32_t *pmmap;
|
||||
static size_t pmmap_size;
|
||||
|
||||
#endif
|
|
@ -25,7 +25,10 @@ static char *mem_types[] = {
|
|||
*
|
||||
*/
|
||||
|
||||
void print_memory_map(multiboot_memory_map_t *mmap, multiboot_memory_map_t *mmap_end) {
|
||||
void print_memory_map(uint32_t mmap_, uint32_t mmap_end_) {
|
||||
|
||||
multiboot_memory_map_t *mmap = (multiboot_memory_map_t *) mmap_;
|
||||
multiboot_memory_map_t *mmap_end = (multiboot_memory_map_t *) mmap_end_;
|
||||
|
||||
printf("Physical Memory Map:\n");
|
||||
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
#include "kernel/pmm.h"
|
||||
|
||||
#include "pmm_internals.h"
|
||||
|
||||
#include "lib/bitmap.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* pmm_init:
|
||||
* ---------
|
||||
*
|
||||
* Set the internal variables and initialize the pmmap data type.
|
||||
* It initializes all memory zones as used by settings all bits in pmmap.
|
||||
* At the moment, pmmap is a bitmap.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_init(uint32_t mmap_addr, size_t size) {
|
||||
|
||||
mem_size = size;
|
||||
max_blocks = (mem_size * 1024) / BLOCK_SIZE;
|
||||
used_blocks = max_blocks;
|
||||
pmmap = (uint32_t *) mmap_addr;
|
||||
|
||||
pmmap_size = mem_size / BLOCKS_PER_BYTE;
|
||||
if (mem_size % BLOCKS_PER_BYTE)
|
||||
pmmap_size++;
|
||||
|
||||
memset(pmmap, 0xFF, pmmap_size);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_init_available_regions:
|
||||
* ---------------------------
|
||||
*
|
||||
* Using multiboot info, it initializes all available memory zones.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_init_available_regions(uint32_t mmap_, uint32_t mmap_end_) {
|
||||
|
||||
multiboot_memory_map_t *mmap = (multiboot_memory_map_t *) mmap_;
|
||||
multiboot_memory_map_t *mmap_end = (multiboot_memory_map_t *) mmap_end_;
|
||||
|
||||
for (int i = 0; mmap < mmap_end; mmap++, i++)
|
||||
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE)
|
||||
pmm_init_region((uint32_t) mmap->addr, (size_t) mmap->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_init_region:
|
||||
* ----------------
|
||||
*
|
||||
* @var blocks - Number of blocks to be unset starting from @align
|
||||
* @var align - Starting index in bitmap
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_init_region(uint32_t base, size_t size) {
|
||||
|
||||
size_t blocks = size / BLOCK_SIZE;
|
||||
uint32_t align = base / BLOCK_SIZE;
|
||||
|
||||
for (size_t i = 0; i < blocks; i++) {
|
||||
|
||||
bitmap_unset(pmmap, align++);
|
||||
used_blocks--;
|
||||
|
||||
}
|
||||
|
||||
bitmap_set(pmmap, 0);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_deinit_region:
|
||||
* ------------------
|
||||
*
|
||||
* Sets the corresponding bit in pmmap and increments the number of
|
||||
* used blocks.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_deinit_region(uint32_t base, size_t size) {
|
||||
|
||||
size_t blocks = size / BLOCK_SIZE;
|
||||
uint32_t align = base / BLOCK_SIZE;
|
||||
|
||||
for (size_t i = 0; i < blocks; i++) {
|
||||
|
||||
bitmap_set(pmmap, align++);
|
||||
used_blocks++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_deinit_kernel:
|
||||
* ------------------
|
||||
*
|
||||
* Deinitializes the blocks containing the kernel and the memory map. There
|
||||
* is an align operation because the routine tries to deinitialize all
|
||||
* blocks where pmmap may sit in memory.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_deinit_kernel(void) {
|
||||
|
||||
extern uint8_t *_kernel_start;
|
||||
extern uint8_t *_kernel_end;
|
||||
|
||||
size_t kernel_size = (size_t) &_kernel_end - (size_t) &_kernel_start;
|
||||
|
||||
uint32_t pmmap_size_aligned = pmmap_size;
|
||||
if (!IS_ALIGNED(pmmap_size_aligned, BLOCK_SIZE))
|
||||
pmmap_size_aligned = ALIGN(pmmap_size_aligned, BLOCK_SIZE);
|
||||
|
||||
pmm_deinit_region((uint32_t) &_kernel_start, kernel_size);
|
||||
pmm_deinit_region((uint32_t) &_kernel_end, pmmap_size_aligned);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_alloc_block:
|
||||
* ----------------
|
||||
*
|
||||
* Searches for a free block and returns a pointer to its physical memory
|
||||
* location.
|
||||
*
|
||||
*/
|
||||
|
||||
void *pmm_alloc_block(void) {
|
||||
|
||||
if (used_blocks - max_blocks <= 0)
|
||||
return NULL;
|
||||
|
||||
int p_index = bitmap_first_unset(pmmap, max_blocks);
|
||||
|
||||
if (p_index == -1)
|
||||
return NULL;
|
||||
|
||||
bitmap_set(pmmap, p_index);
|
||||
used_blocks++;
|
||||
|
||||
return (void *) (BLOCK_SIZE * p_index);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pmm_free_block:
|
||||
* ---------------
|
||||
*
|
||||
* Checks if p is a valid pointer to free (is not first memory block)
|
||||
* and frees its entry it pmmap.
|
||||
*
|
||||
*/
|
||||
|
||||
void pmm_free_block(void *p) {
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
uint32_t p_addr = (uint32_t) p;
|
||||
|
||||
int index = p_addr / BLOCK_SIZE;
|
||||
bitmap_unset(pmmap, index);
|
||||
|
||||
used_blocks--;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue