18 #include <boot/multiboot.h> 20 #define PAGE_SIZE 4096 22 #define MEMORY_SIZE 0x100000000 24 #define PAGE_NUMBER (MEMORY_SIZE / PAGE_SIZE) 26 #define PAGES_PER_DWORD (32 / TYPE_BITS) 27 #define PAGES_BER_BYTE (8 / TYPE_BITS) 28 #define TYPE_MASK (0xFFFFFFFF >> (32 - TYPE_BITS)) 29 #define BITMAP_INIT 0x55555555 31 #define BIT_CHECK(val, bit) (((val) >> (bit)) & 1) 33 #define BITMAP_SET(idx) (bitmap[(idx) / 32] |= 1 << ((idx) % 32)) 35 #define BITMAP_CLEAR(idx) (bitmap[(idx) / 32] &= ~(1 << ((idx) % 32))) 79 logln(
"PMM",
"Kernel memory:");
88 print(
"PMM init ... ");
91 if (!multiboot_free_memory()) {
92 println(
"%4afail%a. Memory map not found.");
99 logln(
"PMM",
"Use the first megabyte for VM86");
106 multiboot_copy_memory();
109 pmm_use((
void*) MULTIBOOT_LOWER_MEMORY,
110 MULTIBOOT_FIRST_PAGE_TABLE - MULTIBOOT_LOWER_MEMORY, PMM_UNUSED, 0);
121 return ((uintptr_t) ptr + offset) >>
PAGE_SHIFT;
131 return (
void*) ((page <<
PAGE_SHIFT) + offset);
142 if (len == 0)
return;
144 log(
"PMM",
"%s %08x-%08x (page %05x-%05x)", flags == PMM_UNUSED ?
"Free" :
"Use ",
145 ptr, ptr + len - 1, start_page, end_page);
147 log(0,
" for %s", tag);
149 for (
int i = start_page; i <= end_page; i++)
161 if (len == 0)
return 0;
169 if (free_pages >= pages)
173 println(
"%4aPMM: Not enough memory%a");
187 pmm_use(ptr, len, flags,
"pmm_alloc");
197 if (len == 0)
return;
198 pmm_use(ptr, len, PMM_UNUSED, 0);
216 if (len == 0)
return;
218 log(
"PMM",
"Memory bitmap from page %05x to %05x:", start_page, end_page);
219 for (
int i = start_page; i <= end_page; i++) {
220 if ((i - start_page) % 64 == 0) {
221 uint32_t kilobytes = i *
PAGE_SIZE / 1024;
222 logln(0,
""), log(
"PMM",
"[%7d%cB] ",
223 kilobytes % 1024 == 0 ? kilobytes / 1024 : kilobytes,
224 kilobytes % 1024 == 0 ?
'M' :
'K');
static uint32_t highest_kernel_page
remember the highest kernel page
#define PAGE_SIZE
4KB pages
#define PAGE_NUMBER
total number of pages
#define ENTRIES
number of entries in a page table
#define BIT_CHECK(val, bit)
checks a bit in a given value
void pmm_free(void *ptr, size_t len)
Frees page frames.
static uint32_t pmm_bitmap_get(uint32_t idx)
Returns a bitmap entry.
void pmm_init()
Initializes the PMM.
void pmm_dump(void *ptr, size_t len)
Dumps information on page frames for a given memory range.
static void pmm_bitmap_set(uint32_t idx, uint32_t value)
Sets a bitmap entry to a value.
#define TYPE_MASK
calc 2^TYPE_BITS-1
uint32_t pmm_get_page(void *ptr, uint32_t offset)
Returns to which page a given memory address belongs.
#define PAGE_SHIFT
bits to shift to get page (2^12=4096)
pmm_flags_t pmm_check(void *ptr)
Returns whether a page frame is used or unused.
static uint32_t bitmap[PAGE_NUMBER/PAGES_PER_DWORD]
Holds information on used page frames.
#define BITMAP_SET(idx)
sets a bit in the memory bitmap
pmm_flags_t
information on who uses a page frame (needs to fit in TYPE_BITS)
static void pmm_use_kernel_memory()
Marks all kernel memory as used.
const void kernel_end
end of the kernel section
void pmm_use(void *ptr, size_t len, pmm_flags_t flags, char *tag)
Marks page frames for a given memory range as used or unused.
static void * pmm_find_free(size_t len)
Finds free page frames.
#define BITMAP_INIT
0b0101...01, use PMM_RESERVED
void * pmm_alloc(size_t len, pmm_flags_t flags)
Allocates page frames.
#define PAGES_BER_BYTE
pages per bitmap entry byte
#define BITMAP_CLEAR(idx)
clears a bit in the memory bitmap
uint32_t pmm_get_highest_kernel_page()
Returns the highest page used by the kernel.
const void main_kernel_stack_end
end of the main kernel stack
#define PAGES_PER_DWORD
pages in each bitmap entry
#define TYPE_BITS
number of bits per page entry
void * pmm_get_address(uint32_t page, uint32_t offset)
Returns a memory address belonging to a given page.
const void kernel_start
start of the kernel section
static void * main_kernel_stack_start
start of the main kernel stack