-
Notifications
You must be signed in to change notification settings - Fork 17
Implement physical memory allocator #89
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
Open
dawidpawliczek4
wants to merge
5
commits into
Operacja-System:main
Choose a base branch
from
dawidpawliczek4:pmem-allocator
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+188
−67
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
34e6f3c
Implement physical memory allocator using bitmap
dawidpawliczek4 773a149
Refactor
dawidpawliczek4 6ca742d
Merge branch 'main' into pmem-allocator
dawidpawliczek4 5077507
update phys_mem_get_frame_size_in_bytes parameter type to frame_order_t
dawidpawliczek4 a82fe62
Fix format
dawidpawliczek4 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,34 +2,151 @@ | |
|
|
||
| #include "memory_management/include/physical_memory/manager.h" | ||
| #include "stdbigos/error.h" | ||
| #include "stdbigos/math.h" | ||
| #include "stdbigos/string.h" | ||
|
|
||
| error_t pmallocator_get_header(memory_area_t area, const memory_area_t* reserved_areas, u32 count, | ||
| typedef struct { | ||
| uintptr_t area_base_addr; | ||
| size_t area_size; | ||
| u64 bitmap[]; | ||
| } pmallocator_header_t; | ||
|
|
||
| typedef struct { | ||
| size_t first_bit; | ||
| size_t bit_count; | ||
| } bitmap_range_t; | ||
|
|
||
| static void bitmap_set(u64* bitmap, size_t bit) { | ||
| bitmap[bit / 64] |= (1ULL << (bit % 64)); | ||
| } | ||
|
|
||
| static void bitmap_clear(u64* bitmap, size_t bit) { | ||
| bitmap[bit / 64] &= ~(1ULL << (bit % 64)); | ||
| } | ||
|
|
||
| static bool bitmap_test(const u64* bitmap, size_t bit) { | ||
| return bitmap[bit / 64] & (1ULL << (bit % 64)); | ||
| } | ||
|
|
||
| static void bitmap_set_range(u64* bitmap, size_t start, size_t count) { | ||
| for (size_t j = start; j < start + count; ++j) { | ||
| bitmap_set(bitmap, j); | ||
| } | ||
| } | ||
|
|
||
| static size_t calculate_header_size(memory_area_t area) { | ||
| const size_t bitmap_bits = area.size / PAGE_SIZE; | ||
| const size_t bitmap_bytes = ALIGN_UP(bitmap_bits, 64) / 8; | ||
| const size_t total = sizeof(pmallocator_header_t) + bitmap_bytes; | ||
| return ALIGN_UP(total, PAGE_SIZE); | ||
| } | ||
|
|
||
| static bitmap_range_t addr_range_to_bitmap_range(uintptr_t range_addr, size_t range_size, uintptr_t base_addr) { | ||
| const uintptr_t aligned_start = ALIGN_DOWN(range_addr, PAGE_SIZE); | ||
| const uintptr_t aligned_end = ALIGN_UP(range_addr + range_size, PAGE_SIZE); | ||
|
|
||
| bitmap_range_t result = { | ||
| .first_bit = (aligned_start - base_addr) / PAGE_SIZE, | ||
| .bit_count = (aligned_end - aligned_start) / PAGE_SIZE, | ||
| }; | ||
| return result; | ||
| } | ||
|
|
||
| error_t pmallocator_get_header(memory_area_t area, const memory_area_t* reserved_areas, u32 reserved_areas_count, | ||
| memory_area_t* headerOUT) { | ||
| (void)area; | ||
| (void)reserved_areas; | ||
| (void)count; | ||
| (void)headerOUT; | ||
| return ERR_NOT_IMPLEMENTED; | ||
| const size_t header_size = calculate_header_size(area); | ||
|
|
||
| for (uintptr_t i = area.addr; i + header_size <= area.addr + area.size; i += PAGE_SIZE) { | ||
| memory_area_t potential_header = { | ||
| .addr = i, | ||
| .size = header_size, | ||
| }; | ||
| bool overlaps_reserved = false; | ||
| for (u32 j = 0; j < reserved_areas_count; ++j) { | ||
| if (do_memory_areas_overlap(potential_header, reserved_areas[j])) { | ||
| overlaps_reserved = true; | ||
| break; | ||
| } | ||
| } | ||
| if (!overlaps_reserved) { | ||
| *headerOUT = potential_header; | ||
| return ERR_NONE; | ||
| } | ||
| } | ||
|
|
||
| return ERR_NOT_ENOUGH_MEMORY; | ||
| } | ||
|
|
||
| error_t pmallocator_init_region(memory_area_t area, memory_region_t header, const memory_area_t* reserved_areas, | ||
| u32 count) { | ||
| (void)area; | ||
| (void)header; | ||
| (void)reserved_areas; | ||
| (void)count; | ||
| return ERR_NOT_IMPLEMENTED; | ||
| error_t pmallocator_init_region(memory_area_t area, memory_region_t header_region, const memory_area_t* reserved_areas, | ||
| u32 reserved_areas_count) { | ||
| pmallocator_header_t* header = header_region.addr; | ||
| header->area_size = area.size; | ||
| header->area_base_addr = area.addr; | ||
|
|
||
| const size_t header_size = calculate_header_size(area); | ||
| const size_t bitmap_size = header_size - sizeof(pmallocator_header_t); | ||
|
|
||
| memset(header->bitmap, 0, bitmap_size); | ||
|
|
||
| for (u32 i = 0; i < reserved_areas_count; ++i) { | ||
| memory_area_t reserved_area = reserved_areas[i]; | ||
| bitmap_range_t bitmap_range = addr_range_to_bitmap_range(reserved_area.addr, reserved_area.size, area.addr); | ||
|
|
||
| bitmap_set_range(header->bitmap, bitmap_range.first_bit, bitmap_range.bit_count); | ||
| } | ||
|
|
||
| bitmap_range_t bitmap_range = | ||
| addr_range_to_bitmap_range((uintptr_t)header_region.addr, header_region.size, area.addr); | ||
| bitmap_set_range(header->bitmap, bitmap_range.first_bit, bitmap_range.bit_count); | ||
|
|
||
| return ERR_NONE; | ||
| } | ||
|
|
||
| error_t pmallocator_allocate(u8 frame_order, memory_region_t header, phys_addr_t* addrOUT) { | ||
| (void)frame_order; | ||
| *addrOUT = *addrOUT; | ||
| (void)header; | ||
| return ERR_NOT_IMPLEMENTED; | ||
| error_t pmallocator_allocate(frame_order_t frame_order, memory_region_t header_region, phys_addr_t* addrOUT) { | ||
| pmallocator_header_t* header = header_region.addr; | ||
|
|
||
| const size_t bitmap_bits = header->area_size / PAGE_SIZE; | ||
| const size_t frame_count = 1ULL << frame_order; | ||
|
|
||
| for (size_t i = 0; i + frame_count <= bitmap_bits; i += frame_count) { | ||
| bool all_free = true; | ||
|
|
||
| for (size_t j = i; j < i + frame_count; ++j) { | ||
| if (bitmap_test(header->bitmap, j)) { | ||
| all_free = false; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (all_free) { | ||
| bitmap_set_range(header->bitmap, i, frame_count); | ||
| *addrOUT = (phys_addr_t)(header->area_base_addr + (i * PAGE_SIZE)); | ||
| return ERR_NONE; | ||
| } | ||
| } | ||
|
|
||
| return ERR_NOT_ENOUGH_MEMORY; | ||
| } | ||
|
|
||
| error_t pmallocator_free(phys_addr_t addr, memory_region_t header) { | ||
| (void)addr; | ||
| (void)header; | ||
| return ERR_NOT_IMPLEMENTED; | ||
| error_t pmallocator_free(frame_order_t frame_order, phys_addr_t addr, memory_region_t header_region) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
| pmallocator_header_t* header = header_region.addr; | ||
|
|
||
| const size_t frame_count = 1ULL << frame_order; | ||
| const uintptr_t phys_addr = (uintptr_t)addr; | ||
| const size_t addr_bit = (phys_addr - header->area_base_addr) / PAGE_SIZE; | ||
| const size_t total_pages = header->area_size / PAGE_SIZE; | ||
|
|
||
| if (phys_addr < header->area_base_addr || addr_bit + frame_count > total_pages) | ||
| return ERR_OUT_OF_BOUNDS; | ||
|
|
||
| for (size_t j = addr_bit; j < addr_bit + frame_count; ++j) { | ||
| if (!bitmap_test(header->bitmap, j)) | ||
| return ERR_NOT_VALID; | ||
| } | ||
|
|
||
| for (size_t j = addr_bit; j < addr_bit + frame_count; ++j) { | ||
| bitmap_clear(header->bitmap, j); | ||
| } | ||
|
|
||
| return ERR_NONE; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,9 +52,9 @@ static error_t store_header(physical_memory_region_t header) { | |
| } else { | ||
| physical_memory_region_t new_reg = { | ||
| .addr = nullptr, | ||
| .size = phys_mem_get_frame_size_in_bytes(FRAME_SIZE_4KiB), | ||
| .size = PAGE_SIZE, | ||
| }; | ||
| error_t err = phys_mem_alloc_frame(FRAME_SIZE_4KiB, &new_reg.addr); | ||
| error_t err = phys_mem_alloc_frame(FRAME_ORDER_4KiB, &new_reg.addr); | ||
| if (err) | ||
| return err; | ||
| err = init_header_storage_node(new_reg); | ||
|
|
@@ -73,7 +73,7 @@ static error_t store_header(physical_memory_region_t header) { | |
| // Public | ||
| // ========================================== | ||
|
|
||
| u64 phys_mem_get_frame_size_in_bytes(frame_size_t fs) { | ||
| u64 phys_mem_get_frame_size_in_bytes(frame_order_t fs) { | ||
| const u64 size_4KiB = 0x1000; | ||
| return (size_4KiB << fs); | ||
| } | ||
|
|
@@ -113,10 +113,10 @@ error_t phys_mem_init(const physical_memory_region_t* pmrs, size_t pmr_count, co | |
| } | ||
| if (g_root_header_storage_node == nullptr) { | ||
| physical_memory_region_t new_reg = { | ||
| .size = phys_mem_get_frame_size_in_bytes(FRAME_SIZE_4KiB), | ||
| .size = PAGE_SIZE, | ||
| .addr = nullptr, | ||
| }; | ||
| err = pmallocator_allocate(12, header_region, &new_reg.addr); | ||
| err = pmallocator_allocate(FRAME_ORDER_4KiB, header_region, &new_reg.addr); | ||
| // NOTE: Since we failed to allocate the smallest possible frame size, we assume that this region is | ||
| // useless. | ||
| if (err) { | ||
|
|
@@ -149,13 +149,13 @@ error_t phys_mem_init(const physical_memory_region_t* pmrs, size_t pmr_count, co | |
| } | ||
| // NOLINTEND readability-function-cognitive-complexity | ||
|
|
||
| error_t phys_mem_alloc_frame(frame_size_t frame_size, phys_addr_t* addrOUT) { | ||
| error_t phys_mem_alloc_frame(frame_order_t frame_size, phys_addr_t* addrOUT) { | ||
| u32 idx = 0; | ||
| physical_memory_region_t header_pmr; | ||
| while (get_header_pmr(idx, &header_pmr) == ERR_NONE) { | ||
| memory_region_t header_region = phys_mem_reg_to_reg(header_pmr); | ||
| phys_addr_t frame_data = nullptr; | ||
| error_t err = pmallocator_allocate(frame_size + 12, header_region, &frame_data); | ||
| error_t err = pmallocator_allocate(frame_size, header_region, &frame_data); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we know why the |
||
| if (err) { | ||
| ++idx; | ||
| continue; | ||
|
|
@@ -169,12 +169,12 @@ error_t phys_mem_alloc_frame(frame_size_t frame_size, phys_addr_t* addrOUT) { | |
| return ERR_OUT_OF_MEMORY; | ||
| } | ||
|
|
||
| error_t phys_mem_free_frame(phys_addr_t addr) { | ||
| error_t phys_mem_free_frame(frame_order_t frame_size, phys_addr_t addr) { | ||
| u32 idx = 0; | ||
| physical_memory_region_t header_pmr; | ||
| while (get_header_pmr(idx, &header_pmr) == ERR_NONE) { | ||
| memory_region_t header_region = phys_mem_reg_to_reg(header_pmr); | ||
| error_t err = pmallocator_free(addr, header_region); | ||
| error_t err = pmallocator_free(frame_size, addr, header_region); | ||
| if (err) { | ||
| ++idx; | ||
| continue; | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be wrapped in a critical section (both signals and for other harts).
For now you can add a blank implementation on
hal_critical_section_{begin/end}to the hal and just call them here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when hal is merged, just do
hal_enable_irq/hal_disable_irqand add aFIXME: use a real critical sectionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was decided there will be no parallelism, so no need for critical section (but interrupt disablement is still required)