hi,
i see thread::raise_exception(ts), and i know this is where l4 notices a linux sys call (int 0x80), however, i do *not* see where the ipc is sent to the linux server to tell it that a syscall has occured (and to get the parameters and handle it)...
thanks in advance, -andrew
On Mon Jun 13, 2005 at 15:03:35 -0400, Andrew Davenport wrote:
i see thread::raise_exception(ts), and i know this is where l4 notices a linux sys call (int 0x80), however, i do *not* see where the ipc is sent to the linux server to tell it that a syscall has occured (and to get the parameters and handle it)...
As already mentioned, there are two ways an exception gets signalled to user land. One is the exception IPC mechanism, the other is the "IDT" mechanism.
Both mechanisms start in Thread::handle_slow_trap().
Thread::raise_exception() is used for the idt mechanism. For this to work, a thread needs to register exception handlers (basically function pointers in a table for each exception) that are called if an exception is raised. So if the thread executes an 'int $0x80' it traps into the kernel and when resuming to user land continues its execution at the code defined for exception 13 (int 80 will trigger an exception 13). All thread state is preserved. No IPC is involved.
The other mechanism, exception IPC, basically works like a page fault. When an exception happens, the kernel generates an exception to the exception handler along with the state and waits for a response to set some new state for the thread which then continues. In handle_slow_trap this is initiated in the Thread::snd_exception() function, and goes on with Thread::exception() where the IPC is sent and the response received.
Adam
Thanks Adam, I must be missing something.
Regardless of the mechanism used, an IPC must be sent from the l4 u-kernel to the linux server, so the linux server can deal with the "fake intterupt" (a system call). I am using V2, so, according to previous discussion, the interrupt parameters and other data are pushed into a data structure that the l4 thread (eg the linux server) can get them after receiving the notification IPC (eg with COOKIE_1, COOKIE_2). There must be an IPC regardless of the mechnanism, is this correct? Furthermore, where is this sent in l4 and where is it handled in l4linux ?
Thanks, Andrew Davenport
Quoting Adam Lackorzynski adam@os.inf.tu-dresden.de:
On Mon Jun 13, 2005 at 15:03:35 -0400, Andrew Davenport wrote:
i see thread::raise_exception(ts), and i know this is where l4 notices a
linux
sys call (int 0x80), however, i do *not* see where the ipc is sent to the linux server to tell it that a syscall has occured (and to get the
parameters
and handle it)...
As already mentioned, there are two ways an exception gets signalled to user land. One is the exception IPC mechanism, the other is the "IDT" mechanism.
Both mechanisms start in Thread::handle_slow_trap().
Thread::raise_exception() is used for the idt mechanism. For this to work, a thread needs to register exception handlers (basically function pointers in a table for each exception) that are called if an exception is raised. So if the thread executes an 'int $0x80' it traps into the kernel and when resuming to user land continues its execution at the code defined for exception 13 (int 80 will trigger an exception 13). All thread state is preserved. No IPC is involved.
The other mechanism, exception IPC, basically works like a page fault. When an exception happens, the kernel generates an exception to the exception handler along with the state and waits for a response to set some new state for the thread which then continues. In handle_slow_trap this is initiated in the Thread::snd_exception() function, and goes on with Thread::exception() where the IPC is sent and the response received.
Adam -- Adam adam@os.inf.tu-dresden.de Lackorzynski http://os.inf.tu-dresden.de/~adam/
_______________________________________________ l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
On Tue Jun 14, 2005 at 13:20:25 -0400, Andrew Davenport wrote:
Regardless of the mechanism used, an IPC must be sent from the l4 u-kernel to the linux server, so the linux server can deal with the "fake intterupt" (a system call). I am using V2, so, according to previous discussion, the interrupt parameters and other data are pushed into a data structure that the l4 thread (eg the linux server) can get them after receiving the notification IPC (eg with COOKIE_1, COOKIE_2). There must be an IPC regardless of the mechnanism, is this correct? Furthermore, where is this sent in l4 and where is it handled in l4linux ?
Yes, eventually an IPC is sent in both cases. But in the idt case this IPC to the linux server is generated by user land, the kernel itself has nothing to do with generating the IPC. I thought we were talking about kernel internals.
Ok, let's concentrate on one case, l4linux 2.6, exc. IPC.
Linux program executes:
mov $20, %eax int $0x80
An exception is generated and execution is continued in the kernel at vec0d_gen_prot in entry-ia32-ux.S. There we push some things on the stack and call the trap_handler. The handler is thread-ia32-ux.cpp:thread_handle_trap() which calls thread::handle_slow_trap(). handle_slow_trap() in the same file now goes through the possible things that can happen (instruction emulation etc) and eventually comes to the
// send exception IPC if requested if (snd_exception(ts)) goto success;
lines. This path is taken in our case.
When the exception handler (same as the pager) of the faulting thread accepts exception IPC we go on in Thread::exception(). Thread::exception() is the function where the send and receive IPCs to the exception handler are set up. Also noteworthy, the utcb_handler for the faulting thread is modified to copy the trap state instead of the utcb itself. Finally, we come to do_send() where the IPC is sent to the handler. The faulting thread now sleeps waiting for do_send() to come back. When the Linux server has received the message it goes on to do_receive() waiting for a reply from the Linux server.
So, now the Linux server wakes up and receives the exception IPC. It also finds the trap state of the faulting thread in its utcb. By looking at the trap number (==13) and the error code (==0x402) it figures out that the Linux program wanted to execute an 'int80'. By looking at eax it knows that sys_getpid is requested which is then called via the syscall-table. Coming back from the syscall, the return value is stored in the eax field of the utcb and the instruction pointer in the utcb is increased by 2 to point after the 'int80'. Then the exception reply IPC is sent. The Linux server now waits for the next request. All this code is in the dispatch.c file in the L4Linux tree.
Now the kernel wakes up again from its do_receive(). The contents of the utcb are copied to the trap state structure of the faulting thread. The utcb handler is reset. That's it in Thread::exception(). We now come back to handle_slow_trap() where we jump to 'success' because we have handled the exception. We come back to the entry.S code where we clear up the stack and finally 'iret' out to userland again.
The Linux user program now continues its execution after the 'int80', and eax is now whatever the PID of the Linux program is.
I hope this makes it more clear what happens when a Linux program executes an int 80.
Adam
Hello,
Thanks for all the previous help. I was wondering: Suppose I have a filenumber as a syscall param (from linux server) inside Thread::do_send() in l4. I want the inode number for that filenumber, how would I get that? Also, how would I get a block list from an inode number?
Thanks, andrew
Quoting Adam Lackorzynski adam@os.inf.tu-dresden.de:
On Tue Jun 14, 2005 at 13:20:25 -0400, Andrew Davenport wrote:
Regardless of the mechanism used, an IPC must be sent from the l4 u-kernel
to
the linux server, so the linux server can deal with the "fake intterupt" (a system call). I am using V2, so, according to previous discussion, the interrupt parameters and other data are pushed into a data structure that
the
l4 thread (eg the linux server) can get them after receiving the
notification
IPC (eg with COOKIE_1, COOKIE_2). There must be an IPC regardless of the mechnanism, is this correct? Furthermore, where is this sent in l4 and
where
is it handled in l4linux ?
Yes, eventually an IPC is sent in both cases. But in the idt case this IPC to the linux server is generated by user land, the kernel itself has nothing to do with generating the IPC. I thought we were talking about kernel internals.
Ok, let's concentrate on one case, l4linux 2.6, exc. IPC.
Linux program executes:
mov $20, %eax int $0x80
An exception is generated and execution is continued in the kernel at vec0d_gen_prot in entry-ia32-ux.S. There we push some things on the stack and call the trap_handler. The handler is thread-ia32-ux.cpp:thread_handle_trap() which calls thread::handle_slow_trap(). handle_slow_trap() in the same file now goes through the possible things that can happen (instruction emulation etc) and eventually comes to the
// send exception IPC if requested if (snd_exception(ts)) goto success;
lines. This path is taken in our case.
When the exception handler (same as the pager) of the faulting thread accepts exception IPC we go on in Thread::exception(). Thread::exception() is the function where the send and receive IPCs to the exception handler are set up. Also noteworthy, the utcb_handler for the faulting thread is modified to copy the trap state instead of the utcb itself. Finally, we come to do_send() where the IPC is sent to the handler. The faulting thread now sleeps waiting for do_send() to come back. When the Linux server has received the message it goes on to do_receive() waiting for a reply from the Linux server.
So, now the Linux server wakes up and receives the exception IPC. It also finds the trap state of the faulting thread in its utcb. By looking at the trap number (==13) and the error code (==0x402) it figures out that the Linux program wanted to execute an 'int80'. By looking at eax it knows that sys_getpid is requested which is then called via the syscall-table. Coming back from the syscall, the return value is stored in the eax field of the utcb and the instruction pointer in the utcb is increased by 2 to point after the 'int80'. Then the exception reply IPC is sent. The Linux server now waits for the next request. All this code is in the dispatch.c file in the L4Linux tree.
Now the kernel wakes up again from its do_receive(). The contents of the utcb are copied to the trap state structure of the faulting thread. The utcb handler is reset. That's it in Thread::exception(). We now come back to handle_slow_trap() where we jump to 'success' because we have handled the exception. We come back to the entry.S code where we clear up the stack and finally 'iret' out to userland again.
The Linux user program now continues its execution after the 'int80', and eax is now whatever the PID of the Linux program is.
I hope this makes it more clear what happens when a Linux program executes an int 80.
Adam -- Adam adam@os.inf.tu-dresden.de Lackorzynski http://os.inf.tu-dresden.de/~adam/
_______________________________________________ l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
On Fri Jul 08, 2005 at 15:31:45 -0400, Andrew Davenport wrote:
Thanks for all the previous help. I was wondering: Suppose I have a filenumber as a syscall param (from linux server) inside Thread::do_send() in l4. I want the inode number for that filenumber, how would I get that? Also, how would I get a block list from an inode number?
Inside the kernel? Not at all. That info buried somewhere in the memory of the Linux server. You have no realistic chance of getting that info in the kernel.
Adam
Hi,
I had an idea I wanted to try out: Taking the esp register from the task state, then masking off the bits (basically perform the current() macro as the linux kernel does) to obtain the address of the task_struct of the currently runnning process. I have a stripped down sched.h which contians the declaration of the struct task_struct { ... } inside .../fiasco/src/kern (i am modifying thread-ipc.cpp). However, the compiler compains that "Struct task struct" is undefined.
Thanks, Andrew
Quoting Adam Lackorzynski adam@os.inf.tu-dresden.de:
On Fri Jul 08, 2005 at 15:31:45 -0400, Andrew Davenport wrote:
Thanks for all the previous help. I was wondering: Suppose I have a
filenumber
as a syscall param (from linux server) inside Thread::do_send() in l4. I
want
the inode number for that filenumber, how would I get that? Also, how would
I
get a block list from an inode number?
Inside the kernel? Not at all. That info buried somewhere in the memory of the Linux server. You have no realistic chance of getting that info in the kernel.
Adam -- Adam adam@os.inf.tu-dresden.de Lackorzynski http://os.inf.tu-dresden.de/~adam/
_______________________________________________ l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
On Mon Jul 11, 2005 at 12:17:03 -0400, Andrew Davenport wrote:
I had an idea I wanted to try out: Taking the esp register from the task state, then masking off the bits (basically perform the current() macro as the linux kernel does) to obtain the address of the task_struct of the currently runnning
In 2.6 the task struct is not on the stack but a structure called thread_info. One can find the task_struct from the thread_info struct.
process. I have a stripped down sched.h which contians the declaration of the struct task_struct { ... } inside .../fiasco/src/kern (i am modifying thread-ipc.cpp). However, the compiler compains that "Struct task struct" is undefined.
Well, hard to say. Go the build directory and issue "make thread-ipc.i" and look at the generated file if the contents are ok. The .i file contains the contents after cpp went over it.
Adam
l4-hackers@os.inf.tu-dresden.de