Hello! Genode,
From time to time, I saw something like this:
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, l4_obj_fpage(A.dst(), 0, L4_FPAGE_RWX), B.dst() | L4_ITEM_MAP);
I think it looks like a unnecessary mapping, because rather than mapping, we can just copy the capability like this, A = B.
Since I'm feeling like I miss something here, could you tell me the difference between two of them?
Best regards, Jaeyong
Hi Jaeyong,
On 01/30/2013 02:20 AM, jaeyong yoo wrote:
Hello! Genode,
From time to time, I saw something like this:
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, l4_obj_fpage(A.dst(), 0, L4_FPAGE_RWX), B.dst() | L4_ITEM_MAP);
I think it looks like a unnecessary mapping, because rather than mapping, we can just copy the capability like this, A = B.
No, that's not the same. Moreover, it has to be "B = A" in your example.
The "l4_task_map" call above, creates a duplicate of the capability referenced by "A.dst()" to "B.dst()". The value given by "dst()" is an index into the capability name space of the task - in the following shortly titled as capability index. You cannot modify the capability name space in user mode. All changes to that space are done explicitly via the "l4_task_map" syscall, or implicitly by sending a capability mapping via IPC.
The second example is simply an assignment, where A and B will reference the same capability index in the end. Moreover, the reference counter in Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition of the capability class for Fiasco.OC.
Normally, we simply use the simple assignments when passing around capabilities by value. But in some rare situations it is necessary to really duplicate a capability index. When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via "l4_task_map".
Regards Stefan
Since I'm feeling like I miss something here, could you tell me the difference between two of them?
Best regards, Jaeyong
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via "l4_task_map".
Thanks for the answer. I would like to check that I understand correctly with the following example. Please stop me if I am going somewhere wrong.
We can consider a thread waiting for an IPC with the following rcv_buf:
rcv_buf { [cap: 0x13000(dst), 0x002f(local_name)] some buf; }
The thread receives an IPC call and the rcv_buf becomes the following:
rcv_buf { [cap: 0x14000, 0x002f] // <--- overwritten to 0x14000. some buf; } And, 0x14000 and 0x13000 is mapped by l4_task_map. And, the thread who waits for the IPC call (who originally created 0x13000) uses the capability index 0x13000 as usual.
Regards, Jaeyong
On Wed, Jan 30, 2013 at 7:34 PM, Stefan Kalkowski < stefan.kalkowski@...1...> wrote:
Hi Jaeyong,
On 01/30/2013 02:20 AM, jaeyong yoo wrote:
Hello! Genode,
From time to time, I saw something like this:
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, l4_obj_fpage(A.dst(), 0, L4_FPAGE_RWX), B.dst() | L4_ITEM_MAP);
I think it looks like a unnecessary mapping, because rather than mapping, we can just copy the capability like this, A = B.
No, that's not the same. Moreover, it has to be "B = A" in your example.
The "l4_task_map" call above, creates a duplicate of the capability referenced by "A.dst()" to "B.dst()". The value given by "dst()" is an index into the capability name space of the task - in the following shortly titled as capability index. You cannot modify the capability name space in user mode. All changes to that space are done explicitly via the "l4_task_map" syscall, or implicitly by sending a capability mapping via IPC.
The second example is simply an assignment, where A and B will reference the same capability index in the end. Moreover, the reference counter in Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition of the capability class for Fiasco.OC.
Normally, we simply use the simple assignments when passing around capabilities by value. But in some rare situations it is necessary to really duplicate a capability index. When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via "l4_task_map".
Regards Stefan
Since I'm feeling like I miss something here, could you tell me the difference between two of them?
Best regards, Jaeyong
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
-- Stefan Kalkowski Genode Labs
http://www.genode-labs.com/ · http://genode.org/
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Jaeyong,
On 01/31/2013 03:59 AM, jaeyong yoo wrote:
When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via "l4_task_map".
Thanks for the answer. I would like to check that I understand correctly with the following example. Please stop me if I am going somewhere wrong.
We can consider a thread waiting for an IPC with the following rcv_buf:
rcv_buf { [cap: 0x13000(dst), 0x002f(local_name)] some buf; }
Well, I suppose that's the point where things get wrong ;-). I fear you're still mixing up Genode and Fiasco.OC abstraction layers. Whereby, I've to admit the topic is quite complicated.
On the kernel API level a capability is just an address value (denoted as "dst" above). In Genode a capability consists of the kernel capability and an additional value (denoted as "local_name"). When transfering a Genode capability via the kernel's IPC mechanism, you transfer the "local_name" as a normal value. Whereby the kernel capability is handled separately. When waiting for, or sending a message via the kernel's IPC primitives, you've to describe what kind of items you'll send or receive via the UTCB (user-level thread control block). Therein you describe how many normal data values, memory mappings, or kernel capability mappings, you're willing to receive or to send.
Imagine a thread wants to receive a single capability. Then it has to tell the kernel where in its task's capability space the received item should end up. The kernel isn't responsible for allocating/freeing items in the capability space. The same way like most microkernels aren't in authority to organize the memory spaces, but let the userland organize their virtual memory themself. So lets say the thread wants the capability to end up at 0x13000 in its capability space. Then it would prepare its UTCB e.g. like the following:
l4_utcb_br()->br[0] = 0x13000 | L4_RCV_ITEM_SINGLE_CAP;
before it triggers an ipc_wait syscall. If on the other side the sender put a capability into its UTCB in an appropriated manner, the kernel will now associate the kernel object behind the capability to be send with address 0x13000 in the capability space of the receiving thread. That means the transfered capability ends up at 0x13000. If the thread wants to invoke the received capability it will use this address for it.
The "local_name" value, which is only meaningful for the Genode abstractions, has to be transfered like every other normal values, like e.g. opcodes, strings, etc.. These values are stored in a different area of the UTCB. The kernel doesn't care about it.
After successfully receiving an IPC on the kernel level, within Genode we transfer the values out of the UTCB of the thread, into the "Msg_buf" object - a Genode abstraction. This message buffer again consists of normal data, hold in a byte array, and kernel capability indices, hold in a corresponding array. Now, if you unmarshal a Genode capability out of such a message buffer object, you will take the "local_name" value out of the normal data array, and the "dst" value out of the capability indices array,and construct a Genode capability out of it.
I've to admit, reality is even more complex, but this is the reasonably neat story. If you want to have a look, how Genode capabilities are constructed out of the message buffer in more detail, please have a look at: base-foc/include/base/ipc.h
I think this whole topic would be better off in a separate article. Nevertheless, I hope my explanatory notes are more enlightening than confusing.
Best regards Stefan
The thread receives an IPC call and the rcv_buf becomes the following:
rcv_buf { [cap: 0x14000, 0x002f] // <--- overwritten to 0x14000. some buf; }
And, 0x14000 and 0x13000 is mapped by l4_task_map. And, the thread who waits for the IPC call (who originally created 0x13000) uses the capability index 0x13000 as usual.
Regards, Jaeyong
On Wed, Jan 30, 2013 at 7:34 PM, Stefan Kalkowski <stefan.kalkowski@...1... mailto:stefan.kalkowski@...1...> wrote:
Hi Jaeyong, On 01/30/2013 02:20 AM, jaeyong yoo wrote: > Hello! Genode, > > From time to time, I saw something like this: > > l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, > l4_obj_fpage(A.dst(), 0, L4_FPAGE_RWX), > B.dst() | L4_ITEM_MAP); > > I think it looks like a unnecessary mapping, because rather than > mapping, we can just copy the capability like this, > A = B. No, that's not the same. Moreover, it has to be "B = A" in your example. The "l4_task_map" call above, creates a duplicate of the capability referenced by "A.dst()" to "B.dst()". The value given by "dst()" is an index into the capability name space of the task - in the following shortly titled as capability index. You cannot modify the capability name space in user mode. All changes to that space are done explicitly via the "l4_task_map" syscall, or implicitly by sending a capability mapping via IPC. The second example is simply an assignment, where A and B will reference the same capability index in the end. Moreover, the reference counter in Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition of the capability class for Fiasco.OC. Normally, we simply use the simple assignments when passing around capabilities by value. But in some rare situations it is necessary to really duplicate a capability index. When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via "l4_task_map". Regards Stefan > > Since I'm feeling like I miss something here, could you tell me the > difference between two of them? > > Best regards, > Jaeyong > > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_jan > > > > _______________________________________________ > Genode-main mailing list > Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> > https://lists.sourceforge.net/lists/listinfo/genode-main > -- Stefan Kalkowski Genode Labs http://www.genode-labs.com/ · http://genode.org/ ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> https://lists.sourceforge.net/lists/listinfo/genode-main
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Thanks a lot. Stefan. I think it is a very nice article for understanding Fiasco.OC/Genode IPC and capability! Also, reading the code, "base-foc/include/base/ipc.h," is much easier and clearer after your kind explanation.
I would like to ask the initial question once again (I'm strongly feeling that I have to buy you beer :) If we could meet in person, I'm gonna!). I think it is the part that you mentioned "reality is even more complex."
In the function, Capability_map::insert_map(int id, addr_t kcap), there is a part that allocating a new capability index:
141 /* if we own the capability already check whether it's the same */ 142 if (i) { 143 l4_msgtag_t tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i->kcap(), kcap) ; 144 if (!l4_msgtag_label(tag)) { 145 /* 146 * they aren't equal, possibly an already revoked cap, 147 * otherwise it's a fake capability and we return an invalid o ne 148 */ 149 tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap()); 150 if (l4_msgtag_label(tag)) 151 return 0; 152 else 153 /* it's invalid so remove it from the tree */ 154 _tree.remove(i); 155 } else 156 /* they are equal so just return the one in the map */ 157 return i; 158 } 159 160 /* the capability doesn't exists in the map so allocate a new one */ 161 i = cap_idx_alloc()->alloc_range(1);
It allocates a new capability index, if the already existing capability is invalid (see line # 153). What I'm wondering is the following: Since the 'kcap' (parameter to insert_map func.) which is valid capability index received from the IPC (and originally allocated in Msgbuf_base creator), would it be possible to use the kcap rather than allocating the new one?
Best regards, Jaeyong
On Fri, Feb 1, 2013 at 4:20 AM, Stefan Kalkowski < stefan.kalkowski@...1...> wrote:
Hi Jaeyong,
On 01/31/2013 03:59 AM, jaeyong yoo wrote:
When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices you specified contain still valid capabilities, they will nevertheless get overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before receiving new ones, already received capabilities are duplicated via
"l4_task_map".
Thanks for the answer. I would like to check that I understand correctly with the following example. Please stop me if I am going somewhere wrong.
We can consider a thread waiting for an IPC with the following rcv_buf:
rcv_buf { [cap: 0x13000(dst), 0x002f(local_name)] some buf; }
Well, I suppose that's the point where things get wrong ;-). I fear you're still mixing up Genode and Fiasco.OC abstraction layers. Whereby, I've to admit the topic is quite complicated.
On the kernel API level a capability is just an address value (denoted as "dst" above). In Genode a capability consists of the kernel capability and an additional value (denoted as "local_name"). When transfering a Genode capability via the kernel's IPC mechanism, you transfer the "local_name" as a normal value. Whereby the kernel capability is handled separately. When waiting for, or sending a message via the kernel's IPC primitives, you've to describe what kind of items you'll send or receive via the UTCB (user-level thread control block). Therein you describe how many normal data values, memory mappings, or kernel capability mappings, you're willing to receive or to send.
Imagine a thread wants to receive a single capability. Then it has to tell the kernel where in its task's capability space the received item should end up. The kernel isn't responsible for allocating/freeing items in the capability space. The same way like most microkernels aren't in authority to organize the memory spaces, but let the userland organize their virtual memory themself. So lets say the thread wants the capability to end up at 0x13000 in its capability space. Then it would prepare its UTCB e.g. like the following:
l4_utcb_br()->br[0] = 0x13000 | L4_RCV_ITEM_SINGLE_CAP;
before it triggers an ipc_wait syscall. If on the other side the sender put a capability into its UTCB in an appropriated manner, the kernel will now associate the kernel object behind the capability to be send with address 0x13000 in the capability space of the receiving thread. That means the transfered capability ends up at 0x13000. If the thread wants to invoke the received capability it will use this address for it.
The "local_name" value, which is only meaningful for the Genode abstractions, has to be transfered like every other normal values, like e.g. opcodes, strings, etc.. These values are stored in a different area of the UTCB. The kernel doesn't care about it.
After successfully receiving an IPC on the kernel level, within Genode we transfer the values out of the UTCB of the thread, into the "Msg_buf" object - a Genode abstraction. This message buffer again consists of normal data, hold in a byte array, and kernel capability indices, hold in a corresponding array. Now, if you unmarshal a Genode capability out of such a message buffer object, you will take the "local_name" value out of the normal data array, and the "dst" value out of the capability indices array,and construct a Genode capability out of it.
I've to admit, reality is even more complex, but this is the reasonably neat story. If you want to have a look, how Genode capabilities are constructed out of the message buffer in more detail, please have a look at: base-foc/include/base/ipc.h
I think this whole topic would be better off in a separate article. Nevertheless, I hope my explanatory notes are more enlightening than confusing.
Best regards Stefan
The thread receives an IPC call and the rcv_buf becomes the following:
rcv_buf { [cap: 0x14000, 0x002f] // <--- overwritten to 0x14000. some buf; }
And, 0x14000 and 0x13000 is mapped by l4_task_map. And, the thread who waits for the IPC call (who originally created 0x13000) uses the capability index 0x13000 as usual.
Regards, Jaeyong
On Wed, Jan 30, 2013 at 7:34 PM, Stefan Kalkowski <stefan.kalkowski@...1... mailto:stefan.kalkowski@...1...> wrote:
Hi Jaeyong, On 01/30/2013 02:20 AM, jaeyong yoo wrote: > Hello! Genode, > > From time to time, I saw something like this: > > l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, > l4_obj_fpage(A.dst(), 0, L4_FPAGE_RWX), > B.dst() | L4_ITEM_MAP); > > I think it looks like a unnecessary mapping, because rather than > mapping, we can just copy the capability like this, > A = B. No, that's not the same. Moreover, it has to be "B = A" in your
example.
The "l4_task_map" call above, creates a duplicate of the capability referenced by "A.dst()" to "B.dst()". The value given by "dst()" is
an
index into the capability name space of the task - in the following shortly titled as capability index. You cannot modify the capability name space in user mode. All changes to that space are done
explicitly
via the "l4_task_map" syscall, or implicitly by sending a capability mapping via IPC. The second example is simply an assignment, where A and B will
reference
the same capability index in the end. Moreover, the reference
counter in
Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition of the capability class for Fiasco.OC. Normally, we simply use the simple assignments when passing around capabilities by value. But in some rare situations it is necessary to really duplicate a capability index. When waiting for IPC you can specify capability indices, which will contain capabilities passed by the sender. If the capability indices
you
specified contain still valid capabilities, they will nevertheless
get
overwritten. In Genode, the message buffer object "Msg_buf" has some capability indices used to hold received capabilities. Before
receiving
new ones, already received capabilities are duplicated via "l4_task_map". Regards Stefan > > Since I'm feeling like I miss something here, could you tell me the > difference between two of them? > > Best regards, > Jaeyong > > >
> Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_jan > > > > _______________________________________________ > Genode-main mailing list > Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> > https://lists.sourceforge.net/lists/listinfo/genode-main > -- Stefan Kalkowski Genode Labs http://www.genode-labs.com/ · http://genode.org/
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> https://lists.sourceforge.net/lists/listinfo/genode-main
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
-- Stefan Kalkowski Genode Labs
http://www.genode-labs.com/ · http://genode.org/
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Jaeyong,
On 2013-02-01 03:47, jaeyong yoo wrote:
Thanks a lot. Stefan. I think it is a very nice article for understanding Fiasco.OC/Genode IPC and capability! Also, reading the code, "base-foc/include/base/ipc.h," is much easier and clearer after your kind explanation.
I would like to ask the initial question once again (I'm strongly feeling that I have to buy you beer :) If we could meet in person, I'm gonna!).
I'll take you at your word ;-)
I think it is the part that you mentioned "reality is even more complex."
In the function, Capability_map::insert_map(int id, addr_t kcap), there is a part that allocating a new capability index:
141 /* if we own the capability already check whether it's the same */ 142 if (i) { 143 l4_msgtag_t tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i->kcap(), kcap) ; 144 if (!l4_msgtag_label(tag)) { 145 /* 146 * they aren't equal, possibly an already revoked cap, 147 * otherwise it's a fake capability and we return an invalid o ne 148 */ 149 tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap()); 150 if (l4_msgtag_label(tag)) 151 return 0; 152 else 153 /* it's invalid so remove it from the tree */ 154 _tree.remove(i); 155 } else 156 /* they are equal so just return the one in the map */ 157 return i; 158 } 159 160 /* the capability doesn't exists in the map so allocate a new one */ 161 i = cap_idx_alloc()->alloc_range(1);
It allocates a new capability index, if the already existing capability is invalid (see line # 153). What I'm wondering is the following: Since the 'kcap' (parameter to insert_map func.) which is valid capability index received from the IPC (and originally allocated in Msgbuf_base creator), would it be possible to use the kcap rather than allocating the new one?
Actually it is possible, but then we must instead allocate a new capability index within the "Msg_buf" object, from where the "kcap" argument originally comes from. As stated in a previous mail: the capability indices in the message buffer are used to receive new capabilities. If we just use these indices without allocating new ones, newly received capabilities would override the old ones.
Does that answers your question?
Best regards Stefan
Best regards, Jaeyong
On Fri, Feb 1, 2013 at 4:20 AM, Stefan Kalkowski <stefan.kalkowski@...1... [21]> wrote:
Hi Jaeyong,
On 01/31/2013 03:59 AM, jaeyong yoo wrote:
When waiting for IPC you can specify capability indices, which
will
contain capabilities passed by the sender. If the capability
indices you
specified contain still valid capabilities, they will
nevertheless get
overwritten. In Genode, the message buffer object "Msg_buf" has
some
capability indices used to hold received capabilities. Before
receiving
new ones, already received capabilities are duplicated via
"l4_task_map".
Thanks for the answer. I would like to check that I understand correctly with the
following
example. Please stop me if I am going somewhere wrong.
We can consider a thread waiting for an IPC with the following
rcv_buf:
rcv_buf { [cap: 0x13000(dst), 0x002f(local_name)] some buf; }
Well, I suppose that's the point where things get wrong ;-). I fear you're still mixing up Genode and Fiasco.OC abstraction layers. Whereby, I've to admit the topic is quite complicated.
On the kernel API level a capability is just an address value (denoted as "dst" above). In Genode a capability consists of the kernel capability and an additional value (denoted as "local_name"). When transfering a Genode capability via the kernel's IPC mechanism, you transfer the "local_name" as a normal value. Whereby the kernel capability is handled separately. When waiting for, or sending a message via the kernel's IPC primitives, you've to describe what kind of items you'll send or receive via the UTCB (user-level thread control block). Therein you describe how many normal data values, memory mappings, or kernel capability mappings, you're willing to receive or to send.
Imagine a thread wants to receive a single capability. Then it has to tell the kernel where in its task's capability space the received item should end up. The kernel isn't responsible for allocating/freeing items in the capability space. The same way like most microkernels aren't in authority to organize the memory spaces, but let the userland organize their virtual memory themself. So lets say the thread wants the capability to end up at 0x13000 in its capability space. Then it would prepare its UTCB e.g. like the following:
l4_utcb_br()->br[0] = 0x13000 | L4_RCV_ITEM_SINGLE_CAP;
before it triggers an ipc_wait syscall. If on the other side the sender put a capability into its UTCB in an appropriated manner, the kernel will now associate the kernel object behind the capability to be send with address 0x13000 in the capability space of the receiving thread. That means the transfered capability ends up at 0x13000. If the thread wants to invoke the received capability it will use this address for it.
The "local_name" value, which is only meaningful for the Genode abstractions, has to be transfered like every other normal values, like e.g. opcodes, strings, etc.. These values are stored in a different area of the UTCB. The kernel doesn't care about it.
After successfully receiving an IPC on the kernel level, within Genode we transfer the values out of the UTCB of the thread, into the "Msg_buf" object - a Genode abstraction. This message buffer again consists of normal data, hold in a byte array, and kernel capability indices, hold in a corresponding array. Now, if you unmarshal a Genode capability out of such a message buffer object, you will take the "local_name" value out of the normal data array, and the "dst" value out of the capability indices array,and construct a Genode capability out of it.
I've to admit, reality is even more complex, but this is the reasonably neat story. If you want to have a look, how Genode capabilities are constructed out of the message buffer in more detail, please have a look at: base-foc/include/base/ipc.h
I think this whole topic would be better off in a separate article. Nevertheless, I hope my explanatory notes are more enlightening than confusing.
Best regards Stefan
The thread receives an IPC call and the rcv_buf becomes the
following:
rcv_buf { [cap: 0x14000, 0x002f] // <--- overwritten to
0x14000.
some buf; } And, 0x14000 and 0x13000 is mapped by l4_task_map. And, the thread who waits for the IPC call (who originally
created
0x13000) uses the capability index 0x13000 as usual.
Regards, Jaeyong
On Wed, Jan 30, 2013 at 7:34 PM, Stefan Kalkowski <stefan.kalkowski@...1... [1]
<mailto:stefan.kalkowski@...1... [2]>> wrote:
Hi Jaeyong,
On 01/30/2013 02:20 AM, jaeyong yoo wrote: > Hello! Genode, > > From time to time, I saw something like this: > > l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, > l4_obj_fpage(A.dst(),
0, L4_FPAGE_RWX),
> B.dst() |
L4_ITEM_MAP);
> > I think it looks like a unnecessary mapping, because
rather than
> mapping, we can just copy the capability like this, > A = B.
No, that's not the same. Moreover, it has to be "B = A" in
your example.
The "l4_task_map" call above, creates a duplicate of the
capability
referenced by "A.dst()" to "B.dst()". The value given by
"dst()" is an
index into the capability name space of the task - in the
following
shortly titled as capability index. You cannot modify the
capability
name space in user mode. All changes to that space are done
explicitly
via the "l4_task_map" syscall, or implicitly by sending a
capability
mapping via IPC.
The second example is simply an assignment, where A and B
will reference
the same capability index in the end. Moreover, the
reference counter in
Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition
of the
capability class for Fiasco.OC.
Normally, we simply use the simple assignments when passing
around
capabilities by value. But in some rare situations it is
necessary to
really duplicate a capability index. When waiting for IPC you can specify capability indices,
which will
contain capabilities passed by the sender. If the
capability indices you
specified contain still valid capabilities, they will
nevertheless get
overwritten. In Genode, the message buffer object "Msg_buf"
has some
capability indices used to hold received capabilities.
Before receiving
new ones, already received capabilities are duplicated via "l4_task_map".
Regards Stefan
> > Since I'm feeling like I miss something here, could you
tell me the
> difference between two of them? > > Best regards, > Jaeyong > > >
> Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_jan [3] > > > > _______________________________________________ > Genode-main mailing list > Genode-main@lists.sourceforge.net [4] <mailto:Genode-main@lists.sourceforge.net [5]>
[6]
>
-- Stefan Kalkowski Genode Labs
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [9] _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net [10] <mailto:Genode-main@lists.sourceforge.net [11]> https://lists.sourceforge.net/lists/listinfo/genode-main
[12]
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [13]
Genode-main mailing list Genode-main@lists.sourceforge.net [14] https://lists.sourceforge.net/lists/listinfo/genode-main [15]
-- Stefan Kalkowski Genode Labs
http://www.genode-labs.com/ [16] · http://genode.org/ [17]
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [18] _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net [19] https://lists.sourceforge.net/lists/listinfo/genode-main [20]
Links:
[1] mailto:stefan.kalkowski@...1... [2] mailto:stefan.kalkowski@...1... [3] http://p.sf.net/sfu/appdyn_d2d_jan [4] mailto:Genode-main@lists.sourceforge.net [5] mailto:Genode-main@lists.sourceforge.net [6] https://lists.sourceforge.net/lists/listinfo/genode-main [7] http://www.genode-labs.com/ [8] http://genode.org/ [9] http://p.sf.net/sfu/appdyn_d2d_jan [10] mailto:Genode-main@lists.sourceforge.net [11] mailto:Genode-main@lists.sourceforge.net [12] https://lists.sourceforge.net/lists/listinfo/genode-main [13] http://p.sf.net/sfu/appdyn_d2d_jan [14] mailto:Genode-main@lists.sourceforge.net [15] https://lists.sourceforge.net/lists/listinfo/genode-main [16] http://www.genode-labs.com/ [17] http://genode.org/ [18] http://p.sf.net/sfu/appdyn_d2d_jan [19] mailto:Genode-main@lists.sourceforge.net [20] https://lists.sourceforge.net/lists/listinfo/genode-main [21] mailto:stefan.kalkowski@...1...
Ah! Now I understand! Because the Msg_buf could be reused, the indices in Msg_buf should be only used for receiving new capabilities. Thank you very much for the kind answer :)
Best regards, Jaeyong
On Sun, Feb 3, 2013 at 10:10 PM, Stefan Kalkowski < stefan.kalkowski@...1...> wrote:
Hi Jaeyong,
On 2013-02-01 03:47, jaeyong yoo wrote:
Thanks a lot. Stefan. I think it is a very nice article for understanding Fiasco.OC/Genode IPC and capability! Also, reading the code, "base-foc/include/base/ipc.h," is much easier and clearer after your kind explanation.
I would like to ask the initial question once again (I'm strongly feeling that I have to buy you beer :) If we could meet in person, I'm gonna!).
I'll take you at your word ;-)
I think it is the part that you mentioned "reality is even more complex."
In the function, Capability_map::insert_map(int id, addr_t kcap), there is a part that allocating a new capability index:
141 /* if we own the capability already check whether it's the same */ 142 if (i) { 143 l4_msgtag_t tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i->kcap(), kcap) ; 144 if (!l4_msgtag_label(tag)) { 145 /* 146 * they aren't equal, possibly an already revoked cap, 147 * otherwise it's a fake capability and we return an invalid o ne 148 */ 149 tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap()); 150 if (l4_msgtag_label(tag)) 151 return 0; 152 else 153 /* it's invalid so remove it from the tree */ 154 _tree.remove(i); 155 } else 156 /* they are equal so just return the one in the map */ 157 return i; 158 } 159 160 /* the capability doesn't exists in the map so allocate a new one */ 161 i = cap_idx_alloc()->alloc_range(1);
It allocates a new capability index, if the already existing capability is invalid (see line # 153). What I'm wondering is the following: Since the 'kcap' (parameter to insert_map func.) which is valid capability index received from the IPC (and originally allocated in Msgbuf_base creator), would it be possible to use the kcap rather than allocating the new one?
Actually it is possible, but then we must instead allocate a new capability index within the "Msg_buf" object, from where the "kcap" argument originally comes from. As stated in a previous mail: the capability indices in the message buffer are used to receive new capabilities. If we just use these indices without allocating new ones, newly received capabilities would override the old ones.
Does that answers your question?
Best regards Stefan
Best regards, Jaeyong
On Fri, Feb 1, 2013 at 4:20 AM, Stefan Kalkowski <stefan.kalkowski@...1... [21]> wrote:
Hi Jaeyong,
On 01/31/2013 03:59 AM, jaeyong yoo wrote:
When waiting for IPC you can specify capability indices, which
will
contain capabilities passed by the sender. If the capability
indices you
specified contain still valid capabilities, they will
nevertheless get
overwritten. In Genode, the message buffer object "Msg_buf" has
some
capability indices used to hold received capabilities. Before
receiving
new ones, already received capabilities are duplicated via
"l4_task_map".
Thanks for the answer. I would like to check that I understand correctly with the
following
example. Please stop me if I am going somewhere wrong.
We can consider a thread waiting for an IPC with the following
rcv_buf:
rcv_buf { [cap: 0x13000(dst), 0x002f(local_name)] some buf; }
Well, I suppose that's the point where things get wrong ;-). I fear you're still mixing up Genode and Fiasco.OC abstraction layers. Whereby, I've to admit the topic is quite complicated.
On the kernel API level a capability is just an address value (denoted as "dst" above). In Genode a capability consists of the kernel capability and an additional value (denoted as "local_name"). When transfering a Genode capability via the kernel's IPC mechanism, you transfer the "local_name" as a normal value. Whereby the kernel capability is handled separately. When waiting for, or sending a message via the kernel's IPC primitives, you've to describe what kind of items you'll send or receive via the UTCB (user-level thread control block). Therein you describe how many normal data values, memory mappings, or kernel capability mappings, you're willing to receive or to send.
Imagine a thread wants to receive a single capability. Then it has to tell the kernel where in its task's capability space the received item should end up. The kernel isn't responsible for allocating/freeing items in the capability space. The same way like most microkernels aren't in authority to organize the memory spaces, but let the userland organize their virtual memory themself. So lets say the thread wants the capability to end up at 0x13000 in its capability space. Then it would prepare its UTCB e.g. like the following:
l4_utcb_br()->br[0] = 0x13000 | L4_RCV_ITEM_SINGLE_CAP;
before it triggers an ipc_wait syscall. If on the other side the sender put a capability into its UTCB in an appropriated manner, the kernel will now associate the kernel object behind the capability to be send with address 0x13000 in the capability space of the receiving thread. That means the transfered capability ends up at 0x13000. If the thread wants to invoke the received capability it will use this address for it.
The "local_name" value, which is only meaningful for the Genode abstractions, has to be transfered like every other normal values, like e.g. opcodes, strings, etc.. These values are stored in a different area of the UTCB. The kernel doesn't care about it.
After successfully receiving an IPC on the kernel level, within Genode we transfer the values out of the UTCB of the thread, into the "Msg_buf" object - a Genode abstraction. This message buffer again consists of normal data, hold in a byte array, and kernel capability indices, hold in a corresponding array. Now, if you unmarshal a Genode capability out of such a message buffer object, you will take the "local_name" value out of the normal data array, and the "dst" value out of the capability indices array,and construct a Genode capability out of it.
I've to admit, reality is even more complex, but this is the reasonably neat story. If you want to have a look, how Genode capabilities are constructed out of the message buffer in more detail, please have a look at: base-foc/include/base/ipc.h
I think this whole topic would be better off in a separate article. Nevertheless, I hope my explanatory notes are more enlightening than confusing.
Best regards Stefan
The thread receives an IPC call and the rcv_buf becomes the
following:
rcv_buf { [cap: 0x14000, 0x002f] // <--- overwritten to
0x14000.
some buf; }
And, 0x14000 and 0x13000 is mapped by l4_task_map. And, the thread who waits for the IPC call (who originally
created
0x13000) uses the capability index 0x13000 as usual.
Regards, Jaeyong
On Wed, Jan 30, 2013 at 7:34 PM, Stefan Kalkowski <stefan.kalkowski@...1... [1]
<mailto:stefan.kalkowski@...1... [2]>> wrote:
Hi Jaeyong, On 01/30/2013 02:20 AM, jaeyong yoo wrote: > Hello! Genode, > > From time to time, I saw something like this: > > l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, > l4_obj_fpage(A.dst(),
0, L4_FPAGE_RWX),
> B.dst() |
L4_ITEM_MAP);
> > I think it looks like a unnecessary mapping, because
rather than
> mapping, we can just copy the capability like this, > A = B. No, that's not the same. Moreover, it has to be "B = A" in
your example.
The "l4_task_map" call above, creates a duplicate of the
capability
referenced by "A.dst()" to "B.dst()". The value given by
"dst()" is an
index into the capability name space of the task - in the
following
shortly titled as capability index. You cannot modify the
capability
name space in user mode. All changes to that space are done
explicitly
via the "l4_task_map" syscall, or implicitly by sending a
capability
mapping via IPC. The second example is simply an assignment, where A and B
will reference
the same capability index in the end. Moreover, the
reference counter in
Genode's capability will be increased. Look at "base-foc/include/base/native_types.h" for the definition
of the
capability class for Fiasco.OC. Normally, we simply use the simple assignments when passing
around
capabilities by value. But in some rare situations it is
necessary to
really duplicate a capability index. When waiting for IPC you can specify capability indices,
which will
contain capabilities passed by the sender. If the
capability indices you
specified contain still valid capabilities, they will
nevertheless get
overwritten. In Genode, the message buffer object "Msg_buf"
has some
capability indices used to hold received capabilities.
Before receiving
new ones, already received capabilities are duplicated via "l4_task_map". Regards Stefan > > Since I'm feeling like I miss something here, could you
tell me the
> difference between two of them? > > Best regards, > Jaeyong > > >
> Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_jan [3] > > > > _______________________________________________ > Genode-main mailing list > Genode-main@lists.sourceforge.net [4] <mailto:Genode-main@lists.sourceforge.net [5]>
> https://lists.sourceforge.net/lists/listinfo/genode-main
[6]
> -- Stefan Kalkowski Genode Labs http://www.genode-labs.com/ [7] · http://genode.org/ [8]
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [9] _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net [10] <mailto:Genode-main@lists.sourceforge.net [11]> https://lists.sourceforge.net/lists/listinfo/genode-main
[12]
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [13]
Genode-main mailing list Genode-main@lists.sourceforge.net [14] https://lists.sourceforge.net/lists/listinfo/genode-main [15]
-- Stefan Kalkowski Genode Labs
http://www.genode-labs.com/ [16] · http://genode.org/ [17]
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan [18] _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net [19] https://lists.sourceforge.net/lists/listinfo/genode-main [20]
Links:
[1] mailto:stefan.kalkowski@...1... [2] mailto:stefan.kalkowski@...1... [3] http://p.sf.net/sfu/appdyn_d2d_jan [4] mailto:Genode-main@lists.sourceforge.net [5] mailto:Genode-main@lists.sourceforge.net [6] https://lists.sourceforge.net/lists/listinfo/genode-main [7] http://www.genode-labs.com/ [8] http://genode.org/ [9] http://p.sf.net/sfu/appdyn_d2d_jan [10] mailto:Genode-main@lists.sourceforge.net [11] mailto:Genode-main@lists.sourceforge.net [12] https://lists.sourceforge.net/lists/listinfo/genode-main [13] http://p.sf.net/sfu/appdyn_d2d_jan [14] mailto:Genode-main@lists.sourceforge.net [15] https://lists.sourceforge.net/lists/listinfo/genode-main [16] http://www.genode-labs.com/ [17] http://genode.org/ [18] http://p.sf.net/sfu/appdyn_d2d_jan [19] mailto:Genode-main@lists.sourceforge.net [20] https://lists.sourceforge.net/lists/listinfo/genode-main [21] mailto:stefan.kalkowski@...1...
-- Stefan Kalkowski Genode Labs
http://www.genode-labs.com/ · http://genode.org/
Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_jan _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main