feat: pmm
This commit is contained in:
parent
fd6ae9ddc9
commit
cf6ab74375
5 changed files with 134 additions and 20 deletions
|
@ -32,6 +32,7 @@ void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) {
|
||||||
debug$("%s (start: %x, len: %x)", handover_tag_name(handover()->records[i].tag), handover()->records[i].start, handover()->records[i].size);
|
debug$("%s (start: %x, len: %x)", handover_tag_name(handover()->records[i].tag), handover()->records[i].start, handover()->records[i].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pmm_init();
|
||||||
kmain();
|
kmain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,111 @@
|
||||||
#include "mod.h"
|
|
||||||
#include <hal>
|
#include <hal>
|
||||||
|
#include <handover>
|
||||||
|
#include <helpers/mem.h>
|
||||||
#include <logger>
|
#include <logger>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
Pmm* pmm = NULL;
|
#include "mod.h"
|
||||||
|
|
||||||
void pmm_init(size_t start, size_t len) {
|
static PmmBitmap bitmap = {0};
|
||||||
(void)start;
|
|
||||||
(void)len;
|
static bool bitmap_is_bit_set(size_t bit) {
|
||||||
if (pmm != NULL) {
|
return bitmap.bitmap[bit / 8] & (1 << (bit % 8));
|
||||||
error$("PMM already initialized");
|
}
|
||||||
hal_brkpoint();
|
|
||||||
|
static void pmm_mark_free(uintptr_t base, size_t len) {
|
||||||
|
size_t start = align_up$(base, page_size()) / page_size();
|
||||||
|
size_t end = align_down$(base + len, page_size()) / page_size();
|
||||||
|
|
||||||
|
for (size_t i = start; i < end; i++) {
|
||||||
|
bitmap.bitmap[i / 8] &= ~(1 << (i % 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pmm_mark_used(uintptr_t base, size_t len) {
|
||||||
|
size_t start = align_up$(base, page_size()) / page_size();
|
||||||
|
size_t end = align_down$(base + len, page_size()) / page_size();
|
||||||
|
|
||||||
|
for (size_t i = start; i < end; i++) {
|
||||||
|
bitmap.bitmap[i / 8] |= 1 << (i % 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_init(void) {
|
||||||
|
HandoverPayload* hand = handover();
|
||||||
|
HandoverRecord last_entry;
|
||||||
|
HandoverRecord record;
|
||||||
|
|
||||||
|
for (size_t i = hand->count; i; i--) {
|
||||||
|
if (hand->records[i - 1].tag != HANDOVER_FILE) {
|
||||||
|
last_entry = hand->records[i - 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap.len = align_up$((last_entry.start + last_entry.size) / (page_size() * 8), page_size());
|
||||||
|
bitmap.last = 0;
|
||||||
|
debug$("Bitmap size: %d bytes", bitmap.len);
|
||||||
|
|
||||||
|
handover_foreach_record(hand, record) {
|
||||||
|
if (record.tag == HANDOVER_FREE && record.size >= bitmap.len) {
|
||||||
|
debug$("Bitmap base: %p", record.start);
|
||||||
|
bitmap.bitmap = (uint8_t*)record.start;
|
||||||
|
record.start += bitmap.len;
|
||||||
|
record.size -= bitmap.len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmap.bitmap == NULL) {
|
||||||
|
error$("Couldn't allocate bitmap");
|
||||||
|
hal_brkpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(bitmap.bitmap, 0xFF, bitmap.len);
|
||||||
|
|
||||||
|
handover_foreach_record(hand, record) {
|
||||||
|
if (record.tag == HANDOVER_FREE) {
|
||||||
|
pmm_mark_free(record.start, record.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysObj pmm_alloc(size_t len) {
|
||||||
|
size_t pages = align_up$(len, page_size()) / page_size();
|
||||||
|
|
||||||
|
static bool try_again = false;
|
||||||
|
size_t size = 0;
|
||||||
|
size_t start_index = 0;
|
||||||
|
|
||||||
|
for (size_t i = bitmap.last; i < bitmap.len * 8; i++) {
|
||||||
|
if (!bitmap_is_bit_set(i)) {
|
||||||
|
if (size == 0) {
|
||||||
|
start_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size++ == pages) {
|
||||||
|
pmm_mark_used(start_index * page_size(), pages * page_size());
|
||||||
|
bitmap.last = i + 1;
|
||||||
|
try_again = false;
|
||||||
|
return (PhysObj){.base = start_index * page_size(), .len = pages * page_size()};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!try_again) {
|
||||||
|
warn$("End of the bitmap reached, trying again");
|
||||||
|
try_again = true;
|
||||||
|
bitmap.last = 0;
|
||||||
|
return pmm_alloc(pages);
|
||||||
|
} else {
|
||||||
|
error$("Out of physical memory");
|
||||||
|
hal_brkpoint();
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free(PhysObj obj) {
|
||||||
|
pmm_mark_free(obj.base, obj.len);
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct _Page {
|
typedef struct
|
||||||
struct _Page* next;
|
{
|
||||||
uintptr_t addr;
|
size_t len;
|
||||||
} Page;
|
size_t last;
|
||||||
|
uint8_t* bitmap;
|
||||||
|
} PmmBitmap;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
size_t total_pages;
|
{
|
||||||
size_t free_pages;
|
size_t len;
|
||||||
Page* freelist;
|
uintptr_t base;
|
||||||
} Pmm;
|
} PhysObj;
|
||||||
|
|
||||||
void pmm_init(size_t start, size_t len);
|
struct pmm_alloc_param {
|
||||||
|
size_t pages;
|
||||||
|
bool low;
|
||||||
|
};
|
||||||
|
|
||||||
|
PhysObj pmm_alloc(size_t pages);
|
||||||
|
|
||||||
|
void pmm_init(void);
|
||||||
|
|
|
@ -130,6 +130,12 @@ typedef void HandoverEntry(
|
||||||
__VA_ARGS__ __VA_OPT__(, ){.tag = HANDOVER_END}, \
|
__VA_ARGS__ __VA_OPT__(, ){.tag = HANDOVER_END}, \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define handover_foreach_record(h, r) \
|
||||||
|
if ((h)->count > 0) \
|
||||||
|
for (size_t i = 0; \
|
||||||
|
i < (h)->count && (((r) = (h)->records[i]), 1); \
|
||||||
|
++i)
|
||||||
|
|
||||||
/* --- Utilities ------------------------------------------------------------ */
|
/* --- Utilities ------------------------------------------------------------ */
|
||||||
|
|
||||||
char const* handover_tag_name(HandoverTag tag);
|
char const* handover_tag_name(HandoverTag tag);
|
||||||
|
@ -156,4 +162,6 @@ char const* handover_str(HandoverPayload const* payload, uint32_t offset);
|
||||||
|
|
||||||
size_t handover_add_string(HandoverPayload* handover, char const* str);
|
size_t handover_add_string(HandoverPayload* handover, char const* str);
|
||||||
|
|
||||||
|
HandoverPayload* handover(void);
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
|
@ -9,5 +9,3 @@
|
||||||
#define mib$(x) (kib$(x) * 1024)
|
#define mib$(x) (kib$(x) * 1024)
|
||||||
|
|
||||||
#define gib$(x) (mib$(x) * 1024)
|
#define gib$(x) (mib$(x) * 1024)
|
||||||
|
|
||||||
#define pages$(x) (kib$(x * 4))
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue