From 50e1b103669a334d31bb27d7d858400c7a12e29e Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 19 Sep 2025 23:29:18 -0400 Subject: kern: proc: Keep track of mapped areas with ranges This commit adds a virtual memory range queue to the process descriptor in order to keep track of mapped pages and free their respective frames upon program exit. Signed-off-by: Ian Moffett --- src/sys/include/sys/proc.h | 18 ++++++++++++++++ src/sys/include/vm/vm.h | 16 ++++++++++++++ src/sys/os/os_proc.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ src/sys/vm/vm_map.c | 9 ++++++++ 4 files changed, 97 insertions(+) (limited to 'src/sys') diff --git a/src/sys/include/sys/proc.h b/src/sys/include/sys/proc.h index 200d5ce..cf00850 100644 --- a/src/sys/include/sys/proc.h +++ b/src/sys/include/sys/proc.h @@ -35,6 +35,7 @@ #include #include #include +#include #include /* standard */ /* @@ -52,6 +53,7 @@ * @flags: State flags (see PROC_*) * @pcb: Process control block * @scdom: Syscall domain + * @maplist: List of mapped regions * @link: TAILQ link */ struct proc { @@ -59,6 +61,7 @@ struct proc { uint32_t flags; struct md_pcb pcb; struct syscall_domain scdom; + TAILQ_HEAD(, vm_range) maplist; TAILQ_ENTRY(proc) link; }; @@ -82,6 +85,21 @@ int proc_init(struct proc *procp, int flags); */ struct proc *proc_self(void); +/* + * Allocate a range descriptor and add it to the + * process's range tracking list for cleanup upon + * exit. + * + * @procp: Process to initialize the range of + * @va: Virtual address to use + * @pa: Physical address to use + * @len: Length to use + * + * Returns zero on success, otherwise a less than + * zero value upon error. + */ +int proc_add_range(struct proc *procp, vaddr_t va, paddr_t pa, size_t len); + /* * Kill a process with a specific status code * diff --git a/src/sys/include/vm/vm.h b/src/sys/include/vm/vm.h index 790fe0b..f5f7b16 100644 --- a/src/sys/include/vm/vm.h +++ b/src/sys/include/vm/vm.h @@ -31,6 +31,7 @@ #define _VM_H_ 1 #include +#include #include #define VM_HIGHER_HALF (get_kernel_base()) @@ -42,6 +43,21 @@ typedef uintptr_t vaddr_t; typedef uintptr_t paddr_t; +/* + * Describes a virtual memory range + * + * @pa_base: Physical memory base + * @va_base: Virtual memory base + * @len: Length of region + * @link: Queue link + */ +struct vm_range { + paddr_t pa_base; + vaddr_t va_base; + size_t len; + TAILQ_ENTRY(vm_range) link; +}; + void vm_init(void); #endif /* !_VM_H_ */ diff --git a/src/sys/os/os_proc.c b/src/sys/os/os_proc.c index 329a3ea..3a42496 100644 --- a/src/sys/os/os_proc.c +++ b/src/sys/os/os_proc.c @@ -30,11 +30,38 @@ #include #include #include +#include +#include #include +#include +#include +#include #include static pid_t next_pid = 0; +/* + * Deallocate saved memory ranges + * + * @proc: Process to target + */ +static void +proc_clear_ranges(struct proc *proc) +{ + const size_t PSIZE = DEFAULT_PAGESIZE; + struct vm_range *range; + size_t n_pages; + + TAILQ_FOREACH(range, &proc->maplist, link) { + if (range == NULL) { + continue; + } + + n_pages = ALIGN_UP(range->len, PSIZE) / PSIZE; + vm_free_frame(range->pa_base, n_pages); + } +} + /* * MI proc init code */ @@ -52,6 +79,7 @@ proc_init(struct proc *procp, int flags) /* Put the process in a known state */ scdp = &procp->scdom; memset(procp, 0, sizeof(*procp)); + TAILQ_INIT(&procp->maplist); /* * Initialize each platform latch @@ -72,6 +100,31 @@ proc_init(struct proc *procp, int flags) return error; } +/* + * Add range to process + */ +int +proc_add_range(struct proc *procp, vaddr_t va, paddr_t pa, size_t len) +{ + const size_t PSIZE = DEFAULT_PAGESIZE; + struct vm_range *range; + + if (procp == NULL) { + return -EINVAL; + } + + range = kalloc(sizeof(*range)); + if (range == NULL) { + return -ENOMEM; + } + + range->pa_base = pa; + range->va_base = va; + range->len = ALIGN_UP(len, PSIZE); + TAILQ_INSERT_TAIL(&procp->maplist, range, link); + return 0; +} + /* * Kill a specific process */ @@ -83,5 +136,6 @@ proc_kill(struct proc *procp, int status) } procp->flags |= PROC_EXITING; + proc_clear_ranges(procp); return md_proc_kill(procp, 0); } diff --git a/src/sys/vm/vm_map.c b/src/sys/vm/vm_map.c index d8cb4b7..27cdcce 100644 --- a/src/sys/vm/vm_map.c +++ b/src/sys/vm/vm_map.c @@ -103,15 +103,19 @@ __vm_map(struct vm_vas *vas, struct mmu_map *spec, size_t len, int prot) int vm_map(struct vm_vas *vas, struct mmu_map *spec, size_t len, int prot) { + const size_t PSIZE = DEFAULT_PAGESIZE; int retval; size_t unmap_len; struct mmu_map spec_cpy; + struct proc *self = proc_self(); if (spec != NULL) { spec_cpy = *spec; } + /* If this fails, unmap the partial region */ + len = ALIGN_UP(len, PSIZE); retval = __vm_map(vas, spec, len, prot); if (retval != 0) { printf("vm_map: could not map <%p>\n", spec_cpy.va); @@ -121,6 +125,11 @@ vm_map(struct vm_vas *vas, struct mmu_map *spec, size_t len, int prot) return -1; } + /* Add the range if we can */ + if (self != NULL) { + proc_add_range(self, spec->va, spec->pa, len); + } + /* Place a guard page at the end */ spec->va = spec_cpy.va + len; __vm_map(vas, spec, DEFAULT_PAGESIZE, 0); -- cgit v1.2.3