aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2026-01-25 17:14:53 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2026-01-25 17:14:53 +0200
commitcd41ed1758f4842d7b78870385e16b579cc89c38 (patch)
tree271e1b437ec5a1511f4ffa400da447122576b94b /src
parente8a7fe3bd5c40168d531a6a4f00a7417a278d58c (diff)
downloadkmi-cd41ed1758f4842d7b78870385e16b579cc89c38.tar.gz
kmi-cd41ed1758f4842d7b78870385e16b579cc89c38.zip
implement dmem semi-properlyHEADmaster
+ Add tests and fix virtual mapping, this is enough to start writing proper userspace drivers
Diffstat (limited to 'src')
-rw-r--r--src/dmem.c77
-rw-r--r--src/fdt.c15
-rw-r--r--src/uapi/dispatch.c2
-rw-r--r--src/uapi/mem.c4
-rw-r--r--src/vmem.c9
5 files changed, 70 insertions, 37 deletions
diff --git a/src/dmem.c b/src/dmem.c
index d21a9c5..6b98003 100644
--- a/src/dmem.c
+++ b/src/dmem.c
@@ -19,13 +19,8 @@ static struct mem_region_root post_ram = { 0 };
stat_t init_devmem(pm_t ram_base, pm_t ram_top)
{
- size_t pre_pages = __pages(ram_base);
- size_t ram_pages = __pages(ram_top - ram_base);
- /* -1 being the effective highest address possible */
- size_t post_pages = __pages(-1) - ram_pages - pre_pages;
-
- init_region(&pre_ram, 0, pre_pages, 0);
- init_region(&post_ram, ram_top, post_pages, 0);
+ init_region(&pre_ram, 0, ram_base, 0);
+ init_region(&post_ram, ram_top, -1, 0);
return OK;
}
@@ -54,39 +49,83 @@ vm_t alloc_devmem(struct tcb *t, pm_t start, size_t bytes, vmflags_t flags)
if (!region)
return NULL;
- vm_t v = alloc_region(region, bytes, &bytes, flags);
- if (!v)
+ /* carve out physical region (vm_t is misleading, this region is
+ * physical memory) */
+ vm_t p = alloc_fixed_region(region, start, bytes, &bytes, flags);
+ if (!p)
+ return NULL;
+
+ /* carve out virtual region */
+ vm_t v = alloc_region(&t->uvmem.region, bytes, &bytes, flags | MR_DEV);
+ if (!v) {
+ free_region(region, p);
return NULL;
+ }
- if (map_fixed_region(t->proc.vmem, v, start, bytes, flags)) {
+ /* convert from literal physical address to direct mapping address,
+ * which map_* expects (kind of annoying to deal with, admittedly, is
+ * there maybe a better way to handle these things?) */
+ p = (pm_t)__va(p);
+ if (map_fixed_region(t->proc.vmem, v, p, bytes, flags)) {
unmap_region(t->proc.vmem, v, bytes);
- free_region(region, v);
+ free_region(&t->uvmem.region, v);
+ free_region(region, p);
return NULL;
}
return v;
}
-stat_t free_devmem(struct tcb *t, vm_t start)
+stat_t free_known_devmem(struct tcb *t, struct mem_region *m)
{
assert(t && is_proc(t));
+
+ /* ensure region is a device memory region and is currently not shared */
+ assert(is_set(m->flags, MR_DEV));
+ assert(m->pid != 0 || m->refcount == 1);
+
pm_t addr = 0;
- stat_vpage(t->proc.vmem, start, &addr, NULL, NULL);
+ stat_vpage(t->proc.vmem, __addr(m->start), &addr, NULL, NULL);
- struct mem_region_root *region = __select_region((pm_t)__pa(addr));
+ /* free physical device memory */
+ pm_t p = (pm_t)__pa(addr);
+ struct mem_region_root *region = __select_region(p);
if (!region)
return ERR_INVAL;
+ free_region(region, p);
- struct mem_region *m = find_used_region(region, start);
- if (!m)
- return ERR_NF;
-
+ /* free virtual allocation associated with device mem */
vm_t base = __addr(m->start);
vm_t end = __addr(m->end);
+
+ /* free virtual memory associated with physical mapping */
size_t size = end - base;
unmap_fixed_region(t->proc.vmem, base, size);
- free_region(region, base);
+ free_known_region(&t->uvmem.region, m);
+ return OK;
+}
+
+stat_t free_devmem(struct tcb *t, vm_t start)
+{
+ assert(t && is_proc(t));
+ struct mem_region *m = find_used_region(&t->uvmem.region, start);
+ if (!m)
+ return ERR_NF;
+
+ /* not a devmem region */
+ if (!is_set(m->flags, MR_DEV))
+ return ERR_INVAL;
+
+ /* mapping is shared, can't free right now */
+ if (m->pid == 0 && m->refcount > 1)
+ return ERR_INVAL;
+
+ stat_t ret = free_known_devmem(t, m);
+ if (ret)
+ return ret;
+
+ free_known_region(&t->uvmem.region, m);
return OK;
}
diff --git a/src/fdt.c b/src/fdt.c
deleted file mode 100644
index 677be7b..0000000
--- a/src/fdt.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file fdt.c
- * Helper functions for handling the global FDT.
- */
-
-#include <libfdt.h>
-
-struct cell_info get_cellinfo(const void *fdt, const int offset)
-{
- return (struct cell_info){ fdt_size_cells(fdt, offset),
- fdt_address_cells(fdt, offset) };
-}
diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c
index 2eef5bc..4d10bbe 100644
--- a/src/uapi/dispatch.c
+++ b/src/uapi/dispatch.c
@@ -49,7 +49,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_NOOP: sys_noop(t, a, b, c, d, e); break;
case SYS_PUTCH: sys_putch(t, a, b, c, d, e); break;
case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break;
- case SYS_REQ_PMEM: sys_req_pmem(t, a, b, c, d, e); break;
+ case SYS_REQ_DMEM: sys_req_dmem(t, a, b, c, d, e); break;
case SYS_REQ_PAGE: sys_req_page(t, a, b, c, d, e); break;
case SYS_REQ_FIXMEM: sys_req_fixmem(t, a, b, c, d, e); break;
case SYS_REQ_SHAREDMEM: sys_req_sharedmem(t, a, b, c, d, e); break;
diff --git a/src/uapi/mem.c b/src/uapi/mem.c
index 7a233a5..20abc96 100644
--- a/src/uapi/mem.c
+++ b/src/uapi/mem.c
@@ -82,7 +82,7 @@ SYSCALL_DEFINE1(free_mem)(struct tcb *t, sys_arg_t start)
}
/**
- * Request physical memory syscall handler.
+ * Request device memory syscall handler.
*
* @param t Current tcb.
* @param paddr Physical address to map.
@@ -91,7 +91,7 @@ SYSCALL_DEFINE1(free_mem)(struct tcb *t, sys_arg_t start)
* @return \ref OK and start of allocation when succesful,
* otherwise an error code.
*/
-SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
+SYSCALL_DEFINE3(req_dmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
sys_arg_t flags)
{
/* this will require some pondering, but essentially this syscall should
diff --git a/src/vmem.c b/src/vmem.c
index 76e0ece..afdac95 100644
--- a/src/vmem.c
+++ b/src/vmem.c
@@ -12,6 +12,7 @@
#include <kmi/panic.h>
#include <kmi/debug.h>
#include <kmi/bits.h>
+#include <kmi/dmem.h>
#include <kmi/vmem.h>
#include <arch/vmem.h>
@@ -197,6 +198,14 @@ static void __free_mapping(struct tcb *t, struct mem_region *m)
if (is_set(m->flags, MR_NONBACKED))
return;
+ if (is_set(m->flags, MR_DEV)) {
+ stat_t ret = free_known_devmem(t, m);
+ MAYBE_UNUSED(ret);
+
+ assert(ret == OK);
+ return;
+ }
+
pm_t start = __addr(m->start);
pm_t end = __addr(m->end);
size_t size = end - start;