diff -urN 2.4.18-ac3/arch/i386/kernel/Makefile 2.4.18-ac3-exceptions/arch/i386/kernel/Makefile --- 2.4.18-ac3/arch/i386/kernel/Makefile Sat Jan 19 10:22:58 2002 +++ 2.4.18-ac3-exceptions/arch/i386/kernel/Makefile Fri Feb 22 20:09:09 2002 @@ -18,7 +18,8 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ - pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o + pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \ + exception.o ifdef CONFIG_PCI diff -urN 2.4.18-ac3/arch/i386/kernel/exception.S 2.4.18-ac3-exceptions/arch/i386/kernel/exception.S --- 2.4.18-ac3/arch/i386/kernel/exception.S Thu Jan 1 02:00:00 1970 +++ 2.4.18-ac3-exceptions/arch/i386/kernel/exception.S Fri Feb 22 20:18:45 2002 @@ -0,0 +1,112 @@ +/* + * linux/arch/i386/kernel/exception.S + * + * 2002, Dan Aloni + * + * i386-specific exceptions implementation + */ + +/* + * offsets of stuff in except_t + */ + +#define VALUE_OFFSET 0x18 +#define PREV_OFFSET 0x1c + +/* + * no data, define anyway + */ + +.data +.align 4 + +/* + * code section + */ + +.text +.align 4 + +/* + * long try_exception(except_t **current_frame, *this_exception) + * + * This function is used in the beginning of the try block. The function + * saves the current state of execution, which is the stack pointers, IP + * to return to, and the registers that a reserved during function calls. + * + * This function returns *twice*. Once with return value 0, for the normal. + * execution, and second when the exception is caught, throw_exception + * restores the execution state and sets the return value to 1. + * + * current_frame is the per-process variable that stores a pointer to + * the current exception frame (except_t), i.e, the exception frame that + * was created by the most recent 'try' block in the current execution. + * + * this_exception is the new exception frame to initialize. + */ + +.globl try_exception +try_exception: + movl 0x4(%esp),%ecx /* current_frame */ + movl 0x8(%esp),%eax /* this_exception */ + + /* this_exception->prev = current_frame */ + /* current_frame = this_exception */ + + movl (%ecx), %edx + movl %edx, PREV_OFFSET (%eax) + movl %eax, (%ecx) + + /* save return address, ebp, esi, edi, ebx, esp */ + movl (%esp), %ecx + movl %ecx, 0x0(%eax) + movl %ebp, 0x4(%eax) + movl %esi, 0x8(%eax) + movl %edi, 0xC(%eax) + movl %ebx, 0x10(%eax) + movl %esp, 0x14(%eax) + xorl %eax, %eax + ret + +/* + * throw_exception(except_t *current_frame, unsigned long value) + * + * Throws an exception with the given value. This restores the state that + * was saved in the frame using try_exception, and jumps back to where + * try_exception was called, with return value of 1. current_frame points + * to the current exception. + * + * If current_frame == NULL, there is no code to catch the exception! + * in that case, throw_exception will return 1 + * + */ + +.align 4 +.globl throw_exception +throw_exception: + movl 0x4(%esp), %eax /* current_frame */ + test %eax, %eax /* return 1 if there's no handler */ + jz no_handler + movl 0x8(%esp), %edx /* value */ + + /* restore execution state */ + movl 0x0(%eax), %ecx + movl 0x4(%eax), %ebp + movl 0x8(%eax), %esi + movl 0xC(%eax), %edi + movl 0x10(%eax), %ebx + movl 0x14(%eax), %esp + + /* set the exception value */ + addl $4, %esp + movl %edx, VALUE_OFFSET (%eax) + + /* jump back to where try_exception returns */ + movl $0x1, %eax + jmpl *%ecx + +no_handler: + xorl %eax, %eax + ret + +.align 4 diff -urN 2.4.18-ac3/include/asm-i386/exception.h 2.4.18-ac3-exceptions/include/asm-i386/exception.h --- 2.4.18-ac3/include/asm-i386/exception.h Thu Jan 1 02:00:00 1970 +++ 2.4.18-ac3-exceptions/include/asm-i386/exception.h Fri Feb 22 21:08:21 2002 @@ -0,0 +1,13 @@ +#ifndef _I386_EXCEPTION_H +#define _I386_EXCEPTION_H + +struct exception_arch_struct { + unsigned long eip; /* 0x0 */ + unsigned long ebp; /* 0x4 */ + unsigned long esi; /* 0x8 */ + unsigned long edi; /* 0xC */ + unsigned long ebx; /* 0x10 */ + unsigned long esp; /* 0x14 */ +}; + +#endif diff -urN 2.4.18-ac3/include/linux/exception.h 2.4.18-ac3-exceptions/include/linux/exception.h --- 2.4.18-ac3/include/linux/exception.h Thu Jan 1 02:00:00 1970 +++ 2.4.18-ac3-exceptions/include/linux/exception.h Fri Feb 22 21:12:40 2002 @@ -0,0 +1,83 @@ +#ifndef _LINUX_EXCEPTION_H +#define _LINUX_EXCEPTION_H + +/* + * linux/include/linux/exception.h + * + * 2002, Dan Aloni + * + * C exceptions for the Linux kernel. + */ + +#include +#include + +/* + * struct exception_struct - an exception frame + * + * These are linked together from the current->exception and down using the 'prev' field + * to the first exception in the current thread. + */ + +struct exception_struct { + struct exception_arch_struct arch; /* arch dependant stuff */ + unsigned long value; /* exception value */ + struct exception_struct *prev; /* previous frame */ + unsigned char caught; /* was this frame's catch ran already */ +}; + +typedef struct exception_struct except_t; + +/* implementation can be found in arch//kernel/exception.S */ + +extern long try_exception(struct exception_struct **current_frame, struct exception_struct *e); +extern void throw_exception(struct exception_struct *current_frame, unsigned long value); + +/* + * try, catch, throw, and yrt overlapping macros with current->exception as the + * current exception frame. + */ + +#define try try__cur_frame(current->exception) +#define catch(_type_, _dec_) catch__cur_frame(current->exception, _type_, _dec_) +#define throw(_value_) throw__cur_frame(current->exception, _value_) +#define yrt yrt__cur_frame(current->exception) + + +/* + * begin a try block: + */ + +#define try__cur_frame(_cur_frame_) { \ + struct exception_struct _exception_; \ + if (!try_exception(&(_cur_frame_), &_exception_)) \ + +/* + * begin a catch block: + */ + +#define catch__cur_frame(_cur_frame_, _type_, _dec_) \ + else { \ + struct exception_struct *_this_frame_ = _cur_frame_; \ + _type_ _dec_ = (_type_)_this_frame_->value; \ + _exception_.caught = 1; \ + _cur_frame_ = _this_frame_->prev; { + +/* + * throw function: + */ + +#define throw__cur_frame(_cur_frame_, _value_) \ + throw_exception(_cur_frame_, (unsigned long)_value_) + +/* + * yrt - this macro must end an exception frame declaration. + */ + +#define yrt__cur_frame(_cur_frame_) } }; \ + if (!_exception_.caught) \ + _cur_frame_ = (_cur_frame_)->prev; \ +} + +#endif + diff -urN 2.4.18-ac3/include/linux/sched.h 2.4.18-ac3-exceptions/include/linux/sched.h --- 2.4.18-ac3/include/linux/sched.h Fri Feb 22 11:51:15 2002 +++ 2.4.18-ac3-exceptions/include/linux/sched.h Fri Feb 22 20:28:40 2002 @@ -385,6 +385,7 @@ struct sem_queue *semsleeping; /* CPU-specific state of this task */ struct thread_struct thread; + struct exception_struct *exception; /* filesystem information */ struct fs_struct *fs; /* open file information */