Capabilities #
Each resource on the system — memory, I/O ports, threads, etc — is a kernel object on Helios. Each of these kernel objects can be referenced from userspace with capabilities. These references can be copied, moved, destroyed, and sent or received between threads or processes. When the last capability referencing a kernel object is destroyed, the object is released.
During system initialization, the kernel provisions sufficient resources to start the initial process, then transfers ownership over all of the required capabilities, plus any additional capabilities that are available at boot, to the init process. From this point onward, all kernel objects are semantically owned and managed by userspace processes.
Each capability is stored in a capability slot, which is a small object in memory which is accessible to the kernel but not to userspace. Most userspace tasks will invoke these capabilities to make use of the associated kernel objects via a capability space, or CSpace. A cspace is itself a capability which stores a (configurable) number of capability slots. Each task is associated with one cspace and invokes them by providing the index of the capability slot they wish to use as a 32-bit unsigned integer. For example, when calling the identify syscall, the user places the index of the desired capability into the first ABI register (e.g. %rdi on x86_64), zero indexed. Calling identify on capability address 4 (caddr 4) looks up the fifth capability slot in the calling task’s configured cspace.
For those familiar with Unix-like systems, a capability can be thought of as a more general form of a file descriptor, and a capability space is a more general form of a file descriptor table.