diff --git a/arch/x86/boot/multiboot.c b/arch/x86/boot/multiboot.c index e05db83f..1be8d238 100644 --- a/arch/x86/boot/multiboot.c +++ b/arch/x86/boot/multiboot.c @@ -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); diff --git a/include/mm/regions.h b/include/mm/regions.h index 114758e3..6bd50aa4 100644 --- a/include/mm/regions.h +++ b/include/mm/regions.h @@ -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); diff --git a/include/multiboot.h b/include/multiboot.h index 976b9ae5..ba97a1a4 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -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 */ diff --git a/include/multiboot2.h b/include/multiboot2.h index fef0ff87..f2ec7045 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -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__ */ diff --git a/mm/pmm.c b/mm/pmm.c index 9bd39a48..72620d35 100644 --- a/mm/pmm.c +++ b/mm/pmm.c @@ -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]); @@ -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); @@ -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); } diff --git a/mm/regions.c b/mm/regions.c index 287be2dd..d0492fda 100644 --- a/mm/regions.c +++ b/mm/regions.c @@ -70,6 +70,11 @@ addr_range_t addr_ranges[] = { {0x0} /* NULL array terminator */ }; +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"); @@ -96,6 +101,29 @@ 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++; + } }