summaryrefslogtreecommitdiffstats
path: root/sys/syscall_pcb.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-10-13 22:31:43 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-10-13 22:31:43 -0400
commit548506392b789f58b1556a6ffca917441e1d89fd (patch)
tree58e4b747446ea64e7951e523353f58510b3a8b2f /sys/syscall_pcb.c
parentc5e3bb7917689bc9ed54fee23a143144fade802d (diff)
downloadjove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.gz
jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.bz2
jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.zip
ipc functions. work on process spawning
Diffstat (limited to 'sys/syscall_pcb.c')
-rw-r--r--sys/syscall_pcb.c172
1 files changed, 169 insertions, 3 deletions
diff --git a/sys/syscall_pcb.c b/sys/syscall_pcb.c
index 4fe557b..3aeb22b 100644
--- a/sys/syscall_pcb.c
+++ b/sys/syscall_pcb.c
@@ -6,17 +6,20 @@
#include "proc/process.h"
#include "proc/scheduler.h"
#include "syscall.h"
-#include "errno.h"
int
s_syscall_pcb_yield(jove_owned_obj_t *pcb_obj,
size_t bytes_left,
void *payload_data)
{
+ //Validate that message is big enough for payload
size_t bytes_needed = sizeof(pid_t);
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
+ //Get subject PID from payload.
pid_t subject_pid = *((pid_t*)payload_data);
+
+ //Yield to target.
return scheduler_yield(subject_pid);
}
@@ -27,13 +30,22 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj,
size_t bytes_left,
void *payload_data)
{
+ //Validate that message is big enough for payload.
size_t bytes_needed = sizeof(struct syscall_pcb_send);
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
-
struct syscall_pcb_send *payload = payload_data;
+
+ //Validate that message is big enough for payload object path.
bytes_needed += payload->send_path_length;
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for subject path");
+ //Validate that subject object path is not the root directory.
+ if(payload->send_path_length == 0) {
+ kprintf("%s: Unable to send root directory\n", __func__);
+ return -EBADPATH;
+ }
+
+ //Validate that the subject objdir path is valid.
jove_perm_obj_t subject_objdir = link_try_traverse_objdir(
objdir_obj, lockstack, payload->send_path_length - 1, payload->send_path);
if(errno) {
@@ -41,8 +53,11 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj,
payload->send_path, payload->send_path_length, errstr(errno));
return -errno;
}
+
+ //Validate that the currently running PCB has mutate permissions for this objdir.
CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send");
+ //Validate that the subject exists in the subject objdir.
jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj,
payload->send_path[payload->send_path_length-1]);
if(subject == 0) {
@@ -51,6 +66,7 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj,
return -errno;
}
+ //Send subject to target.
return pcb_send(obj_deref(pcb_obj), payload->send_target, subject, payload->send_timeout);
}
@@ -61,13 +77,16 @@ s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj,
size_t bytes_left,
void *payload_data)
{
+ //Validate that the message is big enough for the payload.
size_t bytes_needed = sizeof(struct syscall_pcb_recv);
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
-
struct syscall_pcb_recv *payload = payload_data;
+
+ //Validate that the message is big enough for the payload object.
bytes_needed += payload->recv_path_length * sizeof(objpath_part_t);
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for destination path");
+ //Validate that the destination object exists.
jove_perm_obj_t destination = link_try_traverse_objdir(
objdir_obj, lockstack, payload->recv_path_length, payload->recv_path);
if(errno) {
@@ -75,12 +94,147 @@ s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj,
payload->recv_path, payload->recv_path_length, errstr(errno));
return -errno;
}
+
+ //Validate that the destination path is JOVE_OBJ_NONE and that the object has recieve permissions.
+ CHECK_OBJTYPE(destination.obj, JOVE_OBJ_NONE, "Destination object is occupied");
CHECK_OBJPERM(destination, SYSCALL_PERM_PCB_RECV_DST, "Destination object does not permit recv.");
+ //Recieve from some PID into destination.
return pcb_recv(obj_deref(pcb_obj), payload->recv_target, destination.obj, payload->recv_timeout);
}
int
+s_syscall_pcb_swap(jove_owned_obj_t *pcb_obj,
+ lockstack_t *lockstack,
+ jove_owned_obj_t *objdir_obj,
+ size_t bytes_left,
+ void *payload_data)
+{
+ //Validate that the message is big enough for payload.
+ size_t bytes_needed = sizeof(struct syscall_pcb_recv);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
+ struct syscall_pcb_swap *payload = payload_data;
+
+ //Validate that the message is big enough for the subject path.
+ bytes_needed += payload->swap_path_length * sizeof(objpath_part_t);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for swap path");
+
+ //Validate that the subject is not the rootdir.
+ if(payload->swap_path_length == 0) {
+ kprintf("%s: Unable to swap the root directory\n", __func__);
+ return -EBADPATH;
+ }
+
+ //Validate that the subject objdir exists.
+ jove_perm_obj_t subject_objdir = link_try_traverse_objdir(
+ objdir_obj, lockstack, payload->swap_path_length - 1, payload->swap_path);
+ if(errno) {
+ klogf("Unable to get subject %P objdir : %s\n",
+ payload->swap_path, payload->swap_path_length, errstr(errno));
+ return -errno;
+ }
+ //Validate that the subject objdir has send permissions.
+ CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send");
+
+ //Validate that the subject object exists.
+ jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj,
+ payload->swap_path[payload->swap_path_length-1]);
+ if(subject == 0) {
+ klogf("Unable to get subject %P object : %s\n",
+ payload->swap_path, payload->swap_path_length, errstr(errno));
+ return -errno;
+ }
+
+ //Validate that the target PCB exists.
+ if(pcb_frompid(payload->swap_target) == 0) {
+ klogf("Swap PCB target %i does not exist\n", payload->swap_target);
+ return -EBADPROC;
+ }
+
+ //Validate that the message was sent before timeout.
+ int send_result = pcb_send(
+ obj_deref(pcb_obj), payload->swap_target, subject, payload->send_timeout);
+ if(send_result < 0) {
+ klogf("Send to %i failed with code %s\n", payload->swap_target, errstr(-send_result));
+ return send_result;
+ }
+
+ //Validate that a message was recieved before timeout.
+ int recv_result = pcb_recv(
+ obj_deref(pcb_obj), payload->swap_target, subject, payload->recv_timeout);
+ return recv_result;
+}
+
+int
+s_syscall_pcb_stack(jove_owned_obj_t *pcb_obj,
+ lockstack_t *lockstack,
+ jove_owned_obj_t *rootdir,
+ size_t bytes_left,
+ void *payload_data)
+{
+ //Verify the message is big enough for the payload struct.
+ size_t bytes_needed = sizeof(struct syscall_pcb_stack);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
+
+ //Verify the message is big enough for the untyped object path.
+ struct syscall_pcb_stack *payload = payload_data;
+ bytes_needed += sizeof(objpath_part_t) * payload->stack_path_length;
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for untyped path");
+
+ jove_perm_obj_t untyped = link_try_traverse_objdir(rootdir, lockstack,
+ payload->stack_path_length, payload->stack_path);
+ //Verify the untyped object exists.
+ if(untyped.obj == NULL) {
+ klogf("Unable to get untyped %P : %s\n",
+ payload->stack_path, payload->stack_path_length, errstr(errno));
+ return -errno;
+ }
+
+ //Verify the correct type and permissions.
+ CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Subject untyped is not an untyped.");
+ CHECK_OBJPERM(untyped, SYSCALL_PERM_PCB_STACK_OBJ, "Untyped is missing permissions");
+
+ jove_untyped_t *untyped_data = obj_deref(untyped.obj);
+ if((uintptr_t)untyped_data & 0xFFF) {
+ klogf("Untyped object %P is not aligned to page boundary.\n",
+ payload->stack_path, payload->stack_path_length);
+ return -EALIGN;
+ }
+ if(untyped_data->limit != 0x1000) {
+ klogf("Untyped object %P is not page sized.\n",
+ payload->stack_path, payload->stack_path_length);
+ return -EBADSIZE;
+ }
+
+ //Set the stack. Error if bad type or stack already exists.
+ pcb_t *pcb = obj_deref(pcb_obj);
+ switch(payload->type) {
+ case PCB_STACK_SYSTEM:
+ if(pcb_get_syscall_stack(pcb) != 0) {
+ klogf("PCB %p Already has a system stack!\n", pcb);
+ return -EFULL;
+ }
+ pcb_set_syscall_stack(pcb, obj_getvalue(untyped.obj));
+ break;
+ case PCB_STACK_INTERRUPT:
+ if(pcb_get_interrupt_stack(pcb) != 0) {
+ klogf("PCB %p Already has a interrupt stack!\n", pcb);
+ return -EFULL;
+ }
+ pcb_set_interrupt_stack(pcb, obj_getvalue(untyped.obj));
+ break;
+ default:
+ klogf("Unknown stack type %i\n", payload->type);
+ return -EBADARG;
+ }
+
+ //Destroy untyped object.
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
+ obj_setvalue(untyped.obj, 0);
+ return 0;
+}
+
+int
_syscall_handle_pcb(syscall_context_t *ctx)
{
switch(ctx->header->callid) {
@@ -101,6 +255,18 @@ _syscall_handle_pcb(syscall_context_t *ctx)
ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload);
return -EPERM;
+ case SYSCALL_PCB_SWAP:
+ if(ctx->target.permissions & SYSCALL_PERM_PCB_SWAP)
+ return s_syscall_pcb_swap(
+ ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
+ case SYSCALL_PCB_STACK:
+ if(ctx->target.permissions & SYSCALL_PERM_PCB_STACK)
+ return s_syscall_pcb_stack(
+ ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
default:
return -EBADCALL;
}