The distinction between 'ipc.h' and 'ipc_generic.h' is no more. The only
use case for platform-specific extensions of the IPC support was the
marshalling of capabilities. However, this case is accommodated by a
function interface ('_marshal_capability', '_unmarshal_capability'). By
moving the implementation of these functions from the headers into the
respective ipc libraries, we can abandon the platform-specific 'ipc.h'
headers.
The cleanup call must be performed already during the _dissolve function
shortly after the object at the cap_session is freed up. Otherwise there
is the chance that an in-flight IPC will find the to be dissolved function
again.
Bomb test triggered the case, that a already dissolved rpc_object was found
by a in-flight IPC. If the rpc_object was already freed up by alloc->destroy
the thread using this stale rpc_object pointer cause page-faults in core.
Fixes partly #549
If we ran out of capabilities indexes, the bit allocator throws an exception.
If this happens the code seems to hang and nothing happens.
Instead one could catch the exception and print some diagnostic message.
This would be nice, but don't work. Printing some diagnostic message itself
tries to do potentially IPC and will allocate new capability indexes at
least for the receive window.
So, catch the exception and let the thread die, so at least the instruction
pointer is left as trace to identify the reason of the trouble.
Fixes#625
On Linux, we want to attach additional attributes to processes, i.e.,
the chroot location, the designated UID, and GID. Instead of polluting
the generic code with such Linux-specific platform details, I introduced
the new 'Native_pd_args' type, which can be customized for each
platform. The platform-dependent policy of init is factored out in the
new 'pd_args' library.
The new 'base-linux/run/lx_pd_args.run' script can be used to validate
the propagation of those attributes into core.
Note that this patch does not add the interpretation of the new UID and
PID attributes by core. This will be subject of a follow-up patch.
Related to #510.
Extend tracking of delegated and of translated items. The additional
information is used to solely free up unused/unwanted mapped capabilities and
to avoid unnecessary revokes on capability indexes where nothing have been
received.
Fixes#430
Unify handling of UTCBs. The utcb of the main thread is with commit
ea38aad30e at a fixed location - per convention.
So we can remove all the ugly code to transfer the utcb address during process
creation.
To do so also the UTCB of the main thread of Core must be inside Genode's
thread context area to handle it the same way. Unfortunately the UTCB of the
main thread of Core can't be chosen, it is defined by the kernel.
Possible solutions:
- make virtual address of first thread UTCB configurable in hypervisor
- map the utcb of the first thread inside Core to the desired location
This commit implements the second option.
Kernel patch: make utcb map-able
With the patch the Utcb of the main thread of Core is map-able.
Fixes#374
Noux actually uses the sp variable during thread creation and expects to be
set accordingly. This wasn't the case for the main thread, it was ever set
to the address of the main thread UTCB.
Move the context area close to the end of the virtual user available address,
so that Vancouver can obtain as much as possible of the lower virtual address
range for VMs.
This patch introduces the functions 'affinity' and 'num_cpus' to the CPU
session interface. The interface extension will allow the assignment of
individual threads to CPUs. At this point, it is just a stub with no
actual platform support.
The cpu_session interface fails to be virtualized by gdb_monitor because
platform-nova uses an extended nova_cpu_session interface.
The problem was that threads have been created directly at core without
knowledge of gdb_monitor. This lead to the situation that gdb_monitor didn't
know of all threads to be debugged.
Tunnel the additional parameters required on base-nova through the state()
call of the cpu_session interface before the thread actual is started.
The kernel provides a "recall" feature issued on threads to force a thread into
an exception. In the exception the current state of the thread can be obtained
and its execution can be halted/paused.
However, the recall exception is only delivered when the next time the thread
would leave the kernel. That means the delivery is asynchronous and Genode has
to wait until the exception triggered.
Waiting for the exception can either be done in the cpu_session service or
outside the service in the protection domain of the caller.
It turned out that waiting inside the cpu_service is prone to deadlock the
system. The cpu_session interface is one of many session interfaces handled by
the same thread inside Core.
Deadlock situation:
* The caller (thread_c) to pause some thread_p manages to establish the call
to the cpu_session thread_s of Core but get be interrupted before issuing
the actual pause (recall) command.
* Now the - to be recalled thread_p - is scheduled and tries to invoke another
service of Core, like making log output.
* Since the Core thread_s is handling the session request of thread_c, the
kernel uses the timeslice of thread_p to help to finish the request handled
by thread_s.
* Thread_s issues the actual pause/recall on thread_p and blocks inside Core
to wait for the recall exception to be issued.
* thread_p will leave not the kernel before finishing it actual IPC with
thread_s which is blocked waiting for thread_p.
That is the reason why the waiting/blocking for the recall exception taking
place must be done on NOVA in the context of the caller (thread_1).
Introduce a pause_sync call to the cpu_session which returns a semaphore
capability to the caller. The caller blocks on the semaphore and is woken up
when the pager of thread_p receives the recall exception with the state of
thread_p.
Multiple calls to get the dataspace capability on NOVA lead to the situation
that the caller gets each time a new mapping of the same capability at
different indexes.
The client/caller assumes to get every time the very same index, e.g. in
Noux the index is used to look up structures.
Cache the dataspace capability returned via a rm_session for base-nova.
Extend Native_capability type to hold a specific selector index where the to
be received cap during a IPC should be mapped to. This feature is required to
place created caps by the cap_session at specific indexes. This feature is
used by Vancouver to setup the virtualization exception portals (created by
the cap_session) at the intended indexes.
Patch prevents following bugs:
* In sleep_forever the thread return from semaphore down if cap is revoked
during destruction of a thread. This causes an endless loop consuming time
not available for other threads.
* In lock_helper and cap_sel_alloc the thread return from the lock() method
even if the semaphore down call failed because of an revoked semaphore.
This lead to the situation that a thread subject to de-construction returns
from the lock method, but not holding the lock, entering the critical section
and modifying state inside the critical section. Another thread in parallel
already in the critical section or entering the critical section also
modifies the state. This lead to curious bugs ...
* thread_nova, thread_start, irq_session
Detect early bugs if the SM is gone unexpectedly where it should never
happen.
It now can hold a right bit used during IPC to demote rights of the to be
transfered capability.
The local_name field in the native_capability type is not needed anymore
in NOVA. Simplify the class, remove it from constructors and adapt all
invocations in base-nova.
Unfortunately local_name in struct Raw is still used in generic base code
(process.cc, reload_parent_cap.cc), however has no effect in base-nova.
MsgBuf has to keep the number of received capabilities in order
to free/know correctly unused and unwanted capabilities. Explicitly
call rcv_msg->post_ipc to store this information in a MsgBuf.
Don't reset rcv_msg in ipc.cc, since this is used during
un-marshalling of caps in ipc.h afterwards. The MsgBuf is reseted when its
de-constructor is called.
With this patch solely the local ids are used, no global unique ids
are transfered anymore during IPC.
demo.run, signal.run, noux_tool_chain.run works up to the same
point as before the patches for issue #268.
Fixes#268
Kernel patch:
Introduce a transfer item type to express that a cap should be translated
and if this fails to map it instead.
It would be possible without this combined transfer item type however
with additional overhead. In this case Genode/NOVA would
have to map and translate all caps used as parameter in IPC. It would look
like this:
* If the map and translation succeed, the cap at the new cap index
would have to be revoked. Then the translated cap index can be used.
* If the map succeeds and the translation fails then the mapped cap index
can be used.
* It would become complicated when multiple caps are mapped and translated
and only some of the translation succeed. In such cases Genode would have
to figure out the right relation of translated/mapped and not
translated/mapped caps. It would require to make some assumption about the
order how translated/mapped caps are reported at the UTCB by the kernel.
All the points above lead to the decision to create a separate transfer item
type for that.
Genode:
Most the times the translation succeeds, mapping of caps happens either
seldom. This takes now a bit the pressure of not enough aligned receive
cap windows as described in issue #247.
The patch mainly adds adjustments to handle the
translated and mapped caps correctly especially during freeing of the
receive window (don't free translated cap indexes).
Fixes#268