summaryrefslogtreecommitdiff
path: root/kernel/memory/paging.c
diff options
context:
space:
mode:
authorIan McFarlane <i.mcfarlane2002@gmail.com>2025-04-24 15:50:50 -0400
committerIan McFarlane <i.mcfarlane2002@gmail.com>2025-04-24 15:51:29 -0400
commit3c213ce446c6547c79f683f035b191e92b4e914e (patch)
treed05d172ba28e5e6eb0e607b51e1db92d30003508 /kernel/memory/paging.c
parentfix paging free fns (diff)
downloadcomus-3c213ce446c6547c79f683f035b191e92b4e914e.tar.gz
comus-3c213ce446c6547c79f683f035b191e92b4e914e.tar.bz2
comus-3c213ce446c6547c79f683f035b191e92b4e914e.zip
make alloc_pages_at() able to allocate noncontiguous physical pages
Diffstat (limited to 'kernel/memory/paging.c')
-rw-r--r--kernel/memory/paging.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c
index 58c5091..24a9ea7 100644
--- a/kernel/memory/paging.c
+++ b/kernel/memory/paging.c
@@ -796,16 +796,36 @@ void *mem_alloc_pages(mem_ctx_t ctx, size_t count, unsigned int flags)
void *mem_alloc_pages_at(mem_ctx_t ctx, size_t count, void *virt,
unsigned int flags)
{
- void *phys = alloc_phys_pages(count);
- if (phys == NULL)
- return NULL;
+ size_t pages_needed = count;
+ uint8_t *virtual_address = virt;
- if (map_pages((volatile struct pml4 *)ctx->pml4, virt, phys, flags,
- count)) {
- if (phys)
- free_phys_pages(phys, count);
- return NULL;
+ void *phys_start = NULL;
+
+ while (pages_needed > 0) {
+ struct phys_page_slice phys_pages =
+ alloc_phys_page_withextra(pages_needed);
+ if (phys_pages.pagestart == NULL) {
+ free_phys_pages(phys_start ? phys_start : phys_pages.pagestart,
+ count - pages_needed);
+ return NULL;
+ }
+
+ if (!phys_start)
+ phys_start = phys_pages.pagestart;
+
+ assert(pages_needed >= phys_pages.num_pages, "overflow");
+ pages_needed -= phys_pages.num_pages;
+ virtual_address += phys_pages.num_pages * PAGE_SIZE;
+
+ if (map_pages((volatile struct pml4 *)ctx->pml4,
+ (void *)virtual_address, phys_pages.pagestart, flags,
+ phys_pages.num_pages)) {
+ assert(phys_start, "expected something allocated");
+ free_phys_pages(phys_start, count - pages_needed);
+ return NULL;
+ }
}
+
return virt;
}