From 7d17d800d4462a42455b9ac825306acdca6c2a83 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 18 Apr 2024 15:07:25 -0400 Subject: kernel: vm_map: Handle pager physical addresses Signed-off-by: Ian Moffett --- sys/vm/vm_map.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'sys') diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index e8dc0ed..afef6f2 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -143,21 +143,23 @@ vm_mapspace_insert(struct vm_mapspace *ms, struct vm_mapping *mapping) * Create an anonymous mapping. * * @addr: Address to map. + * @physmem: Physical address, set to 0 to alloc one here * @prot: Protection flags. * * Returns zero on failure. */ static paddr_t -vm_anon_map(void *addr, vm_prot_t prot, size_t len) +vm_anon_map(void *addr, paddr_t physmem, vm_prot_t prot, size_t len) { struct proc *td = this_td(); const size_t GRANULE = vm_get_page_size(); - paddr_t physmem; int status; - /* Allocate the physical memory */ - physmem = vm_alloc_pageframe(len / GRANULE); + /* Allocate the physical memory if needed */ + if (physmem == 0) + physmem = vm_alloc_pageframe(len / GRANULE); + if (physmem == 0) return 0; @@ -187,7 +189,8 @@ vm_anon_map(void *addr, vm_prot_t prot, size_t len) static paddr_t vm_fd_map(void *addr, vm_prot_t prot, size_t len, off_t off, int fd) { - paddr_t physmem; + paddr_t physmem = 0; + struct filedesc *filedes; struct vnode *vp; @@ -205,17 +208,35 @@ vm_fd_map(void *addr, vm_prot_t prot, size_t len, off_t off, int fd) if (vm_obj_init(&vp->vmobj, vp) != 0) return 0; - /* Start with a regular anonymous mapping */ - physmem = vm_anon_map(addr, prot, len); - if (physmem == 0) { + /* Try to fetch a physical address */ + if (vm_pager_paddr(vp->vmobj, &physmem, prot) != 0) { vm_obj_destroy(vp->vmobj); return 0; } + /* + * If the pager found a physical address for the object to + * be mapped to, then we start off with an anonymous mapping + * then connect it to the physical address (creates a shared mapping) + */ + if (physmem != 0) { + vm_anon_map(addr, physmem, prot, len); + return physmem; + } + + /* + * If the pager could not find a physical address for + * the object to be mapped to, start of with just a plain + * anonymous mapping then page-in from whatever filesystem + * (creates a shared mapping) + */ + physmem = vm_anon_map(addr, 0, prot, len); pg.physaddr = physmem; - if (vm_pager_get(vp->vmobj, off, len, &pg) != 0) + if (vm_pager_get(vp->vmobj, off, len, &pg) != 0) { + vm_obj_destroy(vp->vmobj); return 0; + } return physmem; } @@ -287,7 +308,7 @@ mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) */ if (__TEST(flags, MAP_ANONYMOUS)) { /* Handle an anonymous map request */ - physmem = vm_anon_map(addr, prot, len); + physmem = vm_anon_map(addr, 0, prot, len); } else if (__TEST(flags, MAP_SHARED)) { physmem = vm_fd_map(addr, prot, len, off, fildes); } -- cgit v1.2.3