Syscall interface
The jsix kernel’s syscall design is based around object handles. Object handles are also a collection of capabilities, encoding certain rights over the object they reference.
Very few syscalls in jsix can be made without some handle, and most of them are requests to the kernel to create a given kind of object. This is analogous to methods on an object in an object-oriented programming language.
object
syscalls
All kernel-exposed objects inherit from the base object
type, so the
object
syscalls can be used with any object’s handle.
- capabilites:
clone
-
j6_result_t j6_object_koid(j6_handle_t self, uint64_t *koid)
Get the internal kernel object id of an object
- Parameters:
self – Handle to the object object
koid – [out] Undocumented
event
syscalls
An event
is a simple synchronization object. It contains up to 64 signals
that threads can wait for and signal in parallel.
- capabilites:
signal
,wait
-
j6_result_t j6_event_create(j6_handle_t *self)
Undocumented
- Parameters:
self – [out] Handle to the new event object
-
j6_result_t j6_event_signal(j6_handle_t self, uint64_t signals)
Signal events on this object
- Capabilities:
signal
- Parameters:
self – Handle to the event object
signals – A bitset of which events to signal
-
j6_result_t j6_event_wait(j6_handle_t self, uint64_t *signals, uint64_t timeout)
Wait for signaled events on this object
- Capabilities:
wait
- Parameters:
self – Handle to the event object
signals – [out] A bitset of which events were signaled
timeout – Wait timeout in nanoseconds
mailbox
syscalls
Mailboxes are objects that enable synchronous IPC via arbitrary message-passing of tagged data and/or handles. Not as efficient as shared memory channels, but more flexible.
- capabilites:
send
,receive
,close
-
j6_result_t j6_mailbox_create(j6_handle_t *self)
Undocumented
- Parameters:
self – [out] Handle to the new mailbox object
-
j6_result_t j6_mailbox_close(j6_handle_t self)
Undocumented
- Capabilities:
close
- Parameters:
self – Handle to the mailbox object
-
j6_result_t j6_mailbox_call(j6_handle_t self, uint64_t *tag, void *data, size_t *data_len, size_t data_size, j6_handle_t *handles, size_t *handles_count, size_t handles_size)
Send a message to the reciever, and block until a response is sent. Note that getting this response does not require the receive capability.
- Capabilities:
send
- Parameters:
self – Handle to the mailbox object
tag – [inout] Undocumented
data – [optional, inout] Undocumented
data_size – number of total bytes in data buffer
handles – [optional, inout, handle, list] Undocumented
handles_size – total size of handles buffer
-
j6_result_t j6_mailbox_respond(j6_handle_t self, uint64_t *tag, void *data, size_t *data_len, size_t data_size, j6_handle_t *handles, size_t *handles_count, size_t handles_size, uint64_t *reply_tag, uint64_t flags)
Respond to a message sent using call, and wait for another message to arrive. Note that this does not require the send capability. A reply tag of 0 skips the reply and goes directly to waiting for a new message.
- Capabilities:
receive
- Parameters:
self – Handle to the mailbox object
tag – [inout] Undocumented
data – [optional, inout] Undocumented
data_size – number of total bytes in data buffer
handles – [optional, inout, handle, list] Undocumented
handles_size – total size of handles buffer
reply_tag – [inout] Undocumented
flags – Undocumented
process
syscalls
A process
object represents a process running on the system, and allows
control over the threads, handles, and virtual memory space of that process.
- capabilites:
kill
,create_thread
-
j6_result_t j6_process_create(j6_handle_t *self, const char *name)
Create a new empty process
- Parameters:
self – [out] Handle to the new process object
name – Undocumented
-
j6_result_t j6_process_kill(j6_handle_t self)
Stop all threads and exit the given process
- Capabilities:
kill
- Parameters:
self – Handle to the process object
-
j6_result_t j6_process_exit(int64_t result)
Stop all threads and exit the current process
- Parameters:
result – The result to retrun to the parent process
-
j6_result_t j6_process_give_handle(j6_handle_t self, j6_handle_t target)
Give the given process a handle that points to the same object as the specified handle.
- Parameters:
self – Handle to the process object
target – [handle] A handle in the caller process to send
system
syscalls
The singular system
object represents a handle to kernel functionality
needed by drivers and other priviledged services.
- capabilites:
get_log
,bind_irq
,map_phys
,change_iopl
-
j6_result_t j6_system_get_log(j6_handle_t self, uint64_t seen, void *buffer, size_t *buffer_len)
Get the next log line from the kernel log
- Capabilities:
get_log
- Parameters:
self – Handle to the system object
seen – Last seen log id
buffer – [out, zero_ok] Buffer for the log message data structure
-
j6_result_t j6_system_bind_irq(j6_handle_t self, j6_handle_t dest, unsigned irq, unsigned signal)
Ask the kernel to send this process messages whenever the given IRQ fires
- Capabilities:
bind_irq
- Parameters:
self – Handle to the system object
dest – Event object that will receive messages
irq – IRQ number to bind
signal – Signal number on the event to bind to
-
j6_result_t j6_system_map_phys(j6_handle_t self, j6_handle_t *area, uintptr_t phys, size_t size, uint32_t flags)
Create a VMA and map an area of physical memory into it, also mapping that VMA into the current process
- Capabilities:
map_phys
- Parameters:
self – Handle to the system object
area – [out] Receives a handle to the VMA created
phys – The physical address of the area
size – Size of the area, in bytes
flags – Flags to apply to the created VMA
-
j6_result_t j6_system_request_iopl(j6_handle_t self, unsigned iopl)
Request the kernel change the IOPL for this process. The only values that make sense are 0 and 3.
- Capabilities:
change_iopl
- Parameters:
self – Handle to the system object
iopl – The IOPL to set for this process
thread
syscalls
A thread
object represents a thread of execution within a process running
on the system. The actual thread does not need to be currently running to
hold a handle to it.
- capabilites:
kill
,join
-
j6_result_t j6_thread_create(j6_handle_t *self, j6_handle_t process, uintptr_t stack_top, uintptr_t entrypoint, uint64_t arg0, uint64_t arg1)
Undocumented
- Parameters:
self – [out] Handle to the new thread object
process – [optional, cap] Undocumented
stack_top – Undocumented
entrypoint – Undocumented
arg0 – Undocumented
arg1 – Undocumented
-
j6_result_t j6_thread_kill(j6_handle_t self)
Undocumented
- Capabilities:
kill
- Parameters:
self – Handle to the thread object
-
j6_result_t j6_thread_join(j6_handle_t self)
Undocumented
- Capabilities:
join
- Parameters:
self – Handle to the thread object
-
j6_result_t j6_thread_exit()
Undocumented
-
j6_result_t j6_thread_sleep(uint64_t duration)
Undocumented
- Parameters:
duration – Undocumented
vma
syscalls
A vma
object represents a single virtual memory area, which may be shared
between several processes. A process having a handle to a vma
does not
necessarily mean that it is mapped into that process’ virtual memory space.
- capabilites:
map
,unmap
,resize
-
j6_result_t j6_vma_create(j6_handle_t *self, size_t size, uint32_t flags)
Undocumented
- Parameters:
self – [out] Handle to the new vma object
size – Undocumented
flags – Undocumented
-
j6_result_t j6_vma_create_map(j6_handle_t *self, size_t size, uintptr_t *address, uint32_t flags)
Undocumented
- Capabilities:
map
- Parameters:
self – [out] Handle to the new vma object
size – Undocumented
address – [inout] Undocumented
flags – Undocumented
-
j6_result_t j6_vma_map(j6_handle_t self, j6_handle_t process, uintptr_t *address, uint32_t flags)
Undocumented
- Capabilities:
map
- Parameters:
self – Handle to the vma object
process – [optional] Undocumented
address – [inout] Undocumented
flags – Undocumented
-
j6_result_t j6_vma_unmap(j6_handle_t self, j6_handle_t process)
Undocumented
- Capabilities:
unmap
- Parameters:
self – Handle to the vma object
process – [optional] Undocumented
-
j6_result_t j6_vma_resize(j6_handle_t self, size_t *size)
Undocumented
- Capabilities:
resize
- Parameters:
self – Handle to the vma object
size – [inout] New size for the VMA, or 0 to query the current size without changing
Non-object syscalls
The following are the system calls that aren’t constructors for objects, and either do not require an object handle, or operate generically on handles.
-
j6_result_t j6_noop()
Simple no-op syscall for testing
-
j6_result_t j6_log(uint8_t area, uint8_t severity, const char *message)
Write a message to the kernel log
- Parameters:
area – Undocumented
severity – Undocumented
message – Undocumented
-
j6_result_t j6_handle_list(struct j6_handle_descriptor *handles, size_t *handles_size)
Get a list of handles owned by this process. If the supplied list is not big enough, will set the size needed in size and return j6_err_insufficient
- Parameters:
handles – [list, inout, zero_ok] A list of handles to be filled
-
j6_result_t j6_handle_clone(j6_handle_t orig, j6_handle_t *clone, uint32_t mask)
Create a clone of an existing handle, possibly with some capabilities masked out.
- Parameters:
orig – [handle, cap] The handle to clone
clone – [out] The new handle
mask – The capability bitmask
-
j6_result_t j6_handle_close(j6_handle_t hnd)
Close the handle to an object
- Parameters:
hnd – [handle] The handle to close
-
j6_result_t j6_futex_wait(const uint32_t *address, uint32_t current, uint64_t timeout)
Block waiting on a futex
- Parameters:
address – Address of the futex value
current – Current value of the futex
timeout – Wait timeout in nanoseconds
-
j6_result_t j6_futex_wake(const uint32_t *address, uint64_t count)
Wake threads waiting on a futex
- Parameters:
address – Address of the futex value
count – Number of threads to wake, or 0 for all
-
j6_result_t j6_test_finish(uint32_t exit_code)
Testing mode only: Have the kernel finish and exit QEMU with the given exit code
- Parameters:
exit_code – Undocumented