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