Files
mango/syscall/vm-object.c

173 lines
3.5 KiB
C
Raw Normal View History

2026-02-19 19:21:50 +00:00
#include <kernel/handle.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/syscall.h>
#include <kernel/vm-object.h>
#include <kernel/vm-region.h>
kern_status_t sys_vm_object_create(
const char *name,
2026-02-19 19:21:50 +00:00
size_t name_len,
size_t data_len,
vm_prot_t prot,
kern_handle_t *out_handle)
{
2026-02-19 19:21:50 +00:00
struct task *self = current_task();
if ((name || name_len) && !validate_access_r(self, name, name_len)) {
return KERN_MEMORY_FAULT;
}
if (!validate_access_w(self, out_handle, sizeof *out_handle)) {
return KERN_MEMORY_FAULT;
}
struct vm_object *obj
= vm_object_create(name, name_len, data_len, prot);
if (!obj) {
return KERN_NO_MEMORY;
}
kern_status_t status
= task_open_handle(self, &obj->vo_base, 0, out_handle);
if (status != KERN_OK) {
object_unref(&obj->vo_base);
return status;
}
return KERN_OK;
}
kern_status_t sys_vm_object_read(
kern_handle_t object,
void *dst,
off_t offset,
size_t count,
size_t *nr_read)
{
struct task *self = current_task();
if (!validate_access_w(self, dst, count)) {
return KERN_MEMORY_FAULT;
}
if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) {
return KERN_MEMORY_FAULT;
}
struct object *obj = NULL;
handle_flags_t flags = 0;
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
if (status != KERN_OK) {
return status;
}
struct vm_object *vmo = vm_object_cast(obj);
if (!vmo) {
return KERN_INVALID_ARGUMENT;
}
return vm_object_read(vmo, dst, offset, count, nr_read);
}
kern_status_t sys_vm_object_write(
kern_handle_t object,
const void *src,
off_t offset,
size_t count,
size_t *nr_written)
{
struct task *self = current_task();
if (!validate_access_r(self, src, count)) {
return KERN_MEMORY_FAULT;
}
if (nr_written
&& !validate_access_w(self, nr_written, sizeof *nr_written)) {
return KERN_MEMORY_FAULT;
}
struct object *obj = NULL;
handle_flags_t flags = 0;
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
if (status != KERN_OK) {
return status;
}
struct vm_object *vmo = vm_object_cast(obj);
if (!vmo) {
return KERN_INVALID_ARGUMENT;
}
return vm_object_write(vmo, src, offset, count, nr_written);
}
kern_status_t sys_vm_object_copy(
kern_handle_t dst,
off_t dst_offset,
kern_handle_t src,
off_t src_offset,
size_t count,
size_t *nr_copied)
{
tracek("vm_object_copy(%x, %zx, %x, %zx, %zx, %p)",
dst,
dst_offset,
src,
src_offset,
count,
nr_copied);
2026-02-19 19:21:50 +00:00
struct task *self = current_task();
if (nr_copied
&& !validate_access_w(self, nr_copied, sizeof *nr_copied)) {
return KERN_MEMORY_FAULT;
}
unsigned long flags;
task_lock_irqsave(self, &flags);
kern_status_t status;
struct object *dst_obj = NULL, *src_obj = NULL;
handle_flags_t dst_flags = 0, src_flags = 0;
status = task_resolve_handle(self, dst, &dst_obj, &dst_flags);
if (status != KERN_OK) {
task_unlock_irqrestore(self, flags);
return status;
}
status = task_resolve_handle(self, src, &src_obj, &src_flags);
if (status != KERN_OK) {
task_unlock_irqrestore(self, flags);
return status;
}
object_ref(src_obj);
object_ref(dst_obj);
task_unlock_irqrestore(self, flags);
struct vm_object *dst_vmo = vm_object_cast(dst_obj);
struct vm_object *src_vmo = vm_object_cast(src_obj);
if (!dst_vmo || !src_vmo) {
object_unref(src_obj);
object_unref(dst_obj);
return KERN_INVALID_ARGUMENT;
}
status = vm_object_copy(
dst_vmo,
dst_offset,
src_vmo,
src_offset,
count,
nr_copied);
object_unref(src_obj);
object_unref(dst_obj);
return status;
}