11#include <include/mm/alloc.h>
2+ #include <include/kernel/logger.h>
3+ #include <include/helpers.h>
24#include <string.h>
35#include <stdint.h>
46
7+ const uint32_t PAGE_SIZE = 4 * 1024 * 1024 ;
8+ const uint32_t NUM_FRAMES = 1024 ;
9+ static const uint32_t PRESENT = 0x1 ;
10+ static const uint32_t READ_WRITE = 0x2 ;
11+ static const uint32_t PAGE_MB = 1 << 7 ;
12+
13+ // Maximum number of frames is 1024 / 32 = 32, so -1 is a valid error number.
14+ static const uint32_t PAGE_ERR = (uint32_t ) -1 ;
15+
516// The current physical memory offset we are allocating in memory. This is a very simple allocator
617// and as such only allocates memory, and never frees it, and so this only ever increases.
7- uint32_t ALLOC_PHYSICAL_ADDRESS_OFFSET ;
8-
9- static const uint32_t PAGE_ALIGNED = 0xFFFFF000 ;
10- static const uint32_t STACK_SIZE = 16 * 1024 * 1024 ;
18+ static uint32_t physical_address_offset ;
19+ static uint32_t * page_directory ;
20+ static uint32_t alloc_bitmap [NUM_FRAMES / 32 ];
1121
1222extern uint32_t PHYSICAL_MEMORY_START ;
1323extern uint32_t PHYSICAL_MEMORY_END ;
1424
25+ static uint32_t index_of (uint32_t frame ) {
26+ return frame / 32 ;
27+ }
28+
29+ static uint32_t first_free_frame () {
30+ // For each bitmapped frame entry
31+ for (uint32_t i = 0 ; i < index_of (NUM_FRAMES ); i ++ ) {
32+ // If all bits are set, then there is nothing here for us
33+ if (alloc_bitmap [i ] != 0xFFFFFFFF ) {
34+ // We know that at least one bit is free, find it
35+ for (uint32_t j = 0 ; j < 32 ; j ++ ) {
36+ uint32_t bit = 0x1 << j ;
37+ // If the bit to test for is unset, we found our entry
38+ if (!(alloc_bitmap [i ] & bit )) {
39+ return i * 32 + j ;
40+ }
41+ }
42+ }
43+ }
44+
45+ return PAGE_ERR ;
46+ }
47+
48+ static void debug_pd (uint32_t idx ) {
49+ uint32_t cr3 ;
50+ asm volatile ("mov %%cr3, %0" : "=r" (cr3 ));
51+ uint32_t * pd = (uint32_t * ) (cr3 + 0xC0000000 );
52+ uint32_t pde = pd [idx ];
53+
54+ uint32_t frame_addr = (pde & 0xFFFFF000 );
55+ bool present = pde & PRESENT ;
56+ bool rw = pde & READ_WRITE ;
57+ bool sz = pde & PAGE_MB ;
58+
59+ KLOG ("PDE #%d: addr:%x,present:%d,rw:%d,sz:%d" , idx , frame_addr , present , rw , sz );
60+ }
61+
1562void alloc_init () {
16- ALLOC_PHYSICAL_ADDRESS_OFFSET = PHYSICAL_MEMORY_START + STACK_SIZE ;
63+ // Zero necessary fields
64+ physical_address_offset = 0 ;
65+ memset (alloc_bitmap , 0 , index_of (NUM_FRAMES ) * sizeof (uint32_t ));
66+
67+ // The kernel directory set in page directory neds to get set
68+ BITMAP_SET (alloc_bitmap , 0 );
69+
70+
71+ // Obtain the bootstrap page directory stored in CR3 register.
72+ uint32_t cr3 ;
73+ asm volatile ("mov %%cr3, %0" : "=r" (cr3 ));
74+ page_directory = (uint32_t * ) (cr3 + 0xC0000000 );
75+ KLOG ("Address of Page Directory: %x" , cr3 );
1776}
1877
19- paddr_t alloc (size_t size , uint32_t * phys_addr , bool aligned ) {
20- // If we need to align it, we need to ensure the pointer is on a 4KB boundary
21- if (aligned && (ALLOC_PHYSICAL_ADDRESS_OFFSET & ~PAGE_ALIGNED )) {
22- ALLOC_PHYSICAL_ADDRESS_OFFSET &= PAGE_ALIGNED ;
23- ALLOC_PHYSICAL_ADDRESS_OFFSET += 0x1000 ;
78+ vaddr_t alloc_block () {
79+ // Obtain the first free frame by cycling through all possible frames for one without it's PRESENT bit set.
80+ bool found = false;
81+ for (int i = 0 ; i < 1024 ; i ++ ) {
82+ uint32_t idx = (physical_address_offset / PAGE_SIZE ) % NUM_FRAMES ;
83+ if (!(page_directory [idx ] & PRESENT )) {
84+ uint32_t frame_idx = first_free_frame ();
85+ KLOG ("Allocation: PDE #%d, Index: %d, Physical Address: %x, Virtual Address: %x" , idx , frame_idx , frame_idx * PAGE_SIZE , physical_address_offset );
86+
87+ // Out of Memory
88+ if (frame_idx == PAGE_ERR ) {
89+ KPANIC ("Could not find a free physical address!" );
90+ }
91+
92+ // Claim the frame
93+ BITMAP_SET (alloc_bitmap , frame_idx );
94+
95+ // Mark frame as present and invalidate for TLB
96+ page_directory [idx ] = (frame_idx * PAGE_SIZE ) | PAGE_MB | PRESENT | READ_WRITE ;
97+ asm volatile ("invlpg (%0)" :: "b" (physical_address_offset ) : "memory" );
98+
99+
100+ debug_pd (idx );
101+ // Exit early
102+ found = true;
103+ break ;
104+ }
105+
106+ physical_address_offset += PAGE_SIZE ;
24107 }
25108
26- // If the user wants the actual physical address...
27- if (phys_addr ) {
28- * phys_addr = ALLOC_PHYSICAL_ADDRESS_OFFSET ;
109+ // Out of Memory
110+ if (! found ) {
111+ KPANIC ( "Could not find a free virtual address!" ) ;
29112 }
30113
31- uint32_t retval = ALLOC_PHYSICAL_ADDRESS_OFFSET ;
32- ALLOC_PHYSICAL_ADDRESS_OFFSET += size ;
114+ uint32_t retval = physical_address_offset ;
115+ physical_address_offset += PAGE_SIZE ;
33116
34- // Clear the memory allocated for the user
35- memset ((void * ) retval , 0 , size );
117+ // Clear the memory allocated frame for the user
118+ memset ((void * ) retval , 0 , PAGE_SIZE );
36119 return retval ;
37120}
0 commit comments