Skip to content

Commit

Permalink
multiboot,regions,pmm: reserve multiboot physical memory
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
sparchatus authored and wipawel committed Dec 4, 2024
1 parent fb882ca commit e52279e
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 1 deletion.
9 changes: 9 additions & 0 deletions arch/x86/boot/multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ void init_multiboot(unsigned long *addr, const char **cmdline) {
}
}

bool mbi_reserved_range(addr_range_t *reserved_range) {
if (multiboot2_hdr == NULL)
return false;

reserved_range->start = multiboot2_hdr;
reserved_range->end = _ptr(_ul(multiboot2_hdr) + multiboot2_hdr_size);
return true;
}

void map_multiboot_areas(void) {
paddr_t mbi_start = _paddr(multiboot2_hdr);
vmap_range(mbi_start, multiboot2_hdr_size, L1_PROT_RO, VMAP_KERNEL | VMAP_IDENT);
Expand Down
1 change: 1 addition & 0 deletions include/mm/regions.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ extern int get_memory_range(paddr_t pa, addr_range_t *r);

extern int get_avail_memory_range(unsigned index, addr_range_t *r);
extern bool has_memory_range(paddr_t pa);
extern bool in_reserved_range(paddr_t pa, size_t size);

extern void init_regions(void);

Expand Down
1 change: 1 addition & 0 deletions include/multiboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ extern unsigned mbi_get_avail_memory_ranges_num(void);
extern int mbi_get_avail_memory_range(unsigned index, addr_range_t *r);
extern int mbi_get_memory_range(paddr_t pa, addr_range_t *r);
extern bool mbi_has_framebuffer(void);
extern bool mbi_reserved_range(addr_range_t *reserved_range);
#endif /* __ASSEMBLY__ */

#endif /* KTF_MULTIBOOT_H */
1 change: 1 addition & 0 deletions include/multiboot2.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ extern void map_multiboot_areas(void);
extern unsigned mbi_get_avail_memory_ranges_num(void);
extern int mbi_get_avail_memory_range(unsigned index, addr_range_t *r);
extern int mbi_get_memory_range(paddr_t pa, addr_range_t *r);
extern bool mbi_reserved_range(addr_range_t *reserved_range);

#endif /* __ASSEMBLY__ */

Expand Down
17 changes: 16 additions & 1 deletion mm/pmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,14 @@ static inline frame_t *new_frame(mfn_t mfn, unsigned int order) {
}

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

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

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

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

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

while (cur + PAGE_SIZE <= end) {
unsigned int order = PADDR_TO_ORDER(cur);

/* Choose the largest region not overlapping a reserved area */
while (in_reserved_range(cur, ORDER_TO_SIZE(order))) {
if (order == PAGE_ORDER_4K) {
goto skip;
}
--order;
}

if (order >= PAGE_ORDER_1G && cur + PAGE_SIZE_1G <= end) {
add_frame(paddr_to_mfn(cur), PAGE_ORDER_1G);
cur += ORDER_TO_SIZE(PAGE_ORDER_1G);
Expand All @@ -321,6 +335,7 @@ static size_t process_memory_range(unsigned index, unsigned first_avail_region)
}

add_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
skip:
cur += ORDER_TO_SIZE(PAGE_ORDER_4K);
}

Expand Down
29 changes: 29 additions & 0 deletions mm/regions.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ addr_range_t addr_ranges[] = {
{0x0} /* NULL array terminator */
};

static unsigned regions_reserved_num;

#define MAX_RESERVED_RANGES 1
static addr_range_t reserved_ranges[MAX_RESERVED_RANGES];

void display_memory_map(void) {
printk("Memory Map:\n");

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

static inline bool ranges_overlap(addr_range_t const *range_a,
addr_range_t const *range_b) {
return (range_a->start < range_b->end) && (range_b->start < range_a->end);
}

bool in_reserved_range(paddr_t pa, size_t size) {
addr_range_t range;
range.start = _ptr(pa);
range.end = _ptr(pa + size);

for (unsigned int i = 0; i < regions_reserved_num; i++) {
if (ranges_overlap(&range, &reserved_ranges[i])) {
return true;
}
}
return false;
}

void init_regions(void) {
regions_num = mbi_get_avail_memory_ranges_num();
regions_reserved_num = 0;

/* If multiboot is enabled, reserve it's physical address range */
if (mbi_reserved_range(&reserved_ranges[regions_reserved_num])) {
regions_reserved_num++;
}
}

0 comments on commit e52279e

Please sign in to comment.