Skip to content

Commit 8ae3c54

Browse files
committed
pmm: dynamically allocate space for frame_t structures
Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
1 parent 321fc96 commit 8ae3c54

File tree

2 files changed

+179
-9
lines changed

2 files changed

+179
-9
lines changed

include/mm/pmm.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ struct frame {
4444
};
4545
typedef struct frame frame_t;
4646

47+
struct frames_array_meta {
48+
uint32_t free_count;
49+
} __packed;
50+
typedef struct frames_array_meta frames_array_meta_t;
51+
52+
struct frames_array {
53+
struct list_head list;
54+
frames_array_meta_t meta;
55+
frame_t frames[(PAGE_SIZE - sizeof(frames_array_meta_t)) / sizeof(frame_t)];
56+
} __packed;
57+
typedef struct frames_array frames_array_t;
58+
4759
#define for_each_order(order) for (int order = 0; order < MAX_PAGE_ORDER + 1; order++)
4860

4961
typedef bool (*free_frames_cond_t)(frame_t *free_frame);
@@ -85,6 +97,13 @@ static inline bool is_frame_used(const frame_t *frame) {
8597
return frame && frame->refcount > 0;
8698
}
8799

100+
static inline bool is_frame_free(const frame_t *frame) {
101+
if (is_frame_used(frame))
102+
return false;
103+
104+
return frame->flags.free;
105+
}
106+
88107
#endif /* __ASSEMBLY__ */
89108

90109
#endif /* KTF_PMM_H */

mm/pmm.c

Lines changed: 160 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030

3131
size_t total_phys_memory;
3232

33+
static list_head_t frames;
34+
static unsigned long total_free_frames = 0;
35+
#define MIN_FREE_FRAMES_THRESHOLD 2
36+
#define MAX_FREE_FRAMES_THRESHOLD (2 * ARRAY_SIZE(memberof(frames_array_t, frames)))
37+
static frames_array_t early_frames;
38+
3339
static list_head_t free_frames[MAX_PAGE_ORDER + 1];
3440
static list_head_t busy_frames[MAX_PAGE_ORDER + 1];
3541

36-
static frame_t early_frames[2 * PAGE_SIZE];
37-
static unsigned int free_frame_idx;
38-
3942
static size_t frames_count[MAX_PAGE_ORDER + 1];
4043

4144
static spinlock_t lock = SPINLOCK_INIT;
@@ -51,15 +54,159 @@ void display_frames_count(void) {
5154
}
5255
}
5356

54-
static inline frame_t *new_frame(mfn_t mfn, unsigned int order) {
55-
frame_t *frame = &early_frames[free_frame_idx++];
57+
static inline void init_frame(frame_t *frame) {
58+
ASSERT(frame);
59+
60+
memset(frame, 0, sizeof(*frame));
61+
frame->order = PAGE_ORDER_INVALID;
62+
frame->flags.free = true;
63+
}
64+
65+
static inline void init_frames_array(frames_array_t *array) {
66+
memset(array, 0, sizeof(*array));
67+
array->meta.free_count = ARRAY_SIZE(array->frames);
68+
for (unsigned i = 0; i < ARRAY_SIZE(array->frames); i++)
69+
init_frame(&array->frames[i]);
70+
list_add(&array->list, &frames);
71+
}
72+
73+
static frames_array_t *new_frames_array(void) {
74+
frame_t *frame = get_free_frame();
75+
frames_array_t *array;
76+
77+
if (!frame)
78+
panic("PMM: Unable to allocate new frame for frame array\n");
79+
80+
array = (frames_array_t *) mfn_to_virt_kern(frame->mfn);
81+
init_frames_array(array);
82+
83+
dprintk("%s: allocated new frames array: %p\n", __func__, array);
84+
85+
total_free_frames += array->meta.free_count;
86+
return array;
87+
}
88+
89+
static void del_frames_array(frames_array_t *array) {
90+
ASSERT(array);
91+
92+
list_unlink(&array->list);
93+
total_free_frames -= array->meta.free_count;
94+
put_free_frame(virt_to_mfn(array));
95+
96+
dprintk("%s: freed frames array: %p\n", __func__, array);
97+
}
98+
99+
static bool is_frames_array_free(const frames_array_t *array) {
100+
ASSERT(array);
101+
102+
if (array->meta.free_count < ARRAY_SIZE(array->frames))
103+
return false;
104+
else if (array->meta.free_count > ARRAY_SIZE(array->frames))
105+
panic("PMM: incorrect number of free slots: %d in array: %p\n",
106+
array->meta.free_count, array);
107+
108+
for (unsigned i = 0; i < ARRAY_SIZE(array->frames); i++) {
109+
const frame_t *frame = &array->frames[i];
110+
111+
if (!is_frame_free(frame))
112+
panic("PMM: found occupied slot in an empty array: %p\n", array);
113+
}
114+
115+
return true;
116+
}
117+
118+
static inline frames_array_t *get_frames_array(void) {
119+
frames_array_t *array;
120+
121+
list_for_each_entry (array, &frames, list) {
122+
if (array->meta.free_count > 0)
123+
return array;
124+
}
125+
126+
return new_frames_array();
127+
}
128+
129+
static inline bool put_frames_array(frames_array_t *array) {
130+
if (is_frames_array_free(array)) {
131+
del_frames_array(array);
132+
return true;
133+
}
134+
135+
return false;
136+
}
56137

57-
if (free_frame_idx > ARRAY_SIZE(early_frames))
58-
panic("Not enough initial frames for PMM allocation!\n");
138+
static inline frames_array_t *find_frames_array(const frame_t *frame) {
139+
frames_array_t *array;
140+
mfn_t frame_mfn = virt_to_mfn(frame);
141+
142+
list_for_each_entry (array, &frames, list) {
143+
if (virt_to_mfn(array) == frame_mfn)
144+
return array;
145+
}
146+
147+
return NULL;
148+
}
149+
150+
static inline frame_t *take_frame(frame_t *frame, frames_array_t *array) {
151+
ASSERT(frame);
152+
153+
if (!array)
154+
array = find_frames_array(frame);
155+
BUG_ON(!array);
156+
157+
frame->flags.free = false;
158+
array->meta.free_count--;
159+
160+
if (--total_free_frames <= MIN_FREE_FRAMES_THRESHOLD)
161+
new_frames_array();
162+
163+
return frame;
164+
}
165+
166+
static inline frame_t *put_frame(frame_t *frame, frames_array_t *array) {
167+
ASSERT(!frame);
168+
169+
if (!array)
170+
array = find_frames_array(frame);
171+
BUG_ON(!array);
172+
173+
array->meta.free_count++;
174+
175+
if (++total_free_frames >= MAX_FREE_FRAMES_THRESHOLD)
176+
put_frames_array(array);
177+
178+
init_frame(frame);
179+
return frame;
180+
}
181+
182+
static inline frame_t *get_frames_array_entry(void) {
183+
frames_array_t *array = get_frames_array();
184+
185+
if (!array)
186+
panic("PMM: Unable to get a free array of frames' metadata\n");
187+
188+
for (unsigned i = 0; i < ARRAY_SIZE(array->frames); i++) {
189+
frame_t *frame = &array->frames[i];
190+
191+
if (is_frame_free(frame))
192+
return take_frame(frame, array);
193+
}
194+
195+
return NULL;
196+
}
197+
198+
static inline void put_frames_array_entry(frame_t *frame) {
199+
if (is_frame_free(frame))
200+
return;
201+
202+
put_frame(frame, NULL);
203+
}
204+
205+
static inline frame_t *new_frame(mfn_t mfn, unsigned int order) {
206+
frame_t *frame = get_frames_array_entry();
59207

60208
frame->order = order;
61209
frame->mfn = mfn;
62-
frame->flags.free = true;
63210

64211
frames_count[order]++;
65212
return frame;
@@ -158,7 +305,11 @@ void reclaim_frame(mfn_t mfn, unsigned int order) { add_frame(mfn, order); }
158305
void init_pmm(void) {
159306
printk("Initialize Physical Memory Manager\n");
160307

161-
BUG_ON(ARRAY_SIZE(free_frames) != ARRAY_SIZE(busy_frames));
308+
BUILD_BUG_ON(sizeof(frames_array_t) > PAGE_SIZE);
309+
list_init(&frames);
310+
init_frames_array(&early_frames);
311+
312+
BUILD_BUG_ON(ARRAY_SIZE(free_frames) != ARRAY_SIZE(busy_frames));
162313
for_each_order (order) {
163314
list_init(&free_frames[order]);
164315
list_init(&busy_frames[order]);

0 commit comments

Comments
 (0)