hi, l4-hackers.
I am now using l4v2 API with L4/Fiasco. I know that on L4 v.2 API, the thread is created if set eip/esp/pager/preempter to real values. And it seems that likewise, thread can be suspended if setting these values to invalid ones. But as I tried it, setting the running thread eip/esp to -1 causes double page fault in that thread. Setting them to 0 does not change these values (though, in headers' comments, documented value is ~0). Setting pager/preempter to L4_INVALID_ID also causes double page fault. This is strange, as docs/comments state the converse.
So, is it possible anyhow to suspend/resume the running thread from another thread? I know, that the thread can be suspended if entering unconditional l4_ipc_wait(), but this is from the inside that thread. How could it be done from an outside thread?
Thanks in advance, valery
Hi,
On Sat Jul 16, 2016 at 11:37:20 +0300, Valery V. Sedletski wrote:
I am now using l4v2 API with L4/Fiasco. I know that on L4 v.2 API, the thread is created if set eip/esp/pager/preempter to real values. And it seems that likewise, thread can be suspended if setting these values to invalid ones. But as I tried it, setting the running thread eip/esp to -1 causes double page fault in that thread. Setting them to 0 does not change these values (though, in headers' comments, documented value is ~0). Setting pager/preempter to L4_INVALID_ID also causes double page fault. This is strange, as docs/comments state the converse.
So I'm looking at the late v2 version of Fiasco and I'm reading the code such that ~0 means "don't change this value". The current/old value is delivered back in any case. Regarding the L4_INVALID_ID, I'm reading the code such that the pager will not be set when the target ID does not exist, which includes L4_INVALID_ID, i.e. the thread's pager should not be changed.
So, is it possible anyhow to suspend/resume the running thread from another thread? I know, that the thread can be suspended if entering unconditional l4_ipc_wait(), but this is from the inside that thread. How could it be done from an outside thread?
One way is to set the thread on such a loop via ex_regs (and paying attention to the register contents which basically means there's some assembly code involved). Another way is to do ex_regs(id, ~0, ~0, L4_THREAD_EX_REGS_RAISE_EXCEPTION) which will trigger an artificial exception in the thread and have it send an exception IPC to its pager. The pager should then just not reply to have the thread suspended, and then reply when you want to have the thread go on later. What makes this a bit tricky is when L4 IPC is involves which you will cancel with ex_regs, or not, if you use the L4_THREAD_EX_REGS_NO_CANCEL flag.
Adam
Adam Lackorzynski wrote:
Hi,
So I'm looking at the late v2 version of Fiasco and I'm reading the code such that ~0 means "don't change this value". The current/old value is delivered back in any case. Regarding the L4_INVALID_ID, I'm reading the code such that the pager will not be set when the target ID does not exist, which includes L4_INVALID_ID, i.e. the thread's pager should not be changed.
but strange that it got a pagefault in case ~0 or L4_INVALID_ID is specified, but does not change the registers or/and pager/preempter if I specify 0 for eip/esp or l4_threadid_t initialized with zeros instead of L4_INVALID_ID
So, is it possible anyhow to suspend/resume the running thread from another thread? I know, that the thread can be suspended if entering unconditional l4_ipc_wait(), but this is from the inside that thread. How could it be done from an outside thread?
One way is to set the thread on such a loop via ex_regs (and paying attention to the register contents which basically means there's some assembly code involved). Another way is to do ex_regs(id, ~0, ~0, L4_THREAD_EX_REGS_RAISE_EXCEPTION) which will trigger an artificial exception in the thread and have it send an exception IPC to its pager. The pager should then just not reply to have the thread suspended, and then reply when you want to have the thread go on later. What makes this a bit tricky is when L4 IPC is involves which you will cancel with ex_regs, or not, if you use the L4_THREAD_EX_REGS_NO_CANCEL flag.
I tried the 1st way -- set eip to the address of IPC wait loop, so it does suspend here, but resume doesn't work. -- You said that I'll need to set some registers via assember, but I wonder which ones -- the changed one is eip only. esp and eflags are only read, but didn't changed, others seems to be not altered with ex_regs...
Adam
Hi,
On Mon Jul 18, 2016 at 07:01:53 +0300, Valery V. Sedletski wrote:
Adam Lackorzynski wrote:
So I'm looking at the late v2 version of Fiasco and I'm reading the code such that ~0 means "don't change this value". The current/old value is delivered back in any case. Regarding the L4_INVALID_ID, I'm reading the code such that the pager will not be set when the target ID does not exist, which includes L4_INVALID_ID, i.e. the thread's pager should not be changed.
but strange that it got a pagefault in case ~0 or L4_INVALID_ID is specified, but does not change the registers or/and pager/preempter if I specify 0 for eip/esp or l4_threadid_t initialized with zeros instead of L4_INVALID_ID
I'm looking at https://svn.tudos.org/repos/tudos/trunk/kernel/fiasco/src/kern/thread.cpp, Thread::initialize, starting at line 850. There, sp and ip are only changed when they're not ~0. Pager and preempter are only set if they're valid (the lookup function is used to derive the pointer, which is 0 for the invalid_id). Are we looking at the same code?
So, is it possible anyhow to suspend/resume the running thread from another thread? I know, that the thread can be suspended if entering unconditional l4_ipc_wait(), but this is from the inside that thread. How could it be done from an outside thread?
One way is to set the thread on such a loop via ex_regs (and paying attention to the register contents which basically means there's some assembly code involved). Another way is to do ex_regs(id, ~0, ~0, L4_THREAD_EX_REGS_RAISE_EXCEPTION) which will trigger an artificial exception in the thread and have it send an exception IPC to its pager. The pager should then just not reply to have the thread suspended, and then reply when you want to have the thread go on later. What makes this a bit tricky is when L4 IPC is involves which you will cancel with ex_regs, or not, if you use the L4_THREAD_EX_REGS_NO_CANCEL flag.
I tried the 1st way -- set eip to the address of IPC wait loop, so it does suspend here, but resume doesn't work. -- You said that I'll need to set some registers via assember, but I wonder which ones -- the changed one is eip only. esp and eflags are only read, but didn't changed, others seems to be not altered with ex_regs...
What I meant is that the code must not change the thread's registers, or it needs to ensure that the original values are restored when resuming the thread. So when forcefully engaging the thread into an IPC, registers might be changed when returning from that IPC, for example, because it was cancelled. Thus the code which does the suspend should save all CPU registers and just restore all of them when doing the resume. That operation will take some assembly efforts. With L4_THREAD_EX_REGS_RAISE_EXCEPTION this effort is taken by the kernel and the pager just needs to memcpy the state away but requires interaction with said pager so it depends on the setup what it easier to do.
Adam
Adam Lackorzynski wrote:
Hi,
...
but strange that it got a pagefault in case ~0 or L4_INVALID_ID is specified, but does not change the registers or/and pager/preempter if I specify 0 for eip/esp or l4_threadid_t initialized with zeros instead of L4_INVALID_ID I'm looking at https://svn.tudos.org/repos/tudos/trunk/kernel/fiasco/src/kern/thread.cpp, Thread::initialize, starting at line 850. There, sp and ip are only changed when they're not ~0. Pager and preempter are only set if they're valid (the lookup function is used to derive the pointer, which is 0 for the invalid_id). Are we looking at the same code?
Yes, I see that in my Fiasco sources. And also I see that it changes pager/preempter only if they are not zero. (probably, it is converted from l4_threadid_t earlier). ip/sp are checked against ~0. And it seems that you're right. -- I changed something in the code, and now it doesn't cause the unhandled pagefault, so, probably, it was my proble,. It seems to suspend/resume without problems now, though I didn't saved/restored thread state yet (as you said later on this text)
So, is it possible anyhow to suspend/resume the running thread from another thread? I know, that the thread can be suspended if entering unconditional l4_ipc_wait(), but this is from the inside that thread. How could it be done from an outside thread?
One way is to set the thread on such a loop via ex_regs (and paying attention to the register contents which basically means there's some assembly code involved). Another way is to do ex_regs(id, ~0, ~0, L4_THREAD_EX_REGS_RAISE_EXCEPTION) which will trigger an artificial exception in the thread and have it send an exception IPC to its pager. The pager should then just not reply to have the thread suspended, and then reply when you want to have the thread go on later. What makes this a bit tricky is when L4 IPC is involves which you will cancel with ex_regs, or not, if you use the L4_THREAD_EX_REGS_NO_CANCEL flag.
I tried the 1st way -- set eip to the address of IPC wait loop, so it does suspend here, but resume doesn't work. -- You said that I'll need to set some registers via assember, but I wonder which ones -- the changed one is eip only. esp and eflags are only read, but didn't changed, others seems to be not altered with ex_regs...
What I meant is that the code must not change the thread's registers, or it needs to ensure that the original values are restored when resuming the thread. So when forcefully engaging the thread into an IPC, registers might be changed when returning from that IPC, for example, because it was cancelled. Thus the code which does the suspend should save all CPU registers and just restore all of them when doing the resume. That operation will take some assembly efforts. With L4_THREAD_EX_REGS_RAISE_EXCEPTION this effort is taken by the kernel and the pager just needs to memcpy the state away but requires interaction with said pager so it depends on the setup what it easier to do.
Ah, so something can be changed when cancelling the IPC -- then I'll need to save/restore the thread state manually (or use the 2nd method with L4_THREAD_EX_REGS_RAISE_EXCEPTION).
Thank you very much for clarification!
Adam
Hello L4-Hackers,
can you tell me, what are the capabilities of Fiasco.OC when it comes to 'dynamic reconfiguration'?
As far as I know, (almost) all the configurations is made in conf.cfg and hw.io, right?
But, is it also possible to do some configuration during run-time i.e. dynamic reconfiguration? Here are two examples I can think of:
- IPC-Channels: Instead of defining Server and its Clients in conf.cfg statically, is it possible to create IPC-Channel during run-time? Let's say, I have a L4re-App in conf.cfg defined as IPC-Server but, no Clients, yet. Now, may any L4re-App create a IPC-Channel by itself and such link to that IPC-Server?
- New Tasks: Is a L4re-App able to create a new task? I.e. push a thread into its own address-space? The new task would require some access rights, too.
Is this any possible? Or is this prohibited due to security issues?
Thanks,
ba_f
Hi,
On 08/04/2016 03:05 PM, ba_f wrote:
Hello L4-Hackers,
can you tell me, what are the capabilities of Fiasco.OC when it comes to 'dynamic reconfiguration'?
As far as I know, (almost) all the configurations is made in conf.cfg and hw.io, right?
But, is it also possible to do some configuration during run-time i.e. dynamic reconfiguration? Here are two examples I can think of:
Well, it depends ...
- IPC-Channels: Instead of defining Server and its Clients in conf.cfg
statically, is it possible to create IPC-Channel during run-time? Let's say, I have a L4re-App in conf.cfg defined as IPC-Server but, no Clients, yet. Now, may any L4re-App create a IPC-Channel by itself and such link to that IPC-Server?
The answer is 'Yes.' and 'No'. The answer to the first question is that this is exactly what ned is doing. Ned creates an IPC gate object and maps it into the tasks as specified in the provided Lua configuration.
The second is not possible for multiple reasons. The first one is, that the server side already needs the IPC gate object to bind its server loop to. Another task has no means to "lookup" the existing IPC gate object. In fact that's the idea behind a capability system.
- New Tasks: Is a L4re-App able to create a new task? I.e. push a thread
into its own address-space? The new task would require some access rights, too.
Yes. Ned and L4Linux are just two examples doing this.
Best, Matthias.
Am 2016-08-05 15:08, schrieb Matthias Lange:
Hi,
On 08/04/2016 03:05 PM, ba_f wrote:
But, is it also possible to do some configuration during run-time i.e. dynamic reconfiguration? Here are two examples I can think of:
Well, it depends ...
- IPC-Channels: Instead of defining Server and its Clients in conf.cfg
statically, is it possible to create IPC-Channel during run-time? Let's say, I have a L4re-App in conf.cfg defined as IPC-Server but, no Clients, yet. Now, may any L4re-App create a IPC-Channel by itself and such link to that IPC-Server?
The answer is 'Yes.' and 'No'. The answer to the first question is that this is exactly what ned is doing. Ned creates an IPC gate object and maps it into the tasks as specified in the provided Lua configuration.
The second is not possible for multiple reasons. The first one is, that the server side already needs the IPC gate object to bind its server loop to. Another task has no means to "lookup" the existing IPC gate object. In fact that's the idea behind a capability system.
So, what you are saying is this: In fact, Ned maps the IPC-Channels at run-time but practically, one has to configure all IPC-Channels possible in Lua.cfg, statically. An ordinary L4Re-App is not able to link to an IPC-Server App if this channel hasn't been configured in Lua.cfg, right? In this case, the L4Re-App also cannot manipulate Ned or something at run-time to create an IPC-Channel, afterwards.
- New Tasks: Is a L4re-App able to create a new task? I.e. push a
thread into its own address-space? The new task would require some access rights, too.
Yes. Ned and L4Linux are just two examples doing this.
Interesting. Can you give an example why and when L4Linux is doing this, please?
As L4Linux is just an "ordinary" L4Re-App I assume that any L4Re-App can create new tasks, don't they? Or, do I have to configure such L4Re-Apps with specific rights, statically in Lua.cfg or something?
Now, what about the security issues? Let's say L4Linux creates a new Task "Child". Does "Child" have the same access rights as L4Linux has, only? Or, may L4Linux even give enhanced access rights to "Child"? E.g. "Child" could be a HW-Driver and such would require access rights to some HW-Address.
Best, Matthias.
Thanks Matthias,
ba_f
On Mon Aug 08, 2016 at 12:32:02 +0200, ba_f wrote:
Am 2016-08-05 15:08, schrieb Matthias Lange:
Hi,
On 08/04/2016 03:05 PM, ba_f wrote:
But, is it also possible to do some configuration during run-time i.e. dynamic reconfiguration? Here are two examples I can think of:
Well, it depends ...
- IPC-Channels: Instead of defining Server and its Clients in conf.cfg
statically, is it possible to create IPC-Channel during run-time? Let's say, I have a L4re-App in conf.cfg defined as IPC-Server but, no Clients, yet. Now, may any L4re-App create a IPC-Channel by itself and such link to that IPC-Server?
The answer is 'Yes.' and 'No'. The answer to the first question is that this is exactly what ned is doing. Ned creates an IPC gate object and maps it into the tasks as specified in the provided Lua configuration.
The second is not possible for multiple reasons. The first one is, that the server side already needs the IPC gate object to bind its server loop to. Another task has no means to "lookup" the existing IPC gate object. In fact that's the idea behind a capability system.
So, what you are saying is this: In fact, Ned maps the IPC-Channels at run-time but practically, one has to configure all IPC-Channels possible in Lua.cfg, statically. An ordinary L4Re-App is not able to link to an IPC-Server App if this channel hasn't been configured in Lua.cfg, right?
Yes.
In this case, the L4Re-App also cannot manipulate Ned or something at run-time to create an IPC-Channel, afterwards.
It cannot because Ned does not have an interface to do that. Generally, if two tasks want to communicate, both need to have a cap on the ipc-channel. As those two cannot communicate (yet), there has to be a third component (with appropriate access to the two that want to communicate) to establish the connection.
- New Tasks: Is a L4re-App able to create a new task? I.e. push a
thread into its own address-space? The new task would require some access rights, too.
Yes. Ned and L4Linux are just two examples doing this.
Interesting. Can you give an example why and when L4Linux is doing this, please?
There's a L4 task for every Linux process. But that task does not have any caps at all because the vCPU in L4Linux uses such a task to execute Linux processes. There's no extra L4 thread in this case. But L4Linux could do that.
As L4Linux is just an "ordinary" L4Re-App I assume that any L4Re-App can create new tasks, don't they?
Yes, given they have access to the factory that allows them to create new tasks and threads. Usually this is the case but it's not mandatory.
Or, do I have to configure such L4Re-Apps with specific rights, statically in Lua.cfg or something?
No.
Now, what about the security issues? Let's say L4Linux creates a new Task "Child". Does "Child" have the same access rights as L4Linux has, only? Or, may L4Linux even give enhanced access rights to "Child"?
L4Linux can give the child any rights it has itself, or less, but obviously not more rights.
E.g. "Child" could be a HW-Driver and such would require access rights to some HW-Address.
Then L4Linux also needs to have the rights to access this IO memory.
Adam
Am 2016-08-08 23:51, schrieb Adam Lackorzynski:
On Mon Aug 08, 2016 at 12:32:02 +0200, ba_f wrote:
Am 2016-08-05 15:08, schrieb Matthias Lange:
Hi,
On 08/04/2016 03:05 PM, ba_f wrote:
But, is it also possible to do some configuration during run-time i.e. dynamic reconfiguration? Here are two examples I can think of:
Well, it depends ...
- IPC-Channels: Instead of defining Server and its Clients in conf.cfg
statically, is it possible to create IPC-Channel during run-time? Let's say, I have a L4re-App in conf.cfg defined as IPC-Server but, no Clients, yet. Now, may any L4re-App create a IPC-Channel by itself and such link to that IPC-Server?
The answer is 'Yes.' and 'No'. The answer to the first question is that this is exactly what ned is doing. Ned creates an IPC gate object and maps it into the tasks as specified in the provided Lua configuration.
The second is not possible for multiple reasons. The first one is, that the server side already needs the IPC gate object to bind its server loop to. Another task has no means to "lookup" the existing IPC gate object. In fact that's the idea behind a capability system.
So, what you are saying is this: In fact, Ned maps the IPC-Channels at run-time but practically, one has to configure all IPC-Channels possible in Lua.cfg, statically. An ordinary L4Re-App is not able to link to an IPC-Server App if this channel hasn't been configured in Lua.cfg, right?
Yes.
In this case, the L4Re-App also cannot manipulate Ned or something at run-time to create an IPC-Channel, afterwards.
It cannot because Ned does not have an interface to do that. Generally, if two tasks want to communicate, both need to have a cap on the ipc-channel. As those two cannot communicate (yet), there has to be a third component (with appropriate access to the two that want to communicate) to establish the connection.
Adam
Ok, I see it's not possible. But, maybe I can take the chance for a deeper understanding.
This is how I understand things, now. Please, correct me if I'm wrong:
1.) Moe starts first, followed by Ned. 2.) Ned parses lua.cfg and, on 'new_channel()' it creates a new IPC-Gate with l4_msgtag_t l4_factory_create_gate( l4_cap_idx_t factory, l4_cap_idx_t target_cap, l4_cap_idx_t thread_cap, l4_umword_t label). 3.) The IPC-Gate is a Kernel-Object and thus stored into the Kernel. (Does Moe help here?) 'thread_cap' is stored/pushed into the servers capability table and 'target_cap' is for the client task, aren't they? 4.) With l4re_env_get_cap() client & server look for a matching capability in their own cap-tables.
If I got it right, any Task can create an IPC-Gate at run-time and thus create child tasks with ipc-server or ipc-client capabilities, don't they?
Thanks,
ba_f
On 08/10/2016 04:31 PM, ba_f wrote:
Am 2016-08-08 23:51, schrieb Adam Lackorzynski:
On Mon Aug 08, 2016 at 12:32:02 +0200, ba_f wrote:
Am 2016-08-05 15:08, schrieb Matthias Lange:
Hi,
On 08/04/2016 03:05 PM, ba_f wrote:
But, is it also possible to do some configuration during run-time
[...]
Ok, I see it's not possible. But, maybe I can take the chance for a deeper understanding.
This is how I understand things, now. Please, correct me if I'm wrong:
1.) Moe starts first, followed by Ned.
Ned is started by moe.
2.) Ned parses lua.cfg and, on 'new_channel()' it creates a new IPC-Gate with l4_msgtag_t l4_factory_create_gate( l4_cap_idx_t factory, l4_cap_idx_t target_cap, l4_cap_idx_t thread_cap, l4_umword_t label).
Yes, this is done via the Lua bindings (see ned.lua).
3.) The IPC-Gate is a Kernel-Object and thus stored into the Kernel. (Does Moe help here?)
No, moe is not involved here.
'thread_cap' is stored/pushed into the servers capability table and 'target_cap' is for the client task, aren't they?
'target_cap' is mapped with the appropriate rights into the new task's capability table. That means it can be mapped with server rights into the server task and with read/write rights into the client task. 'thread_cap' is not used.
4.) With l4re_env_get_cap() client & server look for a matching capability in their own cap-tables.
Yes. Client and server use their local name to lookup the capability.
If I got it right, any Task can create an IPC-Gate at run-time and thus create child tasks with ipc-server or ipc-client capabilities, don't they?
That depends on the task's factory but the general answer is yes.
Matthias.
Am 2016-08-11 09:07, schrieb Matthias Lange:
If I got it right, any Task can create an IPC-Gate at run-time and thus create child tasks with ipc-server or ipc-client capabilities, don't they?
That depends on the task's factory but the general answer is yes.
Matthias.
Hello,
do you have a reference design for this? So maybe one 'parent' Task creating two 'childs' and establishes an IPC between them.
Have a nice day,
ba_f
Hi,
On 08/15/2016 12:47 PM, ba_f wrote:
Am 2016-08-11 09:07, schrieb Matthias Lange:
If I got it right, any Task can create an IPC-Gate at run-time and thus create child tasks with ipc-server or ipc-client capabilities, don't they?
That depends on the task's factory but the general answer is yes.
Matthias.
Hello,
do you have a reference design for this? So maybe one 'parent' Task creating two 'childs' and establishes an IPC between them.
I am afraid that there is no such reference example. I would recommend looking into ned's implementation (look for __alloc(lua_State *l) in lua_factory.cc and exec(lua_State *l) in lua_exec.cc as starting points).
Basically, here is what you have to do (I leave the loading and setup of the child program out):
- create new task - create new thread - create new IPC gate (needs to be done only once) - map thread capability into new task - map initial caps and IPC gate cap into new task - setup pager and exception handler of the new task - start the new thread
For some inspiration you can look at libloader/include/remote_app_model::start_prog(). For ELF loading and setup of the l4re kernel you should also consider using libloader's infrastructure.
Matthias.
Have a nice day,
ba_f
l4-hackers@os.inf.tu-dresden.de