Skip to content

Commit e52279e

Browse files
sparchatuswipawel
authored andcommitted
multiboot,regions,pmm: reserve multiboot physical memory
Add a reserved regions feature to regions.c. Reserved memory regions are prohibited from being used as frames by pmm. Currently, the only reserved region is the multiboot memory. Signed-off-by: Sandro Rüegge <[email protected]>
1 parent fb882ca commit e52279e

File tree

6 files changed

+57
-1
lines changed

6 files changed

+57
-1
lines changed

arch/x86/boot/multiboot.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ void init_multiboot(unsigned long *addr, const char **cmdline) {
182182
}
183183
}
184184

185+
bool mbi_reserved_range(addr_range_t *reserved_range) {
186+
if (multiboot2_hdr == NULL)
187+
return false;
188+
189+
reserved_range->start = multiboot2_hdr;
190+
reserved_range->end = _ptr(_ul(multiboot2_hdr) + multiboot2_hdr_size);
191+
return true;
192+
}
193+
185194
void map_multiboot_areas(void) {
186195
paddr_t mbi_start = _paddr(multiboot2_hdr);
187196
vmap_range(mbi_start, multiboot2_hdr_size, L1_PROT_RO, VMAP_KERNEL | VMAP_IDENT);

include/mm/regions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ extern int get_memory_range(paddr_t pa, addr_range_t *r);
8989

9090
extern int get_avail_memory_range(unsigned index, addr_range_t *r);
9191
extern bool has_memory_range(paddr_t pa);
92+
extern bool in_reserved_range(paddr_t pa, size_t size);
9293

9394
extern void init_regions(void);
9495

include/multiboot.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ extern unsigned mbi_get_avail_memory_ranges_num(void);
297297
extern int mbi_get_avail_memory_range(unsigned index, addr_range_t *r);
298298
extern int mbi_get_memory_range(paddr_t pa, addr_range_t *r);
299299
extern bool mbi_has_framebuffer(void);
300+
extern bool mbi_reserved_range(addr_range_t *reserved_range);
300301
#endif /* __ASSEMBLY__ */
301302

302303
#endif /* KTF_MULTIBOOT_H */

include/multiboot2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ extern void map_multiboot_areas(void);
433433
extern unsigned mbi_get_avail_memory_ranges_num(void);
434434
extern int mbi_get_avail_memory_range(unsigned index, addr_range_t *r);
435435
extern int mbi_get_memory_range(paddr_t pa, addr_range_t *r);
436+
extern bool mbi_reserved_range(addr_range_t *reserved_range);
436437

437438
#endif /* __ASSEMBLY__ */
438439

mm/pmm.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,14 @@ static inline frame_t *new_frame(mfn_t mfn, unsigned int order) {
251251
}
252252

253253
static inline void add_early_frame(mfn_t mfn, unsigned int order) {
254+
BUG_ON(in_reserved_range(mfn_to_paddr(mfn), ORDER_TO_SIZE(order)));
254255
frame_t *frame = new_frame(mfn, order);
255256

256257
list_add(&frame->list, &free_frames[order]);
257258
}
258259

259260
static inline void add_frame(mfn_t mfn, unsigned int order) {
261+
BUG_ON(in_reserved_range(mfn_to_paddr(mfn), ORDER_TO_SIZE(order)));
260262
frame_t *frame = new_frame(mfn, order);
261263

262264
list_add_tail(&frame->list, &free_frames[order]);
@@ -302,12 +304,24 @@ static size_t process_memory_range(unsigned index, unsigned first_avail_region)
302304

303305
/* Add initial 4K frames for early memory. */
304306
while (cur < MB(EARLY_VIRT_MEM) && cur + PAGE_SIZE <= end) {
305-
add_early_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
307+
/* if the current region overlaps with the reserved region then we skip it */
308+
if (!in_reserved_range(cur, ORDER_TO_SIZE(PAGE_ORDER_4K))) {
309+
add_early_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
310+
}
306311
cur += ORDER_TO_SIZE(PAGE_ORDER_4K);
307312
}
308313

309314
while (cur + PAGE_SIZE <= end) {
310315
unsigned int order = PADDR_TO_ORDER(cur);
316+
317+
/* Choose the largest region not overlapping a reserved area */
318+
while (in_reserved_range(cur, ORDER_TO_SIZE(order))) {
319+
if (order == PAGE_ORDER_4K) {
320+
goto skip;
321+
}
322+
--order;
323+
}
324+
311325
if (order >= PAGE_ORDER_1G && cur + PAGE_SIZE_1G <= end) {
312326
add_frame(paddr_to_mfn(cur), PAGE_ORDER_1G);
313327
cur += ORDER_TO_SIZE(PAGE_ORDER_1G);
@@ -321,6 +335,7 @@ static size_t process_memory_range(unsigned index, unsigned first_avail_region)
321335
}
322336

323337
add_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
338+
skip:
324339
cur += ORDER_TO_SIZE(PAGE_ORDER_4K);
325340
}
326341

mm/regions.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ addr_range_t addr_ranges[] = {
7070
{0x0} /* NULL array terminator */
7171
};
7272

73+
static unsigned regions_reserved_num;
74+
75+
#define MAX_RESERVED_RANGES 1
76+
static addr_range_t reserved_ranges[MAX_RESERVED_RANGES];
77+
7378
void display_memory_map(void) {
7479
printk("Memory Map:\n");
7580

@@ -96,6 +101,30 @@ bool has_memory_range(paddr_t pa) {
96101
return mbi_get_memory_range(pa, NULL) == 0;
97102
}
98103

104+
static inline bool ranges_overlap(addr_range_t const *range_a,
105+
addr_range_t const *range_b) {
106+
return (range_a->start < range_b->end) && (range_b->start < range_a->end);
107+
}
108+
109+
bool in_reserved_range(paddr_t pa, size_t size) {
110+
addr_range_t range;
111+
range.start = _ptr(pa);
112+
range.end = _ptr(pa + size);
113+
114+
for (unsigned int i = 0; i < regions_reserved_num; i++) {
115+
if (ranges_overlap(&range, &reserved_ranges[i])) {
116+
return true;
117+
}
118+
}
119+
return false;
120+
}
121+
99122
void init_regions(void) {
100123
regions_num = mbi_get_avail_memory_ranges_num();
124+
regions_reserved_num = 0;
125+
126+
/* If multiboot is enabled, reserve it's physical address range */
127+
if (mbi_reserved_range(&reserved_ranges[regions_reserved_num])) {
128+
regions_reserved_num++;
129+
}
101130
}

0 commit comments

Comments
 (0)