Hello Genode Community,
i am new to Genode and i have two questions.
1) Is it somehow possible to back a virtual address range with two different dataspaces (attaching two different dataspaces at the same virtual address is obviously not possible) ? What i want to achieve is that writing to a virtual address results in writing to two dataspaces at the same time, so that the dataspaces have the same content.
2) As far as i know a thread has to be added to a rm session as a client in order to be able to use it as layout for its virtual address space. Is it possible for a thread to operate on two different rm_sessions at the same time?
Best Regards, David
Hi David,
Am 20.01.2016 um 23:42 schrieb David Werner:
- Is it somehow possible to back a virtual address range with two
different dataspaces (attaching two different dataspaces at the same virtual address is obviously not possible) ? What i want to achieve is that writing to a virtual address results in writing to two dataspaces at the same time, so that the dataspaces have the same content.
The only way I see to do this is by using a managed dataspace combined with instruction emulation. But before going deeper into this: I wonder why you want to access two dataspace at a time anyway?
A managed dataspace is not backed by physical memory but by another virtual address range (see [2]). So, you can install your own region manager implementation that is then called each time someone causes a page fault on the managed dataspace. In your region manager you could then resolve the faulting instruction to a double access. In order to do so, your region manager would have to be able to access the text segment of the component that uses the managed dataspace.
- As far as i know a thread has to be added to a rm session as a client
in order to be able to use it as layout for its virtual address space.
Not exactly. A thread can access any virtual address in the address space of its component, without the need for a registration at the corresponding RM session, *as long as the accessed address is already mapped*. Rm_session::add_client is only needed to enable the handling of page faults for a thread. It requests the RM session to create a a pager for the thread and returns a capability that references this pager (see [3]). To ensure that page faults of the thread are actually forwarded to this pager, you have to call Cpu_session::set_pager(thread_cap, pager_cap) additionally.
However, as virtual addresses are normally mapped on demand, one should assume to cause page faults when accessing virtual addresses and thus register its thread for page-fault handling in advance.
Is it possible for a thread to operate on two different rm_sessions at the same time?
Yes and no. You can call Rm_session::add_client for one thread on two different RM sessions. What this does is that both RM sessions keep ready a pager for the thread but the thread is linked to neither of them yet. The linkage is done by Cpu_session::set_pager. As you can see for example in [1], Cpu_session::set_pager simply overwrites the previous configuration. So, if you call it twice with different pagers, your thread will be linked to the pager you stated last.
But yes, you can incorporate multiple RM sessions into one address space by the means of the already mentioned managed dataspaces. You would then have to register your thread at the top-level RM session. However, also in this case, each address goes down to exactly one "leaf" RM session that is responsible for the corresponding faults.
Cheers, Martin
[1] https://github.com/genodelabs/genode/blob/master/repos/base-hw/src/core/plat...
[2] http://genode.org/documentation/genode-foundations-15-05.pdf Page 63, "Realizing managed dataspaces"
[3] https://github.com/genodelabs/genode/blob/master/repos/base/src/core/rm_sess...
Hi Martin,
thank you for your answer!
Am 21.01.2016 um 12:25 schrieb Martin Stein:
The only way I see to do this is by using a managed dataspace combined with instruction emulation. But before going deeper into this: I wonder why you want to access two dataspace at a time anyway?
My goal is to have access to the memory content of a component at a certain point of time without stopping the component (the threads of the component). So my idea was to maintain a second dataspace (same size, same content) for each dataspace that is attached to the RM session of the component as a copy. So when i want to inspect the memory content i just stop writing to the second dataspace and inspect this dataspace instead of the "main" dataspaces. This way the component would be able to keep running.
Regards, David
Hi David,
Am 21.01.2016 um 14:14 schrieb David Werner:
My goal is to have access to the memory content of a component at a certain point of time without stopping the component (the threads of the component). So my idea was to maintain a second dataspace (same size, same content) for each dataspace that is attached to the RM session of the component as a copy. So when i want to inspect the memory content i just stop writing to the second dataspace and inspect this dataspace instead of the "main" dataspaces. This way the component would be able to keep running.
I wonder why you don't want to pause the component? You would have to stop your carbon-copy code anyway to get a consistent state.
In general, I think the problem with your idea is not Genode but the hardware. Genode only manages the mapping from physical to virtual memory. As soon as this mapping is available to the MMU, the access to a virtual address is completely handled by hardware and there is no way for Genode to interpose itself except by removing the mapping again. So, as long as the hardware doesn't provide such multi-accesses, Genode can't change this for mapped addresses.
That said, the instruction-emulation solution I mentioned uses the fact that you can interpose every memeory access to a virtual address if you never map it. So, on every access you get a fault that is forwarded to the code that does the carbon-copy.
Another solution would be a second component that polls for the memory state of the supervised component. This might be efficient if your interest is restricted to a small range of the target address space.
Cheers, Martin
Hello,
Another solution would be a second component that polls for the memory state of the supervised component. This might be efficient if your interest is restricted to a small range of the target address space.
I think that Martin's suggestion of managed dataspaces points in the right direction. But in contrast to Martin, I don't think that there is the need for an instruction emulator. How about the following approach?
* In line with Martin's suggestions, instead of obtaining RAM dataspaces from core, there is a new RAM service (let's call it VRAM for now) that hands out managed dataspaces instead of real RAM dataspaces. Managed dataspaces represent a mechanism for implementing virtual memory in user space. You can find an example at [1]. Note however that this mechanism requires a kernel that supports the remote manipulation of address spaces. This is the case for all of Genode's base platforms except Linux.
[1] repos/base/src/test/rm_fault/main.cc
* Initially, when handing out a dataspace, the VRAM server attaches a real RAM dataspace within the managed dataspace. So the client can access it as usual. It would not notice any difference from a regular RAM dataspace.
* From time to time, the VRAM server, detaches the RAM dataspace from the managed dataspace.
* The next time the client tries to access the dataspace, it would stop executing. Under the hood, a page fault occurs, which is reflected by the kernel (and Genode's core) to the VRAM server as a signal (RM-fault signal). The VRAM server wakes up upon the reception of the signal and thereby knows that the dataspace was accessed. It can even determine the fault address via the Rm_session::state operation. It can respond to the signal be re-attaching the RAM dataspace to the managed dataspace. This operation will implicitly resume the execution of the client.
In principle, this approach implements a mechanism similar to the dirty-bits in the MMU page tables. The VRAM server becomes able to track the accesses to the dataspace and may copy its content. From the client's perspective, the monitoring is completely transparent. If you want to track the usage of the managed dataspace at a fine granularity, the VRAM server might attach the RAM dataspace as several pieces to the managed dataspace (by using the offset, size, and local_addr arguments to the Rm_session::attach operation).
The only open question left is how to pick a suitable interval of detaching the RAM dataspace from the managed dataspace?
Cheers Norman
Hi Martin, Hi Norman,
Am 21.01.2016 um 14:57 schrieb Martin Stein:
I wonder why you don't want to pause the component? You would have to stop your carbon-copy code anyway to get a consistent state.
I am currently doing my Bachelor thesis at the Chair of Operating Systems at TU München. My goal is to develop a real-time capable checkpoint-restore mechanism on Genode. Therefore i dont want to stop my component.
Am 22.01.2016 um 12:53 schrieb Norman Feske:
The only open question left is how to pick a suitable interval of detaching the RAM dataspace from the managed dataspace?
I thought about using the point of time of the preempt (scheduler) of the component.
Regards, David