diff --git a/arch/x86/boot/multiboot.c b/arch/x86/boot/multiboot.c index 8a656dab..e3fbcff7 100644 --- a/arch/x86/boot/multiboot.c +++ b/arch/x86/boot/multiboot.c @@ -182,11 +182,11 @@ void init_multiboot(unsigned long *addr, const char **cmdline) { } } -paddr_t mbi_reserved_start(void) { - return _paddr(multiboot2_hdr); -} -size_t mbi_reserved_size(void) { - return multiboot2_hdr_size; +bool mbi_reserved_range(addr_range_t *reserved_range) { + reserved_range->start = multiboot2_hdr; + reserved_range->end = multiboot2_hdr + multiboot2_hdr_size; + + return multiboot2_hdr != 0; } void map_multiboot_areas(void) { diff --git a/common/setup.c b/common/setup.c index 5bf82085..f6037198 100644 --- a/common/setup.c +++ b/common/setup.c @@ -209,7 +209,7 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, unsigned long /* Initialize Physical Memory Manager */ init_regions(); - init_pmm(mbi_reserved_start(), mbi_reserved_size()); + init_pmm(); /* Setup final pagetables */ init_pagetables(); diff --git a/include/mm/pmm.h b/include/mm/pmm.h index 221f6112..246c225c 100644 --- a/include/mm/pmm.h +++ b/include/mm/pmm.h @@ -69,7 +69,7 @@ typedef bool (*free_frames_cond_t)(frame_t *free_frame); /* External definitions */ extern void display_frames_count(void); -extern void init_pmm(paddr_t reserved_start, size_t reserved_size); +extern void init_pmm(void); extern frame_t *get_free_frames_cond(free_frames_cond_t cb); extern frame_t *get_free_frames(unsigned int order); diff --git a/include/mm/regions.h b/include/mm/regions.h index 114758e3..dc883ee8 100644 --- a/include/mm/regions.h +++ b/include/mm/regions.h @@ -152,6 +152,8 @@ static inline paddr_t get_region_free_start(void *from) { return start; } +bool in_reserved_range(paddr_t pa, size_t size); + #endif /* __ASSEMBLY__ */ #endif /* KTF_REGIONS_H */ 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 671a921f..f2ec7045 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -433,8 +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); -paddr_t mbi_reserved_start(void); -size_t mbi_reserved_size(void); +extern bool mbi_reserved_range(addr_range_t *reserved_range); #endif /* __ASSEMBLY__ */ diff --git a/mm/pmm.c b/mm/pmm.c index 969e8642..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]); @@ -282,14 +284,7 @@ static unsigned find_first_avail_region(void) { UNREACHABLE(); } -static bool ranges_overlap(paddr_t range_a_start, size_t range_a_size, - paddr_t range_b_start, size_t range_b_size) { - return (range_a_start <= (range_b_start + range_b_size)) && - (range_b_start <= (range_a_start + range_a_size)); -} - -static size_t process_memory_range(unsigned index, paddr_t reserved_start, - size_t reserved_size) { +static size_t process_memory_range(unsigned index, unsigned first_avail_region) { paddr_t start, end, cur; addr_range_t range; size_t size; @@ -309,9 +304,8 @@ static size_t process_memory_range(unsigned index, paddr_t reserved_start, /* Add initial 4K frames for early memory. */ while (cur < MB(EARLY_VIRT_MEM) && cur + PAGE_SIZE <= end) { - // if the current region overlaps with the reserved region we skip it - if (!ranges_overlap(cur, ORDER_TO_SIZE(PAGE_ORDER_4K), reserved_start, - reserved_size)) { + /* 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); @@ -320,8 +314,8 @@ static size_t process_memory_range(unsigned index, paddr_t reserved_start, while (cur + PAGE_SIZE <= end) { unsigned int order = PADDR_TO_ORDER(cur); - // make sure we don't overlap with the reserved region - while (ranges_overlap(cur, ORDER_TO_SIZE(order), reserved_start, reserved_size)) { + /* 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; } @@ -386,7 +380,7 @@ static inline void check_early_frames(unsigned first_avail_region) { } } -void init_pmm(paddr_t reserved_start, size_t reserved_size) { +void init_pmm(void) { unsigned first_region_index; printk("Initialize Physical Memory Manager\n"); @@ -405,7 +399,7 @@ void init_pmm(paddr_t reserved_start, size_t reserved_size) { /* Skip low memory range */ for (unsigned int i = first_region_index; i < regions_num; i++) - total_phys_memory += process_memory_range(i, reserved_start, reserved_size); + total_phys_memory += process_memory_range(i, first_region_index); display_frames_count(); diff --git a/mm/regions.c b/mm/regions.c index 287be2dd..d2114e32 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 +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 bool ranges_overlap(addr_range_t *range_a, addr_range_t *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++; + } }