aboutsummaryrefslogtreecommitdiff
path: root/kernel/mm/physical_mm/physical_mm.c
blob: 407aad6e3abda46b17bcb88f7a89a6706f6ebfe6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* Bitmap Based Allocation:
 * https://web.archive.org/web/20190316115948/http://www.brokenthorn.com/Resources/OSDev17.html
 */

#include <stdbool.h>
#include <stdint.h>

#include <libk/stdio.h>

#include <mm/memory_map.h>
#include <mm/physical_mm.h>

#include <kernel/halt.h>

extern uint32_t kernel_start;
extern uint32_t kernel_end;

uint32_t block_count;
uint32_t *memory_map;

void
physical_mm_init(void)
{
  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",
           "start: 0x%.08x | length: 0x%.08x",
           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",
         ((uint32_t) &kernel_end) - ((uint32_t) &kernel_start));
}

ALWAYS_INLINE void
physical_mm_set(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)
{
  uint32_t memory_map_index = bit / BITMAP_ENTRY_SIZE;
  uint32_t bitmask = 1 << (bit % BITMAP_ENTRY_SIZE);
  memory_map[memory_map_index] &= ~bitmask;
}

/* Returns:
 * True if the bit is unset (block isn't in use)
 * False if the bit is used (block is in use)
 */
ALWAYS_INLINE bool
physical_mm_test_bit(const uint32_t bit)
{
  uint32_t memory_map_index = bit / BITMAP_ENTRY_SIZE;
  uint32_t bitmask = 1 << (bit % BITMAP_ENTRY_SIZE);
  return memory_map[memory_map_index] & bitmask;
}

uint32_t
physical_mm_find_first_free(void)
{
  for (uint32_t i = 0; i < block_count / BITMAP_ENTRY_SIZE; i++)
    /* All blocks in the entry aren'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;
}