aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/include/drivers/vga_text_buffer.h2
-rw-r--r--kernel/include/kernel/io.h4
-rw-r--r--kernel/include/mm/physical_mm.h15
-rw-r--r--kernel/mm/physical_mm/physical_mm.c93
4 files changed, 83 insertions, 31 deletions
diff --git a/kernel/include/drivers/vga_text_buffer.h b/kernel/include/drivers/vga_text_buffer.h
index de498a3..74b77b9 100644
--- a/kernel/include/drivers/vga_text_buffer.h
+++ b/kernel/include/drivers/vga_text_buffer.h
@@ -68,6 +68,6 @@ bool vga_text_buffer_is_initialized(void);
void vga_text_buffer_initialize(void);
void vga_text_buffer_write_char(const char);
void vga_text_buffer_write_string(const char *);
-void vga_text_buffer_printf(const char *string, ...);
+void vga_text_buffer_printf(const char *, ...);
#endif
diff --git a/kernel/include/kernel/io.h b/kernel/include/kernel/io.h
index f58bd2d..952784d 100644
--- a/kernel/include/kernel/io.h
+++ b/kernel/include/kernel/io.h
@@ -21,7 +21,7 @@
#include <stdint.h>
-uint8_t inb(uint16_t port);
-void outb(uint16_t port, uint8_t val);
+uint8_t inb(uint16_t);
+void outb(uint16_t, uint8_t);
#endif
diff --git a/kernel/include/mm/physical_mm.h b/kernel/include/mm/physical_mm.h
index 7bda283..8438286 100644
--- a/kernel/include/mm/physical_mm.h
+++ b/kernel/include/mm/physical_mm.h
@@ -23,20 +23,15 @@
#include <common.h>
-/*
- * A byte has 8 bits, hence we can store information for up to 8 blocks at a
- * time
- */
-#define BLOCKS_PER_BYTE 8
-
/* TODO: Update this to 2MiB when PAE is enabled */
-#define BLOCK_SIZE 4 * KiB
-
-#define BLOCK_ALIGN BLOCK_SIZE
+#define BLOCK_SIZE (4 * KiB)
#define BITMAP_ENTRY_SIZE 32
+/* TODO: This is the maximum number of blocks for a 4GiB system. */
+#define MAX_BLOCKS 1048576
+
void physical_mm_init(void);
-uint32_t mmap_find_first_free(void);
+uint32_t physical_mm_find_first_free_block(void);
#endif
diff --git a/kernel/mm/physical_mm/physical_mm.c b/kernel/mm/physical_mm/physical_mm.c
index 407aad6..5bbe1f7 100644
--- a/kernel/mm/physical_mm/physical_mm.c
+++ b/kernel/mm/physical_mm/physical_mm.c
@@ -2,6 +2,8 @@
* https://web.archive.org/web/20190316115948/http://www.brokenthorn.com/Resources/OSDev17.html
*/
+/* TODO: Stack based allocation? */
+
#include <stdbool.h>
#include <stdint.h>
@@ -15,15 +17,13 @@
extern uint32_t kernel_start;
extern uint32_t kernel_end;
-uint32_t block_count;
-uint32_t *memory_map;
+uint32_t block_count = 0;
+uint32_t total_free_blocks = 0;
+uint32_t memory_map[MAX_BLOCKS];
-void
-physical_mm_init(void)
+ALWAYS_INLINE static void
+physical_mm_log_memory_map(free_memory_regions_t *free_memory_regions)
{
- free_memory_regions_t *free_memory_regions = memory_map_get_free_regions();
-
- /* TODO: Initialize these free memory regions */
printk("\nphysical_mm", "Free Memory Regions:");
for (int i = 0; i < free_memory_regions->n_regions; i++)
printk("physical_mm",
@@ -31,36 +31,94 @@ physical_mm_init(void)
free_memory_regions->region_list[i]->addr_low,
free_memory_regions->region_list[i]->len_low);
- /* TODO: De-initialize region used by the kernel */
printk("\nphysical_mm", "Kernel region:");
printk("physical_mm", "Start: 0x%x", &kernel_start);
printk("physical_mm", "End: 0x%x", &kernel_end);
printk("physical_mm",
- "Size: 0x%x",
+ "Size: 0x%x",
((uint32_t) &kernel_end) - ((uint32_t) &kernel_start));
}
-ALWAYS_INLINE void
-physical_mm_set(const uint32_t bit)
+/* Marks the block as 'used' */
+ALWAYS_INLINE static void
+physical_mm_set_unusable(const uint32_t bit)
{
uint32_t memory_map_index = bit / BITMAP_ENTRY_SIZE;
uint32_t bitmask = 1 << (bit % BITMAP_ENTRY_SIZE);
memory_map[memory_map_index] |= bitmask;
}
-ALWAYS_INLINE void
-physical_mm_unset(const uint32_t bit)
+/* Marks the block as 'unused' */
+ALWAYS_INLINE static void
+physical_mm_set_usable(const uint32_t bit)
{
uint32_t memory_map_index = bit / BITMAP_ENTRY_SIZE;
uint32_t bitmask = 1 << (bit % BITMAP_ENTRY_SIZE);
memory_map[memory_map_index] &= ~bitmask;
}
+ALWAYS_INLINE static void
+physical_mm_initialize_region(uint32_t start, uint32_t length)
+{
+ /* Get the location of the start address in the bitmap */
+ uint32_t bit = start / BLOCK_SIZE;
+ uint32_t n_blocks = length / BLOCK_SIZE;
+
+ for (; n_blocks > 0; n_blocks--) {
+ physical_mm_set_usable(bit++);
+ total_free_blocks++;
+ }
+
+ /* First block is always unusable (first 64 KiB) */
+ physical_mm_set_unusable(0);
+}
+
+ALWAYS_INLINE static void
+physical_mm_deinitialize_region(uint32_t start, uint32_t length)
+{
+ uint32_t align = start / BLOCK_SIZE;
+ uint32_t n_blocks = length / BLOCK_SIZE;
+
+ if (length % BLOCK_SIZE > 0)
+ n_blocks++;
+
+ for (; n_blocks > 0; n_blocks--) {
+ physical_mm_set_unusable(align++);
+ total_free_blocks--;
+ }
+}
+
+void
+physical_mm_init(void)
+{
+ free_memory_regions_t *free_memory_regions = memory_map_get_free_regions();
+ physical_mm_log_memory_map(free_memory_regions);
+
+ /* All blocks are initially unusable */
+ for (uint32_t i = 0; i < MAX_BLOCKS; i++)
+ memory_map[i] = 0xffffffff;
+
+ uint32_t total_free_memory = 0;
+ for (int i = 0; i < free_memory_regions->n_regions; i++) {
+ multiboot_memory_map_t *region = free_memory_regions->region_list[i];
+ total_free_memory += region->len_low;
+ physical_mm_initialize_region(region->addr_low, region->len_low);
+ }
+
+ physical_mm_deinitialize_region((uint32_t) &kernel_start,
+ ((uint32_t) &kernel_end)
+ - ((uint32_t) &kernel_start));
+
+ block_count = total_free_memory / BLOCK_SIZE;
+ printk("\nphysical_mm", "Total blocks: 0x%x", block_count);
+ printk("physical_mm", "Total free blocks: 0x%x", total_free_blocks);
+}
+
/* Returns:
* True if the bit is unset (block isn't in use)
- * False if the bit is used (block is in use)
+ * False if the bit is set (block is in use)
*/
-ALWAYS_INLINE bool
+ALWAYS_INLINE static bool
physical_mm_test_bit(const uint32_t bit)
{
uint32_t memory_map_index = bit / BITMAP_ENTRY_SIZE;
@@ -69,16 +127,15 @@ physical_mm_test_bit(const uint32_t bit)
}
uint32_t
-physical_mm_find_first_free(void)
+physical_mm_find_first_free_block(void)
{
for (uint32_t i = 0; i < block_count / BITMAP_ENTRY_SIZE; i++)
- /* All blocks in the entry aren't in use */
+ /* At least one block in the entry isn't in use */
if (memory_map[i] != 0xffffffff)
/* Test each bit to see if it's zero */
for (uint32_t j = 0; j < BITMAP_ENTRY_SIZE; j++)
if (physical_mm_test_bit(i * BITMAP_ENTRY_SIZE + j))
return i * BITMAP_ENTRY_SIZE + j;
- ASSERT_NOT_REACHED();
return -1;
}