Skip to content

Commit 74afaa6

Browse files
committed
mm: Implement page_frame_alloc/free
1 parent 57634c1 commit 74afaa6

2 files changed

Lines changed: 97 additions & 41 deletions

File tree

kernel/include/page_frame.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#include <multiboot.h>
66

77
int page_frame_init (multiboot_info_t *multiboot_info);
8-
uint32_t * page_frame_alloc (void);
9-
int page_frame_free (uint32_t *page_addr);
8+
void * page_frame_alloc (void);
9+
void page_frame_free (void *page_addr);
1010
void page_frame_dump_map (void);
1111

1212
#endif /* end of include guard: PAGE_FRAME_ALLOC_H_S1KP2ELH */

kernel/mm/page_frame.c

Lines changed: 95 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,69 @@
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;
2114
static int num_frames = 0;
2215
static int num_frames_bitset_lines = 0;
2316
static 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

4651
static 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

5559
int 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

Comments
 (0)