exception -> l4_ipc ?
adam at os.inf.tu-dresden.de
Tue Jun 14 23:32:45 CEST 2005
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
Ok, let's concentrate on one case, l4linux 2.6, exc. IPC.
Linux program executes:
mov $20, %eax
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
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 at os.inf.tu-dresden.de
More information about the l4-hackers