Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reserve multiboot physical memory #344

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
sparchatus marked this conversation as resolved.
Show resolved Hide resolved
#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++;
}
}
Loading