Understanding OKL4 Interrupt and Exception Handling
Interrupts
When an interrupt occurs, the OKL4 kernel handles it by sending a synchronous IPC to a thread. The thread that receives the interrupt IPC is configured using L4_AssociateInterrupt() (See libs/l4/include/thread.h, and iguana/server/src/iguana_server.c:788 for an example of how this is called). So typically, you will have a high-priority thread, running in an event-handling loop, that is registered to handle interrupt IPCs. How the interrupt should be handled is, of course, dependent on the interrupt number and the platform.
Internally, inside the OKL4 kernel, the interrupt vectors are set up during the architecture-specific initialisation such that they point to handle_interrupt(), the function that ends up sending the interrupt IPC. For example, on the MIPS architecture, see arch/mips/pistachio/src/intctrl.cc :: init_arch() and setup_exception_vectors(). You'll notice that IRQs 0-1 and 7 are considered spurious, while IRQs 2-6 will cause an interrupt IPC.
Exceptions
In OKL4, each thread is associated with an exception-handler thread. When a thread causes an exception, the kernel sends a synchronous IPC to the faulter's exception-handler. The exception IPC contains the faulting thread's state at the time of exception, including the register state.
It is up to the exception-handler to determine what to do with the faulting thread. Typically, the exception-handler has enough privileges to do whatever it wants with the faulting thread, including killing it, or swapping its register state to execute an error handling function, etc.
Like interrupts, exception vectors are also set up during arch-specific init time. For example, again on the MIPS architecture, take another look at init_arch() and setup_exception_vectors(). The default exception handling function in the kernel is mips_exception() (implemented in arch/mips/pistachio/src/exception.cc), which ends up calling send_exception_ipc(). (There are, ahem, exceptions to this rule. Some exceptions don't make sense to be handled within a thread's context, for example, software TLB misses should just be handled by the kernel. These special exceptions handlers are set up in setup_exception_vectors().)
Final note: you'll notice that send_exception_ipc() actually sends the IPC to the faulting thread's scheduler, for reasons we can't go into here. Suffice to say that when you create a thread using L4_ThreadControl(), you should set the exception handler and scheduler to the same thread.