Hello Denis,
let me start with the questions raised at the end of your posting:
I also have some general questions about Genode capabilities in Fiasco.OC: In the Genode Foundations book, on page 37, there is a figure (figure 2) with an RPC object and its object identity. What is an object identity in Fiasco.OC?
- How is it called there?
Note that the book is focused on NOVA and base-hw, which resemble the presented capability model quite closely. On other kernels like seL4 and Fiasco.OC, there is a slight mismatch between the kernel-provided capability mechanism and Genode's notion of capabilies. You can find a discussion of one important distinction at [1]. Hence, on these kernels, we need to "emulate" parts of Genode's capability model using the kernel features at hand.
[1] http://sel4.systems/pipermail/devel/2014-November/000112.html
On Fiasco.OC, an object identity consists of two parts:
1. An IPC gate bound to the entrypoint thread. The IPC gate is a Fiasco-internal kernel object. The user-level component refers to it via a kernel-capability selector, which is (like a file descriptor on Unix) a component-local number understood by the kernel. In Genode's code, we use the term "kcap" as an abbreviation of kernel capability selector. The kcap can be used as an argument for kernel operations, in particular as a destination for an IPC call.
Note that kcaps may refer to various kernel objects (like threads, tasks). But - a few exceptions notwithstanding - a Genode capability (as returned by 'Entrypoint::manage') refers to the kcap for an IPC gate.
2. A system-globally unique object ID, which is allocated by core's 'Pd_session::alloc_rpc_cap' operation. Unlike the kcap, the kernel has no idea what this ID is about. It is just a number. Within the Genode code, this number is called "badge" or "Rpc_obj_key". The badge value is used at the server side as a key for looking up the RPC object that belongs to an incoming RPC request.
Each Genode capability carries both parts. When a component inserts a new capability into its capability space, you can see both values as arguments to 'Capability_map::insert_map' (in base-foc/src/lib/base/cap_map.cc).
When a Genode capability is transferred as RPC argument (via 'copy_msgbuf_to_utcb' and 'extract_msg_from_utcb' in base-foc/src/lib/ipc.cc), you can see that the kcap part is passed as a 'L4_MAP_ITEM' whereas the badge is transferred as plain message word.
When a Genode capability is created for an RPC object ('Entrypoint::manage' -> 'PD_session::alloc_rpc_cap'), core imprints the new badge value into the new IPC gate. This way, whenever an IPC is sent to the IPC gate, the receiving thread (the server) receives the badge value of the invoked object directly from the kernel. This way, a misbehaving client cannot deliberately fake the badge when invoking an RPC object.
Given this background, I hope that my remark about base-hw in my previous email becomes more clear. On base-hw, we can simply use the value of a kernel capability selector as badge value. There is no need to system-globally unique ID values.
* ...the owner of the RPC object?
The kcap of a Genode capability refers to an IPC gate. The IPC gate is associated with a thread. The thread lives in a protection domain. The owner of an RPC object is therefore implicitly the PD that created the IPC gate (the caller of 'Entrypoint::manage') for the RPC object.
* ...which component has the data in memory?
Each component keeps track of its local capability space using some meta-data structures managed internally within the 'base' library. On Fiasco.OC, this data structure is called 'cap_map'. It maintains the association of 'kcap' values with their corresponding badges.
For the checkpointing/restarting, these data structure must be interpreted/updated from the monitoring component. This may be tricky because the cap_map is not designed to be easy to manipulate from the outside. I.e., it has an AVL tree with the badges as keys. By solely poking new badge values into the component's cap cap, the order of AVL nodes becomes corrupted.
It may be possible to simplify the cap-map implementation, removing the AVL tree. As far as I can see, the use cases for looking up a kcap by a badge no longer exists except for sanity checks within the implementation of the cap map itself. The method 'Capability_map::find' is actually unused.
* ...where it can be found in the address space?
The cap map is instantiated as local static variable of the function 'Genode::cap_map' in 'base-foc/src/lib/base/cap_map.cc'. Hence, it is located somewhere in the data segment of the binary. You'd need to somehow communicate the pointer value from the component to the monitor, e.g. by writing it to a dataspace shared between the two.
In particular, when the target component creates an Entrypoint object, then it creates a Native_capability (as Ipc_server) from a capability found in the utcb's thread control registers:
repos/base-foc/src/lib/base/ipc.cc:377
The Ipc_server capability is used in two calls to Pd_session::alloc_rpc_cap during Entrypoint object creation. The two calls go to Entrypoint::manage the Exit-handler for the Rpc_entrypoint and for the Signal_proxy_component for the Signal-API. To recreate those Native_capabilities at restore time, I have to use the same Ipc_server capability. How can this be done?
The Ipc_server capability is the kernel capability selector for the entrypoint thread. This selector is used to associate the new IPC gate with this particular thread. So IPCs sent to the IPC gate will arrive at the entrypoint thread. It is not a regular Genode capability because it refers to a thread instead of an IPC gate. Fortunately, the monitor is able to get hold of this capability because the component requests it by calling 'Cpu_thread::state' when creating a new thread (base-foc/src/lib/base/thread_start.cc).
Yes, the topic is really complicated. Is the confusion perfect now? ;-)
Cheers Norman