[docs] Add sphinx documentation
Add a first pass at documentation with sphinx.
This commit is contained in:
436
docs/syscall_interface.rst
Normal file
436
docs/syscall_interface.rst
Normal file
@@ -0,0 +1,436 @@
|
||||
.. jsix syscall interface.
|
||||
.. Automatically update from the definition files using cog!
|
||||
|
||||
.. [[[cog code generation
|
||||
.. from textwrap import indent
|
||||
.. from definitions.context import Context
|
||||
..
|
||||
.. ctx = Context(definitions_path)
|
||||
.. ctx.parse("syscalls.def")
|
||||
.. syscalls = ctx.interfaces["syscalls"]
|
||||
..
|
||||
.. def caplist(caps):
|
||||
.. return ', '.join([f"``{c}``" for c in caps])
|
||||
.. ]]]
|
||||
.. [[[end]]] (checksum: d41d8cd98f00b204e9800998ecf8427e)
|
||||
|
||||
The jsix syscall interface
|
||||
==========================
|
||||
|
||||
The jsix kernel's syscall design is based around object handles. Object handles
|
||||
are also a collections 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.
|
||||
|
||||
.. [[[cog code generation
|
||||
.. cog.outl()
|
||||
.. for obj in syscalls.exposes:
|
||||
.. cog.outl(f"``{obj.name}`` syscalls")
|
||||
.. cog.outl(f"-------------------------")
|
||||
.. desc = obj.desc or "Undocumented"
|
||||
.. cog.outl(desc)
|
||||
.. cog.outl()
|
||||
.. cog.outl(f":capabilites: {caplist(obj.caps)}")
|
||||
.. cog.outl()
|
||||
.. for method in obj.methods:
|
||||
.. args = []
|
||||
.. if method.constructor:
|
||||
.. args.append("j6_handle_t *self")
|
||||
.. elif not method.static:
|
||||
.. args.append("j6_handle_t self")
|
||||
..
|
||||
.. for param in method.params:
|
||||
.. for type, suffix in param.type.c_names(param.options):
|
||||
.. args.append(f"{type} {param.name}{suffix}")
|
||||
..
|
||||
.. cog.outl(f".. cpp:function:: j6_result_t j6_{obj.name}_{method.name} ({', '.join(args)})")
|
||||
.. cog.outl()
|
||||
.. desc = method.desc or "Undocumented"
|
||||
.. cog.outl(indent(desc, " "))
|
||||
.. cog.outl()
|
||||
.. if "cap" in method.options:
|
||||
.. cog.outl(f" :capabilities: {caplist(method.options['cap'])}")
|
||||
.. cog.outl()
|
||||
.. if method.constructor:
|
||||
.. cog.outl(f" :param self: *[out]* Handle to the new {obj.name} object")
|
||||
.. elif not method.static:
|
||||
.. cog.outl(f" :param self: Handle to the {obj.name} object")
|
||||
.. for param in method.params:
|
||||
.. opts = param.options and f"*[{', '.join(param.options)}]*" or ""
|
||||
.. desc = param.desc or 'Undocumented'
|
||||
.. cog.outl(f" :param {param.name}: {opts} {desc}")
|
||||
.. cog.outl()
|
||||
.. ]]]
|
||||
|
||||
``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``
|
||||
|
||||
.. cpp:function:: j6_result_t j6_object_koid (j6_handle_t self, uint64_t * koid)
|
||||
|
||||
Get the internal kernel object id of an object
|
||||
|
||||
:param self: Handle to the object object
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: j6_result_t j6_event_create (j6_handle_t *self)
|
||||
|
||||
Undocumented
|
||||
|
||||
:param self: *[out]* Handle to the new event object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_event_signal (j6_handle_t self, uint64_t signals)
|
||||
|
||||
Signal events on this object
|
||||
|
||||
:capabilities: ``signal``
|
||||
|
||||
:param self: Handle to the event object
|
||||
:param signals: A bitset of which events to signal
|
||||
|
||||
.. cpp:function:: 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``
|
||||
|
||||
:param self: Handle to the event object
|
||||
:param signals: *[out]* A bitset of which events were signaled
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: j6_result_t j6_mailbox_create (j6_handle_t *self)
|
||||
|
||||
Undocumented
|
||||
|
||||
:param self: *[out]* Handle to the new mailbox object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_mailbox_close (j6_handle_t self)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``close``
|
||||
|
||||
:param self: Handle to the mailbox object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_mailbox_call (j6_handle_t self, uint64_t * tag, void * data, size_t * data_len, size_t data_in_len, j6_handle_t * handles, size_t * handles_count)
|
||||
|
||||
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``
|
||||
|
||||
:param self: Handle to the mailbox object
|
||||
:param tag: *[inout]* Undocumented
|
||||
:param data: *[optional, inout]* Undocumented
|
||||
:param data_in_len: number of bytes in data used for input
|
||||
:param handles: *[optional, inout, handle, list]* Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_mailbox_respond (j6_handle_t self, uint64_t * tag, void * data, size_t * data_len, size_t data_in_len, j6_handle_t * handles, size_t * handles_count, 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``
|
||||
|
||||
:param self: Handle to the mailbox object
|
||||
:param tag: *[inout]* Undocumented
|
||||
:param data: *[optional, inout]* Undocumented
|
||||
:param data_in_len: number of bytes in data used for input
|
||||
:param handles: *[optional, inout, handle, list]* Undocumented
|
||||
:param reply_tag: *[inout]* Undocumented
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: j6_result_t j6_process_create (j6_handle_t *self)
|
||||
|
||||
Create a new empty process
|
||||
|
||||
:param self: *[out]* Handle to the new process object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_process_kill (j6_handle_t self)
|
||||
|
||||
Stop all threads and exit the given process
|
||||
|
||||
:capabilities: ``kill``
|
||||
|
||||
:param self: Handle to the process object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_process_exit (int32_t result)
|
||||
|
||||
Stop all threads and exit the current process
|
||||
|
||||
:param result: The result to retrun to the parent process
|
||||
|
||||
.. cpp:function:: 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.
|
||||
|
||||
:param self: Handle to the process object
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: 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``
|
||||
|
||||
:param self: Handle to the system object
|
||||
:param seen: Last seen log id
|
||||
:param buffer: *[out, zero_ok]* Buffer for the log message data structure
|
||||
|
||||
.. cpp:function:: 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``
|
||||
|
||||
:param self: Handle to the system object
|
||||
:param dest: Event object that will receive messages
|
||||
:param irq: IRQ number to bind
|
||||
:param signal: Signal number on the event to bind to
|
||||
|
||||
.. cpp:function:: 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``
|
||||
|
||||
:param self: Handle to the system object
|
||||
:param area: *[out]* Receives a handle to the VMA created
|
||||
:param phys: The physical address of the area
|
||||
:param size: Size of the area, in bytes
|
||||
:param flags: Flags to apply to the created VMA
|
||||
|
||||
.. cpp:function:: 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``
|
||||
|
||||
:param self: Handle to the system object
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: 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
|
||||
|
||||
:param self: *[out]* Handle to the new thread object
|
||||
:param process: *[optional, cap]* Undocumented
|
||||
:param stack_top: Undocumented
|
||||
:param entrypoint: Undocumented
|
||||
:param arg0: Undocumented
|
||||
:param arg1: Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_thread_kill (j6_handle_t self)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``kill``
|
||||
|
||||
:param self: Handle to the thread object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_thread_join (j6_handle_t self)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``join``
|
||||
|
||||
:param self: Handle to the thread object
|
||||
|
||||
.. cpp:function:: j6_result_t j6_thread_exit ()
|
||||
|
||||
Undocumented
|
||||
|
||||
|
||||
.. cpp:function:: j6_result_t j6_thread_sleep (uint64_t duration)
|
||||
|
||||
Undocumented
|
||||
|
||||
:param 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``
|
||||
|
||||
.. cpp:function:: j6_result_t j6_vma_create (j6_handle_t *self, size_t size, uint32_t flags)
|
||||
|
||||
Undocumented
|
||||
|
||||
:param self: *[out]* Handle to the new vma object
|
||||
:param size: Undocumented
|
||||
:param flags: Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_vma_create_map (j6_handle_t *self, size_t size, uintptr_t * address, uint32_t flags)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``map``
|
||||
|
||||
:param self: *[out]* Handle to the new vma object
|
||||
:param size: Undocumented
|
||||
:param address: *[inout]* Undocumented
|
||||
:param flags: Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_vma_map (j6_handle_t self, j6_handle_t process, uintptr_t * address, uint32_t flags)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``map``
|
||||
|
||||
:param self: Handle to the vma object
|
||||
:param process: *[optional]* Undocumented
|
||||
:param address: *[inout]* Undocumented
|
||||
:param flags: Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_vma_unmap (j6_handle_t self, j6_handle_t process)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``unmap``
|
||||
|
||||
:param self: Handle to the vma object
|
||||
:param process: *[optional]* Undocumented
|
||||
|
||||
.. cpp:function:: j6_result_t j6_vma_resize (j6_handle_t self, size_t * size)
|
||||
|
||||
Undocumented
|
||||
|
||||
:capabilities: ``resize``
|
||||
|
||||
:param self: Handle to the vma object
|
||||
:param size: *[inout]* New size for the VMA, or 0 to query the current size without changing
|
||||
|
||||
.. [[[end]]] (checksum: fe448e541c009a1bcf8bdc44f4760e32)
|
||||
|
||||
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.
|
||||
|
||||
.. [[[cog code generation
|
||||
.. cog.outl()
|
||||
.. for func in syscalls.functions:
|
||||
.. args = []
|
||||
.. for param in func.params:
|
||||
.. for type, suffix in param.type.c_names(param.options):
|
||||
.. args.append(f"{type} {param.name}{suffix}")
|
||||
..
|
||||
.. cog.outl(f".. cpp:function:: j6_result_t j6_{func.name} ({', '.join(args)})")
|
||||
.. cog.outl()
|
||||
.. desc = func.desc or "Undocumented"
|
||||
.. cog.outl(indent(desc, " "))
|
||||
.. cog.outl()
|
||||
.. for param in func.params:
|
||||
.. opts = param.options and f"*[{', '.join(param.options)}]*" or ""
|
||||
.. desc = param.desc or 'Undocumented'
|
||||
.. cog.outl(f" :param {param.name}: {opts} {desc}")
|
||||
.. cog.outl()
|
||||
.. ]]]
|
||||
|
||||
.. cpp:function:: j6_result_t j6_noop ()
|
||||
|
||||
Simple no-op syscall for testing
|
||||
|
||||
|
||||
.. cpp:function:: j6_result_t j6_log (uint8_t area, uint8_t severity, const char * message)
|
||||
|
||||
Write a message to the kernel log
|
||||
|
||||
:param area: Undocumented
|
||||
:param severity: Undocumented
|
||||
:param message: Undocumented
|
||||
|
||||
.. cpp:function:: 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
|
||||
|
||||
:param handles: *[list, inout, zero_ok]* A list of handles to be filled
|
||||
|
||||
.. cpp:function:: 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.
|
||||
|
||||
:param orig: *[handle, cap]* The handle to clone
|
||||
:param clone: *[out]* The new handle
|
||||
:param mask: The capability bitmask
|
||||
|
||||
.. cpp:function:: j6_result_t j6_futex_wait (const uint32_t * address, uint32_t current, uint64_t timeout)
|
||||
|
||||
Block waiting on a futex
|
||||
|
||||
:param address: Address of the futex value
|
||||
:param current: Current value of the futex
|
||||
:param timeout: Wait timeout in nanoseconds
|
||||
|
||||
.. cpp:function:: j6_result_t j6_futex_wake (const uint32_t * address, uint64_t count)
|
||||
|
||||
Wake threads waiting on a futex
|
||||
|
||||
:param address: Address of the futex value
|
||||
:param count: Number of threads to wake, or 0 for all
|
||||
|
||||
.. cpp:function:: 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
|
||||
|
||||
:param exit_code: Undocumented
|
||||
|
||||
.. [[[end]]] (checksum: b8b12e99a4a00c99b3859f05000a7bfd)
|
||||
|
||||
Reference in New Issue
Block a user