22#include <page_frame.h>
33#include <multiboot.h>
44#include <logger.h>
5+ #include <string.h>
56
6- /* TODO: These don't belong here */
7- #define BITS_PER_BYTE 4
8- #define NUM_OF_A_PER_B (A , B ) (( (A + B) / (B + 1) ) + 1)
7+ /* TODO: This doesn't belong here */
8+ #define NUM_OF_A_PER_B (A , B ) ((A + B - 1) / B)
99
10- static void memset (const void * base_addr , int c , size_t size )
11- {
12- for (int i = 0 ; i < 20 ; i ++ ) {
13- * ((int * )base_addr + i ) = c ;
14- }
15- }
10+ static char * memory_base_addr ;
1611
17- #define BLOCK_SIZE 1024 /* 1kb */
18- #define FRAME_SIZE 4096 /* 4kb */
12+ static uint32_t * frames_bitset = NULL ;
1913
20- static uint32_t * frames_bitset = 0x0 ;
2114static int num_frames = 0 ;
2215static int num_frames_bitset_lines = 0 ;
2316static int num_frames_bitset_frames = 0 ;
2417
25- #define FRAMES_PER_BITSET_LINE (BITS_PER_BYTE * sizeof(*frames_bitset))
26- #define BITSET_LINES_PER_FRAME (FRAME_SIZE / sizeof(*frames_bitset))
18+ #define BLOCK_SIZE 1024 /* 1kb */
19+ #define FRAME_SIZE 4096 /* 4kb */
20+
21+ #define FRAMES_PER_BITSET (8 * sizeof(*frames_bitset))
22+ #define BITSET_LINES_PER_FRAME (FRAME_SIZE / sizeof(*frames_bitset))
23+
24+ #define FRAME_NUM_TO_PAGE_ADDR (NUM ) (NUM << 12)
25+
26+ #define FRAME_LINE_TO_PAGE_NUM (LINE ) (LINE << 5)
2727
28- #define PAGE_ADDR_TO_LINE (ADDR ) (ADDR / FRAMES_PER_BITSET_LINE)
29- #define PAGE_ADDR_TO_BIT (ADDR ) (0x1 << (ADDR % FRAMES_PER_BITSET_LINE))
28+ #define PAGE_ADDR_TO_FRAME_NUM (ADDR ) ((unsigned long)ADDR >> 12)
29+ #define PAGE_ADDR_TO_LINE (ADDR ) \
30+ (((unsigned long)ADDR >> 12) / FRAMES_PER_BITSET)
31+ #define PAGE_ADDR_TO_BIT (ADDR ) \
32+ (0x1 << (PAGE_ADDR_TO_FRAME_NUM(ADDR) % FRAMES_PER_BITSET))
3033
31- #define PAGE_NUM_TO_ADDR_OFFSET (NUM ) (NUM * FRAME_SIZE)
3234
33- static inline void page_frame_mark_free (uint64_t base_addr )
35+ static inline void page_frame_mark_free (void * base_addr )
3436{
3537 frames_bitset [PAGE_ADDR_TO_LINE (base_addr )] |= PAGE_ADDR_TO_BIT (base_addr );
3638}
3739
38- static inline void page_frame_mark_n_free (uint64_t base_addr , int num_pages )
40+ static inline void page_frame_mark_n_free (void * base_addr , size_t len )
3941{
4042 /* TODO: Optimize to mark bitset in one go */
41- for (int i = 0 ; i < num_pages ; i ++ ) {
42- page_frame_mark_free (base_addr + i );
43+ char * addr = base_addr ;
44+ char * end_addr = addr + len ;
45+ while (addr < end_addr ) {
46+ page_frame_mark_free (addr );
47+ addr += FRAME_SIZE ;
4348 }
4449}
4550
4651static inline void frames_bitset_init (void * base_addr )
4752{
48- /* TODO: Figure out pointer size stuff. This is arch dependant */
4953 frames_bitset = base_addr ;
5054
5155 /* We assume that num_frames et al. are initialized before calling this */
52- memset (frames_bitset , 0 , num_frames_bitset_frames * FRAME_SIZE );
56+ memset (frames_bitset , 0 , num_frames_bitset_lines * sizeof ( * frames_bitset ) );
5357}
5458
5559int page_frame_init (multiboot_info_t * multiboot_info )
5660{
5761 int bitset_initialized = 0 ;
5862
63+ memory_base_addr = 0x0 ;
64+
5965 num_frames = (multiboot_info -> mem_lower + multiboot_info -> mem_upper ) /
6066 (FRAME_SIZE / BLOCK_SIZE );
61- num_frames_bitset_lines = NUM_OF_A_PER_B (num_frames , FRAMES_PER_BITSET_LINE );
67+ num_frames_bitset_lines = NUM_OF_A_PER_B (num_frames , FRAMES_PER_BITSET );
6268 num_frames_bitset_frames =
6369 NUM_OF_A_PER_B (num_frames_bitset_lines , BITSET_LINES_PER_FRAME );
6470
@@ -70,19 +76,17 @@ int page_frame_init(multiboot_info_t *multiboot_info)
7076 FOREACH_MEMORY_MAP (mmap , multiboot_info ) {
7177 if (mmap -> type == MULTIBOOT_MEM_TYPE_FREE ) {
7278 if (!bitset_initialized ) {
73- frames_bitset_init ((void * )(unsigned long )
74- types_concat (mmap -> base_addr_high , mmap -> base_addr_low ));
79+ frames_bitset_init ((void * )(unsigned long )mmap -> base_addr_low );
7580
7681 /* reserve "num_frames_bitset_pages" pages for the frames_bitset */
77- page_frame_mark_n_free (
78- types_concat ( mmap -> base_addr_high , mmap -> base_addr_low ) +
79- PAGE_NUM_TO_ADDR_OFFSET (num_frames_bitset_frames ),
80- types_concat ( mmap -> len_high , mmap -> len_low ) / FRAME_SIZE );
82+ page_frame_mark_n_free (( void * )( unsigned long )
83+ mmap -> base_addr_low
84+ + FRAME_NUM_TO_PAGE_ADDR (num_frames_bitset_frames ),
85+ mmap -> len_low - FRAME_NUM_TO_PAGE_ADDR ( num_frames_bitset_frames ) );
8186 bitset_initialized = 1 ;
8287 } else {
83- page_frame_mark_n_free (
84- types_concat (mmap -> base_addr_high , mmap -> base_addr_low ),
85- types_concat (mmap -> len_high , mmap -> len_low ) / FRAME_SIZE );
88+ page_frame_mark_n_free ((void * )(unsigned long )mmap -> base_addr_low ,
89+ mmap -> len_low );
8690 }
8791 }
8892 }
@@ -92,24 +96,76 @@ void page_frame_dump_map(void)
9296{
9397#ifdef DEBUG
9498 uint32_t * frame = frames_bitset ;
95- klog (LOG_DEBUG , "frame_bitset addr: 0x%x\n" , frame );
96- for (int j = 0 ; j < num_frames_bitset_frames * num_frames_bitset_lines ; j ++ ) {
97- for (int k = 0 ; k < FRAMES_PER_BITSET_LINE ; k ++ ) {
99+ klog (LOG_DEBUG , "frames_bitset addr: 0x%x\n" , frame );
100+ for (int j = 0 ; j < num_frames_bitset_lines ; j ++ ) {
101+ klog (LOG_DEBUG , "\n%x: " , FRAME_NUM_TO_PAGE_ADDR (j * FRAMES_PER_BITSET ));
102+ for (int k = 0 ; k < FRAMES_PER_BITSET ; k ++ ) {
98103 if (frame [j ] & (0x1 << k )) { /* free */
99104 klog (LOG_DEBUG , "." );
100105 } else {
101106 klog (LOG_DEBUG , "#" );
102107 }
103108 }
104- klog (LOG_DEBUG , "%c" , (j + 1 ) % 4 ? ' ' : '\n' );
105109 }
110+ klog (LOG_DEBUG , "\n" );
106111#endif
107112}
108113
109- uint32_t * page_frame_alloc (void )
114+ void * page_frame_alloc (void )
110115{
116+ static uint32_t current_frame_bitset_line = 0 ;
117+ static uint32_t current_frame_bitset_bit = 0 ;
118+
119+ klog (LOG_DEBUG , "page_frame_alloc: Allocating frame " );
120+
121+ /* go to next free frame line */
122+ while (frames_bitset [current_frame_bitset_line ] == 0 ) {
123+ klog (LOG_DEBUG , "x" );
124+ current_frame_bitset_bit = 0 ;
125+ current_frame_bitset_line ++ ;
126+ if (current_frame_bitset_line == num_frames_bitset_lines ) {
127+ /* wrap around */
128+ current_frame_bitset_line = 0 ;
129+ }
130+ }
131+ uint32_t * current_bitset_line = & frames_bitset [current_frame_bitset_line ];
132+
133+ /* go to next free frame bit */
134+ uint32_t current_bitset = 0x1 << current_frame_bitset_bit ;
135+ while ((* current_bitset_line & current_bitset ) == 0 ) {
136+ klog (LOG_DEBUG , "#" );
137+ current_bitset = current_bitset << 1 ;
138+ current_frame_bitset_bit ++ ;
139+ if (current_frame_bitset_bit == FRAMES_PER_BITSET ) {
140+ /* wrap around */
141+ current_frame_bitset_bit = 0 ;
142+ current_bitset = 0x1 ;
143+ }
144+ }
145+
146+ /* mark as used */
147+ * current_bitset_line ^= current_bitset ;
148+
149+ void * frame_address = (memory_base_addr + FRAME_NUM_TO_PAGE_ADDR (
150+ FRAME_LINE_TO_PAGE_NUM (current_frame_bitset_line )
151+ + current_frame_bitset_bit ));
152+ klog (LOG_DEBUG , ". at 0x%x\n" , frame_address );
153+
154+ return frame_address ;
111155}
112156
113- int page_frame_free (uint32_t * page_addr )
157+ void page_frame_free (void * page_addr )
114158{
159+ uint32_t line = PAGE_ADDR_TO_LINE (page_addr );
160+ uint32_t bit = PAGE_ADDR_TO_BIT (page_addr );
161+
162+ if ((frames_bitset [line ] & bit )) {
163+ klog (LOG_WARN ,
164+ "page_frame_free: Attempt to free unallocated address at 0x%x\n" ,
165+ page_addr );
166+ return ;
167+ }
168+
169+ klog (LOG_DEBUG , "page_frame_free: Freeing frame at 0x%x\n" , page_addr );
170+ page_frame_mark_free (page_addr );
115171}
0 commit comments