BMOSP/kernel/mem.cpp
2023-10-12 22:30:54 +03:00

149 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <fb.h>
#include <limine.h>
#include <lock.h>
#include <tool.h>
#define BLOCK_SIZE 4096
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0,
.response = (struct limine_memmap_response *)0
};
static volatile struct limine_hhdm_request hhdm_request = {
.id = LIMINE_HHDM_REQUEST,
.revision = 0,
.response = (struct limine_hhdm_response *)0
};
namespace mem {
#define HHDM_OFFSET (hhdm_request.response->offset)
struct limine_memmap_response *memmap_response;
// Битовая карта для отслеживания занятых и свободных фреймов памяти
uint8_t *bitmap;
// Объем доступных блоков
uint64_t bitmap_available = 0;
// Объем блоков
uint64_t bitmap_limit = 0;
// Верхняя граница доступной памяти
uint64_t limit;
// Объем всего доступного физического адресного пространства
uint64_t usable = 0;
// Объем доступной виртуальной памяти
uint64_t available = 0;
// Наивысший адрес в available space
uint64_t highest = 0;
// Количество записей в карте памяти
uint64_t mmmap_count = 0;
// Массив с описаниями типов памяти
char memory_types[8][82] = {
"Доступно", "Зарезервировано", "ACPI, можно освободить",
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
"Ядро и модули", "Буфер кадра"
};
void free(void *ptr, uint64_t frames) {
// Проход по фреймам памяти и очистка битов в битовой карте
uint64_t frame = (uint64_t)ptr / BLOCK_SIZE;
for (uint64_t i = frame; i < frames + frame; i++) { BIT_CLEAR(i); }
bitmap_available++;
}
// Функция выделения памяти
void *alloc(uint64_t wanted_frames) {
void *ptr;
uint64_t available_frames = 0;
for (uint64_t frame = 1; frame < limit; frame++) {
if (!BIT_GET(frame)) {
available_frames++;
} else if (available_frames != wanted_frames) {
available_frames = 0;
continue;
}
if (available_frames == wanted_frames) {
uint64_t i;
for (i = 0; i < wanted_frames; i++) { BIT_SET(frame - i); }
frame -= i - 1;
ptr = (void *)(BLOCK_SIZE * frame);
return ptr;
}
}
return NULL;
}
void *calloc(uint64_t frames) {
void *ptr = alloc(frames);
tool::memset(ptr + HHDM_OFFSET, 0, frames * BLOCK_SIZE);
return ptr;
}
// Инициализация менеджера памяти
void init( ) {
// Получение информации о доступной памяти из Limine bootloader
memmap_response = memmap_request.response;
mmmap_count = memmap_response->entry_count;
struct limine_memmap_entry **mmaps = memmap_response->entries;
fb::printf("В карте памяти: %u записей.\n", memmap_response->entry_count);
// Обработка каждой записи в карте памяти
for (int i = 0; i < mmmap_count; i++) {
available += mmaps[i]->length;
// fb::printf("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
// mmaps[i]->base, mmaps[i]->length, memory_types[mmaps[i]->type]);
// Пропускаем записи, не являющиеся доступными памятью
if (!mmaps[i]->type == LIMINE_MEMMAP_USABLE) { continue; }
usable += mmaps[i]->length;
uint64_t top = mmaps[i]->base + mmaps[i]->length;
if (top > highest) highest = top;
}
limit = highest / BLOCK_SIZE;
uint64_t bitmap_size = ALIGN_UP(highest / BLOCK_SIZE / 8, BLOCK_SIZE);
// Находим доступное место для битовой карты и устанавливаем ее
for (uint64_t i = 0; i < mmmap_count; i++) {
if (!mmaps[i]->type == LIMINE_MEMMAP_USABLE) continue;
if (mmaps[i]->length >= bitmap_size) {
bitmap = (uint8_t *)mmaps[i]->base;
tool::memset(bitmap, 0xFF, bitmap_size);
mmaps[i]->length -= bitmap_size;
mmaps[i]->base += bitmap_size;
available -= bitmap_size;
break;
}
}
// Освобождаем все доступные фреймы памяти
for (uint64_t i = 0; i < mmmap_count; i++) {
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
bitmap_limit++;
}
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE ||
mmaps[i]->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE)) {
continue;
}
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
free((void *)mmaps[i]->base + t, 1);
}
}
fb::printf("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
usable / 1024 / 1024, available / 1024 / 1024);
fb::printf("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
fb::printf("Размер битовой карты: %u\n", bitmap_size);
}
} // namespace mem