Skip to content

Commit

Permalink
pmm: simpler and bugfix process_memory_range loop
Browse files Browse the repository at this point in the history
This simplifies the adding of frames during boot. It also fixes a bug for
configurations with > 1GB memory. After the initial 4K frames, the current
(`cur`) is aligned to 2MB.  Trying to add a 1GB frame at this point will
lead to page faults further down the line as we end up with misaligned page
frame mfns.

Signed-off-by: Johannes Wikner <[email protected]>
  • Loading branch information
sktt authored and wipawel committed Oct 31, 2024
1 parent c1ab591 commit fa54601
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 24 deletions.
1 change: 1 addition & 0 deletions include/arch/x86/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ typedef unsigned long mfn_t;
#define MAP_FAILED ((void *) 1)

#define IS_ADDR_SPACE_VA(va, as) (_ul(va) >= (as))
#define PADDR_TO_ORDER(addr) (ctz(addr) - PAGE_SHIFT)

/* External declarations */

Expand Down
2 changes: 2 additions & 0 deletions include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,6 @@ typedef uint64_t off_t;
_str; \
})

/* count trailing zeros */
#define ctz __builtin_ctz
#endif /* KTF_COMPILER_H */
42 changes: 18 additions & 24 deletions mm/pmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ static unsigned find_first_avail_region(void) {

static size_t process_memory_range(unsigned index, unsigned first_avail_region) {
paddr_t start, end, cur;
unsigned int max_order;
addr_range_t range;
size_t size;

Expand All @@ -310,39 +309,34 @@ static size_t process_memory_range(unsigned index, unsigned first_avail_region)
* because initial virtual memory mapping is small.
*/

/* Add initial 4K frames and align to 2M. */
while ((cur < MB(EARLY_VIRT_MEM) || cur % PAGE_SIZE_2M) && cur + PAGE_SIZE <= end) {
if (index <= first_avail_region)
add_early_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
else
add_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
/* 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);
cur += ORDER_TO_SIZE(PAGE_ORDER_4K);
}

max_order = find_max_avail_order(end - cur);

/* Add all available max_order frames. */
while (cur + ORDER_TO_SIZE(max_order) <= end) {
add_frame(paddr_to_mfn(cur), max_order);
cur += ORDER_TO_SIZE(max_order);
}
while (cur + PAGE_SIZE <= end) {
unsigned int order = PADDR_TO_ORDER(cur);
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);
continue;
}

/* Add all remaining 2M frames. */
while (cur + PAGE_SIZE_2M <= end) {
add_frame(paddr_to_mfn(cur), PAGE_ORDER_2M);
cur += ORDER_TO_SIZE(PAGE_ORDER_2M);
}
if (order >= PAGE_ORDER_2M && cur + PAGE_SIZE_2M <= end) {
add_frame(paddr_to_mfn(cur), PAGE_ORDER_2M);
cur += ORDER_TO_SIZE(PAGE_ORDER_2M);
continue;
}

/* Add all remaining 4K frames. */
while (cur < end) {
add_frame(paddr_to_mfn(cur), PAGE_ORDER_4K);
cur += ORDER_TO_SIZE(PAGE_ORDER_4K);
}

if (cur != end) {
warning(
"PMM range processing failed: start=0x%016lx end=0x%016lx current=0x%016lx",
start, end, cur);
warning("PMM range processing failed: start=0x%016lx end=0x%016lx "
"current=0x%016lx",
start, end, cur);
}

return size;
Expand Down

0 comments on commit fa54601

Please sign in to comment.