diff -Nurp linux-2.4.22-clean/arch/arm/config.in linux-2.4.22-adeos-ltt/arch/arm/config.in
--- linux-2.4.22-clean/arch/arm/config.in	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/config.in	2003-11-21 23:21:08.000000000 -0800
@@ -699,6 +699,11 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; the
 fi
 
 mainmenu_option next_comment
+comment 'Kernel tracing'
+tristate 'Kernel events tracing support' CONFIG_TRACE
+endmenu
+
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 # RMK wants arm kernels compiled with frame pointers so hardwire this to y.  If
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/entry-common.S linux-2.4.22-adeos-ltt/arch/arm/kernel/entry-common.S
--- linux-2.4.22-clean/arch/arm/kernel/entry-common.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/entry-common.S	2003-11-21 23:21:08.000000000 -0800
@@ -35,6 +35,12 @@ ENTRY(__do_softirq)
  */
 ret_fast_syscall:
 	disable_irq r1				@ ensure IRQs are disabled
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	mov	r7, r0				@ save returned r0
+	bl	SYMBOL_NAME(trace_real_syscall_exit)
+	mov	r0, r7
+#endif
+
 	ldr	r1, [tsk, #TSK_NEED_RESCHED]
 	ldr	r2, [tsk, #TSK_SIGPENDING]
 	teq	r1, #0				@ need_resched || sigpending
@@ -139,6 +145,16 @@ ENTRY(vector_swi)
 	mcr	p15, 0, ip, c1, c0		@ update control register
 #endif
 	enable_irq ip
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	/* zzz note that validity of scno is not yet checked.
+	 * zzz The visualizer checks it.
+	 */
+	add	r1, sp, #S_R0			@ pointer to regs
+	mov	r0, scno  		        @ syscall number
+	bl	SYMBOL_NAME(trace_real_syscall_entry)
+	add	r1, sp, #S_R0			@ pointer to regs
+	ldmia	r1, {r0 - r3}			@ have to reload r0 - r3
+#endif
 
 	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
@@ -179,6 +195,9 @@ __sys_trace:
 
 __sys_trace_return:
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	bl	SYMBOL_NAME(trace_real_syscall_exit)
+#endif
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
 	bl	SYMBOL_NAME(syscall_trace)
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/irq.c linux-2.4.22-adeos-ltt/arch/arm/kernel/irq.c
--- linux-2.4.22-clean/arch/arm/kernel/irq.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/irq.c	2003-11-21 23:21:08.000000000 -0800
@@ -30,6 +30,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/trace.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -332,6 +333,8 @@ asmlinkage void asm_do_IRQ(int irq, stru
 		spin_unlock(&irq_controller_lock);
 		irq_exit(cpu, irq);
 
+	        TRACE_IRQ_EXIT();
+
 		if (softirq_pending(cpu))
 			do_softirq();
 
@@ -350,6 +353,8 @@ static void irqlck_timeout(unsigned long
 {
 	struct irqdesc *desc = (struct irqdesc *)_data;
 
+	TRACE_IRQ_ENTRY(irq, !(user_mode(regs)));
+
 	spin_lock(&irq_controller_lock);
 
 	del_timer(&desc->lck_timer);
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/process.c linux-2.4.22-adeos-ltt/arch/arm/kernel/process.c
--- linux-2.4.22-clean/arch/arm/kernel/process.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/process.c	2003-11-21 23:21:08.000000000 -0800
@@ -23,6 +23,7 @@
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/trace.h>
 
 #include <asm/system.h>
 #include <asm/leds.h>
@@ -401,6 +402,10 @@ pid_t arch_kernel_thread(int (*fn)(void 
         : "=&r" (__ret)
         : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg)
 	: "r0", "r1", "lr");
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	if (__ret > 0)
+		TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, __ret, (int) fn);
+#endif
 	return __ret;
 }
 
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/ptrace.c linux-2.4.22-adeos-ltt/arch/arm/kernel/ptrace.c
--- linux-2.4.22-clean/arch/arm/kernel/ptrace.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/ptrace.c	2003-11-21 23:21:08.000000000 -0800
@@ -477,7 +477,9 @@ void ptrace_break(struct task_struct *ts
 	info.si_code  = TRAP_BRKPT;
 	info.si_addr  = (void *)instruction_pointer(regs);
 
+      	TRACE_TRAP_ENTRY(1, (uint32_t)info.si_addr);	/* debug */
 	force_sig_info(SIGTRAP, &info, tsk);
+ 	TRACE_TRAP_EXIT();
 }
 
 /*
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/sys_arm.c linux-2.4.22-adeos-ltt/arch/arm/kernel/sys_arm.c
--- linux-2.4.22-clean/arch/arm/kernel/sys_arm.c	2001-07-04 14:56:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/sys_arm.c	2003-11-21 23:21:08.000000000 -0800
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
+#include <linux/trace.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -167,6 +168,8 @@ asmlinkage int sys_ipc (uint call, int f
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
+	TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
 	switch (call) {
 	case SEMOP:
 		return sys_semop (first, (struct sembuf *)ptr, second);
diff -Nurp linux-2.4.22-clean/arch/arm/kernel/traps.c linux-2.4.22-adeos-ltt/arch/arm/kernel/traps.c
--- linux-2.4.22-clean/arch/arm/kernel/traps.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/kernel/traps.c	2003-11-21 23:21:08.000000000 -0800
@@ -24,6 +24,7 @@
 #include <linux/elf.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/trace.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -175,6 +176,72 @@ void show_trace_task(struct task_struct 
 	}
 }
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+asmlinkage void trace_real_syscall_entry(int scno,struct pt_regs * regs)
+{
+	int			depth = 0;
+	unsigned long           end_code;
+	unsigned long		*fp;			/* frame pointer */
+	unsigned long		lower_bound;
+	unsigned long		lr;			/* link register */
+	unsigned long		*prev_fp;
+	int			seek_depth;
+	unsigned long           start_code;
+	unsigned long           *start_stack;
+	trace_syscall_entry	trace_syscall_event;
+	unsigned long		upper_bound;
+	int			use_bounds;
+	int			use_depth;
+
+	trace_syscall_event.syscall_id = (uint8_t)scno;
+	trace_syscall_event.address    = instruction_pointer(regs);
+	
+	if (! (user_mode(regs) ))
+		goto trace_syscall_end;
+
+	if (trace_get_config(&use_depth,
+			     &use_bounds,
+			     &seek_depth,
+			     (void*)&lower_bound,
+			     (void*)&upper_bound) < 0)
+		goto trace_syscall_end;
+
+	if ((use_depth == 1) || (use_bounds == 1)) {
+		fp          = (unsigned long *)regs->ARM_fp;
+		end_code    = current->mm->end_code;
+		start_code  = current->mm->start_code;
+		start_stack = (unsigned long *)current->mm->start_stack;
+
+		while (!__get_user(lr, (unsigned long *)(fp - 1))) {
+			if ((lr > start_code) && (lr < end_code)) {
+				if (((use_depth == 1) && (depth >= seek_depth)) ||
+				    ((use_bounds == 1) && (lr > lower_bound) && (lr < upper_bound))) {
+					trace_syscall_event.address = lr;
+					goto trace_syscall_end;
+				} else {
+					depth++;
+				}
+			}
+
+			if ((__get_user((unsigned long)prev_fp, (fp - 3))) ||
+			    (prev_fp > start_stack) ||
+			    (prev_fp <= fp)) {
+				goto trace_syscall_end;
+			}
+			fp = prev_fp;
+		}
+	}
+
+trace_syscall_end:
+	trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}
+
+asmlinkage void trace_real_syscall_exit(void)
+{
+        trace_event(TRACE_EV_SYSCALL_EXIT, NULL);
+}
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
+
 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
 
 /*
@@ -237,8 +304,12 @@ asmlinkage void do_undefinstr(int addres
 	info.si_code  = ILL_ILLOPC;
 	info.si_addr  = pc;
 
+	TRACE_TRAP_ENTRY(current->thread.trap_no, (uint32_t)pc);
+
 	force_sig_info(SIGILL, &info, current);
 
+	TRACE_TRAP_EXIT();
+
 	die_if_kernel("Oops - undefined instruction", regs, mode);
 }
 
@@ -261,8 +332,12 @@ asmlinkage void do_excpt(int address, st
 	info.si_code  = BUS_ADRERR;
 	info.si_addr  = (void *)address;
 
+	TRACE_TRAP_ENTRY(current->thread.trap_no, instruction_pointer(regs));
+
 	force_sig_info(SIGBUS, &info, current);
 
+	TRACE_TRAP_EXIT();
+
 	die_if_kernel("Oops - address exception", regs, mode);
 }
 #endif
@@ -462,7 +537,12 @@ baddataabort(int code, unsigned long ins
 	info.si_code  = ILL_ILLOPC;
 	info.si_addr  = (void *)addr;
 
+	TRACE_TRAP_ENTRY(18, addr);	/* machine check */
+
 	force_sig_info(SIGILL, &info, current);
+
+	TRACE_TRAP_EXIT();
+
 	die_if_kernel("unknown data abort code", regs, instr);
 }
 
diff -Nurp linux-2.4.22-clean/arch/arm/mm/fault-common.c linux-2.4.22-adeos-ltt/arch/arm/mm/fault-common.c
--- linux-2.4.22-clean/arch/arm/mm/fault-common.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/arm/mm/fault-common.c	2003-11-21 23:21:08.000000000 -0800
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/trace.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -276,6 +277,8 @@ int do_page_fault(unsigned long addr, in
 	if (in_interrupt() || !mm)
 		goto no_context;
 
+	TRACE_TRAP_ENTRY(14, instruction_pointer(regs));
+
 	down_read(&mm->mmap_sem);
 	fault = __do_page_fault(mm, addr, error_code, tsk);
 	up_read(&mm->mmap_sem);
@@ -283,8 +286,10 @@ int do_page_fault(unsigned long addr, in
 	/*
 	 * Handle the "normal" case first
 	 */
-	if (fault > 0)
+	if (fault > 0) {
+		TRACE_TRAP_EXIT();
 		return 0;
+	}
 
 	/*
 	 * We had some memory, but were unable to
@@ -310,6 +315,7 @@ int do_page_fault(unsigned long addr, in
 	} else
 		__do_user_fault(tsk, addr, error_code, fault == -1 ?
 				SEGV_ACCERR : SEGV_MAPERR, regs);
+	TRACE_TRAP_EXIT();
 	return 0;
 
 
@@ -332,11 +338,14 @@ do_sigbus:
 #endif
 
 	/* Kernel mode? Handle exceptions or die */
-	if (user_mode(regs))
+	if (user_mode(regs)) {
+		TRACE_TRAP_EXIT();
 		return 0;
+	}
 
 no_context:
 	__do_kernel_fault(mm, addr, error_code, regs);
+	TRACE_TRAP_EXIT();
 	return 0;
 }
 
diff -Nurp linux-2.4.22-clean/arch/i386/config.in linux-2.4.22-adeos-ltt/arch/i386/config.in
--- linux-2.4.22-clean/arch/i386/config.in	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/config.in	2003-11-21 23:25:36.000000000 -0800
@@ -262,6 +262,10 @@ mainmenu_option next_comment
 comment 'General setup'
 
 bool 'Networking support' CONFIG_NET
+tristate 'Adeos support' CONFIG_ADEOS
+if [ "$CONFIG_ADEOS" != "n" ]; then
+   define_bool CONFIG_ADEOS_CORE y
+fi
 
 # Visual Workstation support is utterly broken.
 # If you want to see it working mail an VW540 to hch@infradead.org 8)
@@ -463,6 +467,11 @@ source drivers/usb/Config.in
 source net/bluetooth/Config.in
 
 mainmenu_option next_comment
+comment 'Kernel tracing'
+tristate 'Kernel events tracing support' CONFIG_TRACE
+endmenu
+
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/adeos.c linux-2.4.22-adeos-ltt/arch/i386/kernel/adeos.c
--- linux-2.4.22-clean/arch/i386/kernel/adeos.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/adeos.c	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,381 @@
+/*
+ *   linux/arch/i386/kernel/adeos.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Architecture-dependent ADEOS core support for x86.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/hw_irq.h>
+#include <asm/irq.h>
+#include <asm/desc.h>
+#include <asm/io.h>
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/fixmap.h>
+#include <asm/bitops.h>
+#include <asm/mpspec.h>
+#ifdef CONFIG_X86_IO_APIC
+#include <asm/io_apic.h>
+#endif /* CONFIG_X86_IO_APIC */
+#include <asm/apic.h>
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+struct pt_regs __adeos_tick_regs;
+
+int __adeos_tick_irq;
+
+#ifdef CONFIG_SMP
+
+static volatile unsigned long __adeos_cpu_sync_map;
+
+static volatile unsigned long __adeos_cpu_lock_map;
+
+static spinlock_t __adeos_cpu_barrier = SPIN_LOCK_UNLOCKED;
+
+static atomic_t __adeos_critical_count = ATOMIC_INIT(0);
+
+static void (*__adeos_cpu_sync)(void);
+
+#endif /* CONFIG_SMP */
+
+#define __adeos_call_asm_irq_handler(adp,irq) \
+   __asm__ __volatile__ ("pushfl\n\t" \
+                         "push %%cs\n\t" \
+                         "call *%1\n" \
+			 : /* no output */ \
+			 : "a" (irq), "m" ((adp)->irqs[irq].handler))
+
+#define __adeos_call_c_irq_handler(adp,irq) \
+   __asm__ __volatile__ ("pushl %%ebp\n\t" \
+	                 "pushl %%edi\n\t" \
+                      	 "pushl %%esi\n\t" \
+	                 "pushl %%edx\n\t" \
+                         "pushl %%ecx\n\t" \
+	                 "pushl %%ebx\n\t" \
+                         "pushl %%eax\n\t" \
+                         "call *%1\n\t" \
+                         "addl $4,%%esp\n\t" \
+                         "popl %%ebx\n\t" \
+                         "popl %%ecx\n\t" \
+	                 "popl %%edx\n\t" \
+	                 "popl %%esi\n\t" \
+	                 "popl %%edi\n\t" \
+	                 "popl %%ebp\n" \
+			 : /* no output */ \
+			 : "a" (irq), "m" ((adp)->irqs[irq].handler))
+
+#ifdef CONFIG_PREEMPT
+/* With kernel preemption enabled, ret_from_intr might identify a need
+   for rescheduling raised by the C handler, so we should call it
+   after we have bumped the preemption count. Native (i.e. ASM)
+   handlers are expected to do the same. */
+#define __adeos_call_c_root_irq_handler(adp,irq) \
+   __asm__ __volatile__ ("pushfl\n\t" \
+                         "pushl %%cs\n\t" \
+                         "pushl $1f\n\t" \
+	                 "pushl $-1\n\t" /* Negative (fake) orig_eax. */ \
+	                 "pushl %%es\n\t" \
+	                 "pushl %%ds\n\t" \
+	                 "pushl %%eax\n\t" \
+	                 "pushl %%ebp\n\t" \
+	                 "pushl %%edi\n\t" \
+	                 "pushl %%esi\n\t" \
+	                 "pushl %%edx\n\t" \
+	                 "pushl %%ecx\n\t" \
+	                 "pushl %%ebx\n\t" \
+                         __adeos_bump_count \
+                         "pushl %%eax\n\t" \
+                         "call *%1\n\t" \
+			 "addl $4,%%esp\n\t" \
+	                 "jmp "__stringify(ret_from_intr)"\n\t" \
+	                 "1:\n" \
+			 : /* no output */ \
+			 : "a" (irq), "m" ((adp)->irqs[irq].handler))
+#else /* !CONFIG_PREEMPT */
+#define __adeos_call_c_root_irq_handler(adp,irq) __adeos_call_c_irq_handler(adp,irq)
+#endif /* CONFIG_PREEMPT */
+
+static __inline__ unsigned long flnz (unsigned long word) {
+    __asm__("bsrl %1, %0"
+	    : "=r" (word)
+	    : "r"  (word));
+    return word;
+}
+
+int __adeos_ack_system_irq (unsigned irq) {
+#ifdef CONFIG_X86_LOCAL_APIC
+    ack_APIC_irq();		/* Takes no spin lock, right? */
+#endif /* CONFIG_X86_LOCAL_APIC */
+    return 1;
+}
+
+#ifdef CONFIG_SMP
+
+static void __adeos_do_critical_sync (unsigned irq)
+
+{
+    adeos_declare_cpuid;
+
+    set_bit(cpuid,&__adeos_cpu_sync_map);
+
+    /* Now we are in sync with the lock requestor running on another
+       CPU. Enter a spinning wait until he releases the global
+       lock. */
+    adeos_spin_lock(&__adeos_cpu_barrier);
+
+    /* Got it. Now get out. */
+
+    if (__adeos_cpu_sync)
+	/* Call the sync routine if any. */
+	__adeos_cpu_sync();
+
+    adeos_spin_unlock(&__adeos_cpu_barrier);
+
+    clear_bit(cpuid,&__adeos_cpu_sync_map);
+}
+
+#endif /* CONFIG_SMP */
+
+/* adeos_critical_enter() -- Grab the superlock excluding all CPUs
+   but the current one from a critical section. This lock is used when
+   we must enforce a global critical section for a single CPU in a
+   possibly SMP system whichever context the CPUs are running
+   (i.e. interrupt handler or regular thread). */
+
+unsigned long adeos_critical_enter (void (*syncfn)(void))
+
+{
+    unsigned long flags;
+
+    adeos_hw_local_irq_save(flags);
+
+#ifdef CONFIG_SMP
+    if (smp_num_cpus > 1) /* We might be running a SMP-kernel on a UP box... */
+	{
+	adeos_declare_cpuid;
+
+	if (!test_and_set_bit(cpuid,&__adeos_cpu_lock_map))
+	    {
+	    while (test_and_set_bit(31,&__adeos_cpu_lock_map))
+		{
+		/* Refer to the explanations found in
+		   linux/arch/asm-i386/irq.c about
+		   SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND for more about
+		   this strange loop. */
+		int n = 0;
+		do { cpu_relax(); } while (++n < cpuid);
+		}
+
+	    adeos_spin_lock(&__adeos_cpu_barrier);
+
+	    __adeos_cpu_sync = syncfn;
+
+	    /* Send the sync IPI to all processors but the current one. */
+	    __adeos_send_IPI_allbutself(ADEOS_CRITICAL_VECTOR);
+
+	    while (__adeos_cpu_sync_map != (cpu_online_map & ~__adeos_cpu_lock_map))
+		cpu_relax();
+	    }
+
+	atomic_inc(&__adeos_critical_count);
+	}
+#endif /* CONFIG_SMP */
+
+    return flags;
+}
+
+/* adeos_critical_exit() -- Release the superlock. */
+
+void adeos_critical_exit (unsigned long flags)
+
+{
+#ifdef CONFIG_SMP
+    if (smp_num_cpus > 1) /* We might be running a SMP-kernel on a UP box... */
+	{
+	adeos_declare_cpuid;
+
+	if (atomic_dec_and_test(&__adeos_critical_count))
+	    {
+	    adeos_spin_unlock(&__adeos_cpu_barrier);
+
+	    while (__adeos_cpu_sync_map != 0)
+		cpu_relax();
+
+	    clear_bit(cpuid,&__adeos_cpu_lock_map);
+	    clear_bit(31,&__adeos_cpu_lock_map);
+	    }
+	}
+#endif /* CONFIG_SMP */
+
+    adeos_hw_local_irq_restore(flags);
+}
+
+void __adeos_init_stage (adomain_t *adp)
+
+{
+    int cpuid, n;
+
+    for (cpuid = 0; cpuid < ADEOS_NR_CPUS; cpuid++)
+	{
+	adp->cpudata[cpuid].irq_pending_hi = 0;
+
+	for (n = 0; n < IPIPE_IRQ_IWORDS; n++)
+	    adp->cpudata[cpuid].irq_pending_lo[n] = 0;
+
+	for (n = 0; n < IPIPE_NR_IRQS; n++)
+	    adp->cpudata[cpuid].irq_hits[n] = 0;
+	}
+
+    for (n = 0; n < IPIPE_NR_IRQS; n++)
+	{
+	adp->irqs[n].acknowledge = NULL;
+	adp->irqs[n].handler = NULL;
+	adp->irqs[n].control = IPIPE_PASS_MASK;	/* Pass but don't handle */
+	}
+
+#ifdef CONFIG_SMP
+    adp->irqs[ADEOS_CRITICAL_IPI].acknowledge = &__adeos_ack_system_irq;
+    adp->irqs[ADEOS_CRITICAL_IPI].handler = &__adeos_do_critical_sync;
+    /* Immediately handle in the current domain but *never* pass */
+    adp->irqs[ADEOS_CRITICAL_IPI].control = IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK|IPIPE_SYSTEM_MASK;
+#endif /* CONFIG_SMP */
+}
+
+/* __adeos_sync_stage() -- Flush the pending IRQs for the current
+   domain (and processor).  This routine flushes the interrupt log
+   (see "Optimistic interrupt protection" from D. Stodolsky et al. for
+   more on the deferred interrupt scheme). Every interrupt that
+   occurred while the pipeline was stalled gets played.  WARNING:
+   callers on SMP boxen should always check for CPU migration on
+   return of this routine. */
+
+void __adeos_sync_stage (void)
+
+{
+    unsigned long mask, submask, flags;
+    struct adcpudata *cpudata;
+    adeos_declare_cpuid;
+    int level, rank;
+    adomain_t *adp;
+    unsigned irq;
+
+    adp = adp_cpu_current[cpuid];
+    cpudata = &adp->cpudata[cpuid];
+
+    do
+	{
+	if (unlikely(test_and_set_bit(IPIPE_SYNC_FLAG,&cpudata->status)))
+	    return;
+
+	/* The policy here is to keep the dispatching code
+	   interrupt-free by stalling the current stage. If the upper
+	   domain handler (which we call) wants to re-enable
+	   interrupts while in a safe portion of the code
+	   (e.g. SA_INTERRUPT flag unset for Linux's sigaction()), it
+	   will have to unstall (then stall again before returning to
+	   us!) the stage when it sees fit. */
+
+	while ((mask = cpudata->irq_pending_hi) != 0)
+	    {
+	    /* Give a slight priority advantage to high-numbered IRQs
+	       like the virtual ones. */
+	    level = flnz(mask);
+	    clear_bit(level,&cpudata->irq_pending_hi);
+
+	    while ((submask = cpudata->irq_pending_lo[level]) != 0)
+		{
+		rank = flnz(submask);
+		irq = (level << 5) + rank;
+
+#ifdef CONFIG_SMP
+		if (unlikely(test_bit(IPIPE_LOCK_FLAG,&adp->irqs[irq].control)))
+		    {
+		    clear_bit(rank,&cpudata->irq_pending_lo[level]);
+		    continue;
+		    }
+#endif /* CONFIG_SMP */
+	
+		adeos_hw_local_irq_save(flags);
+
+		if (unlikely(--cpudata->irq_hits[irq] > 0))
+		    set_bit(level,&cpudata->irq_pending_hi);
+		else
+		    clear_bit(rank,&cpudata->irq_pending_lo[level]);
+
+		/* Allow the sync routine to be reentered on behalf of
+		   the IRQ handler and any execution context switched
+		   in by the IRQ handler. The latter also means that
+		   returning from the switched out context is always
+		   safe even if the sync routine has been reentered in
+		   the meantime. */
+
+		set_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+		clear_bit(IPIPE_SYNC_FLAG,&cpudata->status);
+
+		adeos_hw_sti();
+
+		if (test_bit(IPIPE_CALLASM_FLAG,&adp->irqs[irq].control))
+		    __adeos_call_asm_irq_handler(adp,irq);
+		else if (adp == adp_root)
+		    __adeos_call_c_root_irq_handler(adp,irq);
+		else
+		    __adeos_call_c_irq_handler(adp,irq);
+
+		adeos_hw_local_irq_restore(flags);
+
+#ifdef CONFIG_SMP
+		adeos_reload_cpuid();
+		cpudata = &adp->cpudata[cpuid];
+#endif /* CONFIG_SMP */
+
+		clear_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+		if (test_and_set_bit(IPIPE_SYNC_FLAG,&cpudata->status))
+		    return;
+		}
+	    }
+
+	clear_bit(IPIPE_SYNC_FLAG,&cpudata->status);
+	}
+    while (cpudata->irq_pending_hi != 0);
+}
+
+asmlinkage int __adeos_enter_syscall (struct pt_regs regs) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_SYSCALL_PROLOGUE] > 0))
+	return __adeos_handle_event(ADEOS_SYSCALL_PROLOGUE,&regs);
+
+    return 0;
+}
+
+asmlinkage int __adeos_exit_syscall (void) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_SYSCALL_EPILOGUE] > 0))
+	return __adeos_handle_event(ADEOS_SYSCALL_EPILOGUE,NULL);
+
+    return 0;
+}
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/apic.c linux-2.4.22-adeos-ltt/arch/i386/kernel/apic.c
--- linux-2.4.22-clean/arch/i386/kernel/apic.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/apic.c	2003-11-21 23:25:36.000000000 -0800
@@ -1057,7 +1057,7 @@ inline void smp_local_timer_interrupt(st
 	 * Currently this isn't too much of an issue (performance wise),
 	 * we can take more than 100K local irqs per second on a 100 MHz P5.
 	 */
-}
+    }
 
 /*
  * Local APIC timer interrupt. This is the most natural way for doing
@@ -1082,6 +1082,11 @@ void smp_apic_timer_interrupt(struct pt_
 	 * NOTE! We'd better ACK the irq immediately,
 	 * because timer handling can be slow.
 	 */
+#ifdef CONFIG_ADEOS_CORE
+	if (adp_pipelined)
+	    regs = &__adeos_tick_regs;
+	else
+#endif /* CONFIG_ADEOS_CORE */
 	ack_APIC_irq();
 	/*
 	 * update_process_times() expects us to have done irq_enter().
@@ -1129,6 +1134,9 @@ asmlinkage void smp_error_interrupt(void
 	v = apic_read(APIC_ESR);
 	apic_write(APIC_ESR, 0);
 	v1 = apic_read(APIC_ESR);
+#ifdef CONFIG_ADEOS_CORE
+	if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	ack_APIC_irq();
 	atomic_inc(&irq_err_count);
 
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/entry.S linux-2.4.22-adeos-ltt/arch/i386/kernel/entry.S
--- linux-2.4.22-clean/arch/i386/kernel/entry.S	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/entry.S	2003-11-21 23:49:38.000000000 -0800
@@ -138,6 +138,11 @@ ENTRY(lcall7)
 	pushfl			# We get a different stack layout with call gates,
 	pushl %eax		# which has to be cleaned up later..
 	SAVE_ALL
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_enter_syscall)
+	testl %eax,%eax
+	jne   restore_all
+#endif /* CONFIG_ADEOS_CORE */
 	movl EIP(%esp),%eax	# due to call gates, this is eflags, not eip..
 	movl CS(%esp),%edx	# this is eip..
 	movl EFLAGS(%esp),%ecx	# and this is cs..
@@ -155,13 +160,25 @@ ENTRY(lcall7)
 	pushl $0x7
 	call *%edx
 	addl $4, %esp
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_exit_syscall)
+	testl %eax,%eax
 	popl %eax
+	jne   restore_all
+#else /* !CONFIG_ADEOS_CORE */
+	popl %eax
+#endif /* CONFIG_ADEOS_CORE */
 	jmp ret_from_sys_call
 
 ENTRY(lcall27)
 	pushfl			# We get a different stack layout with call gates,
 	pushl %eax		# which has to be cleaned up later..
 	SAVE_ALL
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_enter_syscall)
+	testl %eax,%eax
+	jne   restore_all
+#endif /* CONFIG_ADEOS_CORE */
 	movl EIP(%esp),%eax	# due to call gates, this is eflags, not eip..
 	movl CS(%esp),%edx	# this is eip..
 	movl EFLAGS(%esp),%ecx	# and this is cs..
@@ -179,11 +196,21 @@ ENTRY(lcall27)
 	pushl $0x27
 	call *%edx
 	addl $4, %esp
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_exit_syscall)
+	testl %eax,%eax
+	popl %eax
+	jne   restore_all
+#else /* !CONFIG_ADEOS_CORE */
 	popl %eax
+#endif /* CONFIG_ADEOS_CORE */
 	jmp ret_from_sys_call
 
 
 ENTRY(ret_from_fork)
+#ifdef CONFIG_ADEOS_CORE
+	sti
+#endif /* CONFIG_ADEOS_CORE */
 	pushl %ebx
 	call SYMBOL_NAME(schedule_tail)
 	addl $4, %esp
@@ -202,25 +229,70 @@ ENTRY(ret_from_fork)
 ENTRY(system_call)
 	pushl %eax			# save orig_eax
 	SAVE_ALL
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_enter_syscall)
+	testl %eax,%eax
+	jne   restore_all
+	movl ORIG_EAX(%esp),%eax
+#endif /* CONFIG_ADEOS_CORE */
 	GET_CURRENT(%ebx)
 	testb $0x02,tsk_ptrace(%ebx)	# PT_TRACESYS
 	jne tracesys
 	cmpl $(NR_syscalls),%eax
 	jae badsys
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	movl SYMBOL_NAME(syscall_entry_trace_active), %eax
+	cmpl $1, %eax                   # are we tracing system call entries
+	jne no_syscall_entry_trace
+	movl %esp, %eax                 # copy the stack pointer
+	pushl %eax                      # pass the stack pointer copy
+	call SYMBOL_NAME(trace_real_syscall_entry)
+	addl $4,%esp                    # return stack to state before pass
+no_syscall_entry_trace:
+	movl ORIG_EAX(%esp),%eax	# restore eax to it's original content
+#endif
+
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# save the return value
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	movl SYMBOL_NAME(syscall_exit_trace_active), %eax
+	cmpl $1, %eax                   # are we tracing system call exits
+	jne no_syscall_exit_trace
+	call SYMBOL_NAME(trace_real_syscall_exit)
+no_syscall_exit_trace:	
+#endif
+
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_exit_syscall)
+	testl %eax,%eax
+	jne   restore_all
+#endif /* CONFIG_ADEOS_CORE */
+
 ENTRY(ret_from_sys_call)
-	cli				# need_resched and signals atomic test
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_stall_root)
+#else /* !CONFIG_ADEOS_CORE */
+	cli
+#endif /* CONFIG_ADEOS_CORE */
 	cmpl $0,need_resched(%ebx)
 	jne reschedule
 	cmpl $0,sigpending(%ebx)
 	jne signal_return
+#ifdef CONFIG_ADEOS_CORE
+     call SYMBOL_NAME(__adeos_unstall_root)
+#endif /* CONFIG_ADEOS_CORE */
 restore_all:
 	RESTORE_ALL
 
 	ALIGN
 signal_return:
-	sti				# we can get here from an interrupt handler
+#ifdef CONFIG_ADEOS_CORE
+	call SYMBOL_NAME(__adeos_unstall_root)
+#else /* !CONFIG_ADEOS_CORE */
+	sti
+#endif /* CONFIG_ADEOS_CORE */
 	testl $(VM_MASK),EFLAGS(%esp)
 	movl %esp,%eax
 	jne v86_signal_return
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/i386_ksyms.c linux-2.4.22-adeos-ltt/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.22-clean/arch/i386/kernel/i386_ksyms.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/i386_ksyms.c	2003-11-21 23:25:36.000000000 -0800
@@ -32,6 +32,58 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
 
+#ifdef CONFIG_ADEOS_CORE
+EXPORT_SYMBOL(adeos_critical_enter);
+EXPORT_SYMBOL(adeos_critical_exit);
+EXPORT_SYMBOL(__adeos_sync_stage);
+EXPORT_SYMBOL(__adeos_ack_system_irq);
+EXPORT_SYMBOL(__adeos_tick_regs);
+EXPORT_SYMBOL(__adeos_tick_irq);
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(__adeos_send_IPI_allbutself);
+EXPORT_SYMBOL(__adeos_send_IPI_other);
+EXPORT_SYMBOL(__adeos_set_irq_affinity);
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_ADEOS_MODULE
+#ifdef CONFIG_X86_LOCAL_APIC
+extern int using_apic_timer;
+EXPORT_SYMBOL_NOVERS(using_apic_timer);
+#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_ADEOS_MODULE */
+/* The following are per-platform convenience exports which are needed
+   by some Adeos domains loaded as kernel modules. */
+extern irq_desc_t irq_desc[];
+EXPORT_SYMBOL_NOVERS(irq_desc);
+extern struct desc_struct idt_table[];
+EXPORT_SYMBOL_NOVERS(idt_table);
+extern void ret_from_intr(void);
+EXPORT_SYMBOL_NOVERS(ret_from_intr);
+extern struct tty_driver console_driver;
+EXPORT_SYMBOL_NOVERS(console_driver);
+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
+EXPORT_SYMBOL_NOVERS(kd_mksound);
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL_NOVERS(cpu_tlbstate);
+#ifdef CONFIG_MULTIQUAD
+EXPORT_SYMBOL_NOVERS(logical_apicid_2_cpu);
+#else  /* CONFIG_MULTIQUAD */
+EXPORT_SYMBOL_NOVERS(physical_apicid_2_cpu);
+#endif /* CONFIG_MULTIQUAD */
+#endif /* CONFIG_SMP */
+#if defined(CONFIG_ADEOS_MODULE) && defined(CONFIG_X86_IO_APIC)
+EXPORT_SYMBOL_NOVERS(io_apic_irqs);
+EXPORT_SYMBOL_NOVERS(irq_vector);
+#endif /* CONFIG_ADEOS_MODULE && CONFIG_X86_IO_APIC */
+EXPORT_SYMBOL_NOVERS(set_ldt_desc);
+EXPORT_SYMBOL_NOVERS(default_ldt);
+EXPORT_SYMBOL_NOVERS(__switch_to);
+EXPORT_SYMBOL_NOVERS(cpu_khz);
+extern void show_stack(unsigned long *esp);
+EXPORT_SYMBOL_NOVERS(show_stack);
+extern void show_registers(struct pt_regs *regs);
+EXPORT_SYMBOL_NOVERS(show_registers);
+#endif /* CONFIG_ADEOS_CORE */
+
 #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
 extern void machine_real_restart(unsigned char *, int);
 EXPORT_SYMBOL(machine_real_restart);
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/i8259.c linux-2.4.22-adeos-ltt/arch/i386/kernel/i8259.c
--- linux-2.4.22-clean/arch/i386/kernel/i8259.c	2001-09-17 23:03:09.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/i8259.c	2003-11-21 23:25:36.000000000 -0800
@@ -265,6 +265,36 @@ static inline int i8259A_irq_real(unsign
  */
 void mask_and_ack_8259A(unsigned int irq)
 {
+#ifdef CONFIG_ADEOS_CORE
+	unsigned int irqmask = 1 << irq;
+
+	spin_lock(&i8259A_lock);
+
+	if (cached_irq_mask & irqmask)
+		goto spurious_8259A_irq;
+
+	if (irq == 0) {
+	    /* Fast timer ack -- don't mask
+	      (unless supposedly spurious) */
+	    outb(0x20,0x20);
+	    spin_unlock(&i8259A_lock);
+	    return;
+	}
+
+	cached_irq_mask |= irqmask;
+
+handle_real_irq:
+	if (irq & 8) {
+		outb(cached_A1,0xA1);
+		outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
+		outb(0x62,0x20);	/* 'Specific EOI' to master-IRQ2 */
+	} else {
+		outb(cached_21,0x21);
+		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
+	}
+	spin_unlock(&i8259A_lock);
+	return;
+#else /* !CONFIG_ADEOS_CORE */
 	unsigned int irqmask = 1 << irq;
 	unsigned long flags;
 
@@ -301,6 +331,7 @@ handle_real_irq:
 	}
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 	return;
+#endif /* CONFIG_ADEOS_CORE */
 
 spurious_8259A_irq:
 	/*
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/io_apic.c linux-2.4.22-adeos-ltt/arch/i386/kernel/io_apic.c
--- linux-2.4.22-clean/arch/i386/kernel/io_apic.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/io_apic.c	2003-11-21 23:25:36.000000000 -0800
@@ -1246,6 +1246,25 @@ static unsigned int startup_edge_ioapic_
  * interrupt for real. This prevents IRQ storms from unhandled
  * devices.
  */
+
+#ifdef CONFIG_ADEOS_CORE
+
+static void ack_edge_ioapic_irq (unsigned irq)
+
+{
+    if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) == (IRQ_PENDING | IRQ_DISABLED))
+	{
+	unsigned long flags;
+	adeos_spin_lock_irqsave(&ioapic_lock,flags);
+	__mask_IO_APIC_irq(irq);
+	adeos_spin_unlock_irqrestore(&ioapic_lock,flags);
+	}
+
+    ack_APIC_irq();
+}
+
+#else /* !CONFIG_ADEOS_CORE */
+
 static void ack_edge_ioapic_irq(unsigned int irq)
 {
 	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
@@ -1254,6 +1273,8 @@ static void ack_edge_ioapic_irq(unsigned
 	ack_APIC_irq();
 }
 
+#endif /* CONFIG_ADEOS_CORE */
+
 static void end_edge_ioapic_irq (unsigned int i) { /* nothing */ }
 
 
@@ -1282,6 +1303,65 @@ static unsigned int startup_level_ioapic
 #define enable_level_ioapic_irq		unmask_IO_APIC_irq
 #define disable_level_ioapic_irq	mask_IO_APIC_irq
 
+#ifdef CONFIG_ADEOS_CORE
+
+/* The standard Linux implementation for acknowledging IO-APIC
+   interrupts has been changed in order to guarantee that low priority
+   IRQs won't be delayed waiting for a high priority interrupt handler
+   to call end_level_ioapic_irq(). Therefore we immediately ack in
+   mask_and_ack_level_ioapic_irq(), still handling the 82093AA bugous
+   edge case. */
+
+static unsigned long bugous_edge_triggers;
+
+static void end_level_ioapic_irq (unsigned irq)
+
+{
+    if (test_and_clear_bit(irq,&bugous_edge_triggers))
+	{
+#ifdef APIC_MISMATCH_DEBUG
+	atomic_inc(&irq_mis_count);
+#endif
+	spin_lock(&ioapic_lock);
+	__unmask_and_level_IO_APIC_irq(irq);
+	spin_unlock(&ioapic_lock);
+	}
+    else
+	{
+	spin_lock(&ioapic_lock);
+	__unmask_IO_APIC_irq(irq);
+	spin_unlock(&ioapic_lock);
+	}
+}
+
+static void mask_and_ack_level_ioapic_irq (unsigned irq)
+
+{
+    unsigned long v;
+    int i;
+
+    i = IO_APIC_VECTOR(irq);
+    v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+    if (!(v & (1 << (i & 0x1f))))
+	{
+	set_bit(irq,&bugous_edge_triggers);
+	spin_lock(&ioapic_lock);
+	__mask_and_edge_IO_APIC_irq(irq);
+	spin_unlock(&ioapic_lock);
+	}
+    else
+	{
+	spin_lock(&ioapic_lock);
+	__mask_IO_APIC_irq(irq);
+	spin_unlock(&ioapic_lock);
+	}
+
+    ack_APIC_irq();
+}
+
+#else /* !CONFIG_ADEOS_CORE */
+
 static void end_level_ioapic_irq (unsigned int irq)
 {
 	unsigned long v;
@@ -1343,6 +1423,8 @@ static void end_level_ioapic_irq (unsign
 
 static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
 
+#endif /* CONFIG_ADEOS_CORE */
+
 #ifndef CONFIG_SMP
 
 void send_IPI_self(int vector)
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/irq.c linux-2.4.22-adeos-ltt/arch/i386/kernel/irq.c
--- linux-2.4.22-clean/arch/i386/kernel/irq.c	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/irq.c	2003-11-21 23:25:36.000000000 -0800
@@ -33,6 +33,8 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 
+#include <linux/trace.h>
+
 #include <asm/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -441,6 +443,8 @@ int handle_IRQ_event(unsigned int irq, s
 
 	irq_enter(cpu, irq);
 
+	TRACE_IRQ_ENTRY(irq, !(user_mode(regs)));
+
 	status = 1;	/* Force the "do bottom halves" bit */
 
 	if (!(action->flags & SA_INTERRUPT))
@@ -457,6 +461,8 @@ int handle_IRQ_event(unsigned int irq, s
 
 	irq_exit(cpu, irq);
 
+	TRACE_IRQ_EXIT();
+
 	return status;
 }
 
@@ -594,6 +600,9 @@ asmlinkage unsigned int do_IRQ(struct pt
 
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
+#ifdef CONFIG_ADEOS_CORE
+	if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	desc->handler->ack(irq);
 	/*
 	   REPLAY is when Linux resends an IRQ that was dropped earlier
@@ -635,6 +644,11 @@ asmlinkage unsigned int do_IRQ(struct pt
 	 */
 	for (;;) {
 		spin_unlock(&desc->lock);
+#ifdef CONFIG_ADEOS_CORE
+		if (likely(adp_pipelined && __adeos_tick_irq == irq))
+		    handle_IRQ_event(irq,&__adeos_tick_regs,action);
+		else
+#endif /* CONFIG_ADEOS_CORE */
 		handle_IRQ_event(irq, &regs, action);
 		spin_lock(&desc->lock);
 		
@@ -1124,6 +1138,29 @@ static int irq_affinity_write_proc (stru
 	return full_count;
 }
 
+#ifdef CONFIG_ADEOS_CORE
+
+unsigned long __adeos_set_irq_affinity (unsigned irq, unsigned long cpumask)
+
+{
+    unsigned long oldmask = irq_affinity[irq];
+
+    if (cpumask == 0)
+	return oldmask; /* Return mask value -- no change. */
+
+    cpumask &= cpu_online_map;
+
+    if (cpumask == 0 || irq_desc[irq].handler->set_affinity == NULL)
+	return 0;	/* Error -- bad mask value or non-routable IRQ. */
+
+    irq_affinity[irq] = cpumask;
+    irq_desc[irq].handler->set_affinity(irq,cpumask);
+
+    return oldmask;
+}
+
+#endif /* CONFIG_ADEOS_CORE */
+
 #endif
 
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
@@ -1211,4 +1248,3 @@ void init_irq_proc (void)
 	for (i = 0; i < NR_IRQS; i++)
 		register_irq_proc(i);
 }
-
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/Makefile linux-2.4.22-adeos-ltt/arch/i386/kernel/Makefile
--- linux-2.4.22-clean/arch/i386/kernel/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/Makefile	2003-11-21 23:25:36.000000000 -0800
@@ -14,7 +14,7 @@ all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
 
-export-objs     := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o setup.o
+export-objs     := adeos.o mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o setup.o
 
 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 \
@@ -30,6 +30,7 @@ obj-y			+= pci-pc.o pci-irq.o
 endif
 endif
 
+obj-$(CONFIG_ADEOS_CORE)	+= adeos.o
 obj-$(CONFIG_MCA)		+= mca.o
 obj-$(CONFIG_MTRR)		+= mtrr.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/nmi.c linux-2.4.22-adeos-ltt/arch/i386/kernel/nmi.c
--- linux-2.4.22-clean/arch/i386/kernel/nmi.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/nmi.c	2003-11-21 23:25:36.000000000 -0800
@@ -344,7 +344,11 @@ void nmi_watchdog_tick (struct pt_regs *
 	 * Since current-> is always on the stack, and we always switch
 	 * the stack NMI-atomically, it's safe to use smp_processor_id().
 	 */
+#ifdef CONFIG_ADEOS_CORE
+	int sum, cpu = adeos_processor_id();
+#else /* !CONFIG_ADEOS_CORE */
 	int sum, cpu = smp_processor_id();
+#endif /* CONFIG_ADEOS_CORE */
 
 	sum = apic_timer_irqs[cpu];
 
@@ -363,6 +367,9 @@ void nmi_watchdog_tick (struct pt_regs *
 			bust_spinlocks(1);
 			printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
 			show_registers(regs);
+#ifdef CONFIG_ADEOS_CORE
+			__adeos_dump_state();
+#endif /* CONFIG_ADEOS_CORE */
 			printk("console shuts up ...\n");
 			console_silent();
 			spin_unlock(&nmi_print_lock);
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/process.c linux-2.4.22-adeos-ltt/arch/i386/kernel/process.c
--- linux-2.4.22-clean/arch/i386/kernel/process.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/process.c	2003-11-21 23:25:36.000000000 -0800
@@ -34,6 +34,8 @@
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -132,6 +134,9 @@ void cpu_idle (void)
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
+#ifdef CONFIG_ADEOS_CORE
+		adeos_suspend_domain();
+#endif /* CONFIG_ADEOS_CORE */
 		while (!current->need_resched)
 			idle();
 		schedule();
@@ -508,6 +513,10 @@ int arch_kernel_thread(int (*fn)(void *)
 		 "r" (arg), "r" (fn),
 		 "b" (flags | CLONE_VM)
 		: "memory");
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+   if (retval > 0)
+     TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, retval, (int) fn);
+#endif
 
 	return retval;
 }
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/smp.c linux-2.4.22-adeos-ltt/arch/i386/kernel/smp.c
--- linux-2.4.22-clean/arch/i386/kernel/smp.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/smp.c	2003-11-21 23:25:36.000000000 -0800
@@ -134,6 +134,11 @@ static inline void __send_IPI_shortcut(u
 	 */
 	unsigned int cfg;
 
+#ifdef CONFIG_ADEOS_CORE
+	unsigned long flags;
+	adeos_hw_local_irq_save(flags);
+#endif /* !CONFIG_ADEOS_CORE */
+
 	/*
 	 * Wait for idle.
 	 */
@@ -148,6 +153,10 @@ static inline void __send_IPI_shortcut(u
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
 	apic_write_around(APIC_ICR, cfg);
+
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_local_irq_restore(flags);
+#endif /* !CONFIG_ADEOS_CORE */
 }
 
 void send_IPI_self(int vector)
@@ -160,9 +169,12 @@ static inline void send_IPI_mask_bitmask
 	unsigned long cfg;
 	unsigned long flags;
 
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_local_irq_save(flags);
+#else /* !CONFIG_ADEOS_CORE */
 	__save_flags(flags);
 	__cli();
-
+#endif /* CONFIG_ADEOS_CORE */
 		
 	/*
 	 * Wait for idle.
@@ -185,7 +197,11 @@ static inline void send_IPI_mask_bitmask
 	 */
 	apic_write_around(APIC_ICR, cfg);
 
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_local_irq_restore(flags);
+#else /* !CONFIG_ADEOS_CORE */
 	__restore_flags(flags);
+#endif /* CONFIG_ADEOS_CORE */
 }
 
 static inline void send_IPI_mask_sequence(int mask, int vector)
@@ -199,8 +215,12 @@ static inline void send_IPI_mask_sequenc
 	 * should be modified to do 1 message per cluster ID - mbligh
 	 */ 
 
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_local_irq_save(flags);
+#else /* !CONFIG_ADEOS_CORE */
 	__save_flags(flags);
 	__cli();
+#endif /* CONFIG_ADEOS_CORE */
 
 	for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) {
 		query_mask = 1 << query_cpu;
@@ -231,7 +251,11 @@ static inline void send_IPI_mask_sequenc
 			apic_write_around(APIC_ICR, cfg);
 		}
 	}
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_local_irq_restore(flags);
+#else /* !CONFIG_ADEOS_CORE */
 	__restore_flags(flags);
+#endif /* CONFIG_ADEOS_CORE */
 }
 
 static inline void send_IPI_mask(int mask, int vector)
@@ -382,7 +406,11 @@ asmlinkage void smp_invalidate_interrupt
 		} else
 			leave_mm(cpu);
 	}
+#ifdef CONFIG_ADEOS_CORE
+	if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	ack_APIC_irq();
+
 	clear_bit(cpu, &flush_cpumask);
 }
 
@@ -603,6 +631,9 @@ void smp_send_stop(void)
  */
 asmlinkage void smp_reschedule_interrupt(void)
 {
+#ifdef CONFIG_ADEOS_CORE
+	if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	ack_APIC_irq();
 }
 
@@ -612,6 +643,9 @@ asmlinkage void smp_call_function_interr
 	void *info = call_data->info;
 	int wait = call_data->wait;
 
+#ifdef CONFIG_ADEOS_CORE
+	if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	ack_APIC_irq();
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
@@ -629,3 +663,14 @@ asmlinkage void smp_call_function_interr
 	}
 }
 
+#ifdef CONFIG_ADEOS_CORE
+
+void __adeos_send_IPI_allbutself (int vector) {
+    send_IPI_allbutself(vector);
+}
+
+void __adeos_send_IPI_other (int cpu, int vector) {
+    send_IPI_mask(1 << cpu,vector);
+}
+
+#endif /* CONFIG_ADEOS_CORE */
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/sys_i386.c linux-2.4.22-adeos-ltt/arch/i386/kernel/sys_i386.c
--- linux-2.4.22-clean/arch/i386/kernel/sys_i386.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/sys_i386.c	2003-11-21 23:21:08.000000000 -0800
@@ -19,6 +19,8 @@
 #include <linux/file.h>
 #include <linux/utsname.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 
@@ -137,6 +139,8 @@ asmlinkage int sys_ipc (uint call, int f
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
+	TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
 	switch (call) {
 	case SEMOP:
 		return sys_semtimedop (first, (struct sembuf *)ptr, second, NULL);
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/time.c linux-2.4.22-adeos-ltt/arch/i386/kernel/time.c
--- linux-2.4.22-clean/arch/i386/kernel/time.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/time.c	2003-11-21 23:25:36.000000000 -0800
@@ -211,13 +211,22 @@ static unsigned long do_slow_gettimeoffs
 
 			int i;
 
+#ifdef CONFIG_ADEOS_CORE
+			unsigned long flags;
+			adeos_spin_lock_irqsave(&i8259A_lock, flags);
+#else /* !CONFIG_ADEOS_CORE */
 			spin_lock(&i8259A_lock);
+#endif /* CONFIG_ADEOS_CORE */
 			/*
 			 * This is tricky when I/O APICs are used;
 			 * see do_timer_interrupt().
 			 */
 			i = inb(0x20);
+#ifdef CONFIG_ADEOS_CORE
+			adeos_spin_unlock_irqrestore(&i8259A_lock, flags);
+#else /* !CONFIG_ADEOS_CORE */
 			spin_unlock(&i8259A_lock);
+#endif /* CONFIG_ADEOS_CORE */
 
 			/* assumption about timer being IRQ0 */
 			if (i & 0x01) {
@@ -576,11 +585,20 @@ static inline void do_timer_interrupt(in
 		 * This will also deassert NMI lines for the watchdog if run
 		 * on an 82489DX-based system.
 		 */
+#ifdef CONFIG_ADEOS_CORE
+		unsigned long flags;
+		adeos_spin_lock_irqsave(&i8259A_lock, flags);
+#else /* !CONFIG_ADEOS_CORE */
 		spin_lock(&i8259A_lock);
+#endif /* CONFIG_ADEOS_CORE */
 		outb(0x0c, 0x20);
 		/* Ack the IRQ; AEOI will end it automatically. */
 		inb(0x20);
+#ifdef CONFIG_ADEOS_CORE
+		adeos_spin_unlock_irqrestore(&i8259A_lock, flags);
+#else /* !CONFIG_ADEOS_CORE */
 		spin_unlock(&i8259A_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	}
 #endif
 
@@ -673,6 +691,7 @@ static void timer_interrupt(int irq, voi
 
 		rdtscl(last_tsc_low);
 
+#ifndef CONFIG_ADEOS_CORE
 		spin_lock(&i8253_lock);
 		outb_p(0x00, 0x43);     /* latch the count ASAP */
 
@@ -704,6 +723,7 @@ static void timer_interrupt(int irq, voi
 
 		count = ((LATCH-1) - count) * TICK_SIZE;
 		delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+#endif /* !CONFIG_ADEOS_CORE */
 	}
 
 	do_timer_interrupt(irq, NULL, regs);
diff -Nurp linux-2.4.22-clean/arch/i386/kernel/traps.c linux-2.4.22-adeos-ltt/arch/i386/kernel/traps.c
--- linux-2.4.22-clean/arch/i386/kernel/traps.c	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/i386/kernel/traps.c	2003-11-21 23:25:36.000000000 -0800
@@ -25,6 +25,8 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 
+#include <linux/trace.h>
+
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
 #include <asm/processor.h>
@@ -280,6 +282,82 @@ bug:
 	printk("Kernel BUG\n");
 }
 
+/* Trace related code */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+asmlinkage void trace_real_syscall_entry(struct pt_regs * regs)
+{
+        int                 use_depth;
+	int                 use_bounds;
+	int                 depth = 0;
+        int                 seek_depth;
+        unsigned long       lower_bound;
+        unsigned long       upper_bound;
+	unsigned long       addr;
+	unsigned long*      stack;
+	trace_syscall_entry trace_syscall_event;
+
+        /* Set the syscall ID */
+        trace_syscall_event.syscall_id = (uint8_t) regs->orig_eax;
+
+	/* Set the address in any case */
+	trace_syscall_event.address  = regs->eip;
+
+	/* Are we in the kernel (This is a kernel thread)? */
+	if(!(regs->xcs & 3))
+	  /* Don't go diging anywhere */
+	  goto trace_syscall_end;
+
+	/* Get the trace configuration */
+	if(trace_get_config(&use_depth,
+			    &use_bounds,
+			    &seek_depth,
+			    (void*)&lower_bound,
+			    (void*)&upper_bound) < 0)
+	  goto trace_syscall_end;
+
+	/* Do we have to search for an eip address range */
+	if((use_depth == 1) || (use_bounds == 1))
+	  {
+	  /* Start at the top of the stack (bottom address since stacks grow downward) */
+	  stack = (unsigned long*) regs->esp;
+
+	  /* Keep on going until we reach the end of the process' stack limit (wherever it may be) */
+	  while(!get_user(addr, stack))
+	    {
+	    /* Does this LOOK LIKE an address in the program */
+	    if((addr > current->mm->start_code)
+             &&(addr < current->mm->end_code))
+	      {
+	      /* Does this address fit the description */
+	      if(((use_depth == 1) && (depth == seek_depth))
+               ||((use_bounds == 1) && (addr > lower_bound) && (addr < upper_bound)))
+		{
+		/* Set the address */
+		trace_syscall_event.address = addr;
+
+		/* We're done */
+		goto trace_syscall_end;
+		}
+	      else
+		/* We're one depth more */
+		depth++;
+	      }
+	    /* Go on to the next address */
+	    stack++;
+	    }
+	  }
+
+trace_syscall_end:
+	/* Trace the event */
+	trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}
+
+asmlinkage void trace_real_syscall_exit(void)
+{
+        trace_event(TRACE_EV_SYSCALL_EXIT, NULL);
+}
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
+
 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -313,6 +391,8 @@ static inline unsigned long get_cr2(void
 static void inline do_trap(int trapnr, int signr, char *str, int vm86,
 			   struct pt_regs * regs, long error_code, siginfo_t *info)
 {
+  TRACE_TRAP_ENTRY(trapnr, regs->eip);
+    
 	if (regs->eflags & VM_MASK) {
 		if (vm86)
 			goto vm86_trap;
@@ -331,6 +411,7 @@ static void inline do_trap(int trapnr, i
 			force_sig_info(signr, info, tsk);
 		else
 			force_sig(signr, tsk);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -340,14 +421,17 @@ static void inline do_trap(int trapnr, i
 			regs->eip = fixup;
 		else	
 			die(str, regs, error_code);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
 	vm86_trap: {
 		int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
 		if (ret) goto trap_signal;
+		TRACE_TRAP_EXIT();
 		return;
 	}
+	TRACE_TRAP_EXIT();
 }
 
 #define DO_ERROR(trapnr, signr, str, name) \
@@ -407,11 +491,15 @@ asmlinkage void do_general_protection(st
 
 	current->thread.error_code = error_code;
 	current->thread.trap_no = 13;
+        TRACE_TRAP_ENTRY(13, regs->eip);
 	force_sig(SIGSEGV, current);
+        TRACE_TRAP_EXIT();
 	return;
 
 gp_in_vm86:
+        TRACE_TRAP_ENTRY(13, regs->eip);
 	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+        TRACE_TRAP_EXIT();
 	return;
 
 gp_in_kernel:
@@ -471,7 +559,16 @@ asmlinkage void do_nmi(struct pt_regs * 
 {
 	unsigned char reason = inb(0x61);
 
+#ifndef CONFIG_X86_LOCAL_APIC /* On an machine with APIC enabled NMIs are used to implement a
+				 watchdog and will hang the machine if traced. */
+        TRACE_TRAP_ENTRY(2, regs->eip);
+#endif
+
+#ifdef CONFIG_ADEOS_CORE
+	++nmi_count(adeos_processor_id());
+#else /* !CONFIG_ADEOS_CORE */
 	++nmi_count(smp_processor_id());
+#endif /* CONFIG_ADEOS_CORE */
 
 	if (!(reason & 0xc0)) {
 #if CONFIG_X86_LOCAL_APIC
@@ -481,10 +578,12 @@ asmlinkage void do_nmi(struct pt_regs * 
 		 */
 		if (nmi_watchdog) {
 			nmi_watchdog_tick(regs);
+			TRACE_TRAP_EXIT();
 			return;
 		}
 #endif
 		unknown_nmi_error(reason, regs);
+	        TRACE_TRAP_EXIT();
 		return;
 	}
 	if (reason & 0x80)
@@ -499,6 +598,8 @@ asmlinkage void do_nmi(struct pt_regs * 
 	inb(0x71);		/* dummy */
 	outb(0x0f, 0x70);
 	inb(0x71);		/* dummy */
+
+        TRACE_TRAP_EXIT();
 }
 
 /*
@@ -577,7 +678,9 @@ asmlinkage void do_debug(struct pt_regs 
 	 */
 	info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : 
 	                                        (void *)regs->eip;
+        TRACE_TRAP_ENTRY(1, regs->eip);
 	force_sig_info(SIGTRAP, &info, tsk);
+        TRACE_TRAP_EXIT();
 
 	/* Disable additional traps. They'll be re-enabled when
 	 * the signal is delivered.
@@ -589,7 +692,9 @@ clear_dr7:
 	return;
 
 debug_vm86:
+        TRACE_TRAP_ENTRY(1, regs->eip);
 	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+        TRACE_TRAP_EXIT();
 	return;
 
 clear_TF:
@@ -739,10 +844,12 @@ asmlinkage void do_simd_coprocessor_erro
 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
 					  long error_code)
 {
+        TRACE_TRAP_ENTRY(16, regs->eip);
 #if 0
 	/* No need to warn about this any longer. */
 	printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
 #endif
+        TRACE_TRAP_EXIT();	
 }
 
 /*
@@ -770,8 +877,10 @@ asmlinkage void math_emulate(long arg)
 {
 	printk("math-emulation not enabled and no coprocessor found.\n");
 	printk("killing %s.\n",current->comm);
+        TRACE_TRAP_ENTRY(7, 0);
 	force_sig(SIGFPE,current);
 	schedule();
+        TRACE_TRAP_EXIT();
 }
 
 #endif /* CONFIG_MATH_EMULATION */
@@ -804,7 +913,6 @@ do { \
 	 "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
 } while (0)
 
-
 /*
  * This needs to use 'idt_table' rather than 'idt', and
  * thus use the _nonmapped_ version of the IDT, as the
diff -Nurp linux-2.4.22-clean/arch/i386/mm/fault.c linux-2.4.22-adeos-ltt/arch/i386/mm/fault.c
--- linux-2.4.22-clean/arch/i386/mm/fault.c	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/i386/mm/fault.c	2003-11-21 23:25:36.000000000 -0800
@@ -20,6 +20,8 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 
+#include <linux/trace.h>
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -153,7 +155,11 @@ asmlinkage void do_page_fault(struct pt_
 
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
-		local_irq_enable();
+#ifdef CONFIG_ADEOS_CORE
+	    adeos_hw_sti();
+#else /* !CONFIG_ADEOS_CORE */
+	    local_irq_enable();
+#endif /* CONFIG_ADEOS_CORE */
 
 	tsk = current;
 
@@ -176,6 +182,8 @@ asmlinkage void do_page_fault(struct pt_
 	mm = tsk->mm;
 	info.si_code = SEGV_MAPERR;
 
+	TRACE_TRAP_ENTRY(14, regs->eip);
+
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
@@ -258,6 +266,7 @@ good_area:
 			tsk->thread.screen_bitmap |= 1 << bit;
 	}
 	up_read(&mm->mmap_sem);
+        TRACE_TRAP_EXIT();
 	return;
 
 /*
@@ -277,6 +286,7 @@ bad_area:
 		/* info.si_code has been set above */
 		info.si_addr = (void *)address;
 		force_sig_info(SIGSEGV, &info, tsk);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -290,6 +300,7 @@ bad_area:
 
 		if (nr == 6) {
 			do_invalid_op(regs, 0);
+			TRACE_TRAP_EXIT();
 			return;
 		}
 	}
@@ -298,6 +309,7 @@ no_context:
 	/* Are we prepared to handle this kernel fault?  */
 	if ((fixup = search_exception_table(regs->eip)) != 0) {
 		regs->eip = fixup;
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -362,6 +374,7 @@ do_sigbus:
 	/* Kernel mode? Handle exceptions or die */
 	if (!(error_code & 4))
 		goto no_context;
+        TRACE_TRAP_EXIT();
 	return;
 
 vmalloc_fault:
@@ -395,6 +408,8 @@ vmalloc_fault:
 		pte_k = pte_offset(pmd_k, address);
 		if (!pte_present(*pte_k))
 			goto no_context;
+		TRACE_TRAP_EXIT();
 		return;
 	}
+	TRACE_TRAP_EXIT();
 }
diff -Nurp linux-2.4.22-clean/arch/i386/mm/ioremap.c linux-2.4.22-adeos-ltt/arch/i386/mm/ioremap.c
--- linux-2.4.22-clean/arch/i386/mm/ioremap.c	2002-08-02 17:39:42.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/i386/mm/ioremap.c	2003-11-21 23:25:36.000000000 -0800
@@ -81,6 +81,9 @@ static int remap_area_pages(unsigned lon
 		if (remap_area_pmd(pmd, address, end - address,
 					 phys_addr + address, flags))
 			break;
+#ifdef CONFIG_ADEOS_CORE
+		set_pgdir(address, *dir);
+#endif /* CONFIG_ADEOS_CORE */
 		error = 0;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
diff -Nurp linux-2.4.22-clean/arch/mips/baget/irq.c linux-2.4.22-adeos-ltt/arch/mips/baget/irq.c
--- linux-2.4.22-clean/arch/mips/baget/irq.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/baget/irq.c	2003-11-21 23:21:08.000000000 -0800
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/trace.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -177,6 +178,8 @@ static void do_IRQ(int irq, struct pt_re
 	struct irqaction *action;
 	int do_random, cpu;
 
+	TRACE_IRQ_ENTRY(irq, !user_mode(regs));
+
 	cpu = smp_processor_id();
 	irq_enter(cpu, irq);
 	kstat.irqs[cpu][irq]++;
@@ -202,6 +205,8 @@ static void do_IRQ(int irq, struct pt_re
 	unmask_irq(irq);
 	irq_exit(cpu, irq);
 
+	TRACE_IRQ_EXIT();
+
 	/* unmasking and bottom half handling is done magically for us. */
 }
 
diff -Nurp linux-2.4.22-clean/arch/mips/config-shared.in linux-2.4.22-adeos-ltt/arch/mips/config-shared.in
--- linux-2.4.22-clean/arch/mips/config-shared.in	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/config-shared.in	2003-11-21 23:21:08.000000000 -0800
@@ -1027,6 +1027,11 @@ source drivers/usb/Config.in
 source net/bluetooth/Config.in
 
 mainmenu_option next_comment
+comment 'Kernel tracing --INCOMPLETE, WILL NOT WORK'
+tristate 'Kernel events tracing support--INCOMPLETE, WILL NOT WORK' CONFIG_TRACE
+endmenu
+
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/i8259.c linux-2.4.22-adeos-ltt/arch/mips/kernel/i8259.c
--- linux-2.4.22-clean/arch/mips/kernel/i8259.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/i8259.c	2003-11-21 23:21:08.000000000 -0800
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/trace.h>
 
 #include <asm/i8259.h>
 #include <asm/io.h>
@@ -266,6 +267,9 @@ void __init init_8259A(int auto_eoi)
 asmlinkage void i8259_do_irq(int irq, struct pt_regs regs)
 {
 	panic("i8259_do_irq: I want to be implemented");
+
+	TRACE_IRQ_ENTRY(irq, !user_mode(regs));
+	TRACE_IRQ_EXIT();
 }
 
 /*
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/ipc.c linux-2.4.22-adeos-ltt/arch/mips/kernel/ipc.c
--- linux-2.4.22-clean/arch/mips/kernel/ipc.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/ipc.c	2003-11-21 23:21:08.000000000 -0800
@@ -13,6 +13,7 @@
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <linux/trace.h>
 
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
@@ -30,6 +31,8 @@ asmlinkage int sys_ipc (uint call, int f
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
+	TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
 	switch (call) {
 	case SEMOP:
 		return sys_semop (first, (struct sembuf *)ptr, second);
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/irq.c linux-2.4.22-adeos-ltt/arch/mips/kernel/irq.c
--- linux-2.4.22-clean/arch/mips/kernel/irq.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/irq.c	2003-11-21 23:21:08.000000000 -0800
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/trace.h>
 
 #include <asm/atomic.h>
 #include <asm/system.h>
@@ -429,6 +430,8 @@ asmlinkage unsigned int do_IRQ(int irq, 
 	struct irqaction * action;
 	unsigned int status;
 
+	TRACE_IRQ_ENTRY(irq, !user_mode(regs));
+
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
@@ -488,6 +491,8 @@ out:
 	desc->handler->end(irq);
 	spin_unlock(&desc->lock);
 
+        TRACE_IRQ_EXIT();
+
 	if (softirq_pending(cpu))
 		do_softirq();
 	return 1;
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/scall_o32.S linux-2.4.22-adeos-ltt/arch/mips/kernel/scall_o32.S
--- linux-2.4.22-clean/arch/mips/kernel/scall_o32.S	2002-11-28 15:53:10.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/scall_o32.S	2003-11-21 23:21:08.000000000 -0800
@@ -46,6 +46,19 @@ NESTED(handle_sys, PT_SIZE, sp)
 
 stack_done:
         sw      a3, PT_R26(sp)          # save for syscall restart
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	sw	t2, PT_R1(sp)
+	move	a0, sp
+	jal	trace_real_syscall_entry
+	lw	t2, PT_R1(sp)
+
+	lw	a0, PT_R4(sp)		# Restore argument registers
+	lw	a1, PT_R5(sp)
+	lw	a2, PT_R6(sp)
+	lw	a3, PT_R7(sp)
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */	
+
 	lw	t0, TASK_PTRACE($28)	# syscall tracing enabled?
 	andi	t0, _PT_TRACESYS
 	bnez	t0, trace_a_syscall
@@ -61,6 +74,10 @@ stack_done:
 	sw	v0, PT_R0(sp)		# set flag for syscall restarting
 1:	sw	v0, PT_R2(sp)		# result
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	jal	trace_real_syscall_exit
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */	
+
 fast_ret_from_sys_call:
 ret_from_schedule:
 	mfc0	t0, CP0_STATUS		# need_resched and signals atomic test
@@ -140,6 +157,10 @@ trace_a_syscall:
 	sw	v0, PT_R0(sp)		# set flag for syscall restarting
 1:	sw	v0, PT_R2(sp)		# result
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	jal	trace_real_syscall_exit
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */	
+
 tracesys_exit:
 	jal	syscall_trace
 	j	static_ret_from_sys_call
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/time.c linux-2.4.22-adeos-ltt/arch/mips/kernel/time.c
--- linux-2.4.22-clean/arch/mips/kernel/time.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/time.c	2003-11-21 23:21:08.000000000 -0800
@@ -23,6 +23,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/trace.h>
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
@@ -483,6 +484,8 @@ asmlinkage void ll_timer_interrupt(int i
 {
 	int cpu = smp_processor_id();
 
+	TRACE_TRAP_ENTRY(irq, CAUSE_EPC(regs));
+
 	irq_enter(cpu, irq);
 	kstat.irqs[cpu][irq]++;
 
@@ -491,6 +494,8 @@ asmlinkage void ll_timer_interrupt(int i
 
 	irq_exit(cpu, irq);
 
+	TRACE_IRQ_EXIT();
+
 	if (softirq_pending(cpu))
 		do_softirq();
 }
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/traps.c linux-2.4.22-adeos-ltt/arch/mips/kernel/traps.c
--- linux-2.4.22-clean/arch/mips/kernel/traps.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/traps.c	2003-11-21 23:21:08.000000000 -0800
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/trace.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -38,6 +39,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/unistd.h>
 
 extern asmlinkage void handle_mod(void);
 extern asmlinkage void handle_tlbl(void);
@@ -349,6 +351,8 @@ asmlinkage void do_be(struct pt_regs *re
 	int data = regs->cp0_cause & 4;
 	int action = MIPS_BE_FATAL;
 
+	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
+
 	if (data && !user_mode(regs))
 		fixup = search_dbe_table(regs->cp0_epc);
 
@@ -360,12 +364,14 @@ asmlinkage void do_be(struct pt_regs *re
 
 	switch (action) {
 	case MIPS_BE_DISCARD:
+		TRACE_TRAP_EXIT();
 		return;
 	case MIPS_BE_FIXUP:
 		if (fixup) {
 			new_epc = fixup_exception(dpf_reg, fixup,
 						  regs->cp0_epc);
 			regs->cp0_epc = new_epc;
+			TRACE_TRAP_EXIT();
 			return;
 		}
 		break;
@@ -381,18 +387,22 @@ asmlinkage void do_be(struct pt_regs *re
 	       regs->cp0_epc, regs->regs[31]);
 	die_if_kernel("Oops", regs);
 	force_sig(SIGBUS, current);
+	TRACE_TRAP_EXIT();
 }
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
 {
 	unsigned int *epc;
 
+	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
+
 	epc = (unsigned int *) regs->cp0_epc +
 	      ((regs->cp0_cause & CAUSEF_BD) != 0);
 	if (!get_user(*opcode, epc))
 		return 0;
 
 	force_sig(SIGSEGV, current);
+ 	TRACE_TRAP_EXIT(); 	
 	return 1;
 }
 
@@ -517,10 +527,12 @@ static inline int simulate_llsc(struct p
 
 	if ((opcode & OPCODE) == LL) {
 		simulate_ll(regs, opcode);
+		TRACE_TRAP_EXIT();
 		return 0;
 	}
 	if ((opcode & OPCODE) == SC) {
 		simulate_sc(regs, opcode);
+		TRACE_TRAP_EXIT();
 		return 0;
 	}
 }
@@ -528,12 +540,14 @@ static inline int simulate_llsc(struct p
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	siginfo_t info;
+ 	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
 
 	info.si_code = FPE_INTOVF;
 	info.si_signo = SIGFPE;
 	info.si_errno = 0;
 	info.si_addr = (void *)regs->cp0_epc;
 	force_sig_info(SIGFPE, &info, current);
+ 	TRACE_TRAP_EXIT();
 }
 
 /*
@@ -541,6 +555,7 @@ asmlinkage void do_ov(struct pt_regs *re
  */
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
+	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
 	if (fcr31 & FPU_CSR_UNI_X) {
 		int sig;
 
@@ -572,11 +587,15 @@ asmlinkage void do_fpe(struct pt_regs *r
 		/* If something went wrong, signal */
 		if (sig)
 			force_sig(sig, current);
-
+ 		TRACE_TRAP_EXIT();
 		return;
 	}
-
+ 	if (compute_return_epc(regs)){
+ 		TRACE_TRAP_EXIT();
+   		return;
+ 	}
 	force_sig(SIGFPE, current);
+ 	TRACE_TRAP_EXIT();
 }
 
 asmlinkage void do_bp(struct pt_regs *regs)
@@ -615,6 +634,7 @@ asmlinkage void do_bp(struct pt_regs *re
 	default:
 		force_sig(SIGTRAP, current);
 	}
+	TRACE_TRAP_EXIT();
 }
 
 asmlinkage void do_tr(struct pt_regs *regs)
@@ -649,7 +669,10 @@ asmlinkage void do_tr(struct pt_regs *re
 		break;
 	default:
 		force_sig(SIGTRAP, current);
+		
 	}
+ 	TRACE_TRAP_EXIT();
+	
 }
 
 asmlinkage void do_ri(struct pt_regs *regs)
@@ -661,6 +684,7 @@ asmlinkage void do_ri(struct pt_regs *re
 			return;
 
 	force_sig(SIGILL, current);
+	TRACE_TRAP_EXIT();
 }
 
 asmlinkage void do_cpu(struct pt_regs *regs)
@@ -669,6 +693,8 @@ asmlinkage void do_cpu(struct pt_regs *r
 
 	die_if_kernel("do_cpu invoked from kernel context!", regs);
 
+	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
+
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 
 	switch (cpid) {
@@ -1016,3 +1042,75 @@ void __init trap_init(void)
 	current_cpu_data.asid_cache = ASID_FIRST_VERSION;
 	TLBMISS_HANDLER_SETUP();
 }
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+asmlinkage void trace_real_syscall_entry(struct pt_regs * regs)
+{
+	unsigned long       addr;
+	int                 depth = 0;
+	unsigned long       end_code;
+	unsigned long       lower_bound;
+	int                 seek_depth;
+	unsigned long       *stack;
+	unsigned long       start_code;
+	unsigned long       *start_stack;
+	trace_syscall_entry trace_syscall_event;
+	unsigned long       upper_bound;
+	int                 use_bounds;
+	int                 use_depth;
+
+	/* syscall_id will be negative for SVR4, IRIX5, BSD43, and POSIX
+	 * syscalls -- these are not supported at this point by LTT
+	 */
+	trace_syscall_event.syscall_id = (uint8_t) (regs->regs[2] - __NR_Linux);
+
+	trace_syscall_event.address  = regs->cp0_epc;
+
+	if (!user_mode(regs))
+		goto trace_syscall_end;
+
+	if (trace_get_config(&use_depth,
+			     &use_bounds,
+			     &seek_depth,
+			     (void*)&lower_bound,
+			     (void*)&upper_bound) < 0)
+		goto trace_syscall_end;
+
+	/* Heuristic that might work:
+	 * (BUT DOESN'T WORK for any of the cases I tested...) zzz
+	 * Search through stack until a value is found that is within the
+	 * range start_code .. end_code.  (This is looking for a return
+	 * pointer to where a shared library was called from.)  If a stack
+	 * variable contains a valid code address then an incorrect
+	 * result will be generated.
+	 */
+	if ((use_depth == 1) || (use_bounds == 1)) {
+		stack       = (unsigned long*) regs->regs[29];
+		end_code    = current->mm->end_code;
+		start_code  = current->mm->start_code;
+		start_stack = (unsigned long *)current->mm->start_stack;
+
+		while ((stack <= start_stack) && (!__get_user(addr, stack))) {
+			if ((addr > start_code) && (addr < end_code)) {
+				if (((use_depth  == 1) && (depth == seek_depth)) ||
+				    ((use_bounds == 1) && (addr > lower_bound) && (addr < upper_bound))) {
+					trace_syscall_event.address = addr;
+					goto trace_syscall_end;
+				} else {
+					depth++;
+				}
+			}
+		stack++;
+		}
+	}
+
+trace_syscall_end:
+	trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}
+
+asmlinkage void trace_real_syscall_exit(void)
+{
+        trace_event(TRACE_EV_SYSCALL_EXIT, NULL);
+}
+
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
diff -Nurp linux-2.4.22-clean/arch/mips/kernel/unaligned.c linux-2.4.22-adeos-ltt/arch/mips/kernel/unaligned.c
--- linux-2.4.22-clean/arch/mips/kernel/unaligned.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/kernel/unaligned.c	2003-11-21 23:21:08.000000000 -0800
@@ -77,6 +77,7 @@
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/trace.h>
 
 #include <asm/asm.h>
 #include <asm/branch.h>
@@ -502,6 +503,7 @@ asmlinkage void do_ade(struct pt_regs *r
 	extern int do_dsemulret(struct pt_regs *);
 	mm_segment_t seg;
 	unsigned long pc;
+        TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
 
 	/*
 	 * Address errors may be deliberately induced by the FPU emulator to
@@ -509,8 +511,10 @@ asmlinkage void do_ade(struct pt_regs *r
 	 * delay slot of an emulated branch.
 	 */
 	/* Terminate if exception was recognized as a delay slot return */
-	if (do_dsemulret(regs))
+	if (do_dsemulret(regs)) {
+		TRACE_TRAP_EXIT();
 		return;
+	}
 
 	/* Otherwise handle as normal */
 
@@ -544,6 +548,8 @@ asmlinkage void do_ade(struct pt_regs *r
 	}
 	set_fs(seg);
 
+	TRACE_TRAP_EXIT();
+	TRACE_TRAP_EXIT();
 	return;
 
 sigbus:
diff -Nurp linux-2.4.22-clean/arch/mips/mm/fault.c linux-2.4.22-adeos-ltt/arch/mips/mm/fault.c
--- linux-2.4.22-clean/arch/mips/mm/fault.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/mips/mm/fault.c	2003-11-21 23:21:08.000000000 -0800
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/version.h>
+#include <linux/trace.h>
 #include <linux/vt_kern.h>
 
 #include <asm/branch.h>
@@ -28,6 +29,7 @@
 #include <asm/softirq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/mipsregs.h>
 
 #define development_version (LINUX_VERSION_CODE & 0x100)
 
@@ -83,6 +85,8 @@ asmlinkage void do_page_fault(struct pt_
 	unsigned long fixup;
 	siginfo_t info;
 
+	TRACE_TRAP_ENTRY(CAUSE_EXCCODE(regs), CAUSE_EPC(regs));
+
 	/*
 	 * We fault-in kernel-space virtual memory on-demand. The
 	 * 'reference' page table is init_mm.pgd.
@@ -151,6 +155,7 @@ survive:
 	}
 
 	up_read(&mm->mmap_sem);
+	TRACE_TRAP_EXIT();
 	return;
 
 /*
@@ -178,6 +183,7 @@ bad_area:
 		/* info.si_code has been set above */
 		info.si_addr = (void *) address;
 		force_sig_info(SIGSEGV, &info, tsk);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -193,6 +199,7 @@ no_context:
 			printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
 			       tsk->comm, regs->cp0_epc, new_epc);
 		regs->cp0_epc = new_epc;
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -239,6 +246,7 @@ do_sigbus:
 	if (!user_mode(regs))
 		goto no_context;
 
+	TRACE_TRAP_EXIT();
 	return;
 
 vmalloc_fault:
@@ -273,4 +281,5 @@ vmalloc_fault:
 			goto no_context;
 		return;
 	}
+	TRACE_TRAP_EXIT();
 }
diff -Nurp linux-2.4.22-clean/arch/ppc/config.in linux-2.4.22-adeos-ltt/arch/ppc/config.in
--- linux-2.4.22-clean/arch/ppc/config.in	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/config.in	2003-11-21 23:21:08.000000000 -0800
@@ -441,6 +441,11 @@ source crypto/Config.in
 source lib/Config.in
 
 mainmenu_option next_comment
+comment 'Kernel tracing'
+tristate 'Kernel events tracing support' CONFIG_TRACE
+endmenu
+
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/entry.S linux-2.4.22-adeos-ltt/arch/ppc/kernel/entry.S
--- linux-2.4.22-clean/arch/ppc/kernel/entry.S	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/entry.S	2003-11-21 23:21:08.000000000 -0800
@@ -39,6 +39,32 @@ show_syscalls_task:
 	.long	-1
 #endif
 
+/* LTT stuff */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+#define TRACE_REAL_ASM_SYSCALL_ENTRY	\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;  	/* Put pointer to registers into r3 */	\
+	mflr	r29;				/* Save LR */ \
+	bl	trace_real_syscall_entry;	/* Call real trace function */ \
+	mtlr	r29;				/* Restore LR */ \
+	lwz	r0,GPR0(r1);			/* Restore original registers */ \
+	lwz	r3,GPR3(r1);	\
+	lwz	r4,GPR4(r1);	\
+	lwz	r5,GPR5(r1);	\
+	lwz	r6,GPR6(r1);	\
+	lwz	r7,GPR7(r1);	\
+	lwz	r8,GPR8(r1);
+#define TRACE_REAL_ASM_SYSCALL_EXIT \
+	bl	trace_real_syscall_exit;	/* Call real trace function */ \
+	lwz	r0,GPR0(r1);			/* Restore original registers */ \
+	lwz	r3,RESULT(r1); \
+	lwz	r4,GPR4(r1); \
+	lwz	r5,GPR5(r1); \
+	lwz	r6,GPR6(r1); \
+	lwz	r7,GPR7(r1); \
+	lwz	r8,GPR8(r1); \
+	addi	r9,r1,STACK_FRAME_OVERHEAD;
+#endif
+
 /*
  * Handle a system call.
  */
@@ -96,11 +122,17 @@ _GLOBAL(DoSyscall)
 	cmpi	0,r10,0
 	beq-	66f
 	mtlr	r10
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	TRACE_REAL_ASM_SYSCALL_ENTRY ;
+#endif
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	blrl			/* Call handler */
 	.globl	ret_from_syscall_1
 ret_from_syscall_1:
 20:	stw	r3,RESULT(r1)	/* Save result */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	TRACE_REAL_ASM_SYSCALL_EXIT ; 
+#endif
 #ifdef SHOW_SYSCALLS
 #ifdef SHOW_SYSCALLS_TASK
 	cmp	0,r2,r31
@@ -158,11 +190,17 @@ ret_from_syscall_1:
 	cmpi	0,r10,0
 	beq-	66f
 	mtlr	r10
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	TRACE_REAL_ASM_SYSCALL_ENTRY ;
+#endif
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	blrl			/* Call handler */
 	.globl	ret_from_syscall_2
 ret_from_syscall_2:
 	stw	r3,RESULT(r1)	/* Save result */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	TRACE_REAL_ASM_SYSCALL_EXIT ; 
+#endif
 	li	r10,-_LAST_ERRNO
 	cmpl	0,r3,r10
 	blt	60f
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/irq.c linux-2.4.22-adeos-ltt/arch/ppc/kernel/irq.c
--- linux-2.4.22-clean/arch/ppc/kernel/irq.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/irq.c	2003-11-21 23:21:08.000000000 -0800
@@ -45,6 +45,8 @@
 #include <linux/proc_fs.h>
 #include <linux/random.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/system.h>
@@ -431,6 +433,8 @@ void ppc_irq_dispatch_handler(struct pt_
 	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 
+	TRACE_IRQ_ENTRY(irq, !(user_mode(regs)));
+
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
 	ack_irq(irq);
@@ -508,6 +512,8 @@ out:
 			irq_desc[irq].handler->enable(irq);
 	}
 	spin_unlock(&desc->lock);
+
+	TRACE_IRQ_EXIT();
 }
 
 int do_IRQ(struct pt_regs *regs)
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/misc.S linux-2.4.22-adeos-ltt/arch/ppc/kernel/misc.S
--- linux-2.4.22-clean/arch/ppc/kernel/misc.S	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/misc.S	2003-11-21 23:21:08.000000000 -0800
@@ -959,7 +959,11 @@ _GLOBAL(cvt_df)
  * Create a kernel thread
  *   arch_kernel_thread(fn, arg, flags)
  */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+_GLOBAL(original_kernel_thread)
+#else
 _GLOBAL(arch_kernel_thread)
+#endif
 	mr	r6,r3		/* function */
 	ori	r3,r5,CLONE_VM	/* flags */
 	li	r0,__NR_clone
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/process.c linux-2.4.22-adeos-ltt/arch/ppc/kernel/process.c
--- linux-2.4.22-clean/arch/ppc/kernel/process.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/process.c	2003-11-21 23:21:08.000000000 -0800
@@ -33,6 +33,8 @@
 #include <linux/init.h>
 #include <linux/prctl.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -305,6 +307,19 @@ out:
 	print_backtrace((unsigned long *)regs->gpr[1]);
 }
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+long original_kernel_thread(int (*fn) (void *), void* arg, unsigned long flags);
+long kernel_thread(int (*fn) (void *), void* arg, unsigned long flags)
+{
+        long   retval;
+
+	retval = original_kernel_thread(fn, arg, flags);
+	if (retval > 0)
+	        TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, retval, (int) fn);
+	return retval;
+}
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
+
 void exit_thread(void)
 {
 	if (last_task_used_math == current)
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/syscalls.c linux-2.4.22-adeos-ltt/arch/ppc/kernel/syscalls.c
--- linux-2.4.22-clean/arch/ppc/kernel/syscalls.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/syscalls.c	2003-11-21 23:21:08.000000000 -0800
@@ -36,6 +36,8 @@
 #include <linux/utsname.h>
 #include <linux/file.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 #include <asm/semaphore.h>
@@ -64,6 +66,8 @@ sys_ipc (uint call, int first, int secon
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
+	TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
 	ret = -EINVAL;
 	switch (call) {
 	case SEMOP:
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/time.c linux-2.4.22-adeos-ltt/arch/ppc/kernel/time.c
--- linux-2.4.22-clean/arch/ppc/kernel/time.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/time.c	2003-11-21 23:21:08.000000000 -0800
@@ -57,6 +57,8 @@
 #include <linux/time.h>
 #include <linux/init.h>
 
+#include <linux/trace.h>
+
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -148,6 +150,8 @@ int timer_interrupt(struct pt_regs * reg
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
 
+	TRACE_TRAP_ENTRY(regs->trap, instruction_pointer(regs));
+
 	hardirq_enter(cpu);
 
 	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
@@ -208,6 +212,8 @@ int timer_interrupt(struct pt_regs * reg
 	if (softirq_pending(cpu))
 		do_softirq();
 
+	TRACE_TRAP_EXIT();
+
 	return 1; /* lets ret_from_int know we can do checks */
 }
 
diff -Nurp linux-2.4.22-clean/arch/ppc/kernel/traps.c linux-2.4.22-adeos-ltt/arch/ppc/kernel/traps.c
--- linux-2.4.22-clean/arch/ppc/kernel/traps.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/kernel/traps.c	2003-11-21 23:21:08.000000000 -0800
@@ -30,6 +30,8 @@
 #include <linux/config.h>
 #include <linux/init.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -113,7 +115,9 @@ _exception(int signr, struct pt_regs *re
 	info.si_errno = 0;
 	info.si_code = code;
 	info.si_addr = (void *) addr;
+	TRACE_TRAP_ENTRY(regs->trap, instruction_pointer(regs));
 	force_sig_info(signr, &info, current);
+	TRACE_TRAP_EXIT();
 }
 
 /*
@@ -420,6 +424,89 @@ StackOverflow(struct pt_regs *regs)
 	panic("kernel stack overflow");
 }
 
+/* Trace related code */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+asmlinkage void trace_real_syscall_entry(struct pt_regs * regs)
+{
+        int                 use_depth;
+	int                 use_bounds;
+	int                 depth = 0;
+        int                 seek_depth;
+        unsigned long       lower_bound;
+        unsigned long       upper_bound;
+	unsigned long       addr;
+	unsigned long*      stack;
+	trace_syscall_entry trace_syscall_event;
+
+        /* Set the syscall ID */
+	trace_syscall_event.syscall_id = (uint8_t) regs->gpr[0];
+
+	/* Set the address in any case */
+	trace_syscall_event.address  = instruction_pointer(regs);
+
+	/* Are we in the kernel (This is a kernel thread)? */
+	if(!user_mode(regs))
+	  /* Don't go digining anywhere */
+	  goto trace_syscall_end;
+
+	/* Get the trace configuration */
+	if(trace_get_config(&use_depth,
+			    &use_bounds,
+			    &seek_depth,
+			    (void*)&lower_bound,
+			    (void*)&upper_bound) < 0)
+	  goto trace_syscall_end;
+
+	/* Do we have to search for an eip address range */
+	if((use_depth == 1) || (use_bounds == 1))
+	  {
+	  /* Start at the top of the stack (bottom address since stacks grow downward) */
+	  stack = (unsigned long*) regs->gpr[1];
+
+	  /* Skip over first stack frame as the return address isn't valid */
+	  if(get_user(addr, stack))
+	    goto trace_syscall_end;
+	  stack = (unsigned long*) addr;
+
+	  /* Keep on going until we reach the end of the process' stack limit (wherever it may be) */
+	  while(!get_user(addr, stack + 1)) /* "stack + 1", since this is where the IP is */
+	    {
+	    /* Does this LOOK LIKE an address in the program */
+	    if((addr > current->mm->start_code)
+             &&(addr < current->mm->end_code))
+	      {
+	      /* Does this address fit the description */
+	      if(((use_depth == 1) && (depth == seek_depth))
+               ||((use_bounds == 1) && (addr > lower_bound) && (addr < upper_bound)))
+		{
+		/* Set the address */
+		trace_syscall_event.address = addr;
+
+		/* We're done */
+		goto trace_syscall_end;
+		}
+	      else
+		/* We're one depth more */
+		depth++;
+	      }
+	    /* Go on to the next address */
+	    if(get_user(addr, stack))
+	      goto trace_syscall_end;
+	    stack = (unsigned long*) addr;
+	    }
+	  }
+
+trace_syscall_end:
+	/* Trace the event */
+	trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}
+
+asmlinkage void trace_real_syscall_exit(void)
+{
+        trace_event(TRACE_EV_SYSCALL_EXIT, NULL);
+}
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
+
 void
 trace_syscall(struct pt_regs *regs)
 {
diff -Nurp linux-2.4.22-clean/arch/ppc/mm/fault.c linux-2.4.22-adeos-ltt/arch/ppc/mm/fault.c
--- linux-2.4.22-clean/arch/ppc/mm/fault.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/ppc/mm/fault.c	2003-11-21 23:21:08.000000000 -0800
@@ -27,6 +27,8 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
+#include <linux/trace.h>
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
@@ -117,22 +119,28 @@ void do_page_fault(struct pt_regs *regs,
 		is_write = error_code & 0x02000000;
 #endif /* CONFIG_4xx */
 
+	TRACE_TRAP_ENTRY(regs->trap, instruction_pointer(regs));
+
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_fault_handler && regs->trap == 0x300) {
 		debugger_fault_handler(regs);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 #if !defined(CONFIG_4xx)
 	if (error_code & 0x00400000) {
 		/* DABR match */
-		if (debugger_dabr_match(regs))
+   	        if (debugger_dabr_match(regs)){
+		        TRACE_TRAP_EXIT();
 			return;
+		}
 	}
 #endif /* !CONFIG_4xx */
 #endif /* CONFIG_XMON || CONFIG_KGDB */
 
 	if (in_interrupt() || mm == NULL) {
 		bad_page_fault(regs, address, SIGSEGV);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 	down_read(&mm->mmap_sem);
@@ -237,6 +245,7 @@ good_area:
 	 * -- Cort
 	 */
 	pte_misses++;
+	TRACE_TRAP_EXIT();
 	return;
 
 bad_area:
@@ -250,10 +259,12 @@ bad_area:
 		info.si_code = code;
 		info.si_addr = (void *) address;
 		force_sig_info(SIGSEGV, &info, current);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
 	bad_page_fault(regs, address, SIGSEGV);
+	TRACE_TRAP_EXIT();
 	return;
 
 /*
@@ -270,6 +281,7 @@ out_of_memory:
 	if (user_mode(regs))
 		do_exit(SIGKILL);
 	bad_page_fault(regs, address, SIGKILL);
+	TRACE_TRAP_EXIT();
 	return;
 
 do_sigbus:
@@ -281,6 +293,7 @@ do_sigbus:
 	force_sig_info (SIGBUS, &info, current);
 	if (!user_mode(regs))
 		bad_page_fault(regs, address, SIGBUS);
+	TRACE_TRAP_EXIT();
 }
 
 /*
diff -Nurp linux-2.4.22-clean/arch/s390/config.in linux-2.4.22-adeos-ltt/arch/s390/config.in
--- linux-2.4.22-clean/arch/s390/config.in	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/s390/config.in	2003-11-21 23:21:08.000000000 -0800
@@ -70,6 +70,11 @@ fi
 source fs/Config.in
 
 mainmenu_option next_comment
+comment 'Kernel tracing'                             
+tristate 'Kernel events tracing support' CONFIG_TRACE
+endmenu                                              
+
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
diff -Nurp linux-2.4.22-clean/arch/s390/kernel/entry.S linux-2.4.22-adeos-ltt/arch/s390/kernel/entry.S
--- linux-2.4.22-clean/arch/s390/kernel/entry.S	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/s390/kernel/entry.S	2003-11-21 23:21:08.000000000 -0800
@@ -7,6 +7,7 @@
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *  Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
  */
 
 #include <linux/sys.h>
@@ -179,6 +180,14 @@ system_call:
         sll     %r8,2
         GET_CURRENT               # load pointer to task_struct to R9
         stosm   24(%r15),0x03     # reenable interrupts
+/* call to ltt trace done here.  R8 has the syscall (svc) number to trace */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) /* tjh - ltt port */              
+        /* add call to trace_real_syscall_entry */                          
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter     
+        l       %r1,BASED(.Ltracesysent)                                    
+        basr    %r14,%r1                                                    
+        lm      %r0,%r6,SP_R0(%r15) /* restore call clobbered regs tjh */   
+#endif
         l       %r8,sys_call_table-entry_base(%r8,%r13) # get system call addr.
         tm      __TASK_ptrace+3(%r9),0x02 # PT_TRACESYS
         bnz     BASED(sysc_tracesys)
@@ -187,6 +196,13 @@ system_call:
                                   # ATTENTION: check sys_execve_glue before
                                   # changing anything here !!
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) /* tjh - ltt port *            
+        /* add call to trace_real_syscall_exit */ 
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter  
+        l       %r1,BASED(.Ltracesysext)                                 
+        basr    %r14,%r1                                                 
+        lm      %r0,%r6,SP_R0(%r15) /* restore call clobbered regs */
+#endif                                                                   
 sysc_return:
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
         bno     BASED(sysc_leave) # no-> skip resched & signal
@@ -867,6 +883,8 @@ restart_go:
 .Lsigaltstack: .long  sys_sigaltstack
 .Ltrace:       .long  syscall_trace
 .Lvfork:       .long  sys_vfork
+.Ltracesysent: .long  trace_real_syscall_entry
+.Ltracesysext: .long  trace_real_syscall_exit 
 
 .Lschedtail:   .long  schedule_tail
 
diff -Nurp linux-2.4.22-clean/arch/s390/kernel/process.c linux-2.4.22-adeos-ltt/arch/s390/kernel/process.c
--- linux-2.4.22-clean/arch/s390/kernel/process.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/s390/kernel/process.c	2003-11-21 23:21:08.000000000 -0800
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/trace.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -129,6 +130,10 @@ int arch_kernel_thread(int (*fn)(void *)
                 : "d" (clone_arg), "i" (__NR_clone), "i" (__NR_exit),
                   "d" (arg), "d" (fn), "i" (__LC_KERNEL_STACK) , "i" (-STACK_FRAME_OVERHEAD)
                 : "2", "3", "4" );
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)                           
+        if (retval > 0)                                             
+          TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, retval, (int) fn);
+#endif
         return retval;
 }
 
diff -Nurp linux-2.4.22-clean/arch/s390/kernel/sys_s390.c linux-2.4.22-adeos-ltt/arch/s390/kernel/sys_s390.c
--- linux-2.4.22-clean/arch/s390/kernel/sys_s390.c	2001-03-19 12:35:11.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/s390/kernel/sys_s390.c	2003-11-21 23:21:08.000000000 -0800
@@ -24,6 +24,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
+#include <linux/trace.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -145,6 +146,8 @@ asmlinkage int sys_ipc (uint call, int f
         struct ipc_kludge tmp;
 	int ret;
 
+        TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
         switch (call) {
         case SEMOP:
                 return sys_semop (first, (struct sembuf *)ptr, second);
diff -Nurp linux-2.4.22-clean/arch/s390/kernel/traps.c linux-2.4.22-adeos-ltt/arch/s390/kernel/traps.c
--- linux-2.4.22-clean/arch/s390/kernel/traps.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/s390/kernel/traps.c	2003-11-21 23:21:08.000000000 -0800
@@ -5,6 +5,7 @@
  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *  Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
  *
  *  Derived from "arch/i386/kernel/traps.c"
  *    Copyright (C) 1991, 1992 Linus Torvalds
@@ -28,6 +29,8 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 
+#include <linux/trace.h>
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -275,12 +278,18 @@ void die(const char * str, struct pt_reg
 static void inline do_trap(long interruption_code, int signr, char *str,
                            struct pt_regs *regs, siginfo_t *info)
 {
+        trapid_t ltt_interruption_code; 
+        char * ic_ptr = (char *) &ltt_interruption_code;
+
 	/*
 	 * We got all needed information from the lowcore and can
 	 * now safely switch on interrupts.
 	 */
         if (regs->psw.mask & PSW_PROBLEM_STATE)
 		__sti();
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+4,&interruption_code,sizeof(interruption_code));
+        TRACE_TRAP_ENTRY(ltt_interruption_code, (regs->psw.addr & PSW_ADDR_MASK));
 
         if (regs->psw.mask & PSW_PROBLEM_STATE) {
                 struct task_struct *tsk = current;
@@ -310,6 +319,7 @@ static void inline do_trap(long interrup
                 else
                         die(str, regs, interruption_code);
         }
+	TRACE_TRAP_EXIT();
 }
 
 static inline void *get_check_address(struct pt_regs *regs)
@@ -407,6 +417,8 @@ asmlinkage void illegal_op(struct pt_reg
 {
         __u8 opcode[6];
 	__u16 *location;
+        trapid_t ltt_interruption_code;
+        char * ic_ptr = (char *) &ltt_interruption_code;
 	int signal = 0;
 
 	location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
@@ -417,6 +429,9 @@ asmlinkage void illegal_op(struct pt_reg
 	 */
 	if (regs->psw.mask & PSW_PROBLEM_STATE)
 		__sti();
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+4,&interruption_code,sizeof(interruption_code));
+        TRACE_TRAP_ENTRY(ltt_interruption_code, (regs->psw.addr & PSW_ADDR_MASK));
 
 	if (regs->psw.mask & PSW_PROBLEM_STATE)
 		get_user(*((__u16 *) opcode), location);
@@ -458,6 +473,7 @@ asmlinkage void illegal_op(struct pt_reg
         else if (signal)
 		do_trap(interruption_code, signal,
 			"illegal operation", regs, NULL);
+        TRACE_TRAP_EXIT();
 }
 
 
@@ -468,6 +484,8 @@ specification_exception(struct pt_regs *
 {
         __u8 opcode[6];
 	__u16 *location = NULL;
+        trapid_t ltt_interruption_code;
+        char * ic_ptr = (char *) &ltt_interruption_code;
 	int signal = 0;
 
 	location = (__u16 *) get_check_address(regs);
@@ -478,6 +496,9 @@ specification_exception(struct pt_regs *
 	 */
 	if (regs->psw.mask & PSW_PROBLEM_STATE)
 		__sti();
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+4,&interruption_code,sizeof(interruption_code));
+        TRACE_TRAP_ENTRY(ltt_interruption_code, (regs->psw.addr & PSW_ADDR_MASK));
 		
         if (regs->psw.mask & PSW_PROBLEM_STATE) {
 		get_user(*((__u16 *) opcode), location);
@@ -522,6 +543,7 @@ specification_exception(struct pt_regs *
 		do_trap(interruption_code, signal, 
 			"specification exception", regs, &info);
 	}
+        TRACE_TRAP_EXIT();
 }
 #else
 DO_ERROR_INFO(SIGILL, "specification exception", specification_exception,
@@ -532,6 +554,8 @@ asmlinkage void data_exception(struct pt
 {
         __u8 opcode[6];
 	__u16 *location;
+        trapid_t ltt_interruption_code;
+        char * ic_ptr = (char *) &ltt_interruption_code;
 	int signal = 0;
 
 	location = (__u16 *) get_check_address(regs);
@@ -542,6 +566,9 @@ asmlinkage void data_exception(struct pt
 	 */
 	if (regs->psw.mask & PSW_PROBLEM_STATE)
 		__sti();
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+4,&interruption_code,sizeof(interruption_code));
+        TRACE_TRAP_ENTRY(ltt_interruption_code, (regs->psw.addr & PSW_ADDR_MASK));
 
 	if (MACHINE_HAS_IEEE)
 		__asm__ volatile ("stfpc %0\n\t" 
@@ -617,6 +644,7 @@ asmlinkage void data_exception(struct pt
 		do_trap(interruption_code, signal, 
 			"data exception", regs, &info);
 	}
+        TRACE_TRAP_EXIT();
 }
 
 
@@ -671,6 +699,11 @@ void __init trap_init(void)
 
 void handle_per_exception(struct pt_regs *regs)
 {
+        trapid_t ltt_interruption_code;
+        char * ic_ptr = (char *) &ltt_interruption_code;
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+6,&S390_lowcore.pgm_code,2); /* copy the interrupt code */
+        TRACE_TRAP_ENTRY(ltt_interruption_code,(regs->psw.addr & PSW_ADDR_MASK));
 	if(regs->psw.mask&PSW_PROBLEM_STATE)
 	{
 		per_struct *per_info=&current->thread.per_info;
@@ -687,5 +720,91 @@ void handle_per_exception(struct pt_regs
 		/* Hopefully switching off per tracing will help us survive */
 		regs->psw.mask &= ~PSW_PER_MASK;
 	}
+        TRACE_TRAP_EXIT();
 }
 
+/* ltt - Trace related code  */                                
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)                      
+asmlinkage void trace_real_syscall_entry(struct pt_regs * regs)
+{                                                              
+        int                 use_depth;                         
+        int                 use_bounds;                        
+        int                 depth = 0;                         
+        int                 seek_depth;                        
+        unsigned long       lower_bound;                       
+        unsigned long       upper_bound;                       
+        unsigned long       addr;                              
+        unsigned long*      stack;
+        unsigned long       temp_stack;
+        trace_syscall_entry trace_syscall_event;               
+        /* Set the syscall ID                               */ 
+        /* Register 8 is setup just prior to the call       */ 
+        /* This instruction is just following linkage       */ 
+        /* so it's ok.  If moved and chance of R8 being     */ 
+        /* clobbered, would need to dig it out of the stack */ 
+        __asm__ volatile(                                      
+        "  stc  8,%0\n\t"                                      
+        : "=m" (trace_syscall_event.syscall_id));              
+        /* get the psw address */                              
+        trace_syscall_event.address  = regs->psw.addr;         
+        /* and off the hi-order bit */                                          
+        trace_syscall_event.address &= PSW_ADDR_MASK;                           
+        if(!(user_mode(regs))) /* if kernel mode, return */                     
+           goto trace_syscall_end;                                              
+        /* Get the trace configuration - if none, return */                     
+        if(trace_get_config(&use_depth,                                         
+                            &use_bounds,                                        
+                            &seek_depth,                                        
+                            (void*)&lower_bound,                                
+                            (void*)&upper_bound) < 0)                           
+          goto trace_syscall_end;                                               
+        /* Do we have to search for an instruction pointer address range */     
+        if((use_depth == 1) || (use_bounds == 1))                               
+        {                                                                       
+          /* Start at the top of the stack */                                   
+          /* stack pointer is register 15 */                                    
+          stack = (unsigned long*) regs->gprs[15]; /* stack pointer */      
+          /* Keep on going until we reach the end of the process' stack limit */
+          do
+          {
+            get_user(addr,stack+14);  /* get the program address +0x38 */ 
+            /* and off the hi-order bit */
+            addr &= PSW_ADDR_MASK;                                
+            /* Does this LOOK LIKE an address in the program */
+            if ((addr > current->mm->start_code)               
+               &&(addr < current->mm->end_code))               
+            { 
+              /* Does this address fit the description */      
+              if(((use_depth == 1) && (depth == seek_depth))   
+                ||((use_bounds == 1) && (addr > lower_bound)   
+                && (addr < upper_bound)))
+                {
+                  /* Set the address */   
+                  trace_syscall_event.address = addr; 
+                  /* We're done */                             
+                  goto trace_syscall_end;                      
+                }                                              
+              else                                             
+                /* We're one depth more */                     
+                depth++; 
+            }
+            /* Go on to the next address */
+            get_user(temp_stack,stack); /* get contents of stack */
+            temp_stack &= PSW_ADDR_MASK; /* and off hi order bit */
+            stack = (unsigned long *)temp_stack; /* move into stack */
+            /* stack may or may not go to zero when end hit               */
+            /* using 0x7fffffff-_STK_LIM to validate that the address is  */
+            /* within the range of a valid stack address                  */
+            /* If outside that range, exit the loop, stack end must have  */
+            /* been hit.                                                  */
+          } while (stack >= (unsigned long *)(0x7fffffff-_STK_LIM));
+        }                                                         
+trace_syscall_end:                                                
+        /* Trace the event */                                     
+        trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}                                                                 
+asmlinkage void trace_real_syscall_exit(void)                     
+{                                                                 
+  trace_event(TRACE_EV_SYSCALL_EXIT, NULL);                       
+}                                                                 
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */                
diff -Nurp linux-2.4.22-clean/arch/s390/mm/fault.c linux-2.4.22-adeos-ltt/arch/s390/mm/fault.c
--- linux-2.4.22-clean/arch/s390/mm/fault.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.22-adeos-ltt/arch/s390/mm/fault.c	2003-11-21 23:21:08.000000000 -0800
@@ -5,6 +5,7 @@
  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *               Ulrich Weigand (uweigand@de.ibm.com)
+ *  Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
  *
  *  Derived from "arch/i386/mm/fault.c"
  *    Copyright (C) 1995  Linus Torvalds
@@ -25,6 +26,7 @@
 #include <linux/compatmac.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/trace.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -154,6 +156,8 @@ extern inline void do_exception(struct p
 	int user_address;
         unsigned long fixup;
 	int si_code = SEGV_MAPERR;
+        trapid_t ltt_interruption_code;                 
+        char * ic_ptr = (char *) &ltt_interruption_code; 
 
         tsk = current;
         mm = tsk->mm;
@@ -201,6 +205,9 @@ extern inline void do_exception(struct p
 	 */
 	__sti();
 
+        memset(&ltt_interruption_code,0,sizeof(ltt_interruption_code));
+        memcpy(ic_ptr+4,&error_code,sizeof(error_code));
+        TRACE_TRAP_ENTRY(ltt_interruption_code,(regs->psw.addr & PSW_ADDR_MASK));
         down_read(&mm->mmap_sem);
 
         vma = find_vma(mm, address);
@@ -247,6 +254,7 @@ survive:
 	}
 
         up_read(&mm->mmap_sem);
+        TRACE_TRAP_EXIT();
         return;
 
 /*
@@ -261,6 +269,7 @@ bad_area:
                 tsk->thread.prot_addr = address;
                 tsk->thread.trap_no = error_code;
 		force_sigsegv(regs, error_code, si_code, address);
+                TRACE_TRAP_EXIT();
                 return;
 	}
 
@@ -268,6 +277,7 @@ no_context:
         /* Are we prepared to handle this kernel fault?  */
         if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
                 regs->psw.addr = fixup;
+                TRACE_TRAP_EXIT();
                 return;
         }
 
@@ -315,6 +325,8 @@ do_sigbus:
 	/* Kernel mode? Handle exceptions or die */
 	if (!(regs->psw.mask & PSW_PROBLEM_STATE))
 		goto no_context;
+
+	TRACE_TRAP_EXIT();
 }
 
 void do_protection_exception(struct pt_regs *regs, unsigned long error_code)
diff -Nurp linux-2.4.22-clean/arch/sh/config.in linux-2.4.22-adeos-ltt/arch/sh/config.in
--- linux-2.4.22-clean/arch/sh/config.in	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/config.in	2003-11-21 23:21:08.000000000 -0800
@@ -396,6 +396,12 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
    bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
    dep_tristate '  SuperH Watchdog' CONFIG_SH_WDT $CONFIG_SUPERH
 fi
+
+mainmenu_option next_comment
+comment 'Kernel tracing'
+tristate 'Kernel events tracing support' CONFIG_TRACE
+endmenu
+
 endmenu
 
 tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
diff -Nurp linux-2.4.22-clean/arch/sh/kernel/entry.S linux-2.4.22-adeos-ltt/arch/sh/kernel/entry.S
--- linux-2.4.22-clean/arch/sh/kernel/entry.S	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/kernel/entry.S	2003-11-21 23:21:08.000000000 -0800
@@ -387,6 +387,20 @@ system_call:
 	! New Syscall ABI
 	STI()
 	!
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	! TODO: for i386 this code only happens when not ptrace'd
+	mov 	r15, r4     	    	! pass pt_regs* as first arg
+	mov.l	__trsen, r11 	    	! Call trace_real_syscall_entry()
+	jsr	@r11	    	    	! (will chomp R[0-7])
+	 nop
+	!   	    	    	    	Reload R4-R7 from kernel stack
+	mov.l	@(OFF_R4,r15), r4   ! arg0
+	mov.l	@(OFF_R5,r15), r5
+	mov.l	@(OFF_R6,r15), r6
+	mov.l	@(OFF_R7,r15), r7   ! arg3
+	mov.l	@(OFF_R3,r15), r3   ! syscall_nr
+#endif
+
 	stc	k_current, r11
 	mov.l	@(tsk_ptrace,r11), r10	! Is current PTRACE_SYSCALL'd?
 	mov	#PT_TRACESYS, r11
@@ -442,6 +456,14 @@ system_call:
 	! In case of trace
 syscall_ret_trace:
 	mov.l	r0, @(OFF_R0,r15)		! save the return value
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+    	! TODO: for i386 this code only happens when not ptrace'd
+	mov.l	__trsex, r1 	    	! Call trace_real_syscall_exit()
+	jsr	@r1
+	 nop
+#endif
+
 	mov.l	__syscall_trace, r1
 	mova	SYMBOL_NAME(ret_from_syscall), r0
 	jmp	@r1    	! Call syscall_trace() which notifies superior
@@ -457,6 +479,14 @@ __syscall_ret_trace:
 	.long	syscall_ret_trace
 __syscall_ret:
 	.long	syscall_ret
+	
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+__trsen:
+	.long	SYMBOL_NAME(trace_real_syscall_entry)
+__trsex:
+	.long	SYMBOL_NAME(trace_real_syscall_exit)
+#endif
+
 __INV_IMASK:
 	.long	0xffffff0f	! ~(IMASK)
 
@@ -500,6 +530,14 @@ ret_from_exception:
 	.align 2
 syscall_ret:
 	mov.l	r0, @(OFF_R0,r15)	! save the return value
+
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	! TODO: for i386 this code only happens when not ptrace'd
+	mov.l	__trsex2, r1 	    	! Call trace_real_syscall_exit()
+	jsr	@r1
+	 nop
+#endif
+
 	/* fall through */
 
 ENTRY(ret_from_syscall)
@@ -529,6 +567,10 @@ __do_signal:
 	.long	SYMBOL_NAME(do_signal)
 __irq_stat:
 	.long	SYMBOL_NAME(irq_stat)
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+__trsex2:
+	.long	SYMBOL_NAME(trace_real_syscall_exit)
+#endif
 
 	.align 2
 restore_all:
diff -Nurp linux-2.4.22-clean/arch/sh/kernel/irq.c linux-2.4.22-adeos-ltt/arch/sh/kernel/irq.c
--- linux-2.4.22-clean/arch/sh/kernel/irq.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/kernel/irq.c	2003-11-21 23:21:08.000000000 -0800
@@ -28,6 +28,8 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 
+#include <linux/trace.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -126,6 +128,12 @@ int handle_IRQ_event(unsigned int irq, s
 
 	irq_enter(cpu, irq);
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+    	if (irq != TIMER_IRQ) { /* avoid double-reporting the timer IRQ */
+		TRACE_IRQ_ENTRY(irq, !(user_mode(regs)));
+	}
+#endif
+
 	status = 1;	/* Force the "do bottom halves" bit */
 
 	if (!(action->flags & SA_INTERRUPT))
@@ -142,6 +150,12 @@ int handle_IRQ_event(unsigned int irq, s
 
 	irq_exit(cpu, irq);
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+    	if (irq != TIMER_IRQ) { /* avoid double-reporting the timer IRQ */
+		TRACE_IRQ_EXIT();
+	}
+#endif
+
 	return status;
 }
 
diff -Nurp linux-2.4.22-clean/arch/sh/kernel/process.c linux-2.4.22-adeos-ltt/arch/sh/kernel/process.c
--- linux-2.4.22-clean/arch/sh/kernel/process.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/kernel/process.c	2003-11-21 23:21:08.000000000 -0800
@@ -14,6 +14,8 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 
+#include <linux/trace.h>
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -143,7 +145,16 @@ int arch_kernel_thread(int (*fn)(void *)
 		: "i" (__NR_exit), "r" (__sc3), "r" (__sc4), "r" (__sc5), 
 		  "r" (__sc8), "r" (__sc9)
 		: "memory", "t");
-	return __sc0;
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	{
+		volatile unsigned long retval = __sc0;
+		if (retval > 0)
+			TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, retval, (int) fn);
+		return retval;
+	}
+#else
+ 	return __sc0;
+#endif
 }
 
 /*
diff -Nurp linux-2.4.22-clean/arch/sh/kernel/sys_sh.c linux-2.4.22-adeos-ltt/arch/sh/kernel/sys_sh.c
--- linux-2.4.22-clean/arch/sh/kernel/sys_sh.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/kernel/sys_sh.c	2003-11-21 23:21:08.000000000 -0800
@@ -21,6 +21,8 @@
 #include <linux/file.h>
 #include <linux/utsname.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 #include <asm/cachectl.h>
@@ -140,6 +142,8 @@ asmlinkage int sys_ipc(uint call, int fi
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
+	TRACE_IPC(TRACE_EV_IPC_CALL, call, first);
+
 	if (call <= SEMCTL)
 		switch (call) {
 		case SEMOP:
diff -Nurp linux-2.4.22-clean/arch/sh/kernel/traps.c linux-2.4.22-adeos-ltt/arch/sh/kernel/traps.c
--- linux-2.4.22-clean/arch/sh/kernel/traps.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/kernel/traps.c	2003-11-21 23:21:08.000000000 -0800
@@ -26,6 +26,8 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 
+#include <linux/trace.h>
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -57,7 +59,9 @@ asmlinkage void do_##name(unsigned long 
 	tsk->thread.error_code = error_code; \
 	tsk->thread.trap_no = trapnr; \
         CHK_REMOTE_DEBUG(&regs); \
+        TRACE_TRAP_ENTRY(trapnr, regs.pc); \
 	force_sig(signr, tsk); \
+        TRACE_TRAP_EXIT(); \
 	die_if_no_fixup(str,&regs,error_code); \
 }
 
@@ -480,6 +484,8 @@ asmlinkage void do_address_error(struct 
 
 	asm volatile("stc       r2_bank,%0": "=r" (error_code));
 
+	TRACE_TRAP_ENTRY(error_code >> 5, regs->pc);
+
 	oldfs = get_fs();
 
 	if (user_mode(regs)) {
@@ -503,8 +509,10 @@ asmlinkage void do_address_error(struct 
 		tmp = handle_unaligned_access(instruction, regs);
 		set_fs(oldfs);
 
-		if (tmp==0)
-			return; /* sorted */
+		if (tmp==0) {
+			TRACE_TRAP_EXIT();
+ 			return; /* sorted */
+		}
 
 	uspace_segv:
 		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
@@ -525,6 +533,7 @@ asmlinkage void do_address_error(struct 
 		handle_unaligned_access(instruction, regs);
 		set_fs(oldfs);
 	}
+	TRACE_TRAP_EXIT();
 }
 
 DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
@@ -624,3 +633,78 @@ void show_trace_task(struct task_struct 
 {
 	show_task((unsigned long *)tsk->thread.sp);
 }
+
+/* Trace related code */
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+asmlinkage void trace_real_syscall_entry(struct pt_regs * regs)
+{
+	int                 use_depth;
+	int                 use_bounds;
+	int                 depth = 0;
+	int                 seek_depth;
+	unsigned long       lower_bound;
+	unsigned long       upper_bound;
+	unsigned long       addr;
+	unsigned long*      stack;
+	trace_syscall_entry trace_syscall_event;
+
+	/* Set the syscall ID */
+	trace_syscall_event.syscall_id = (uint8_t) regs->regs[REG_REG0+3];
+
+	/* Set the address in any case */
+	trace_syscall_event.address  = regs->pc;
+
+	/* Are we in the kernel (This is a kernel thread)? */
+	if(!user_mode(regs))
+		/* Don't go digining anywhere */
+		goto trace_syscall_end;
+
+	/* Get the trace configuration */
+	if(trace_get_config(&use_depth, &use_bounds, &seek_depth,
+	   (void*)&lower_bound, (void*)&upper_bound) < 0)
+		goto trace_syscall_end;
+
+	/* Do we have to search for an eip address range */
+	if((use_depth == 1) || (use_bounds == 1))
+	{
+		/* Start at the top of the stack (bottom address since stacks grow downward) */
+		stack = (unsigned long*) regs->regs[REG_REG15];
+
+		/* Keep on going until we reach the end of the process' stack limit (wherever it may be) */
+		while(!get_user(addr, stack))
+		{
+			/* Does this LOOK LIKE an address in the program */
+			/* TODO: does this work with shared libraries?? - Greg Banks */
+			if((addr > current->mm->start_code) &&(addr < current->mm->end_code))
+			{
+				/* Does this address fit the description */
+				if(((use_depth == 1) && (depth == seek_depth))
+				   ||((use_bounds == 1) && (addr > lower_bound)
+				   && (addr < upper_bound)))
+				{
+					/* Set the address */
+					trace_syscall_event.address = addr;
+
+					/* We're done */
+					goto trace_syscall_end;
+				}
+				else
+					/* We're one depth more */
+					depth++;
+			}
+			/* Go on to the next address */
+			stack++;
+		}
+	}
+
+trace_syscall_end:
+	/* Trace the event */
+	trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event);
+}
+
+asmlinkage void trace_real_syscall_exit(void)
+{
+	trace_event(TRACE_EV_SYSCALL_EXIT, NULL);
+}
+#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */
+
diff -Nurp linux-2.4.22-clean/arch/sh/lib/checksum.S linux-2.4.22-adeos-ltt/arch/sh/lib/checksum.S
--- linux-2.4.22-clean/arch/sh/lib/checksum.S	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/lib/checksum.S	2003-11-21 23:21:08.000000000 -0800
@@ -172,7 +172,6 @@ unsigned int csum_partial_copy_generic (
 	.long 9999b, 6002f	;	\
 	.previous
 
-!
 ! r4:	const char *SRC
 ! r5:	char *DST
 ! r6:	int LEN
diff -Nurp linux-2.4.22-clean/arch/sh/mm/fault.c linux-2.4.22-adeos-ltt/arch/sh/mm/fault.c
--- linux-2.4.22-clean/arch/sh/mm/fault.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/arch/sh/mm/fault.c	2003-11-21 23:21:08.000000000 -0800
@@ -20,6 +20,8 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
+#include <linux/trace.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -107,6 +109,14 @@ asmlinkage void do_page_fault(struct pt_
 	tsk = current;
 	mm = tsk->mm;
 
+#if (CONFIG_TRACE || CONFIG_TRACE_MODULE)
+	{
+		unsigned long trapnr;
+		asm volatile("stc       r2_bank,%0": "=r" (trapnr));
+		TRACE_TRAP_ENTRY(trapnr >> 5, regs->pc);  /* trap 4,5 or 6 */
+	}
+#endif
+
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
@@ -158,6 +168,7 @@ survive:
 	}
 
 	up_read(&mm->mmap_sem);
+	TRACE_TRAP_EXIT();
 	return;
 
 /*
@@ -171,6 +182,7 @@ bad_area:
 		tsk->thread.address = address;
 		tsk->thread.error_code = writeaccess;
 		force_sig(SIGSEGV, tsk);
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -179,6 +191,7 @@ no_context:
 	fixup = search_exception_table(regs->pc);
 	if (fixup != 0) {
 		regs->pc = fixup;
+		TRACE_TRAP_EXIT();
 		return;
 	}
 
@@ -239,6 +252,8 @@ do_sigbus:
 	/* Kernel mode? Handle exceptions or die */
 	if (!user_mode(regs))
 		goto no_context;
+
+	TRACE_TRAP_EXIT();
 }
 
 /*
diff -Nurp linux-2.4.22-clean/Documentation/adeos.txt linux-2.4.22-adeos-ltt/Documentation/adeos.txt
--- linux-2.4.22-clean/Documentation/adeos.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/Documentation/adeos.txt	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,176 @@
+
+The Adeos nanokernel is based on research and publications made in the
+early '90s on the subject of nanokernels. Our basic method was to
+reverse the approach described in most of the papers on the subject.
+Instead of first building the nanokernel and then building the client
+OSes, we started from a live and known-to-be-functional OS, Linux, and
+inserted a nanokernel beneath it. Starting from Adeos, other client
+OSes can now be put side-by-side with the Linux kernel.
+
+To this end, Adeos enables multiple domains to exist simultaneously on
+the same hardware. None of these domains see each other, but all of
+them see Adeos. A domain is most probably a complete OS, but there is
+no assumption being made regarding the sophistication of what's in
+a domain.
+
+To share the hardware among the different OSes, Adeos implements an
+interrupt pipeline (ipipe). Every OS domain has an entry in the ipipe.
+Each interrupt that comes in the ipipe is passed on to every domain
+in the ipipe. Instead of disabling/enabling interrupts, each domain
+in the pipeline only needs to stall/unstall his pipeline stage. If
+an ipipe stage is stalled, then the interrupts do not progress in the
+ipipe until that stage has been unstalled. Each stage of the ipipe
+can, of course, decide to do a number of things with an interrupt.
+Among other things, it can decide that it's the last recipient of the
+interrupt. In that case, the ipipe does not propagate the interrupt
+to the rest of the domains in the ipipe.
+
+Regardless of the operations being done in the ipipe, the Adeos code
+does __not__ play with the interrupt masks. The only case where the
+hardware masks are altered is during the addition/removal of a domain
+from the ipipe. This also means that no OS is allowed to use the real
+hardware cli/sti. But this is OK, since the stall/unstall calls
+achieve the same functionality.
+
+Our approach is based on the following papers (links to these
+papers are provided at the bottom of this message):
+[1] D. Probert, J. Bruno, and M. Karzaorman. "Space: a new approach to
+operating system abstraction." In: International Workshop on Object
+Orientation in Operating Systems, pages 133-137, October 1991.
+[2] D. Probert, J. Bruno. "Building fundamentally extensible application-
+specific operating systems in Space", March 1995.
+[3] D. Cheriton, K. Duda. "A caching model of operating system kernel
+functionality". In: Proc. Symp. on Operating Systems Design and
+Implementation, pages 179-194, Monterey CA (USA), 1994.
+[4] D. Engler, M. Kaashoek, and J. O'Toole Jr. "Exokernel: an operating
+system architecture for application-specific resource management",
+December 1995.
+
+If you don't want to go fetch the complete papers, here's a summary.
+The first 2 discuss the Space nanokernel, the 3rd discussed the cache
+nanokernel, and the last discusses exokernel.
+
+The complete Adeos approach has been thoroughly documented in a whitepaper
+published more than a year ago entitled "Adaptive Domain Environment
+for Operating Systems" and available here: http://www.opersys.com/adeos
+The current implementation is slightly different. Mainly, we do not
+implement the functionality to move Linux out of ring 0. Although of
+interest, this approach is not very portable.
+
+Instead, our patch taps right into Linux's main source of control
+over the hardware, the interrupt dispatching code, and inserts an
+interrupt pipeline which can then serve all the nanokernel's clients,
+including Linux.
+
+This is not a novelty in itself. Other OSes have been modified in such
+a way for a wide range of purposes. One of the most interesting
+examples is described by Stodolsky, Chen, and Bershad in a paper
+entitled "Fast Interrupt Priority Management in Operating System
+Kernels" published in 1993 as part of the Usenix Microkernels and
+Other Kernel Architectures Symposium. In that case, cli/sti were
+replaced by virtual cli/sti which did not modify the real interrupt
+mask in any way. Instead, interrupts were defered and delivered to
+the OS upon a call to the virtualized sti.
+
+Mainly, this resulted in increased performance for the OS. Although
+we haven't done any measurements on Linux's interrupt handling
+performance with Adeos, our nanokernel includes by definition the
+code implementing the technique described in the abovementioned
+Stodolsky paper, which we use to redirect the hardware interrupt flow
+to the pipeline.
+
+i386 and armnommu are currently supported. Most of the
+architecture-dependent code is easily portable to other architectures.
+
+Aside of adding the Adeos module (driver/adeos), we also modified some
+files to tap into Linux interrupt and system event dispatching (all
+the modifications are encapsulated in #ifdef CONFIG_ADEOS_*/#endif).
+
+We modified the idle task so it gives control back to Adeos in order for
+the ipipe to continue propagation.
+
+We modified init/main.c to initialize Adeos very early in the startup.
+
+Of course, we also added the appropriate makefile modifications and
+config options so that you can choose to enable/disable Adeos as
+part of the kernel build configuration.
+
+Adeos' public API is fully documented here:
+http://www.freesoftware.fsf.org/adeos/doc/api/index.html.
+
+In Linux's case, adeos_register_domain() is called very early during
+system startup.
+
+To add your domain to the ipipe, you need to:
+1) Register your domain with Adeos using adeos_register_domain()
+2) Call adeos_virtualize_irq() for all the IRQs you wish to be
+notified about in the ipipe.
+
+That's it. Provided you gave Adeos appropriate handlers in step
+#2, your interrupts will be delivered via the ipipe.
+
+During runtime, you may change your position in the ipipe using
+adeos_renice_domain(). You may also stall/unstall the pipeline
+and change the ipipe's handling of the interrupts according to your
+needs.
+
+Adeos supports SMP, and APIC support on UP.
+
+Here are some of the possible uses for Adeos (this list is far
+from complete):
+1) Much like User-Mode Linux, it should now be possible to have 2
+Linux kernels living side-by-side on the same hardware. In contrast
+to UML, this would not be 2 kernels one ontop of the other, but
+really side-by-side. Since Linux can be told at boot time to use
+only one portion of the available RAM, on a 128MB machine this
+would mean that the first could be made to use the 0-64MB space and
+the second would use the 64-128MB space. We realize that many
+modifications are required. Among other things, one of the 2 kernels
+will not need to conduct hardware initialization. Nevertheless, this
+possibility should be studied closer.
+
+2) It follows from #1 that adding other kernels beside Linux should
+be feasible. BSD is a prime candidate, but it would also be nice to
+see what virtualizers such as VMWare and Plex86 could do with Adeos.
+Proprietary operating systems could potentially also be accomodated.
+
+3) All the previous work that has been done on nanokernels should now
+be easily ported to Linux. Mainly, we would be very interested to
+hear about extensions to Adeos. Primarily, we have no mechanisms
+currently enabling multiple domains to share information. The papers
+mentioned earlier provide such mechanisms, but we'd like to see
+actual practical examples.
+
+4) Kernel debuggers' main problem (tapping into the kernel's
+interrupts) is solved and it should then be possible to provide
+patchless kernel debuggers. They would then become loadable kernel
+modules.
+
+5) Drivers who require absolute priority and dislike other kernel
+portions who use cli/sti can now create a domain of their own
+and place themselves before Linux in the ipipe. This provides a
+mechanism for the implementation of systems that can provide guaranteed
+realtime response.
+
+Philippe Gerum <rpm@xenomai.org>
+Karim Yaghmour <karim@opersys.com>
+
+----------------------------------------------------------------------
+Links to papers:
+1-
+http://citeseer.nj.nec.com/probert91space.html
+ftp://ftp.cs.ucsb.edu/pub/papers/space/iwooos91.ps.gz (not working)
+http://www4.informatik.uni-erlangen.de/~tsthiel/Papers/Space-iwooos91.ps.gz
+
+2-
+http://www.cs.ucsb.edu/research/trcs/abstracts/1995-06.shtml
+http://www4.informatik.uni-erlangen.de/~tsthiel/Papers/Space-trcs95-06.ps.gz
+
+3-
+http://citeseer.nj.nec.com/kenneth94caching.html
+http://guir.cs.berkeley.edu/projects/osprelims/papers/cachmodel-OSkernel.ps.gz
+
+4-
+http://citeseer.nj.nec.com/engler95exokernel.html
+ftp://ftp.cag.lcs.mit.edu/multiscale/exokernel.ps.Z
+----------------------------------------------------------------------
diff -Nurp linux-2.4.22-clean/Documentation/Configure.help linux-2.4.22-adeos-ltt/Documentation/Configure.help
--- linux-2.4.22-clean/Documentation/Configure.help	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/Documentation/Configure.help	2003-11-21 23:21:08.000000000 -0800
@@ -22268,6 +22268,44 @@ CONFIG_DCACHE_DISABLE
   This option allows you to run the kernel with data cache disabled.
   Say Y if you experience CPM lock-ups.
 
+Kernel events tracing support
+CONFIG_TRACE
+  It is possible for the kernel to log important events to a tracing
+  driver. Doing so, enables the use of the generated traces in order
+  to reconstruct the dynamic behavior of the kernel, and hence the
+  whole system.
+
+  The tracing process contains 4 parts :
+      1) The logging of events by key parts of the kernel.
+      2) The trace driver that keeps the events in a data buffer.
+      3) A trace daemon that opens the trace driver and is notified
+         every time there is a certain quantity of data to read
+         from the trace driver (using SIG_IO).
+      4) A trace event data decoder that reads the accumulated data
+         and formats it in a human-readable format.
+
+  If you say Y or M here, the first part of the tracing process will
+  always take place. That is, critical parts of the kernel will call
+  upon the kernel tracing function. The data generated doesn't go
+  any further until a trace driver registers himself as such with the
+  kernel. Therefore, if you answer Y, then the driver will be part of
+  the kernel and the events will always proceed onto the driver and
+  if you say M, then the events will only proceed onto the driver when
+  it's module is loaded. Note that event's aren't logged in the driver
+  until the profiling daemon opens the device, configures it and
+  issues the "start" command through ioctl().
+
+  The impact of a fully functionnal system (kernel event logging +
+  driver event copying + active trace daemon) is of 2.5% for core events.
+  This means that for a task that took 100 seconds on a normal system, it
+  will take 102.5 seconds on a traced system. This is very low compared
+  to other profiling or tracing methods.
+
+  For more information on kernel tracing, the trace daemon or the event
+  decoder, please check the following address :
+       http://www.opersys.com/LTT
+
+
 #
 # m68k-specific kernel options
 # Documented by Chris Lawrence <mailto:quango@themall.net> et al.
diff -Nurp linux-2.4.22-clean/drivers/adeos/generic.c linux-2.4.22-adeos-ltt/drivers/adeos/generic.c
--- linux-2.4.22-clean/drivers/adeos/generic.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/adeos/generic.c	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,674 @@
+/*
+ *   linux/drivers/adeos/generic.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Architecture-independent ADEOS services.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/wrapper.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+
+MODULE_DESCRIPTION("Adeos nanokernel");
+MODULE_AUTHOR("Philippe Gerum");
+MODULE_LICENSE("GPL");
+
+extern spinlock_t __adeos_pipelock;
+
+extern unsigned long __adeos_virtual_irq_map;
+
+extern struct list_head __adeos_pipeline;
+
+/* adeos_register_domain() -- Add a new domain to the system. All
+   client domains must call this routine to register themselves to
+   ADEOS before using its services. */
+
+int adeos_register_domain (adomain_t *adp, adattr_t *attr)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+    adeos_declare_cpuid;
+    int n;
+
+    if (adp_current != adp_root)
+	{
+	printk(KERN_WARNING "ADEOS: Only the root domain may register a new domain.\n");
+	return -EPERM;
+	}
+
+    for (n = 0; n < ADEOS_NR_CPUS; n++)
+	adp->cpudata[n].status = 0;
+
+    /* A special case for domains who won't process events (i.e. no
+       entry). We have to mark them as suspended so that
+       adeos_suspend_domain() won't consider them, unless they
+       _actually_ receive events, which would lead to a panic
+       situation since they have no stack context... :o> */
+
+    if (attr->entry == NULL)
+	for (n = 0; n < ADEOS_NR_CPUS; n++)
+	    set_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[n].status);
+
+    adp->name = attr->name;
+    adp->priority = attr->priority;
+    adp->domid = attr->domid;
+    adp->dswitch = attr->dswitch;
+    adp->ptd_setfun = attr->ptdset;
+    adp->ptd_getfun = attr->ptdget;
+    adp->ptd_keymap = 0;
+    adp->ptd_keycount = 0;
+    adp->ptd_keymax = attr->nptdkeys;
+
+    for (n = 0; n < ADEOS_NR_EVENTS; n++)
+	/* Event handlers must be cleared before the i-pipe stage is
+	   inserted since an exception may occur on behalf of the new
+	   emerging domain. */
+	adp->events[n].handler = NULL;
+
+    if (attr->entry != NULL)
+	__adeos_init_domain(adp,attr);
+
+    printk("ADEOS: Domain %s registered.\n",adp->name);
+
+    /* Insert the domain in the interrupt pipeline last, so it won't
+       be resumed for processing interrupts until it has a valid stack
+       context. */
+
+    __adeos_init_stage(adp);
+
+    INIT_LIST_HEAD(&adp->p_link);
+
+    flags = adeos_critical_enter(NULL);
+
+    list_for_each(pos,&__adeos_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+	if (adp->priority > _adp->priority)
+            break;
+    }
+
+    list_add_tail(&adp->p_link,pos);
+
+    adeos_critical_exit(flags);
+
+    /* Finally, allow the new domain to perform its initialization
+       chores on behalf of its own stack context. */
+
+    if (attr->entry != NULL)
+	{
+	__adeos_switch_to(adp,cpuid);
+
+	adeos_reload_cpuid();	/* Processor might have changed. */
+
+	if (!test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status) &&
+	    adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage();
+	}
+
+    return 0;
+}
+
+/* adeos_unregister_domain() -- Remove a domain from the system. All
+   client domains must call this routine to unregister themselves from
+   the ADEOS layer. */
+
+int adeos_unregister_domain (adomain_t *adp)
+
+{
+    unsigned long flags;
+    unsigned event;
+
+    if (adp_current != adp_root)
+	{
+	printk(KERN_WARNING "ADEOS: Only the root domain may unregister a domain.\n");
+	return -EPERM;
+	}
+
+    if (adp == adp_root)
+	{
+	printk(KERN_WARNING "ADEOS: Cannot unregister the root domain.\n");
+	return -EPERM;
+	}
+
+    for (event = 0; event < ADEOS_NR_EVENTS; event++)
+	/* Need this to update the monitor count. */
+	adeos_catch_event(event,NULL);
+
+    /* Simply remove the domain from the pipeline and we are almost
+       done. */
+
+    flags = adeos_critical_enter(NULL);
+    list_del_init(&adp->p_link);
+    adeos_critical_exit(flags);
+
+    __adeos_cleanup_domain(adp);
+
+    printk("ADEOS: Domain %s unregistered.\n",adp->name);
+
+    return 0;
+}
+
+/* adeos_renice_domain() -- Change a domain's priority. This affects
+   the position of the domain in the interrupt pipeline. The greater
+   the priority value, the earlier the domain is informed of incoming
+   events when the pipeline is processed. */
+
+void adeos_renice_domain (adomain_t *adp, int newpri)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+
+    /* Allows round-robin effect if newpri == oldpri. */
+
+    flags = adeos_critical_enter(NULL);
+
+    list_del_init(&adp->p_link);
+
+    list_for_each(pos,&__adeos_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+	if (newpri > _adp->priority)
+            break;
+    }
+
+    list_add_tail(&adp->p_link,pos);
+    adp->priority = newpri;
+
+    adeos_critical_exit(flags);
+}
+
+int __adeos_schedule_irq (unsigned irq, struct list_head *head)
+
+{
+    struct list_head *ln;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    if (irq >= IPIPE_NR_IRQS ||
+	(adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)))
+	return -EINVAL;
+
+    adeos_hw_local_irq_save(flags);
+
+    ln = head;
+
+    while (ln != &__adeos_pipeline)
+	{
+	adomain_t *adp = list_entry(ln,adomain_t,p_link);
+
+	if (test_bit(IPIPE_HANDLE_FLAG,&adp->irqs[irq].control))
+	    {
+	    adp->cpudata[cpuid].irq_hits[irq]++;
+	    __adeos_set_irq_bit(adp,cpuid,irq);
+	    adeos_hw_local_irq_restore(flags);
+	    return 1;
+	    }
+
+	ln = adp->p_link.next;
+	}
+
+    adeos_hw_local_irq_restore(flags);
+
+    return 0;
+}
+
+/* adeos_propagate_irq() -- Force a given IRQ propagation on behalf of
+   a running interrupt handler to the next domain down the pipeline.
+   Returns non-zero if a domain has received the interrupt
+   notification, zero otherwise.
+   This call is useful for handling shared interrupts among domains.
+   e.g. pipeline = [domain-A]---[domain-B]...
+   Both domains share IRQ #X.
+   - domain-A handles IRQ #X but does not pass it down (i.e. Terminate
+   or Dynamic interrupt control mode)
+   - domain-B handles IRQ #X (i.e. Terminate or Accept interrupt
+   control modes).
+   When IRQ #X is raised, domain-A's handler determines whether it
+   should process the interrupt by identifying its source. If not,
+   adeos_propagate_irq() is called so that the next domain down the
+   pipeline which handles IRQ #X is given a chance to process it. This
+   process can be repeated until the end of the pipeline is
+   reached. */
+
+int adeos_propagate_irq (unsigned irq) {
+
+    return __adeos_schedule_irq(irq,adp_current->p_link.next);
+}
+
+/* adeos_schedule_irq() -- Almost the same as adeos_propagate_irq(),
+   but attempts to pend the interrupt for the current domain first. */
+
+int adeos_schedule_irq (unsigned irq) {
+
+    return __adeos_schedule_irq(irq,&adp_current->p_link);
+}
+
+unsigned long adeos_set_irq_affinity (unsigned irq, unsigned long cpumask)
+
+{
+#ifdef CONFIG_SMP
+     if (irq < NR_IRQS && smp_num_cpus > 1)
+	 /* Allow changing affinity of external IRQs only. */
+	 return __adeos_set_irq_affinity(irq,cpumask);
+#endif /* CONFIG_SMP */
+
+    return 0;
+}
+
+/* adeos_alloc_irq() -- Allocate a virtual/soft pipelined interrupt.
+   Virtual interrupts are handled in exactly the same way than their
+   hw-generated counterparts. This is a very basic, one-way only,
+   inter-domain communication system (see adeos_trigger_irq()).  Note:
+   it is not necessary for a domain to allocate a virtual interrupt to
+   trap it using adeos_virtualize_irq(). The newly allocated VIRQ
+   number which can be passed to other IRQ-related services is
+   returned on success, zero otherwise (i.e. no more virtual interrupt
+   channel is available). */
+
+unsigned adeos_alloc_irq (void)
+
+{
+    unsigned long flags, irq = 0;
+    int ipos;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (__adeos_virtual_irq_map != ~0)
+	{
+	ipos = ffz(__adeos_virtual_irq_map);
+	set_bit(ipos,&__adeos_virtual_irq_map);
+	irq = ipos + IPIPE_VIRQ_BASE;
+	}
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return irq;
+}
+
+/* adeos_free_irq() -- Return a previously allocated virtual/soft
+   pipelined interrupt to the pool of allocatable interrupts. */
+
+int adeos_free_irq (unsigned irq)
+
+{
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    clear_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map);
+
+    return 0;
+}
+
+/* adeos_unstall_pipeline_from() -- Unstall the interrupt pipeline and
+   synchronize pending events from a given domain. */
+
+void adeos_unstall_pipeline_from (adomain_t *adp)
+
+{
+    struct list_head *pos;
+    adeos_declare_cpuid;
+
+    clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    if (adp == adp_cpu_current[cpuid])
+	{
+	if (adp->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage();
+
+	return;
+	}
+
+    /* Attempt to flush all events that might be pending at the
+       unstalled domain level. This code is roughly lifted from
+       drivers/adeos/x86.c:__adeos_walk_pipeline(). */
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+
+	if (test_bit(IPIPE_STALL_FLAG,&_adp->cpudata[cpuid].status))
+	    break; /* Stalled stage -- do not go further. */
+
+	if (_adp->cpudata[cpuid].irq_pending_hi != 0)
+	    {
+	    /* Since the critical IPI might be triggered by the
+	       following actions, the current domain might not be
+	       linked to the pipeline anymore after its handler
+	       returns on SMP boxen, even if the domain remains valid
+	       (see adeos_unregister_domain()), so don't make any
+	       hazardous assumptions here. */
+
+	    if (_adp == adp_cpu_current[cpuid])
+		__adeos_sync_stage();
+	    else
+		{
+		__adeos_switch_to(_adp,cpuid);
+
+		adeos_reload_cpuid(); /* Processor might have changed. */
+
+		if (!test_bit(IPIPE_STALL_FLAG,&adp_cpu_current[cpuid]->cpudata[cpuid].status) &&
+		    adp_cpu_current[cpuid]->cpudata[cpuid].irq_pending_hi != 0)
+		    __adeos_sync_stage();
+		}
+	    
+	    break;
+	    }
+	else if (_adp == adp_cpu_current[cpuid])
+	    break;
+    }
+}
+
+/* adeos_catch_event_from() -- Interpose an event handler starting
+   from a given domain. */
+
+int adeos_catch_event_from (adomain_t *adp, unsigned event, void (*handler)(adevinfo_t *))
+
+{
+    if (event >= ADEOS_NR_EVENTS)
+	return -EINVAL;
+
+    if (!xchg(&adp->events[event].handler,handler))
+	{
+	if (handler)
+	    __adeos_event_monitors[event]++;
+	}
+    else if (!handler)
+	__adeos_event_monitors[event]--;
+
+    return 0;
+}
+
+void (*adeos_hook_dswitch(void (*handler)(void))) (void) {
+
+    return (void (*)(void))xchg(&adp_current->dswitch,handler);
+}
+
+void adeos_init_attr (adattr_t *attr)
+
+{
+    attr->name = "Anonymous";
+    attr->domid = 1;
+    attr->entry = NULL;
+    attr->estacksz = 0;	/* Let ADEOS choose a reasonable stack size */
+    attr->priority = ADEOS_ROOT_PRI;
+    attr->dswitch = NULL;
+    attr->nptdkeys = 0;
+    attr->ptdset = NULL;
+    attr->ptdget = NULL;
+}
+
+int adeos_alloc_ptdkey (void)
+
+{
+    unsigned long flags;
+    int key = -1;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (adp_current->ptd_keycount < adp_current->ptd_keymax)
+	{
+	key = ffz(adp_current->ptd_keymap);
+	set_bit(key,&adp_current->ptd_keymap);
+	adp_current->ptd_keycount++;
+	}
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return key;
+}
+
+int adeos_free_ptdkey (int key)
+
+{
+    unsigned long flags; 
+
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return -EINVAL;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (test_and_clear_bit(key,&adp_current->ptd_keymap))
+	adp_current->ptd_keycount--;
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return 0;
+}
+
+int adeos_set_ptd (int key, void *value)
+
+{
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return -EINVAL;
+
+    if (!adp_current->ptd_setfun)
+	{
+	printk(KERN_WARNING "ADEOS: not ptdset hook for %s\n",adp_current->name);
+	return -EINVAL;
+	}
+
+    adp_current->ptd_setfun(key,value);
+
+    return 0;
+}
+
+void *adeos_get_ptd (int key)
+
+{
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return NULL;
+
+    if (!adp_current->ptd_getfun)
+	{
+	printk(KERN_WARNING "ADEOS: not ptdget hook for %s\n",adp_current->name);
+	return NULL;
+	}
+
+    return adp_current->ptd_getfun(key);
+}
+
+static inline void __adeos_sleepon_mutex (admutex_t *mutex, adomain_t *sleeper, int cpuid)
+
+{
+    adomain_t *owner = mutex->owner;
+    unsigned long flags;
+
+    /* Make the current domain (== sleeper) wait for the mutex to be
+       released. Adeos' pipelined scheme guarantees that the new
+       sleeper _is_ more prioritary than any aslept domain since we
+       have stalled each sleeper's stage. */
+    adeos_hw_local_irq_save(flags);
+    sleeper->m_link = mutex->sleepq;
+    mutex->sleepq = sleeper;
+    __adeos_switch_to(owner,cpuid);
+    adeos_hw_local_irq_restore(flags);
+}
+
+static inline void __adeos_signal_mutex (admutex_t *mutex, int cpuid)
+
+{
+    unsigned long flags;
+    adomain_t *sleeper;
+
+    /* Wake up first most prioritary sleeper. */
+
+    adeos_hw_local_irq_save(flags);
+    sleeper = mutex->sleepq;
+    mutex->sleepq = sleeper->m_link;
+    __adeos_switch_to(sleeper,cpuid);
+    adeos_hw_local_irq_restore(flags);
+}
+
+unsigned long adeos_lock_mutex (admutex_t *mutex)
+
+{
+    unsigned long flags;
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	adomain_t *adp;
+
+	adp = adp_cpu_current[cpuid];
+	flags = test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+	/* Two cases to handle here on SMP systems, only one for UP:
+	   1) in case of a conflicting access from a prioritary domain
+	   running on the same cpu, make this domain sleep on the mutex,
+	   and resume the current owner so it can release the lock asap.
+	   2) in case of a conflicting access from any domain on a
+	   different cpu than the current owner's, simply enter a spinning
+	   loop. Note that testing mutex->owncpu is safe since it is only
+	   changed by the current owner, and set to -1 when the mutex is
+	   unlocked. */
+
+	while (!adeos_spin_trylock(&mutex->lock))
+	    {
+#ifdef CONFIG_SMP
+	    if (mutex->owncpu == cpuid)
+		{
+		__adeos_sleepon_mutex(mutex,adp,cpuid);
+		adeos_reload_cpuid();
+		}
+#else  /* !CONFIG_SMP */
+	    __adeos_sleepon_mutex(mutex,adp,cpuid);
+#endif /* CONFIG_SMP */
+	    }
+
+	mutex->owner = adp;
+
+#ifdef CONFIG_SMP
+	mutex->owncpu = cpuid;
+#endif /* CONFIG_SMP */
+	}
+    else
+	{
+	adeos_hw_local_irq_save(flags);
+	flags = !adeos_hw_test_iflag(flags);
+	adeos_spin_lock(&mutex->lock);
+	}
+
+    return flags;
+}
+
+void adeos_unlock_mutex (admutex_t *mutex, unsigned long flags)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	adomain_t *adp;
+
+#ifdef CONFIG_SMP
+	mutex->owncpu = -1;
+#endif /* CONFIG_SMP */
+
+	adeos_spin_unlock(&mutex->lock);
+
+	if (unlikely(mutex->sleepq != NULL))
+	    {
+	    __adeos_signal_mutex(mutex,cpuid); /* Wake up one sleeper. */
+#ifdef CONFIG_SMP
+	    adeos_reload_cpuid();
+#endif  /* CONFIG_SMP */
+	    }
+
+	adp = adp_cpu_current[cpuid];
+
+	if (flags)
+	    set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+	else
+	    {
+	    adeos_hw_sti();	/* Absolutely needed. */
+
+	    clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+	    if (adp->cpudata[cpuid].irq_pending_hi != 0)
+		__adeos_sync_stage();
+	    }
+	}
+    else
+	{
+	adeos_spin_unlock(&mutex->lock);
+
+	if (flags)
+	    adeos_hw_cli();
+	else
+	    adeos_hw_sti();
+	}
+}
+
+void __adeos_takeover (void)
+
+{
+    __adeos_enable_pipeline();
+    printk("ADEOS: Pipelining started.\n");
+}
+
+#ifdef MODULE
+
+static int __init adeos_init_module (void)
+
+{
+    __adeos_takeover();
+    return 0;
+}
+
+static void __exit adeos_exit_module (void)
+
+{
+    __adeos_disable_pipeline();
+    printk("ADEOS: Pipelining stopped.\n");
+}
+
+module_init(adeos_init_module);
+module_exit(adeos_exit_module);
+
+#endif /* MODULE */
+
+EXPORT_SYMBOL(adeos_register_domain);
+EXPORT_SYMBOL(adeos_unregister_domain);
+EXPORT_SYMBOL(adeos_renice_domain);
+EXPORT_SYMBOL(adeos_virtualize_irq);
+EXPORT_SYMBOL(adeos_control_irq);
+EXPORT_SYMBOL(adeos_propagate_irq);
+EXPORT_SYMBOL(adeos_schedule_irq);
+EXPORT_SYMBOL(adeos_alloc_irq);
+EXPORT_SYMBOL(adeos_free_irq);
+EXPORT_SYMBOL(adeos_trigger_irq);
+EXPORT_SYMBOL(adeos_trigger_ipi);
+EXPORT_SYMBOL(adeos_stall_pipeline);
+EXPORT_SYMBOL(adeos_unstall_pipeline);
+EXPORT_SYMBOL(adeos_unstall_pipeline_from);
+EXPORT_SYMBOL(adeos_catch_event_from);
+EXPORT_SYMBOL(adeos_hook_dswitch);
+EXPORT_SYMBOL(adeos_init_attr);
+EXPORT_SYMBOL(adeos_get_sysinfo);
+EXPORT_SYMBOL(adeos_tune_timer);
+EXPORT_SYMBOL(adeos_alloc_ptdkey);
+EXPORT_SYMBOL(adeos_free_ptdkey);
+EXPORT_SYMBOL(adeos_set_ptd);
+EXPORT_SYMBOL(adeos_get_ptd);
+EXPORT_SYMBOL(adeos_set_irq_affinity);
+EXPORT_SYMBOL(adeos_lock_mutex);
+EXPORT_SYMBOL(adeos_unlock_mutex);
diff -Nurp linux-2.4.22-clean/drivers/adeos/Makefile linux-2.4.22-adeos-ltt/drivers/adeos/Makefile
--- linux-2.4.22-clean/drivers/adeos/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/adeos/Makefile	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,26 @@
+#
+# Makefile for the Adeos driver.
+#
+
+O_TARGET := driver.o
+
+export-objs	:= generic.o
+list-multi	:= adeos.o
+adeos-objs	:= generic.o
+
+ifdef CONFIG_X86
+adeos-objs	+= x86.o
+endif
+
+ifdef CONFIG_ARM
+ifdef CONFIG_UCLINUX
+adeos-objs	+= armnommu.o
+endif
+endif
+
+obj-$(CONFIG_ADEOS)	+= adeos.o
+
+include $(TOPDIR)/Rules.make
+
+adeos.o: $(adeos-objs)
+	$(LD) -r -o $@ $(adeos-objs)
diff -Nurp linux-2.4.22-clean/drivers/adeos/x86.c linux-2.4.22-adeos-ltt/drivers/adeos/x86.c
--- linux-2.4.22-clean/drivers/adeos/x86.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/adeos/x86.c	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,1046 @@
+/*
+ *   linux/drivers/adeos/x86.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Architecture-dependent ADEOS support for x86.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/hw_irq.h>
+#include <asm/irq.h>
+#include <asm/desc.h>
+#include <asm/io.h>
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/fixmap.h>
+#include <asm/bitops.h>
+#include <asm/mpspec.h>
+#ifdef CONFIG_X86_IO_APIC
+#include <asm/io_apic.h>
+#endif /* CONFIG_X86_IO_APIC */
+#include <asm/apic.h>
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+extern struct desc_struct idt_table[];
+
+extern spinlock_t __adeos_pipelock;
+
+extern unsigned long __adeos_virtual_irq_map;
+
+extern struct list_head __adeos_pipeline;
+
+static void (*__adeos_std_vector_table[256])(void);
+
+static struct hw_interrupt_type __adeos_std_irq_dtype[NR_IRQS];
+
+/* Lifted from arch/i386/kernel/traps.c */ 
+#define __adeos_set_gate(gate_addr,type,dpl,addr)  \
+do { \
+  int __d0, __d1; \
+  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
+	"movw %4,%%dx\n\t" \
+	"movl %%eax,%0\n\t" \
+	"movl %%edx,%1" \
+	:"=m" (*((long *) (gate_addr))), \
+	 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
+	:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
+	 "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
+} while (0)
+
+#define __adeos_get_gate_addr(v) \
+	((void *)((idt_table[v].b & 0xffff0000)|(idt_table[v].a & 0xffff)))
+
+#define __adeos_set_irq_gate(vector,addr) \
+__adeos_set_gate(idt_table+vector,14,0,addr)
+
+#define __adeos_set_trap_gate(vector,addr) \
+__adeos_set_gate(idt_table+vector,15,0,addr)
+
+#define __adeos_set_sys_gate(vector,addr) \
+__adeos_set_gate(idt_table+vector,15,3,addr)
+
+#define BUILD_IRQ_BODY() \
+__asm__( \
+	"\n" __ALIGN_STR"\n" \
+        SYMBOL_NAME_STR(__adeos_irq_common) ":\n\t" \
+	"pushl %es\n\t" \
+	"pushl %ds\n\t" \
+	"pushl %eax\n\t" \
+	"pushl %ebp\n\t" \
+	"pushl %edi\n\t" \
+	"pushl %esi\n\t" \
+	"pushl %edx\n\t" \
+	"pushl %ecx\n\t" \
+	"pushl %ebx\n\t" \
+	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
+	"movl %edx,%ds\n\t" \
+	"movl %edx,%es\n\t" \
+	"call " SYMBOL_NAME_STR(__adeos_handle_irq) "\n\t" \
+	"testl %eax,%eax\n\t" \
+	"jnz  1f\n\t" \
+        "popl %ebx\n\t" \
+	"popl %ecx\n\t" \
+	"popl %edx\n\t" \
+	"popl %esi\n\t" \
+	"popl %edi\n\t" \
+	"popl %ebp\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"popl %es\n\t" \
+	"addl $4,%esp\n\t" \
+        "iret\n\t" \
+        "1: cld\n\t" \
+        __adeos_bump_count_noarg /* Depends on CONFIG_PREEMPT. */ \
+        "jmp " SYMBOL_NAME_STR(ret_from_intr) "\n");
+
+
+#define BUILD_IRQ_PROTO(irq)  __adeos_irq_##irq(void)
+#define BUILD_1_IRQ(irq) \
+asmlinkage void BUILD_IRQ_PROTO(irq); \
+__asm__( \
+	"\n" __ALIGN_STR"\n" \
+        SYMBOL_NAME_STR(__adeos_irq_) #irq ":\n\t" \
+	"pushl $"#irq"-256 \n\t" \
+	"jmp " SYMBOL_NAME_STR(__adeos_irq_common) "\n");
+
+#define BUILD_IRQ_N(x,y) \
+BUILD_1_IRQ(x##y)
+
+#define BUILD_16_IRQS(x) \
+BUILD_IRQ_N(x,0)  BUILD_IRQ_N(x,1)  BUILD_IRQ_N(x,2)  BUILD_IRQ_N(x,3) \
+BUILD_IRQ_N(x,4)  BUILD_IRQ_N(x,5)  BUILD_IRQ_N(x,6)  BUILD_IRQ_N(x,7) \
+BUILD_IRQ_N(x,8)  BUILD_IRQ_N(x,9)  BUILD_IRQ_N(x,a)  BUILD_IRQ_N(x,b) \
+BUILD_IRQ_N(x,c)  BUILD_IRQ_N(x,d)  BUILD_IRQ_N(x,e)  BUILD_IRQ_N(x,f)
+
+BUILD_IRQ_BODY();
+
+BUILD_16_IRQS(0x0)
+#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_IO_APIC)
+BUILD_16_IRQS(0x1)  BUILD_16_IRQS(0x2)  BUILD_16_IRQS(0x3) BUILD_16_IRQS(0x4)
+BUILD_16_IRQS(0x5)  BUILD_16_IRQS(0x6)  BUILD_16_IRQS(0x7) BUILD_16_IRQS(0x8)
+BUILD_16_IRQS(0x9)  BUILD_16_IRQS(0xa)  BUILD_16_IRQS(0xb) BUILD_16_IRQS(0xc)
+BUILD_16_IRQS(0xd)
+#endif /* CONFIG_X86_LOCAL_APIC || CONFIG_X86_IO_APIC */
+
+#define LIST_1_IRQ(irq) &__adeos_irq_ ## irq
+
+#define LIST_IRQ_N(x,y) \
+LIST_1_IRQ(x##y)
+
+#define LIST_16_IRQS(x) \
+LIST_IRQ_N(x,0),  LIST_IRQ_N(x,1),  LIST_IRQ_N(x,2), LIST_IRQ_N(x,3), \
+LIST_IRQ_N(x,4),  LIST_IRQ_N(x,5),  LIST_IRQ_N(x,6), LIST_IRQ_N(x,7), \
+LIST_IRQ_N(x,8),  LIST_IRQ_N(x,9),  LIST_IRQ_N(x,a), LIST_IRQ_N(x,b), \
+LIST_IRQ_N(x,c),  LIST_IRQ_N(x,d),  LIST_IRQ_N(x,e), LIST_IRQ_N(x,f)
+
+static void (*__adeos_irq_trampolines[])(void) = {
+    LIST_16_IRQS(0x0),
+#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_IO_APIC)
+    LIST_16_IRQS(0x1), LIST_16_IRQS(0x2), LIST_16_IRQS(0x3), LIST_16_IRQS(0x4),
+    LIST_16_IRQS(0x5), LIST_16_IRQS(0x6), LIST_16_IRQS(0x7), LIST_16_IRQS(0x8),
+    LIST_16_IRQS(0x9), LIST_16_IRQS(0xa), LIST_16_IRQS(0xb), LIST_16_IRQS(0xc),
+    LIST_16_IRQS(0xd)
+#endif /* CONFIG_X86_LOCAL_APIC || CONFIG_X86_IO_APIC */
+};
+
+#define BUILD_TRAP_PROTO(trapnr)  __adeos_trap_##trapnr(void)
+
+#define BUILD_TRAP_ERRCODE(trapnr) \
+asmlinkage void BUILD_TRAP_PROTO(trapnr); \
+__asm__ ( \
+	"\n" __ALIGN_STR"\n\t" \
+        SYMBOL_NAME_STR(__adeos_trap_) #trapnr ":\n\t" \
+        "cld\n\t" \
+        "pushl %es\n\t" \
+        "pushl %ds\n\t" \
+        "pushl %eax\n\t" \
+        "pushl %ebp\n\t" \
+        "pushl %edi\n\t" \
+        "pushl %esi\n\t" \
+        "pushl %edx\n\t" \
+        "pushl %ecx\n\t" \
+        "pushl %ebx\n\t" \
+        "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
+	"mov %dx,%ds\n\t" \
+	"mov %dx,%es\n\t" \
+        "movl ("__stringify(__adeos_event_monitors + 4 * trapnr)"),%eax\n\t" \
+	"testl %eax,%eax\n\t" \
+	"jz 1f\n\t" \
+	"movl %esp,%eax\n\t" \
+        "pushl %eax\n\t" \
+	"pushl $"#trapnr"\n\t" \
+        "call " __stringify(__adeos_handle_event) "\n\t" \
+	"addl $8,%esp\n\t" \
+	"testl %eax,%eax\n\t" \
+"1:      popl %ebx\n\t" \
+        "popl %ecx\n\t" \
+	"popl %edx\n\t" \
+        "popl %esi\n\t" \
+        "popl %edi\n\t" \
+	"popl %ebp\n\t" \
+	"jz 2f\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"popl %es\n\t" \
+	"addl $4,%esp\n\t" \
+	"iret\n" \
+"2:      movl ("SYMBOL_NAME_STR(__adeos_std_vector_table + 4 * trapnr)"),%eax\n\t" \
+	"movl 8(%esp),%es\n\t" \
+	"movl %eax,8(%esp)\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"ret\n");
+
+#define BUILD_TRAP_NOERRCODE(trapnr) \
+asmlinkage void BUILD_TRAP_PROTO(trapnr); \
+__asm__ ( \
+	"\n" __ALIGN_STR"\n\t" \
+        SYMBOL_NAME_STR(__adeos_trap_) #trapnr ":\n\t" \
+        "cld\n\t" \
+        "pushl $0\n\t" \
+        "pushl %es\n\t" \
+        "pushl %ds\n\t" \
+        "pushl %eax\n\t" \
+        "pushl %ebp\n\t" \
+        "pushl %edi\n\t" \
+        "pushl %esi\n\t" \
+        "pushl %edx\n\t" \
+        "pushl %ecx\n\t" \
+        "pushl %ebx\n\t" \
+        "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
+	"mov %dx,%ds\n\t" \
+	"mov %dx,%es\n\t" \
+        "movl (" __stringify(__adeos_event_monitors + 4 * trapnr)"),%eax\n\t" \
+	"testl %eax,%eax\n\t" \
+	"jz 1f\n\t" \
+	"movl %esp,%eax\n\t" \
+        "pushl %eax\n\t" \
+	"pushl $"#trapnr"\n\t" \
+        "call " __stringify(__adeos_handle_event) "\n\t" \
+	"addl $8,%esp\n\t" \
+	"testl %eax,%eax\n\t" \
+"1:      popl %ebx\n\t" \
+        "popl %ecx\n\t" \
+	"popl %edx\n\t" \
+        "popl %esi\n\t" \
+        "popl %edi\n\t" \
+	"popl %ebp\n\t" \
+	"jz 2f\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"popl %es\n\t" \
+	"addl $4,%esp\n\t" \
+	"iret\n" \
+"2:      movl ("SYMBOL_NAME_STR(__adeos_std_vector_table + 4 * trapnr)"),%eax\n\t" \
+	"movl %eax,12(%esp)\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"popl %es\n\t" \
+	"ret\n");
+
+BUILD_TRAP_NOERRCODE(0x0)   BUILD_TRAP_NOERRCODE(0x1)   BUILD_TRAP_NOERRCODE(0x2)
+BUILD_TRAP_NOERRCODE(0x3)   BUILD_TRAP_NOERRCODE(0x4)   BUILD_TRAP_NOERRCODE(0x5)
+BUILD_TRAP_NOERRCODE(0x6)   BUILD_TRAP_NOERRCODE(0x7)   BUILD_TRAP_ERRCODE(0x8)
+BUILD_TRAP_NOERRCODE(0x9)   BUILD_TRAP_ERRCODE(0xa)     BUILD_TRAP_ERRCODE(0xb)
+BUILD_TRAP_ERRCODE(0xc)     BUILD_TRAP_ERRCODE(0xd)     BUILD_TRAP_ERRCODE(0xe)
+BUILD_TRAP_NOERRCODE(0xf)   BUILD_TRAP_NOERRCODE(0x10)  BUILD_TRAP_ERRCODE(0x11)
+BUILD_TRAP_NOERRCODE(0x12)  BUILD_TRAP_NOERRCODE(0x13)  BUILD_TRAP_ERRCODE(0x14)
+BUILD_TRAP_ERRCODE(0x15)    BUILD_TRAP_ERRCODE(0x16)    BUILD_TRAP_ERRCODE(0x17)
+BUILD_TRAP_ERRCODE(0x18)    BUILD_TRAP_ERRCODE(0x19)    BUILD_TRAP_ERRCODE(0x1a)
+BUILD_TRAP_ERRCODE(0x1b)    BUILD_TRAP_ERRCODE(0x1c)    BUILD_TRAP_ERRCODE(0x1d)
+BUILD_TRAP_ERRCODE(0x1e)    BUILD_TRAP_ERRCODE(0x1f)
+
+#define LIST_TRAP(trapnr) &__adeos_trap_ ## trapnr
+
+static void (*__adeos_trap_trampolines[])(void) = {
+    LIST_TRAP(0x0), LIST_TRAP(0x1), LIST_TRAP(0x2), LIST_TRAP(0x3),
+    LIST_TRAP(0x4), LIST_TRAP(0x5), LIST_TRAP(0x6), LIST_TRAP(0x7),
+    LIST_TRAP(0x8), LIST_TRAP(0x9), LIST_TRAP(0xa), LIST_TRAP(0xb),
+    LIST_TRAP(0xc), LIST_TRAP(0xd), LIST_TRAP(0xe), LIST_TRAP(0xf),
+    LIST_TRAP(0x10), LIST_TRAP(0x11), LIST_TRAP(0x12), LIST_TRAP(0x13),
+    LIST_TRAP(0x14), LIST_TRAP(0x15), LIST_TRAP(0x16), LIST_TRAP(0x17),
+    LIST_TRAP(0x18), LIST_TRAP(0x19), LIST_TRAP(0x1a), LIST_TRAP(0x1b),
+    LIST_TRAP(0x1c), LIST_TRAP(0x1d), LIST_TRAP(0x1e), LIST_TRAP(0x1f)
+};
+
+static int __adeos_ack_common_irq (unsigned irq)
+
+{
+    irq_desc_t *desc = irq_desc + irq;
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    desc->handler->ack(irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+
+    return 1;
+}
+
+static unsigned __adeos_override_irq_startup (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+    unsigned s;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_unlock_irq(adp_cpu_current[cpuid],irq);
+    s = __adeos_std_irq_dtype[irq].startup(irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+
+    return s;
+}
+
+static void __adeos_override_irq_shutdown (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_std_irq_dtype[irq].shutdown(irq);
+    __adeos_clear_irq(adp_cpu_current[cpuid],irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_enable (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_unlock_irq(adp_cpu_current[cpuid],irq);
+    __adeos_std_irq_dtype[irq].enable(irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_disable (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_std_irq_dtype[irq].disable(irq);
+    __adeos_lock_irq(adp_cpu_current[cpuid],cpuid,irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_end (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+
+#ifdef CONFIG_X86_IO_APIC
+    if (!IO_APIC_IRQ(irq) || !(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+#else /* !CONFIG_X86_IO_APIC */
+    if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+#endif /* CONFIG_X86_IO_APIC */
+	__adeos_unlock_irq(adp_cpu_current[cpuid],irq);
+
+    __adeos_std_irq_dtype[irq].end(irq);
+
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_affinity (unsigned irq, unsigned long mask)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_std_irq_dtype[irq].set_affinity(irq,mask);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+/* __adeos_enable_pipeline() -- Take over the interrupt control from
+   the root domain (i.e. Linux). After this routine has returned, all
+   interrupts go through the pipeline. */
+
+void __adeos_enable_pipeline (void)
+
+{
+    unsigned vector, irq;
+    unsigned long flags;
+
+    /* Collect the original vector table. */
+
+    for (vector = 0; vector < 256; vector++)
+	__adeos_std_vector_table[vector] = __adeos_get_gate_addr(vector);
+
+#ifdef CONFIG_SMP
+
+    /* This vector must be set up prior to call
+       adeos_critical_enter(). */
+
+    __adeos_set_irq_gate(ADEOS_CRITICAL_VECTOR,
+			 __adeos_irq_trampolines[ADEOS_CRITICAL_IPI]);
+
+#endif /* CONFIG_SMP */
+
+    flags = adeos_critical_enter(NULL);
+
+    /* First, grab the ISA and IO-APIC interrupts. */
+
+    for (irq = 0; irq < NR_IRQS && irq + FIRST_EXTERNAL_VECTOR < FIRST_SYSTEM_VECTOR; irq++)
+	{
+#ifdef CONFIG_X86_IO_APIC
+	if (IO_APIC_IRQ(irq))
+	    {
+	    vector = IO_APIC_VECTOR(irq);
+
+	    if (vector == 0)
+		continue;
+	    }
+	else
+#endif /* CONFIG_X86_IO_APIC */
+	    {
+	    vector = irq + FIRST_EXTERNAL_VECTOR;
+
+	    if (vector == SYSCALL_VECTOR)
+		continue;
+	    }
+
+	/* Fails for ADEOS_CRITICAL_IPI but that's ok. */
+
+	adeos_virtualize_irq(irq,
+			     (void (*)(unsigned))__adeos_std_vector_table[vector],
+			     &__adeos_ack_common_irq,
+			     IPIPE_CALLASM_MASK|IPIPE_HANDLE_MASK|IPIPE_PASS_MASK);
+
+	__adeos_set_irq_gate(vector,__adeos_irq_trampolines[irq]);
+	}
+
+    /* Interpose on the IRQ control routines so we can make them
+       atomic using hw masking and prevent the interrupt log from
+       being untimely flushed. Since we don't want to be too smart
+       about what's going on into irq.c and we want to change only
+       some of the controller members, let's be dumb and interpose the
+       rough way. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	__adeos_std_irq_dtype[irq] = *irq_desc[irq].handler;
+
+    /* The original controller structs are often shared, so we first
+       save them all before changing any of them. Notice that we don't
+       redirect the ack handler since the relevant XT-PIC/IO-APIC
+       management code is already Adeos-aware. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	{
+	irq_desc[irq].handler->startup = &__adeos_override_irq_startup;
+	irq_desc[irq].handler->shutdown = &__adeos_override_irq_shutdown;
+	irq_desc[irq].handler->enable = &__adeos_override_irq_enable;
+	irq_desc[irq].handler->disable = &__adeos_override_irq_disable;
+	irq_desc[irq].handler->end = &__adeos_override_irq_end;
+
+	if (irq_desc[irq].handler->set_affinity != NULL)
+	    irq_desc[irq].handler->set_affinity = &__adeos_override_irq_affinity;
+	}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+    /* Map the APIC system vectors including the unused ones so that
+       client domains can virtualize the corresponding IRQs. */
+
+    for (vector = FIRST_SYSTEM_VECTOR; vector < CALL_FUNCTION_VECTOR; vector++)
+      {
+      adeos_virtualize_irq(vector - FIRST_EXTERNAL_VECTOR,
+			   (void (*)(unsigned))__adeos_std_vector_table[vector],
+			   &__adeos_ack_system_irq,
+			   IPIPE_CALLASM_MASK|IPIPE_HANDLE_MASK|IPIPE_PASS_MASK);
+      
+      __adeos_set_irq_gate(vector,
+			   __adeos_irq_trampolines[vector - FIRST_EXTERNAL_VECTOR]);
+      }
+
+    __adeos_tick_irq = using_apic_timer ? LOCAL_TIMER_VECTOR - FIRST_EXTERNAL_VECTOR : 0;
+
+#else  /* !CONFIG_X86_LOCAL_APIC */
+
+    __adeos_tick_irq = 0;
+
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#ifdef CONFIG_SMP
+
+    /* All interrupts must be pipelined, but the spurious one since we
+       don't even want to acknowledge it. */
+
+    for (vector = CALL_FUNCTION_VECTOR; vector < SPURIOUS_APIC_VECTOR; vector++)
+      {
+      adeos_virtualize_irq(vector - FIRST_EXTERNAL_VECTOR,
+			   (void (*)(unsigned))__adeos_std_vector_table[vector],
+			   &__adeos_ack_system_irq,
+			   IPIPE_CALLASM_MASK|IPIPE_HANDLE_MASK|IPIPE_PASS_MASK);
+      
+      __adeos_set_irq_gate(vector,
+			   __adeos_irq_trampolines[vector - FIRST_EXTERNAL_VECTOR]);
+      }
+
+    __adeos_set_irq_gate(ADEOS_SERVICE_VECTOR,
+			 __adeos_irq_trampolines[ADEOS_SERVICE_IPI]);
+
+#endif /* CONFIG_SMP */
+
+    /* Redirect traps and exceptions (except NMI). */
+
+    __adeos_set_trap_gate(0,__adeos_trap_trampolines[0]);
+    __adeos_set_trap_gate(1,__adeos_trap_trampolines[1]);
+    __adeos_set_sys_gate(3,__adeos_trap_trampolines[3]);
+    __adeos_set_sys_gate(4,__adeos_trap_trampolines[4]);
+    __adeos_set_sys_gate(5,__adeos_trap_trampolines[5]);
+    __adeos_set_trap_gate(6,__adeos_trap_trampolines[6]);
+    __adeos_set_trap_gate(7,__adeos_trap_trampolines[7]);
+    __adeos_set_trap_gate(8,__adeos_trap_trampolines[8]);
+    __adeos_set_trap_gate(9,__adeos_trap_trampolines[9]);
+    __adeos_set_trap_gate(10,__adeos_trap_trampolines[10]);
+    __adeos_set_trap_gate(11,__adeos_trap_trampolines[11]);
+    __adeos_set_trap_gate(12,__adeos_trap_trampolines[12]);
+    __adeos_set_trap_gate(13,__adeos_trap_trampolines[13]);
+    __adeos_set_irq_gate(14,__adeos_trap_trampolines[14]);
+    __adeos_set_trap_gate(15,__adeos_trap_trampolines[15]);
+    __adeos_set_trap_gate(16,__adeos_trap_trampolines[16]);
+    __adeos_set_trap_gate(17,__adeos_trap_trampolines[17]);
+    __adeos_set_trap_gate(18,__adeos_trap_trampolines[18]);
+    __adeos_set_trap_gate(19,__adeos_trap_trampolines[19]);
+
+#if defined(CONFIG_ADEOS_MODULE) || defined(CONFIG_X86_IO_APIC)
+    adp_pipelined = 1;
+#endif /* CONFIG_ADEOS_MODULE || CONFIG_X86_IO_APIC */
+
+    adeos_critical_exit(flags);
+}
+
+/* __adeos_disable_pipeline() -- Disengage the pipeline. */
+
+void __adeos_disable_pipeline (void)
+
+{
+    unsigned vector, irq;
+    unsigned long flags;
+
+    flags = adeos_critical_enter(NULL);
+
+    /* Restore interrupt controllers. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	*irq_desc[irq].handler = __adeos_std_irq_dtype[irq];
+
+    /* Restore original IDT settings. */
+
+    for (irq = 0; irq < NR_IRQS && irq + FIRST_EXTERNAL_VECTOR < FIRST_SYSTEM_VECTOR; irq++)
+	{
+#ifdef CONFIG_X86_IO_APIC
+	if (IO_APIC_IRQ(irq))
+	    {
+	    vector = IO_APIC_VECTOR(irq);
+
+	    if (vector == 0)
+		continue;
+	    }
+	else
+#endif /* CONFIG_X86_IO_APIC */
+	    {
+	    vector = irq + FIRST_EXTERNAL_VECTOR;
+
+	    if (vector == SYSCALL_VECTOR)
+		continue;
+	    }
+
+	__adeos_set_irq_gate(vector,__adeos_std_vector_table[vector]);
+	}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+    for (vector = FIRST_SYSTEM_VECTOR; vector < CALL_FUNCTION_VECTOR; vector++)
+      __adeos_set_irq_gate(vector,__adeos_std_vector_table[vector]);
+
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#ifdef CONFIG_SMP
+
+    for (vector = CALL_FUNCTION_VECTOR; vector < SPURIOUS_APIC_VECTOR; vector++)
+	__adeos_set_irq_gate(vector,__adeos_std_vector_table[vector]);
+
+    __adeos_set_irq_gate(ADEOS_SERVICE_VECTOR,__adeos_std_vector_table[ADEOS_SERVICE_VECTOR]);
+    __adeos_set_irq_gate(ADEOS_CRITICAL_VECTOR,__adeos_std_vector_table[ADEOS_CRITICAL_VECTOR]);
+
+#endif /* CONFIG_SMP */
+
+    __adeos_set_trap_gate(0,__adeos_std_vector_table[0]);
+    __adeos_set_trap_gate(1,__adeos_std_vector_table[1]);
+    __adeos_set_sys_gate(3,__adeos_std_vector_table[3]);
+    __adeos_set_sys_gate(4,__adeos_std_vector_table[4]);
+    __adeos_set_sys_gate(5,__adeos_std_vector_table[5]);
+    __adeos_set_trap_gate(6,__adeos_std_vector_table[6]);
+    __adeos_set_trap_gate(7,__adeos_std_vector_table[7]);
+    __adeos_set_trap_gate(8,__adeos_std_vector_table[8]);
+    __adeos_set_trap_gate(9,__adeos_std_vector_table[9]);
+    __adeos_set_trap_gate(10,__adeos_std_vector_table[10]);
+    __adeos_set_trap_gate(11,__adeos_std_vector_table[11]);
+    __adeos_set_trap_gate(12,__adeos_std_vector_table[12]);
+    __adeos_set_trap_gate(13,__adeos_std_vector_table[13]);
+    __adeos_set_irq_gate(14,__adeos_std_vector_table[14]);
+    __adeos_set_trap_gate(15,__adeos_std_vector_table[15]);
+    __adeos_set_trap_gate(16,__adeos_std_vector_table[16]);
+    __adeos_set_trap_gate(17,__adeos_std_vector_table[17]);
+    __adeos_set_trap_gate(18,__adeos_std_vector_table[18]);
+    __adeos_set_trap_gate(19,__adeos_std_vector_table[19]);
+
+#if defined(CONFIG_ADEOS_MODULE) || defined(CONFIG_X86_IO_APIC)
+    adp_pipelined = 0;
+#endif /* CONFIG_ADEOS_MODULE || CONFIG_X86_IO_APIC */
+
+    adeos_critical_exit(flags);
+}
+
+/* adeos_virtualize_irq() -- Attach a handler (and optionally a hw
+   acknowledge routine) to an interrupt for the current domain. */
+
+int adeos_virtualize_irq (unsigned irq,
+			  void (*handler)(unsigned irq),
+			  int (*acknowledge)(unsigned irq),
+			  unsigned modemask)
+{
+    unsigned long flags;
+
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    if (adp_current->irqs[irq].control & IPIPE_SYSTEM_MASK)
+	return -EPERM;
+	
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (handler != NULL)
+	{
+	if ((modemask & IPIPE_EXCLUSIVE_MASK) != 0)
+	    {
+	    if (adp_current->irqs[irq].handler != NULL)
+		return -EBUSY;
+	    }
+
+	if ((modemask & IPIPE_STICKY_MASK) != 0)
+	    modemask |= IPIPE_HANDLE_MASK;
+	}
+    else
+	modemask &= ~(IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK);
+
+    if (acknowledge == NULL)
+	acknowledge = adp_root->irqs[irq].acknowledge;
+
+    adp_current->irqs[irq].handler = handler;
+    adp_current->irqs[irq].acknowledge = acknowledge;
+    adp_current->irqs[irq].control = modemask;
+
+    if (!adeos_virtual_irq_p(irq) && handler != NULL &&
+	(modemask & IPIPE_ENABLE_MASK) != 0 && irq < NR_IRQS)
+	irq_desc[irq].handler->enable(irq);
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return 0;
+}
+
+/* adeos_control_irq() -- Change an interrupt mode. This affects the
+   way a given interrupt is handled by ADEOS for the current
+   domain. setmask is a bitmask telling whether:
+   - the interrupt should be passed to the domain (IPIPE_HANDLE_MASK),
+     and/or
+   - the interrupt should be passed down to the lower priority domain(s)
+     in the pipeline (IPIPE_PASS_MASK).
+   This leads to four possibilities:
+   - PASS only => Ignore the interrupt
+   - HANDLE only => Terminate the interrupt (process but don't pass down)
+   - PASS + HANDLE => Accept the interrupt (process and pass down)
+   - <none> => Discard the interrupt
+   - DYNAMIC is currently an alias of HANDLE since it marks an interrupt
+   which is processed by the current domain but not implicitely passed
+   down to the pipeline, letting the domain's handler choose on a case-
+   by-case basis whether the interrupt propagation should be forced
+   using adeos_propagate_irq().
+   clrmask clears the corresponding bits from the control field before
+   setmask is applied.
+*/
+
+int adeos_control_irq (unsigned irq,
+		       unsigned clrmask,
+		       unsigned setmask)
+{
+    unsigned long flags;
+    irq_desc_t *desc;
+
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    if (adp_current->irqs[irq].control & IPIPE_SYSTEM_MASK)
+	return -EPERM;
+	
+    desc = irq_desc + irq;
+
+    if (adp_current->irqs[irq].handler == NULL)
+	setmask &= ~(IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK);
+
+    if ((setmask & IPIPE_STICKY_MASK) != 0)
+	setmask |= IPIPE_HANDLE_MASK;
+
+    if ((clrmask & (IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK)) != 0)	/* If one goes, both go. */
+	clrmask |= (IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK);
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    adp_current->irqs[irq].control &= ~clrmask;
+    adp_current->irqs[irq].control |= setmask;
+
+    if ((setmask & IPIPE_ENABLE_MASK) != 0)
+	desc->handler->enable(irq);
+    else if ((clrmask & IPIPE_ENABLE_MASK) != 0)
+	desc->handler->disable(irq);
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return 0;
+}
+
+static inline void __adeos_walk_pipeline (struct list_head *pos, int cpuid)
+
+{
+    while (pos != &__adeos_pipeline)
+	{
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+
+	if (test_bit(IPIPE_STALL_FLAG,&_adp->cpudata[cpuid].status))
+	    break; /* Stalled stage -- do not go further. */
+
+	if (_adp->cpudata[cpuid].irq_pending_hi != 0)
+	    {
+	    /* Since the critical IPI might be serviced by the
+	       following actions, the current domain might not be
+	       linked to the pipeline anymore after its handler
+	       returns on SMP boxes, even if the domain remains valid
+	       (see adeos_unregister_domain()), so don't make any
+	       hazardous assumptions here. */
+
+	    if (_adp == adp_cpu_current[cpuid])
+		__adeos_sync_stage();
+	    else
+		{
+		__adeos_switch_to(_adp,cpuid);
+
+		adeos_reload_cpuid(); /* Processor might have changed. */
+
+		if (!test_bit(IPIPE_STALL_FLAG,&adp_cpu_current[cpuid]->cpudata[cpuid].status) &&
+		    adp_cpu_current[cpuid]->cpudata[cpuid].irq_pending_hi != 0)
+		    __adeos_sync_stage();
+		}
+
+	    break;
+	    }
+	else if (_adp == adp_cpu_current[cpuid])
+	    break;
+
+	pos = _adp->p_link.next;
+	}
+}
+
+/* __adeos_handle_irq() -- ADEOS' generic IRQ handler. An optimistic
+   interrupt protection log is maintained here for each
+   domain. Interrupts are off. */
+
+int __adeos_handle_irq (struct pt_regs regs)
+
+{
+    unsigned irq = regs.orig_eax & 0xff;
+    int acked = regs.orig_eax >= 0;
+    struct list_head *head, *pos;
+    adeos_declare_cpuid;
+
+    if (unlikely(test_bit(IPIPE_STICKY_FLAG,&adp_cpu_current[cpuid]->irqs[irq].control)))
+	head = &adp_cpu_current[cpuid]->p_link;
+    else
+	head = __adeos_pipeline.next;
+
+    /* Ack the interrupt. */
+
+    pos = head;
+
+    while (pos != &__adeos_pipeline)
+	{
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+
+	/* For each domain handling the incoming IRQ, mark it as
+           pending in its log. */
+
+	if (test_bit(IPIPE_HANDLE_FLAG,&_adp->irqs[irq].control))
+	    {
+	    /* Domains that handle this IRQ are polled for
+	       acknowledging it by decreasing priority order. The
+	       interrupt must be made pending _first_ in the domain's
+	       status flags before the PIC is unlocked. */
+
+	    _adp->cpudata[cpuid].irq_hits[irq]++;
+	    __adeos_set_irq_bit(_adp,cpuid,irq);
+
+	    if (!acked)
+		acked = _adp->irqs[irq].acknowledge(irq);
+	    }
+
+	/* If the domain does not want the IRQ to be passed down the
+	   interrupt pipe, exit the loop now. */
+
+	if (!test_bit(IPIPE_PASS_FLAG,&_adp->irqs[irq].control))
+	    break;
+
+	pos = _adp->p_link.next;
+	}
+
+    if (likely(irq == __adeos_tick_irq))
+	{
+	__adeos_tick_regs.eflags = regs.eflags;
+	__adeos_tick_regs.eip = regs.eip;
+	__adeos_tick_regs.xcs = regs.xcs;
+	}
+
+    /* Now walk the pipeline, yielding control to the highest priority
+       domain that has pending interrupt(s) or immediately to the
+       current domain if the interrupt has been marked as
+       'sticky'. This search does not go beyond the current domain in
+       the pipeline. To understand this code properly, one must keep
+       in mind that domains having a higher priority than the current
+       one are sleeping on the adeos_suspend_domain() service. In
+       addition, domains having a lower priority have been preempted
+       by an interrupt dispatched to a more prioritary domain. Once
+       the first and most prioritary stage has been selected here, the
+       subsequent stages will be activated in turn when each visited
+       domain calls adeos_suspend_domain() to wake up its neighbour
+       down the pipeline. */
+
+    __adeos_walk_pipeline(head,cpuid);
+
+    adeos_reload_cpuid();
+    
+    return (adp_cpu_current[cpuid] == adp_root &&
+	    !test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status));
+}
+
+void __adeos_init_domain (adomain_t *adp, adattr_t *attr)
+
+{
+    int estacksz = attr->estacksz > 0 ? attr->estacksz : 8192, _cpuid;
+    adeos_declare_cpuid;
+
+    for (_cpuid = 0; _cpuid < smp_num_cpus; _cpuid++)
+	{
+	int **psp = &adp->esp[_cpuid];
+
+	adp->estackbase[_cpuid] = (int *)kmalloc(estacksz,GFP_KERNEL);
+    
+	if (adp->estackbase[_cpuid] == NULL)
+	    panic("ADEOS: no memory for domain stack on CPU #%d",_cpuid);
+
+	adp->esp[_cpuid] = adp->estackbase[_cpuid];
+	**psp = 0;
+	*psp = (int *)(((unsigned long)*psp + estacksz - 0x10) & ~0xf);
+	*--(*psp) = (_cpuid == cpuid);
+	*--(*psp) = 0;
+	*--(*psp) = (int)attr->entry;
+	}
+}
+
+void __adeos_cleanup_domain (adomain_t *adp)
+
+{
+    int _cpuid;
+
+    for (_cpuid = 0; _cpuid < smp_num_cpus; _cpuid++)
+	{
+	adp->cpudata[_cpuid].irq_pending_hi = 0;
+	clear_bit(IPIPE_XPEND_FLAG,&adp->cpudata[_cpuid].status);
+	kfree(adp->estackbase[_cpuid]);
+	}
+}
+
+int adeos_get_sysinfo (adsysinfo_t *info)
+
+{
+#ifdef CONFIG_SMP
+    info->ncpus = smp_num_cpus;
+#else /* !CONFIG_SMP */
+    info->ncpus = 1;
+#endif /* CONFIG_SMP */
+
+    if (cpu_has_tsc)
+	info->cpufreq = 1000LL * cpu_khz;
+    else
+	info->cpufreq = CLOCK_TICK_RATE;
+
+    info->archdep.tmirq = __adeos_tick_irq;
+
+    return 0;
+}
+
+int adeos_tune_timer (unsigned long ns, int flags)
+
+{
+    unsigned ghz, latch;
+    unsigned long x;
+
+    if (flags & ADEOS_RESET_TIMER)
+	latch = LATCH;
+    else
+	{
+	if (ns < 122071 || ns > (1000 / HZ) * 1000000) /* HZ max, 8khz min */
+	    return -EINVAL;
+
+	ghz = 1000000000 / ns;
+	latch = (CLOCK_TICK_RATE + ghz/2) / ghz;
+	}
+
+    x = adeos_critical_enter(NULL); /* Sync with all CPUs */
+
+    /* Shamelessly lifted from init_IRQ() in i8259.c */
+    outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+    outb_p(latch & 0xff,0x40);	/* LSB */
+    outb(latch >> 8,0x40);	/* MSB */
+
+    adeos_critical_exit(x);
+
+    return 0;
+}
+
+/* adeos_trigger_irq() -- Push the interrupt to the pipeline entry
+   just like if it has been actually received from a hw source. This
+   both works for real and virtual interrupts. This also means that
+   the current domain might be immediately preempted by a more
+   prioritary domain who happens to handle this interrupt. */
+
+int adeos_trigger_irq (unsigned irq)
+
+{
+    struct pt_regs regs;
+
+    if (irq >= IPIPE_NR_IRQS ||
+	(adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)))
+	return -EINVAL;
+
+    regs.orig_eax = irq; /* Won't be acked */
+    regs.xcs = __KERNEL_CS;
+    adeos_hw_local_irq_flags(regs.eflags);
+
+    __adeos_handle_irq(regs);
+
+    return 1;
+}
+
+/* adeos_trigger_ipi() -- Send the ADEOS service IPI to other
+   processors. */
+
+int adeos_trigger_ipi (int _cpuid)
+
+{
+#ifdef CONFIG_SMP
+    adeos_declare_cpuid;
+
+    if (unlikely(_cpuid == cpuid)) /* Self-posting the service interrupt? */
+	adeos_trigger_irq(ADEOS_SERVICE_IPI);
+    else
+	{
+	unsigned long flags;
+
+	adeos_hw_local_irq_save(flags);
+
+	if (cpuid == ADEOS_OTHER_CPUS)
+	    {
+	    if (smp_num_cpus > 1)
+		/* Send the service IPI to all processors but the current one. */
+		__adeos_send_IPI_allbutself(ADEOS_SERVICE_VECTOR);
+	    }
+	else if (_cpuid >= 0 && _cpuid < smp_num_cpus)
+	    __adeos_send_IPI_other(_cpuid,ADEOS_SERVICE_VECTOR);
+
+	adeos_hw_local_irq_restore(flags);
+	}
+
+    return cpuid != ADEOS_OTHER_CPUS ? 1 : smp_num_cpus - 1;
+#else  /* !CONFIG_SMP */
+    return 0;
+#endif /* CONFIG_SMP */
+}
diff -Nurp linux-2.4.22-clean/drivers/input/mousedev.c linux-2.4.22-adeos-ltt/drivers/input/mousedev.c
--- linux-2.4.22-clean/drivers/input/mousedev.c	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.22-adeos-ltt/drivers/input/mousedev.c	2003-11-21 23:21:08.000000000 -0800
@@ -82,6 +82,10 @@ static struct mousedev mousedev_mix;
 static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
 static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
 
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+extern int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down);
+#endif
+
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL };
@@ -137,6 +141,11 @@ static void mousedev_event(struct input_
 						case BTN_MIDDLE: index = 2; break;	
 						default: return;
 					}
+
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+				        index = mac_hid_mouse_emulate_buttons(2, index, 0);
+#endif
+
 					switch (value) {
 						case 0: clear_bit(index, &list->buttons); break;
 						case 1: set_bit(index, &list->buttons); break;
diff -Nurp linux-2.4.22-clean/drivers/Makefile linux-2.4.22-adeos-ltt/drivers/Makefile
--- linux-2.4.22-clean/drivers/Makefile	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/drivers/Makefile	2003-11-21 23:25:36.000000000 -0800
@@ -8,7 +8,7 @@
 
 mod-subdirs :=	dio hil mtd sbus video macintosh usb input telephony ide \
 		message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
-		fc4 net/hamradio i2c acpi bluetooth
+		fc4 net/hamradio i2c acpi bluetooth adeos
 
 subdir-y :=	parport char block net sound misc media cdrom hotplug
 subdir-m :=	$(subdir-y)
@@ -40,6 +40,7 @@ subdir-$(CONFIG_PNP)		+= pnp
 subdir-$(CONFIG_ISDN_BOOL)	+= isdn
 subdir-$(CONFIG_ATM)		+= atm
 subdir-$(CONFIG_FC4)		+= fc4
+subdir-$(CONFIG_TRACE)		+= trace
 
 # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set  -- ch
 subdir-$(CONFIG_HAMRADIO)	+= net/hamradio
@@ -48,4 +49,6 @@ subdir-$(CONFIG_ACPI_BOOT)	+= acpi
 
 subdir-$(CONFIG_BLUEZ)		+= bluetooth
 
+subdir-$(CONFIG_ADEOS)		+= adeos
+
 include $(TOPDIR)/Rules.make
diff -Nurp linux-2.4.22-clean/drivers/s390/s390io.c linux-2.4.22-adeos-ltt/drivers/s390/s390io.c
--- linux-2.4.22-clean/drivers/s390/s390io.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-adeos-ltt/drivers/s390/s390io.c	2003-11-21 23:21:08.000000000 -0800
@@ -60,6 +60,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/ctype.h>
+#include <linux/trace.h>
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #endif
@@ -2389,9 +2390,11 @@ do_IRQ (struct pt_regs regs)
 			}
 
 			irq_enter (cpu, irq);
+			TRACE_IRQ_ENTRY(irq, !(((regs).psw.mask&PSW_PROBLEM_STATE) != 0));
 			s390irq_spin_lock (irq);
 			s390_process_IRQ (irq);
 			s390irq_spin_unlock (irq);
+			TRACE_IRQ_EXIT();
 			irq_exit (cpu, irq);
 		}
 
diff -Nurp linux-2.4.22-clean/drivers/s390/s390mach.c linux-2.4.22-adeos-ltt/drivers/s390/s390mach.c
--- linux-2.4.22-clean/drivers/s390/s390mach.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-adeos-ltt/drivers/s390/s390mach.c	2003-11-21 23:21:08.000000000 -0800
@@ -6,12 +6,14 @@
  *  S390 version
  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ *  Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
  */
 
 #include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/trace.h>
 #ifdef CONFIG_SMP
 #include <linux/smp.h>
 #endif
@@ -162,6 +164,8 @@ void s390_do_machine_check( void )
 {
 	int      crw_count;
 	mcic_t   mcic;
+        trapid_t ltt_interruption_code;
+        uint32_t ltt_old_psw;
 
 #ifdef S390_MACHCHK_DEBUG
 	printk( KERN_INFO "s390_do_machine_check : starting ...\n");
@@ -170,6 +174,14 @@ void s390_do_machine_check( void )
 	memcpy( &mcic,
 	        &S390_lowcore.mcck_interruption_code,
 	        sizeof(__u64));
+	memcpy( &ltt_interruption_code,
+	        &S390_lowcore.mcck_interruption_code,
+	        sizeof(__u64));
+	memcpy( &ltt_old_psw,
+	        &S390_lowcore.mcck_old_psw,
+	        sizeof(uint32_t));
+        ltt_old_psw &=  PSW_ADDR_MASK;
+        TRACE_TRAP_ENTRY(ltt_interruption_code,ltt_old_psw);
  		
 	if (mcic.mcc.mcd.sd) /* system damage */
 		s390_handle_damage("received system damage machine check\n");
diff -Nurp linux-2.4.22-clean/drivers/trace/Makefile linux-2.4.22-adeos-ltt/drivers/trace/Makefile
--- linux-2.4.22-clean/drivers/trace/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/trace/Makefile	2003-11-21 23:21:08.000000000 -0800
@@ -0,0 +1,17 @@
+#
+# Makefile for the kernel tracing drivers.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now inherited from the
+# parent makes..
+#
+
+O_TARGET := trace_driver.o
+
+# Is it loaded as a module or as part of the kernel
+obj-$(CONFIG_TRACE) = tracer.o
+
+include $(TOPDIR)/Rules.make
diff -Nurp linux-2.4.22-clean/drivers/trace/tracer.c linux-2.4.22-adeos-ltt/drivers/trace/tracer.c
--- linux-2.4.22-clean/drivers/trace/tracer.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/trace/tracer.c	2003-11-21 23:21:08.000000000 -0800
@@ -0,0 +1,1421 @@
+/*****************************************************************
+ * File : tracer.c
+ * Description :
+ *    Contains the code for the kernel tracing driver (tracer
+ *    for short).
+ * Author :
+ *    Karim Yaghmour
+ * Date :
+ *    03/12/01, Added user event support.
+ *    05/01/01, Modified PPC bit manipulation functions for
+ *              x86 compatibility.  (andy_lowe@mvista.com)
+ *    15/11/00, Finally fixed memory allocation and remapping
+ *              method. Now using BTTV-driver-inspired code.
+ *    13/03/00, Modified tracer so that the daemon mmaps the 
+ *              tracer's buffers in it's address space rather
+ *              than use "read".
+ *    26/01/00, Added support for standardized buffer sizes and
+ *              extensibility of events.
+ *    01/10/99, Modified tracer in order to used double-buffering.
+ *    28/09/99, Adding tracer configuration support.
+ *    09/09/99, Chaging the format of an event record in order to
+ *              reduce the size of the traces.
+ *    04/03/99, Initial typing.
+ * Note :
+ *    The sizes of the variables used to store the details of an
+ *    event are planned for a system who gets at least one clock
+ *    tick every 10milli-seconds. There has to be at least one
+ *    event every 2^32-1 microseconds, otherwise the size of the
+ *    variable holding the time doesn't work anymore.
+ *****************************************************************/
+
+/* Module and initialization stuff */
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* Necessary includes */
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/trace.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include <asm/io.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+
+/* Local defintions */
+#include "tracer.h"
+
+/* Module information */
+MODULE_AUTHOR     ("Karim Yaghmour (karym@opersys.com)");
+MODULE_DESCRIPTION("Linux Trace Toolkit (LTT) kernel tracing driver");
+MODULE_LICENSE    ("GPL");
+
+/* Local variables */
+/*  Driver */
+static int                    sMajorNumber;          /* Major number of the tracer */
+static int                    sOpenCount;            /* Number of times device is open */
+/*  Locking */
+static int                    sTracLock;             /* Tracer lock used to lock primary buffer */
+static spinlock_t             sSpinLock;             /* Spinlock in order to lock kernel */
+/*  Daemon */
+static int                    sSignalSent;           /* A signal has been sent to the daemon */
+static struct task_struct*    sDaemonTaskStruct;     /* Task structure of the tracer daemon */
+/*  Tracer configuration */
+static int                    sTracerStarted;        /* Is the tracer started */
+static trace_event_mask       sTracedEvents;         /* Bit-field of events being traced */
+static trace_event_mask       sLogEventDetailsMask;  /* Log the details of the events mask */
+static int                    sLogCPUID;             /* Log the CPUID associated with each event */
+static int                    sUseSyscallEIPBounds;  /* Use adress bounds to fetch the EIP where call is made */
+static int                    sLowerEIPBoundSet;     /* The lower bound EIP has been set */
+static int                    sUpperEIPBoundSet;     /* The upper bound EIP has been set */
+static void*                  sLowerEIPBound;        /* The lower bound EIP */
+static void*                  sUpperEIPBound;        /* The upper bound EIP */
+static int                    sTracingPID;           /* Tracing only the events for one pid */
+static int                    sTracingPGRP;          /* Tracing only the events for one process group */
+static int                    sTracingGID;           /* Tracing only the events for one gid */
+static int                    sTracingUID;           /* Tracing only the events for one uid */
+static pid_t                  sTracedPID;            /* PID being traced */
+static pid_t                  sTracedPGRP;           /* Process group being traced */
+static gid_t                  sTracedGID;            /* GID being traced */
+static uid_t                  sTracedUID;            /* UID being traced */
+static int                    sSyscallEIPDepthSet;   /* The call depth at which to fetch EIP has been set */
+static int                    sSyscallEIPDepth;      /* The call depth at which to fetch the EIP */
+/*  Event data buffers */
+static int                    sBufReadComplete;      /* Number of buffers completely filled */
+static int                    sSizeReadIncomplete;   /* Quantity of data read from incomplete buffers */
+static int                    sEventsLost;           /* Number of events lost because of lack of buffer space */
+static uint32_t               sBufSize;              /* Buffer sizes */
+static uint32_t               sAllocSize;            /* Size of buffers allocated */
+static uint32_t               sBufferID;             /* Unique buffer ID */
+static char*                  sTracBuf = NULL;       /* Trace buffer */
+static char*                  sWritBuf = NULL;       /* Buffer used for writting */
+static char*                  sReadBuf = NULL;       /* Buffer used for reading */
+static char*                  sWritBufEnd;           /* End of write buffer */
+static char*                  sReadBufEnd;           /* End of read buffer */
+static char*                  sWritPos;              /* Current position for writting */
+static char*                  sReadLimit;            /* Limit at which read should stop */
+static char*                  sWritLimit;            /* Limit at which write should stop */
+/*  Time */
+static struct timeval         sBufferStartTime;      /* The time at which the buffer was started */
+/*  Large data components allocated at load time */
+static char*                  sUserEventData = NULL; /* The data associated with a user event */
+
+
+/* The size of the structures used to describe the events */
+static int sEventStructSize[TRACE_EV_MAX + 1] =
+{
+  sizeof(trace_start)             /* TRACE_START */,
+  sizeof(trace_syscall_entry)     /* TRACE_SYSCALL_ENTRY */,
+  0                               /* TRACE_SYSCALL_EXIT */,
+  sizeof(trace_trap_entry)        /* TRACE_TRAP_ENTRY */,
+  0                               /* TRACE_TRAP_EXIT */,
+  sizeof(trace_irq_entry)         /* TRACE_IRQ_ENTRY */,
+  0                               /* TRACE_IRQ_EXIT */,
+  sizeof(trace_schedchange)       /* TRACE_SCHEDCHANGE */,
+  0                               /* TRACE_KERNEL_TIMER */,
+  sizeof(trace_soft_irq)          /* TRACE_SOFT_IRQ */,
+  sizeof(trace_process)           /* TRACE_PROCESS */,
+  sizeof(trace_file_system)       /* TRACE_FILE_SYSTEM */,
+  sizeof(trace_timer)             /* TRACE_TIMER */,
+  sizeof(trace_memory)            /* TRACE_MEMORY */,
+  sizeof(trace_socket)            /* TRACE_SOCKET */,
+  sizeof(trace_ipc)               /* TRACE_IPC */,
+  sizeof(trace_network)           /* TRACE_NETWORK */,
+  sizeof(trace_buffer_start)      /* TRACE_BUFFER_START */,
+  0                               /* TRACE_BUFFER_END */,
+  sizeof(trace_new_event)         /* TRACE_NEW_EVENT */,
+  sizeof(trace_custom)            /* TRACE_CUSTOM */,
+  sizeof(trace_change_mask)       /* TRACE_CHANGE_MASK */
+};
+
+/* The file operations available for the tracer */
+static struct file_operations sTracerFileOps =
+{
+  owner:            THIS_MODULE,
+  ioctl:            tracer_ioctl,
+  mmap:             tracer_mmap,
+  open:             tracer_open,
+  release:          tracer_release,
+  fsync:            tracer_fsync,
+};
+
+/************************************************************************************************************/
+/************************************** Code inspired from BTTV driver **************************************/
+/************************************************************************************************************/
+#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE /* This inspired by rtai/shmem */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+        unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+  
+	if (!pgd_none(*pgd)) {
+                pmd = pmd_offset(pgd, adr);
+                if (!pmd_none(*pmd)) {
+                        ptep = pte_offset(pmd, adr);
+                        pte = *ptep;
+                        if(pte_present(pte)) {
+				ret = (unsigned long) page_address(pte_page(pte));
+                                ret |= (adr & (PAGE_SIZE - 1));
+			}
+                }
+        }
+	return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+        unsigned long va, kva, ret;
+
+        va = VMALLOC_VMADDR(adr);
+        kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = __pa(kva);
+        return ret;
+}
+
+static void * rvmalloc(signed long size)
+{
+	void * mem;
+	unsigned long adr, page;
+
+	mem=vmalloc_32(size);
+	if (mem) 
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	        adr=(unsigned long) mem;
+		while (size > 0) 
+                {
+	                page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, signed long size)
+{
+        unsigned long adr, page;
+        
+	if (mem) 
+	{
+	        adr=(unsigned long) mem;
+		while (size > 0) 
+                {
+	                page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+static int tracer_mmap_region(const char *adr, const char *start_pos, unsigned long size)
+{
+        unsigned long start=(unsigned long) adr;
+	unsigned long page,pos;
+
+	pos=(unsigned long) start_pos;
+	while (size > 0) 
+	{
+	        page = kvirt_to_pa(pos);
+		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+		        return -EAGAIN;
+		start+=PAGE_SIZE;
+		pos+=PAGE_SIZE;
+		size-=PAGE_SIZE;    
+	}
+	return 0;
+}
+/************************************************************************************************************/
+/************************************************************************************************************/
+/************************************************************************************************************/
+
+/**************************************************************
+ * Macro : tracer_write_to_buffer()
+ * Description :
+ *     Writes data to the destination buffer and updates the
+ *     begining the buffer write position.
+ **************************************************************/
+#define tracer_write_to_buffer(DEST, SRC, SIZE) \
+do\
+{\
+   memcpy(DEST, SRC, SIZE);\
+   DEST += SIZE;\
+} while(0);
+
+/**************************************************************
+ * Function : trace()
+ * Description : Tracing function per se.
+ * Parameters :
+ *     pmEventID, ID of event as defined in linux/trace.h
+ *     pmEventStruct, struct describing the event
+ * Return values : 
+ *     0, if everything went OK (event got registered)
+ *     -ENODEV, no tracing daemon opened the driver.
+ *     -ENOMEM, no more memory to store events.
+ *     -EBUSY, tracer not started yet.
+ * Note :
+ *     The kernel has to be locked here because trace() could
+ *     be called from an interrupt handling routine and from 
+ *     a process service routine.
+ **************************************************************/
+int trace(uint8_t   pmEventID,
+	  void*     pmEventStruct)
+{
+  int                 lVarDataLen = 0;          /* Length of variable length data to be copied, if any */
+  void*               lVarDataBeg = NULL;       /* Begining of variable length data to be copied */
+  int                 lSendSignal = FALSE;      /* Should the daemon be summoned */
+  uint8_t             lCPUID;                   /* CPUID of currently runing process */
+  uint16_t            lDataSize;                /* Size of tracing data */
+  struct siginfo      lSigInfo;                 /* Signal information */
+  struct timeval      lTime;                    /* Event time */
+  unsigned long int   lFlags;                   /* CPU flags for lock */
+  trace_time_delta    lTimeDelta;               /* The time elapsed between now and the last event */
+  struct task_struct* pIncomingProcess = NULL;  /* Pointer to incoming process */
+
+  /* Is there a tracing daemon */
+  if(sDaemonTaskStruct == NULL)
+    return -ENODEV;
+
+  /* Is this the exit of a process? */
+  if((pmEventID == TRACE_EV_PROCESS) &&
+     (pmEventStruct != NULL) &&
+     ((((trace_process*) pmEventStruct)->event_sub_id) == TRACE_EV_PROCESS_EXIT))
+    trace_destroy_owners_events(current->pid);
+
+  /* Do we trace the event */
+  if((sTracerStarted == TRUE) || (pmEventID == TRACE_EV_START) || (pmEventID == TRACE_EV_BUFFER_START))
+    goto TraceEvent;
+
+  /* We can't continue */
+  return -EBUSY;
+
+TraceEvent:
+
+  /* Are we monitoring this event */
+  if(!ltt_test_bit(pmEventID, &sTracedEvents))
+    return 0;
+
+  /* Always let the start event pass, whatever the IDs */
+  if((pmEventID != TRACE_EV_START) && (pmEventID != TRACE_EV_BUFFER_START))
+    {
+    /* Is this a scheduling change */
+    if(pmEventID == TRACE_EV_SCHEDCHANGE)
+      {
+      /* Get pointer to incoming process */
+      pIncomingProcess = (struct task_struct*) (((trace_schedchange*) pmEventStruct)->in);
+
+      /* Set PID information in schedchange event */
+      (((trace_schedchange*) pmEventStruct)->in) = pIncomingProcess->pid;
+      }
+
+    /* Are we monitoring a particular process */
+    if((sTracingPID == TRUE) && (current->pid != sTracedPID))
+      {
+      /* Record this event if it is the scheduling change bringing in the traced PID */
+      if(pIncomingProcess == NULL)
+	return 0;
+      else if (pIncomingProcess->pid != sTracedPID)
+	return 0;
+      }
+
+    /* Are we monitoring a particular process group */
+    if((sTracingPGRP == TRUE) && (current->pgrp != sTracedPGRP))
+      {
+      /* Record this event if it is the scheduling change bringing in a process of the traced PGRP */
+      if(pIncomingProcess == NULL)
+	return 0;
+      else if (pIncomingProcess->pgrp != sTracedPGRP)
+	return 0;
+      }
+
+    /* Are we monitoring the processes of a given group of users */
+    if((sTracingGID == TRUE) && (current->egid != sTracedGID))
+      {
+      /* Record this event if it is the scheduling change bringing in a process of the traced GID */
+      if(pIncomingProcess == NULL)
+	return 0;
+      else if (pIncomingProcess->egid != sTracedGID)
+	return 0;
+      }
+
+    /* Are we monitoring the processes of a given user */
+    if((sTracingUID == TRUE) && (current->euid != sTracedUID))
+      {
+      /* Record this event if it is the scheduling change bringing in a process of the traced UID */
+      if(pIncomingProcess == NULL)
+	return 0;
+      else if (pIncomingProcess->euid != sTracedUID)
+	return 0;
+      }
+    }
+
+  /* Compute size of tracing data */
+  lDataSize = sizeof(pmEventID) + sizeof(lTimeDelta) + sizeof(lDataSize);
+
+  /* Do we log the event details */
+  if(ltt_test_bit(pmEventID, &sLogEventDetailsMask))
+    {
+    /* Update the size of the data entry */
+    lDataSize += sEventStructSize[pmEventID];
+
+    /* Some events have variable length */
+    switch(pmEventID)
+      {
+      /* Is there a file name in this */
+      case TRACE_EV_FILE_SYSTEM:
+	if((((trace_file_system*) pmEventStruct)->event_sub_id == TRACE_EV_FILE_SYSTEM_EXEC)
+	|| (((trace_file_system*) pmEventStruct)->event_sub_id == TRACE_EV_FILE_SYSTEM_OPEN))
+	  {
+	  /* Remember the string's begining and update size variables */
+	  lVarDataBeg = ((trace_file_system*) pmEventStruct)->file_name;
+	  lVarDataLen = ((trace_file_system*) pmEventStruct)->event_data2 + 1;
+	  lDataSize += (uint16_t) lVarDataLen;
+	  }
+	break;
+
+      /* Logging of a custom event */
+      case TRACE_EV_CUSTOM:
+	lVarDataBeg = ((trace_custom*) pmEventStruct)->data;
+	lVarDataLen = ((trace_custom*) pmEventStruct)->data_size;
+	lDataSize += (uint16_t) lVarDataLen;
+	break;
+      }
+    }
+
+  /* Do we record the CPUID */
+  if((sLogCPUID == TRUE) && (pmEventID != TRACE_EV_START) && (pmEventID != TRACE_EV_BUFFER_START))
+    {
+    /* Remember the CPUID */
+    lCPUID = smp_processor_id();
+
+    /* Update the size of the data entry */
+    lDataSize += sizeof(lCPUID);
+    }
+
+  /* Lock the kernel */
+  spin_lock_irqsave(&sSpinLock, lFlags);
+
+  /* The following time calculations have to be done within the spinlock because
+     otherwise the event order could be inverted. */
+
+  /* Get the time of the event */
+  do_gettimeofday(&lTime);
+
+  /* Compute the time delta between this event and the time at which this buffer was started */
+  lTimeDelta = (lTime.tv_sec - sBufferStartTime.tv_sec) * 1000000
+             + (lTime.tv_usec - sBufferStartTime.tv_usec);
+
+  /* Is there enough space left in the write buffer */
+  if(sWritPos + lDataSize > sWritLimit)
+    {
+    /* Have we already switched buffers and informed the daemon of it */
+    if(sSignalSent == TRUE)
+      {
+      /* We've lost another event */
+      sEventsLost++;
+
+      /* Bye, bye, now */
+      spin_unlock_irqrestore(&sSpinLock, lFlags);
+      return -ENOMEM;
+      }
+
+    /* We need to inform the daemon */
+    lSendSignal = TRUE;
+
+    /* Switch buffers */
+    tracer_switch_buffers(lTime);
+
+    /* Recompute the time delta since sBufferStartTime has changed because of the buffer change */
+    lTimeDelta = (lTime.tv_sec - sBufferStartTime.tv_sec) * 1000000
+               + (lTime.tv_usec - sBufferStartTime.tv_usec);
+    }
+
+  /* Write the CPUID to the tracing buffer, if required */
+  if((sLogCPUID == TRUE)  && (pmEventID != TRACE_EV_START) && (pmEventID != TRACE_EV_BUFFER_START))
+    tracer_write_to_buffer(sWritPos,
+			   &lCPUID,
+			   sizeof(lCPUID));
+
+  /* Write event type to tracing buffer */
+  tracer_write_to_buffer(sWritPos,
+			 &pmEventID,
+			 sizeof(pmEventID));
+
+  /* Write event time delta to tracing buffer */
+  tracer_write_to_buffer(sWritPos,
+			 &lTimeDelta,
+			 sizeof(lTimeDelta));
+
+  /* Do we log event details */
+  if(ltt_test_bit(pmEventID, &sLogEventDetailsMask))
+    {
+    /* Write event structure */
+    tracer_write_to_buffer(sWritPos,
+			   pmEventStruct,
+			   sEventStructSize[pmEventID]);
+
+    /* Write string if any */
+    if(lVarDataLen)
+      tracer_write_to_buffer(sWritPos,
+			     lVarDataBeg,
+			     lVarDataLen);
+    }
+
+  /* Write the length of the event description */
+  tracer_write_to_buffer(sWritPos,
+			 &lDataSize,
+			 sizeof(lDataSize));
+
+  /* Should the tracing daemon be notified  */
+  if(lSendSignal == TRUE)
+    {
+    /* Remember that a signal has been sent */
+    sSignalSent = TRUE;
+
+    /* Unlock the kernel */
+    spin_unlock_irqrestore(&sSpinLock, lFlags);
+
+    /* Setup signal information */
+    lSigInfo.si_signo = SIGIO;
+    lSigInfo.si_errno = 0;
+    lSigInfo.si_code  = SI_KERNEL;
+
+    /* DEBUG */
+#if 0
+    printk("<1> Sending SIGIO to %d \n", sDaemonTaskStruct->pid);
+#endif
+
+    /* Signal the tracing daemon */
+    send_sig_info(SIGIO, &lSigInfo, sDaemonTaskStruct);
+    }
+  else
+    /* Unlock the kernel */
+    spin_unlock_irqrestore(&sSpinLock, lFlags);
+  
+  /* Indicate to the caller that everything is OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_switch_buffers()
+ * Description :
+ *     Put the current write buffer to be read and reset put
+ *     the old read buffer to be written to. Set the tracer
+ *     variables in consequence.
+ * Parameters :
+ *     pmTime, current time
+ * Return values :
+ *     NONE
+ * Note :
+ *     This should be called from within a spin_lock.
+ *************************************************************/
+void tracer_switch_buffers(struct timeval pmTime)
+{
+  char*               lTempBuf;              /* Temporary buffer pointer */
+  char*               lTempBufEnd;           /* Temporary buffer end pointer */
+  char*               lInitWritPos;          /* Initial write position */
+  uint8_t             lEventID;              /* Event ID of last event */
+  uint8_t             lCPUID;                /* CPUID of currently runing process */
+  uint16_t            lDataSize;             /* Size of tracing data */
+  uint32_t            lSizeLost;             /* Size delta between last event and end of buffer */
+  trace_time_delta    lTimeDelta;            /* The time elapsed between now and the last event */
+  trace_buffer_start  lStartBufferEvent;     /* Start of the new buffer event */
+
+  /* Remember initial write position */
+  lInitWritPos = sWritPos;
+
+  /* Write the end event at the write of the buffer */
+
+  /* Write the CPUID to the tracing buffer, if required */
+  if(sLogCPUID == TRUE)
+    {
+    lCPUID = smp_processor_id();
+    tracer_write_to_buffer(sWritPos,
+			   &lCPUID,
+			   sizeof(lCPUID));
+    }
+
+  /* Write event type to tracing buffer */
+  lEventID = TRACE_EV_BUFFER_END;
+  tracer_write_to_buffer(sWritPos,
+			 &lEventID,
+			 sizeof(lEventID));
+
+  /* Write event time delta to tracing buffer */
+  lTimeDelta = 0;
+  tracer_write_to_buffer(sWritPos,
+			 &lTimeDelta,
+			 sizeof(lTimeDelta));
+
+  /* Get size lost */
+  lSizeLost = sWritBufEnd - lInitWritPos;
+
+  /* Write size lost at the end of the buffer */
+  *((uint32_t*) (sWritBufEnd - sizeof(lSizeLost))) = lSizeLost;
+
+  /* Switch buffers */
+  lTempBuf = sReadBuf;
+  sReadBuf = sWritBuf;
+  sWritBuf = lTempBuf;
+
+  /* Set buffer ends */
+  lTempBufEnd = sReadBufEnd;
+  sReadBufEnd = sWritBufEnd;
+  sWritBufEnd = lTempBufEnd;
+
+  /* Set read limit */
+  sReadLimit = sReadBufEnd;
+
+  /* Set write limit */
+  sWritLimit = sWritBufEnd - TRACER_LAST_EVENT_SIZE;
+
+  /* Set write position */
+  sWritPos = sWritBuf;
+
+  /* Increment buffer ID */
+  sBufferID++;
+
+  /* Set the time of begining of this buffer */
+  sBufferStartTime = pmTime;
+
+  /* Write the start of buffer event */
+  lStartBufferEvent.ID   = sBufferID;
+  lStartBufferEvent.Time = pmTime;
+
+  /* Write event type to tracing buffer */
+  lEventID = TRACE_EV_BUFFER_START;
+  tracer_write_to_buffer(sWritPos,
+			 &lEventID,
+			 sizeof(lEventID));
+
+  /* Write event time delta to tracing buffer */
+  lTimeDelta = 0;
+  tracer_write_to_buffer(sWritPos,
+			 &lTimeDelta,
+			 sizeof(lTimeDelta));
+
+  /* Write event structure */
+  tracer_write_to_buffer(sWritPos,
+			 &lStartBufferEvent,
+			 sizeof(lStartBufferEvent));
+
+  /* Compute the data size */
+  lDataSize = sizeof(lEventID)
+            + sizeof(lTimeDelta)
+            + sizeof(lStartBufferEvent)
+            + sizeof(lDataSize);
+
+  /* Write the length of the event description */
+  tracer_write_to_buffer(sWritPos,
+			 &lDataSize,
+			 sizeof(lDataSize));
+}
+
+/*************************************************************
+ * Function : tracer_ioctl()
+ * Description : "Ioctl" file op
+ * Parameters :
+ *     pmInode, the inode associated with the device
+ *     pmFile, file structure given to the acting process
+ *     pmCmd, command given by the caller
+ *     pmArg, arguments to the command
+ * Return values :
+ *     >0, In case the caller requested the number of events
+ *         lost.
+ *     0, Everything went OK
+ *     -ENOSYS, no such command
+ *     -EINVAL, tracer not properly configured
+ *     -EBUSY, tracer can't be reconfigured while in operation
+ *     -ENOMEM, no more memory
+ *     -EFAULT, unable to access user space memory
+ * Note :
+ *     In the future, this function should check to make sure
+ *     that it's the server that make thes ioctl.
+ *************************************************************/
+int tracer_ioctl(struct inode* pmInode,
+		 struct file*  pmFile,
+		 unsigned int  pmCmd,
+		 unsigned long pmArg)
+{
+  int                    lRetValue;             /* Function return value */
+  int                    lDevMinor;             /* Device minor number */
+  int                    lNewUserEventID;       /* ID of newly created user event */
+  trace_start            lStartEvent;           /* Event marking the begining of the trace */
+  unsigned long int      lFlags;                /* CPU flags for lock */
+  trace_custom           lUserEvent;            /* The user event to be logged */
+  trace_change_mask      lTraceMask;            /* Event mask */
+  trace_new_event        lNewUserEvent;         /* The event to be created for the user */
+  trace_buffer_start     lStartBufferEvent;     /* Start of the new buffer event */
+
+#if 0
+  printk("Tracer: Command %d \n", pmCmd);
+#endif
+
+  /* Get device's minor number */
+  lDevMinor = MINOR(pmInode->i_rdev) & 0xf;
+
+  /* If the tracer is started, the daemon can't modify the configuration */
+  if((lDevMinor == 0)
+   && (sTracerStarted == TRUE) && (pmCmd != TRACER_STOP) && (pmCmd != TRACER_DATA_COMITTED))
+    return -EBUSY;
+
+  /* Only some operation are permitted to user processes trying to log events */
+  if((lDevMinor == 1)
+     && (pmCmd != TRACER_CREATE_USER_EVENT)
+     && (pmCmd != TRACER_DESTROY_USER_EVENT)
+     && (pmCmd != TRACER_TRACE_USER_EVENT)
+     && (pmCmd != TRACER_SET_EVENT_MASK)
+     && (pmCmd != TRACER_GET_EVENT_MASK))
+    return -ENOSYS;
+
+  /* Depending on the command executed */
+  switch(pmCmd)
+    {
+    /* Start the tracer */
+    case TRACER_START :
+      /* Check if the device has been properly set up */
+      if(((sUseSyscallEIPBounds == TRUE)
+        &&(sSyscallEIPDepthSet  == TRUE))
+       ||((sUseSyscallEIPBounds == TRUE)
+        &&((sLowerEIPBoundSet != TRUE)
+         ||(sUpperEIPBoundSet != TRUE)))
+       ||((sTracingPID  == TRUE)
+        &&(sTracingPGRP == TRUE)))
+	return -EINVAL;
+
+      /* Set the kernel-side trace configuration */
+      if(trace_set_config(trace,
+			  sSyscallEIPDepthSet,
+			  sUseSyscallEIPBounds,
+			  sSyscallEIPDepth,
+			  sLowerEIPBound,
+			  sUpperEIPBound) < 0)
+	return -EINVAL;
+
+      /* Always log the start event and the buffer start event */
+      ltt_set_bit(TRACE_EV_BUFFER_START, &sTracedEvents);
+      ltt_set_bit(TRACE_EV_BUFFER_START, &sLogEventDetailsMask);
+      ltt_set_bit(TRACE_EV_START, &sTracedEvents);
+      ltt_set_bit(TRACE_EV_START, &sLogEventDetailsMask);
+      ltt_set_bit(TRACE_EV_CHANGE_MASK, &sTracedEvents);
+      ltt_set_bit(TRACE_EV_CHANGE_MASK, &sLogEventDetailsMask);
+
+      /* Get the time of start */
+      do_gettimeofday(&sBufferStartTime);
+
+      /* Set the event description */
+      lStartBufferEvent.ID   = sBufferID;
+      lStartBufferEvent.Time = sBufferStartTime;
+
+      /* Set the event description */
+      lStartEvent.MagicNumber   = TRACER_MAGIC_NUMBER;
+#ifdef __i386__
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_I386;
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_NONE;
+#endif
+#ifdef __powerpc__
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_PPC;
+#if defined(CONFIG_4xx)
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_PPC_4xx;
+#elif defined(CONFIG_6xx)
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_PPC_6xx;
+#elif defined(CONFIG_8xx)
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_PPC_8xx;
+#elif defined(CONFIG_PPC_ISERIES)
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_PPC_ISERIES;
+#endif
+#endif
+#ifdef __sh__
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_SH;
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_NONE;
+#endif
+#ifdef __s390__
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_S390;      
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_NONE;
+#endif
+#ifdef __mips__
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_MIPS;      
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_NONE;
+#endif
+#ifdef CONFIG_ARM
+      lStartEvent.ArchType      = TRACE_ARCH_TYPE_ARM;
+      lStartEvent.ArchVariant   = TRACE_ARCH_VARIANT_NONE;
+#endif
+      lStartEvent.SystemType    = TRACE_SYS_TYPE_VANILLA_LINUX;
+      lStartEvent.MajorVersion  = TRACER_VERSION_MAJOR;
+      lStartEvent.MinorVersion  = TRACER_VERSION_MINOR;
+      lStartEvent.BufferSize    = sBufSize;
+      lStartEvent.EventMask     = sTracedEvents;
+      lStartEvent.DetailsMask   = sLogEventDetailsMask;
+      lStartEvent.LogCPUID      = sLogCPUID;
+
+      /* Trace the buffer start event */
+      trace(TRACE_EV_BUFFER_START, &lStartBufferEvent);
+
+      /* Trace the start event */
+      trace(TRACE_EV_START, &lStartEvent);
+
+      /* Start tapping into Linux's syscall flow */
+      syscall_entry_trace_active = ltt_test_bit(TRACE_EV_SYSCALL_ENTRY, &sTracedEvents);
+      syscall_exit_trace_active  = ltt_test_bit(TRACE_EV_SYSCALL_EXIT, &sTracedEvents);
+
+      /* We can start tracing */
+      sTracerStarted = TRUE;
+
+      /* Reregister custom trace events created earlier */
+      trace_reregister_custom_events();
+      break;
+
+    /* Stop the tracer */
+    case TRACER_STOP :
+      /* Stop tracing */
+      sTracerStarted = FALSE;
+
+      /* Stop interrupting the normal flow of system calls */
+      syscall_entry_trace_active = 0;
+      syscall_exit_trace_active  = 0;
+
+      /* Acquire the lock to avoid SMP case of where another CPU is writing a trace
+         while buffer is being switched */
+      spin_lock_irqsave(&sSpinLock, lFlags);
+
+      /* Switch the buffers to ensure that the end of the buffer mark is set (time isn't important) */
+      tracer_switch_buffers(sBufferStartTime);
+
+      /* Release lock */
+      spin_unlock_irqrestore(&sSpinLock, lFlags);
+      break;
+
+    /* Set the tracer to the default configuration */
+    case TRACER_CONFIG_DEFAULT :
+      tracer_set_default_config();
+      break;
+
+    /* Set the memory buffers the daemon wants us to use */
+    case TRACER_CONFIG_MEMORY_BUFFERS :
+      /* Is the given size "reasonnable" */
+      if(pmArg < TRACER_MIN_BUF_SIZE)
+	return -EINVAL;
+
+      /* Set the buffer's size */
+      return tracer_set_buffer_size(pmArg);
+      break;
+
+    /* Trace the given events */
+    case TRACER_CONFIG_EVENTS :
+      if(copy_from_user(&sTracedEvents, (void*) pmArg, sizeof(sTracedEvents)))
+	return -EFAULT;
+      break;
+
+    /* Record the details of the event, or not */
+    case TRACER_CONFIG_DETAILS :
+      if(copy_from_user(&sLogEventDetailsMask, (void*) pmArg, sizeof(sLogEventDetailsMask)))
+	return -EFAULT;
+      break;
+      
+    /* Record the CPUID associated with the event */
+    case TRACER_CONFIG_CPUID :
+      sLogCPUID = TRUE;
+      break;
+
+    /* Trace only one process */
+    case TRACER_CONFIG_PID :
+      sTracingPID = TRUE;
+      sTracedPID  = pmArg;
+      break;
+
+    /* Trace only the given process group */
+    case TRACER_CONFIG_PGRP :
+      sTracingPGRP = TRUE;
+      sTracedPGRP  = pmArg;
+      break;
+
+    /* Trace the processes of a given group of users */
+    case TRACER_CONFIG_GID :
+      sTracingGID = TRUE;
+      sTracedGID  = pmArg;
+      break;
+
+    /* Trace the processes of a given user */
+    case TRACER_CONFIG_UID :
+      sTracingUID = TRUE;
+      sTracedUID  = pmArg;
+      break;
+
+    /* Set the call depth a which the EIP should be fetched on syscall */
+    case TRACER_CONFIG_SYSCALL_EIP_DEPTH :
+      sSyscallEIPDepthSet = TRUE;
+      sSyscallEIPDepth    = pmArg;
+      break;
+
+    /* Set the lowerbound address from which EIP is recorded on syscall */
+    case TRACER_CONFIG_SYSCALL_EIP_LOWER :
+      /* We are using bounds for fetching the EIP where syscall was made */
+      sUseSyscallEIPBounds = TRUE;
+
+      /* Set the lower bound */
+      sLowerEIPBound = (void*) pmArg;
+
+      /* The lower bound has been set */
+      sLowerEIPBoundSet = TRUE;
+      break;
+
+    /* Set the upperbound address from which EIP is recorded on syscall */
+    case TRACER_CONFIG_SYSCALL_EIP_UPPER :
+      /* We are using bounds for fetching the EIP where syscall was made */
+      sUseSyscallEIPBounds = TRUE;
+
+      /* Set the lower bound */
+      sUpperEIPBound = (void*) pmArg;
+
+      /* The lower bound has been set */
+      sUpperEIPBoundSet = TRUE;
+      break;
+
+    /* The daemon has comitted the last trace */
+    case TRACER_DATA_COMITTED :
+#if 0
+      printk("Tracer: Data has been comitted \n");
+#endif
+
+      /* Safely set the signal sent flag to FALSE */
+      spin_lock_irqsave(&sSpinLock, lFlags);
+      sSignalSent = FALSE;
+      spin_unlock_irqrestore(&sSpinLock, lFlags);
+      break;
+
+    /* Get the number of events lost */
+    case TRACER_GET_EVENTS_LOST :
+      return sEventsLost;
+      break;
+
+    /* Create a user event */
+    case TRACER_CREATE_USER_EVENT :
+      /* Copy the information from user space */
+      if(copy_from_user(&lNewUserEvent, (void*) pmArg, sizeof(lNewUserEvent)))
+	return -EFAULT;
+
+      /* Create the event */
+      lNewUserEventID = trace_create_owned_event(lNewUserEvent.type,
+						 lNewUserEvent.desc,
+						 lNewUserEvent.format_type,
+						 lNewUserEvent.form,
+						 current->pid);
+
+      /* Has the operation succeded */
+      if(lNewUserEventID >= 0)
+	{
+	/* Set the event ID */
+	lNewUserEvent.id = lNewUserEventID;
+
+	/* Copy the event information back to user space */
+	if(copy_to_user((void*) pmArg, &lNewUserEvent, sizeof(lNewUserEvent)))
+	  {
+	  /* Since we were unable to tell the user about the event, destroy it */
+	  trace_destroy_event(lNewUserEventID);
+	  return -EFAULT;
+	  }
+	}
+      else
+	/* Forward trace_create_event()'s error code */
+	return lNewUserEventID;
+      break;
+
+    /* Destroy a user event */
+    case TRACER_DESTROY_USER_EVENT :
+      /* Pass on the user's request */
+      trace_destroy_event((int) pmArg);
+      break;
+
+    /* Trace a user event */
+    case TRACER_TRACE_USER_EVENT :
+      /* Copy the information from user space */
+      if(copy_from_user(&lUserEvent, (void*) pmArg, sizeof(lUserEvent)))
+	return -EFAULT;
+
+      /* Copy the user event data */
+      if(copy_from_user(sUserEventData, lUserEvent.data, lUserEvent.data_size))
+	return -EFAULT;
+
+      /* Log the raw event */
+      lRetValue = trace_raw_event(lUserEvent.id,
+				  lUserEvent.data_size,
+				  sUserEventData);
+
+      /* Has the operation failed */
+      if(lRetValue < 0)
+	/* Forward trace_create_event()'s error code */
+	return lRetValue;
+      break;
+
+    /* Set event mask */
+    case TRACER_SET_EVENT_MASK :
+      /* Copy the information from user space */
+      if(copy_from_user(&(lTraceMask.mask), (void*) pmArg, sizeof(lTraceMask.mask)))
+	return -EFAULT;
+
+      /* Trace the event */
+      lRetValue = trace(TRACE_EV_CHANGE_MASK, &lTraceMask);
+
+      /* Change the event mask. (This has to be done second or else may loose the
+       information if the user decides to stop logging "change mask" events) */
+      memcpy(&sTracedEvents, &(lTraceMask.mask), sizeof(lTraceMask.mask));
+      syscall_entry_trace_active = ltt_test_bit(TRACE_EV_SYSCALL_ENTRY, &sTracedEvents);
+      syscall_exit_trace_active  = ltt_test_bit(TRACE_EV_SYSCALL_EXIT, &sTracedEvents);
+
+      /* Always trace the buffer start, the trace start and the change mask */
+      ltt_set_bit(TRACE_EV_BUFFER_START, &sTracedEvents);
+      ltt_set_bit(TRACE_EV_START, &sTracedEvents);
+      ltt_set_bit(TRACE_EV_CHANGE_MASK, &sTracedEvents);
+
+      /* Forward trace()'s error code */
+      return lRetValue;
+      break;
+
+    /* Get event mask */
+    case TRACER_GET_EVENT_MASK :
+      /* Copy the information to user space */
+      if(copy_to_user((void*) pmArg, &sTracedEvents, sizeof(sTracedEvents)))
+	return -EFAULT;
+      break;
+
+    /* Unknow command */
+    default :
+      return -ENOSYS;
+    }
+
+  /* Everything went OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_mmap()
+ * Description : "Mmap" file op
+ * Parameters :
+ *     pmInode, the inode associated with the device
+ *     pmFile, file structure given to the acting process
+ *     pmVmArea, Virtual memory area description structure
+ * Return values :
+ *     0 if ok
+ *     -EAGAIN, when remap failed
+ *     -EACCESS, permission denied
+ ************************************************************/
+int tracer_mmap(struct file*            pmFile,
+		struct vm_area_struct*  pmVmArea)
+{
+  int      lRetValue;     /* Function's return value */
+
+  /* Only the trace daemon is allowed access to mmap */
+  if(current != sDaemonTaskStruct)
+    return -EACCES;
+
+  /* Remap trace buffer into the process's memory space */
+  lRetValue = tracer_mmap_region((char*) pmVmArea->vm_start,
+				 sTracBuf,
+				 pmVmArea->vm_end - pmVmArea->vm_start);
+
+#if 0
+  printk("Tracer: Trace buffer virtual address                  => 0x%08X \n", (uint32_t)sTracBuf);
+  printk("Tracer: Trace buffer physical address                 => 0x%08X \n", (uint32_t)virt_to_phys(sTracBuf));
+  printk("Tracer: Trace buffer virtual address in daemon space  => 0x%08X \n", (uint32_t)pmVmArea->vm_start);
+  printk("Tracer: Trace buffer physical address in daemon space => 0x%08X \n", (uint32_t)virt_to_phys((void*)pmVmArea->vm_start));
+#endif
+
+  /* Tell the caller that the memory mapping worked OK */
+  return lRetValue;
+}
+
+/*************************************************************
+ * Function : tracer_open()
+ * Description : "Open" file op
+ * Parameters : 
+ *     pmInode, the inode associated with the device
+ *     pmFile, file structure given to the acting process
+ * Return values :
+ *     0, everything went OK
+ *     -ENODEV, no such device.
+ *     -EBUSY, daemon channel (minor number 0) already in use.
+ ************************************************************/
+int tracer_open(struct inode* pmInode,
+		struct file*  pmFile)
+{
+  int lDevMinor = MINOR(pmInode->i_rdev) & 0xf;  /* Device minor number */
+
+  /* Only minor number 0 and 1 are used */
+  if((lDevMinor > 0) && (lDevMinor != 1))
+    return -ENODEV;
+
+  /* If the device has already been opened */
+  if(sOpenCount)
+    {
+    /* Is there another process trying to open the daemon's channel (minor number 0) */
+    if(lDevMinor == 0)
+      /* This isn't allowed */
+      return -EBUSY;
+    else
+      /* Only increment use, this is just another user process trying to log user events */
+      goto IncrementUse;
+    }
+
+  /* Fetch the task structure of the process that opened the device */
+  sDaemonTaskStruct = current;
+
+  /* Reset the default configuration since this is the daemon and he will complete the setup */
+  tracer_set_default_config();
+
+#if 0
+  /* DEBUG */
+  printk("<1>Process %d opened the tracing device \n", sDaemonTaskStruct->pid);
+#endif
+
+IncrementUse:
+  /* Lock the device */
+  sOpenCount++;
+
+#ifdef MODULE
+  /* Increment module usage */
+  MOD_INC_USE_COUNT;
+#endif
+
+  /* Everything is OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_release()
+ * Description : "Release" file op
+ * Parameters :
+ *     pmInode, the inode associated with the device
+ *     pmFile, file structure given to the acting process
+ * Return values : 
+ *     0, everything went OK
+ * Note :
+ *     It is assumed that if the tracing daemon dies, exits
+ *     or simply stops existing, the kernel or "someone" will
+ *     call tracer_release. Otherwise, we're in trouble ...
+ *************************************************************/
+int tracer_release(struct inode* pmInode,
+		   struct file*  pmFile)
+{
+  int lDevMinor = MINOR(pmInode->i_rdev) & 0xf;  /* Device minor number */
+
+  /* Is this a simple user process exiting? */
+  if(lDevMinor != 0)
+    goto DecrementUse;
+
+  /* Did we loose any events */
+  if(sEventsLost > 0)
+    printk(KERN_ALERT "Tracer: Lost %d events \n", sEventsLost);
+
+  /* Reset the daemon PID */
+  sDaemonTaskStruct = NULL;
+
+  /* Free the current buffers, if any */
+  if(sTracBuf != NULL)
+    rvfree(sTracBuf, sAllocSize);
+
+  /* Reset the read and write buffers */
+  sTracBuf    = NULL;
+  sWritBuf    = NULL;
+  sReadBuf    = NULL;
+  sWritBufEnd = NULL;
+  sReadBufEnd = NULL;
+  sWritPos    = NULL;
+  sReadLimit  = NULL;
+  sWritLimit  = NULL;
+
+  /* Reset the tracer's configuration */
+  tracer_set_default_config();
+  sTracerStarted = FALSE;
+
+  /* Reset number of bytes recorded and number of events lost */
+  sBufReadComplete    = 0;
+  sSizeReadIncomplete = 0;
+  sEventsLost         = 0;
+
+  /* Reset signal sent */
+  sSignalSent = FALSE;
+
+DecrementUse:
+  /* Unlock the device */
+  sOpenCount--;
+
+#ifdef MODULE
+  /* Decrement module usage */
+  MOD_DEC_USE_COUNT;
+#endif
+
+  /* Tell the caller that everything is OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_fsync()
+ * Description : "Fsync" file op
+ * Parameters :
+ *     pmFile, file structure given to the acting process
+ *     pmDEntry, dentry associated with file
+ * Return values : 
+ *     0, everything went OK
+ *     -EACCESS, permission denied
+ * Note :
+ *     We need to look the modifications of the values because
+ *     they are read and written by trace().
+ * Sonia : ne m oublie pas, je suis toujours a toi....
+ *************************************************************/
+int tracer_fsync(struct file*   pmFile,
+		 struct dentry* pmDEntry,
+		 int            pmDataSync)
+{
+  unsigned long int   lFlags;      /* CPU flags for lock */
+
+  /* Only the trace daemon is allowed access to fsync */
+  if(current != sDaemonTaskStruct)
+    return -EACCES;
+
+  /* Lock the kernel */
+  spin_lock_irqsave(&sSpinLock, lFlags);
+  
+  /* Reset the write positions */
+  sWritPos   = sWritBuf;
+
+  /* Reset read limit */
+  sReadLimit = sReadBuf;
+
+  /* Reset bytes recorded */
+  sBufReadComplete    = 0;
+  sSizeReadIncomplete = 0;
+  sEventsLost         = 0;
+
+  /* Reset signal sent */
+  sSignalSent = FALSE;
+
+  /* Unlock the kernel */
+  spin_unlock_irqrestore(&sSpinLock, lFlags);
+
+  /* Tell the caller that everything is OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_set_buffer_size()
+ * Description :
+ *     Sets the size of the buffers containing the trace data.
+ * Parameters :
+ *     pmSize, Size of buffers
+ * Return values :
+ *     0, Size setting went OK
+ *     -ENOMEM, unable to get a hold of memory for tracer
+ *************************************************************/
+int tracer_set_buffer_size(int pmSize)
+{
+  int       lSizeAlloc;     /* Size to be allocated */
+
+  /* Set size to allocate (= pmSize * 2) and fix it's size to be on a page boundary */
+  lSizeAlloc = FIX_SIZE(pmSize << 1);
+
+  /* Free the current buffers, if any */
+  if(sTracBuf != NULL)
+    rvfree(sTracBuf, sAllocSize);
+
+  /* Allocate space for the tracing buffers */
+  if((sTracBuf = (char*) rvmalloc(lSizeAlloc)) == NULL)
+    return -ENOMEM;
+
+  /* Remember the size set */
+  sBufSize = pmSize;
+  sAllocSize = lSizeAlloc;
+
+  /* Set the read and write buffers */
+  sWritBuf = sTracBuf;
+  sReadBuf = sTracBuf + sBufSize;
+
+  /* Set end of buffers */
+  sWritBufEnd = sWritBuf + sBufSize;
+  sReadBufEnd = sReadBuf + sBufSize;
+
+  /* Set write position */
+  sWritPos = sWritBuf;
+
+  /* Set read limit */
+  sReadLimit = sReadBuf;
+
+  /* Set write limit */
+  sWritLimit = sWritBufEnd - TRACER_LAST_EVENT_SIZE;
+
+  /* All is OK */
+  return 0;
+}
+
+/*************************************************************
+ * Function : tracer_set_default_config()
+ * Description : Sets the tracer in its default config
+ * Parameters :
+ *     NONE
+ * Return values :
+ *    0, everything went OK
+ *    -ENOMEM, unable to get a hold of memory for tracer
+ *************************************************************/
+int tracer_set_default_config(void)
+{
+  int  i;          /* Generic index */
+  int  lError = 0; /* Error, if any */
+
+  /* Initialize the event mask */
+  sTracedEvents = 0;
+  
+  /* Initialize the event mask with all existing events with their details*/
+  for(i = 0; i <= TRACE_EV_MAX; i++)
+    {
+    ltt_set_bit(i, &sTracedEvents);
+    ltt_set_bit(i, &sLogEventDetailsMask);
+    }
+
+  /* Do not interfere with Linux's syscall flow until we actually start tracing */
+  syscall_entry_trace_active = 0;
+  syscall_exit_trace_active  = 0;
+
+  /* Forget about the CPUID */
+  sLogCPUID = FALSE;
+  
+  /* We aren't tracing any PID or GID in particular */
+  sTracingPID  = FALSE;
+  sTracingPGRP = FALSE;
+  sTracingGID  = FALSE;
+  sTracingUID  = FALSE;
+
+  /* We aren't looking for a particular call depth */
+  sSyscallEIPDepthSet = FALSE;
+
+  /* We aren't going to place bounds on syscall EIP fetching */
+  sUseSyscallEIPBounds = FALSE;
+  sLowerEIPBoundSet = FALSE;
+  sUpperEIPBoundSet = FALSE;
+
+  /* Set the kernel trace configuration to it's basics */
+  trace_set_config(trace,
+		   sSyscallEIPDepthSet,
+		   sUseSyscallEIPBounds,
+		   0,
+		   0,
+		   0);
+
+  /* Return the error code */
+  return lError;
+}
+
+/**************************************************************
+ * Function : tracer_init()
+ * Description : Tracer initialization function.
+ * Parameters :
+ *     NONE
+ * Return values : 
+ *    0, everything went OK
+ *    -ENONMEM, incapable of allocating necessary memory
+ *    Forwarded error code otherwise
+ **************************************************************/
+int __init tracer_init(void)
+{
+  int  lError = 0; /* Error, if any */
+
+  /* Initialize configuration */
+  if((lError = tracer_set_default_config()) < 0)
+    return lError;
+
+  /* Initialize open count */
+  sOpenCount = 0;
+
+  /* Initialize tracer lock */
+  sTracLock = 0;
+
+  /* Initialize signal sent */
+  sSignalSent = FALSE;
+
+  /* Initialize bytes read and events lost */
+  sBufReadComplete    = 0;
+  sSizeReadIncomplete = 0;
+  sEventsLost         = 0;
+
+  /* Initialize buffer ID */
+  sBufferID    = 0;
+
+  /* Initialize tracing daemon task structure */
+  sDaemonTaskStruct = NULL;
+
+  /* Allocate memory for large data components */
+  if((sUserEventData = vmalloc(CUSTOM_EVENT_MAX_SIZE)) < 0)
+    return -ENOMEM;
+
+  /* Initialize spin lock */
+  sSpinLock = SPIN_LOCK_UNLOCKED;
+
+  /* Register the tracer as a char device */ 
+  sMajorNumber = register_chrdev(0, TRACER_NAME, &sTracerFileOps);
+
+  /* Register the tracer with the kernel */
+  if((lError = register_tracer(trace)) < 0)
+    {
+    /* Tell the user about the problem */
+    printk(KERN_ALERT "Tracer: Unable to register tracer with kernel, tracer disabled \n");
+
+    /* Make sure no one can open this device */
+    sOpenCount = 1;
+    }
+  else
+    printk(KERN_INFO "Tracer: Initialization complete \n");
+
+  /* Return error code */
+  return lError;
+}
+
+/* Is this loaded as a module */
+#ifdef MODULE
+/**************************************************************
+ * Function : cleanup_module()
+ * Description : Cleanup of the tracer.
+ * Parameters : NONE
+ * Return values : NONE
+ * Note : The order of the unregesterings is important. First,
+ *        rule out any possibility of getting more trace 
+ *        data. Second, rule out any possibility of being read
+ *        by the tracing daemon. Last, free the tracing
+ *        buffer.
+ **************************************************************/
+void tracer_exit(void)
+{
+  /* Unregister the tracer from the kernel */
+  unregister_tracer(trace);
+
+  /* Unregister the tracer from being a char device */
+  unregister_chrdev(sMajorNumber, TRACER_NAME);
+
+  /* Free the current buffers, if any */
+  if(sTracBuf != NULL)
+    rvfree(sTracBuf, sAllocSize);
+
+  /* Paranoia */
+  sTracBuf = NULL;
+}
+module_exit(tracer_exit);
+#endif /* MODULE */
+
+module_init(tracer_init);
diff -Nurp linux-2.4.22-clean/drivers/trace/tracer.h linux-2.4.22-adeos-ltt/drivers/trace/tracer.h
--- linux-2.4.22-clean/drivers/trace/tracer.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/drivers/trace/tracer.h	2003-11-21 23:21:08.000000000 -0800
@@ -0,0 +1,276 @@
+/*
+ * drivers/trace/tracer.h
+ *
+ * Copyright (C) 1999, 2000, 2001 Karim Yaghmour (karym@opersys.com)
+ * Portions contributed by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
+ *
+ * This contains the necessary definitions the system tracer
+ */
+
+#ifndef _TRACER_H
+#define _TRACER_H
+
+/* Logic values */
+#define FALSE 0
+#define TRUE  1
+
+/* Structure packing within the trace */
+#ifndef LTT_PACKED_STRUCT
+#if LTT_UNPACKED_STRUCTS
+#define LTT_PACKED_STRUCT
+#else  /* if LTT_UNPACKED_STRUCTS */
+#define LTT_PACKED_STRUCT __attribute__ ((packed));
+#endif /* if LTT_UNPACKED_STRUCTS */
+#endif /* if LTT_PACKED_STRUCT */
+
+/* Tracer properties */
+#define TRACER_NAME      "tracer"     /* Name of the device as seen in /proc/devices */
+
+/* Tracer buffer information */
+#define TRACER_DEFAULT_BUF_SIZE   50000   /* Default size of tracing buffer */
+#define TRACER_MIN_BUF_SIZE        1000   /* Minimum size of tracing buffer */
+#define TRACER_MAX_BUF_SIZE      500000   /* Maximum size of tracing buffer */
+
+/* Local definitions */
+typedef uint32_t    trace_time_delta;    /* The type used to start the time delta between events */
+
+/* Number of bytes set aside for last event */
+#define TRACER_LAST_EVENT_SIZE   (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(trace_time_delta) + sizeof(uint32_t))
+
+/* Architecture types */
+#define TRACE_ARCH_TYPE_I386                1   /* i386 system */
+#define TRACE_ARCH_TYPE_PPC                 2   /* PPC system */
+#define TRACE_ARCH_TYPE_SH                  3   /* SH system */
+#define TRACE_ARCH_TYPE_S390                4   /* S/390 system */
+#define TRACE_ARCH_TYPE_MIPS                5   /* MIPS system */
+#define TRACE_ARCH_TYPE_ARM                 6   /* ARM system */
+
+/* Standard definitions for variants */
+#define TRACE_ARCH_VARIANT_NONE             0   /* Main architecture implementation */
+
+/* PowerPC variants */
+#define TRACE_ARCH_VARIANT_PPC_4xx          1   /* 4xx systems (IBM embedded series) */
+#define TRACE_ARCH_VARIANT_PPC_6xx          2   /* 6xx/7xx/74xx/8260/POWER3 systems (desktop flavor) */
+#define TRACE_ARCH_VARIANT_PPC_8xx          3   /* 8xx system (Motoral embedded series) */
+#define TRACE_ARCH_VARIANT_PPC_ISERIES      4   /* 8xx system (iSeries) */
+
+/* System types */
+#define TRACE_SYS_TYPE_VANILLA_LINUX        1   /* Vanilla linux kernel  */
+
+/* The information logged when the tracing is started */
+#define TRACER_MAGIC_NUMBER     0x00D6B7ED      /* That day marks an important historical event ... */
+#define TRACER_VERSION_MAJOR    1               /* Major version number */
+#define TRACER_VERSION_MINOR   14               /* Minor version number */
+typedef struct _trace_start
+{
+  uint32_t           MagicNumber;  /* Magic number to identify a trace */
+  uint32_t           ArchType;     /* Type of architecture */
+  uint32_t           ArchVariant;  /* Variant of the given type of architecture */
+  uint32_t           SystemType;   /* Operating system type */
+  uint8_t            MajorVersion; /* Major version of trace */
+  uint8_t            MinorVersion; /* Minor version of trace */
+
+  uint32_t           BufferSize;   /* Size of buffers */
+  trace_event_mask   EventMask;    /* The event mask */
+  trace_event_mask   DetailsMask;  /* Are the event details logged */
+  uint8_t            LogCPUID;     /* Is the CPUID logged */
+} LTT_PACKED_STRUCT trace_start;
+
+/* Start and end of trace buffer information */
+typedef struct _trace_buffer_start
+{
+  struct timeval     Time;  /* Time stamp of this buffer */
+  uint32_t           ID;    /* Unique buffer ID */  
+} LTT_PACKED_STRUCT trace_buffer_start;
+
+/* The configurations possible */
+#define TRACER_START                      TRACER_MAGIC_NUMBER + 0  /* Start tracing events using the current configuration */
+#define TRACER_STOP                       TRACER_MAGIC_NUMBER + 1  /* Stop tracing */
+#define TRACER_CONFIG_DEFAULT             TRACER_MAGIC_NUMBER + 2  /* Set the tracer to the default configuration */
+#define TRACER_CONFIG_MEMORY_BUFFERS      TRACER_MAGIC_NUMBER + 3  /* Set the memory buffers the daemon wants us to use */
+#define TRACER_CONFIG_EVENTS              TRACER_MAGIC_NUMBER + 4  /* Trace the given events */
+#define TRACER_CONFIG_DETAILS             TRACER_MAGIC_NUMBER + 5  /* Record the details of the event, or not */
+#define TRACER_CONFIG_CPUID               TRACER_MAGIC_NUMBER + 6  /* Record the CPUID associated with the event */
+#define TRACER_CONFIG_PID                 TRACER_MAGIC_NUMBER + 7  /* Trace only one process */
+#define TRACER_CONFIG_PGRP                TRACER_MAGIC_NUMBER + 8  /* Trace only the given process group */
+#define TRACER_CONFIG_GID                 TRACER_MAGIC_NUMBER + 9  /* Trace the processes of a given group of users */
+#define TRACER_CONFIG_UID                 TRACER_MAGIC_NUMBER + 10 /* Trace the processes of a given user */
+#define TRACER_CONFIG_SYSCALL_EIP_DEPTH   TRACER_MAGIC_NUMBER + 11 /* Set the call depth at which the EIP should be fetched on syscall */
+#define TRACER_CONFIG_SYSCALL_EIP_LOWER   TRACER_MAGIC_NUMBER + 12 /* Set the lowerbound address from which EIP is recorded on syscall */
+#define TRACER_CONFIG_SYSCALL_EIP_UPPER   TRACER_MAGIC_NUMBER + 13 /* Set the upperbound address from which EIP is recorded on syscall */
+#define TRACER_DATA_COMITTED              TRACER_MAGIC_NUMBER + 14 /* The daemon has comitted the last trace */
+#define TRACER_GET_EVENTS_LOST            TRACER_MAGIC_NUMBER + 15 /* Get the number of events lost */
+#define TRACER_CREATE_USER_EVENT          TRACER_MAGIC_NUMBER + 16 /* Create a user tracable event */
+#define TRACER_DESTROY_USER_EVENT         TRACER_MAGIC_NUMBER + 17 /* Destroy a user tracable event */
+#define TRACER_TRACE_USER_EVENT           TRACER_MAGIC_NUMBER + 18 /* Trace a user event */
+#define TRACER_SET_EVENT_MASK             TRACER_MAGIC_NUMBER + 19 /* Set the trace event mask */
+#define TRACER_GET_EVENT_MASK             TRACER_MAGIC_NUMBER + 20 /* Get the trace event mask */
+
+#ifdef __powerpc__
+/* We need to replace the usual PPC kernel bit manipulation functions with
+ * equivalent functions that are cross-platform compatible.  The PPC kernel
+ * functions define bit order as follows:
+ *
+ * bit  0: 0x0000000100000000
+ * bit  1: 0x0000000200000000
+ * .
+ * .
+ * .
+ * bit  7: 0x0000008000000000
+ * bit  8: 0x0000010000000000
+ * bit  9: 0x0000020000000000
+ * .
+ * .
+ * .
+ * bit 31: 0x8000000000000000
+ * bit 32: 0x0000000000000001
+ * bit 33: 0x0000000000000002
+ * .
+ * .
+ * .
+ * bit 63: 0x0000000080000000
+ *
+ * Our redefined functions define bit order the same as the kernel bit functions
+ * for x86 targets:
+ *
+ * bit  0: 0x0100000000000000
+ * bit  1: 0x0200000000000000
+ * .
+ * .
+ * .
+ * bit  7: 0x8000000000000000
+ * bit  8: 0x0001000000000000
+ * bit  9: 0x0002000000000000
+ * .
+ * .
+ * .
+ * bit 31: 0x0000000800000000
+ * bit 32: 0x0000000001000000
+ * bit 33: 0x0000000002000000
+ * .
+ * .
+ * .
+ * bit 63: 0x0000000000000080
+ */
+static inline int ltt_set_bit(int nr, volatile void * addr)
+{
+	unsigned long old, t;
+	unsigned long mask = 1 << (24 - (nr & 0x18) + (nr & 0x7));
+	volatile unsigned long *p = ((volatile unsigned long *)addr) + (nr >> 5);
+	
+	__asm__ __volatile__(
+		"1:lwarx %0,0,%3 \n\t"
+		"or	%1,%0,%2 \n\t"
+		"stwcx.	%1,0,%3 \n\t"
+		"bne	1b \n\t"
+		: "=&r" (old), "=&r" (t)	/*, "=m" (*p)*/
+		: "r" (mask), "r" (p)
+		/*: "cc" */);
+
+	return (old & mask) != 0;
+}
+
+static inline int ltt_clear_bit(unsigned long nr, volatile void *addr)
+{
+	unsigned long old, t;
+	unsigned long mask = 1 << (24 - (nr & 0x18) + (nr & 0x7));
+	volatile unsigned long *p = ((volatile unsigned long *)addr) + (nr >> 5);
+
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3
+	andc	%1,%0,%2
+	stwcx.	%1,0,%3
+	bne	1b"
+	: "=&r" (old), "=&r" (t)	/*, "=m" (*p)*/
+	: "r" (mask), "r" (p)
+      /*: "cc"*/);
+
+	return (old & mask) != 0;
+}
+
+static inline int ltt_test_bit(int nr, __const__ volatile void *addr)
+{
+	__const__ volatile unsigned int *p = (__const__ volatile unsigned int *) addr;
+
+	return ((p[nr >> 5] >> (24 - (nr & 0x18) + (nr & 0x7))) & 1) != 0;
+}
+#else  /* ifdef __powerpc__ */
+#if defined(__s390__) || defined(__mips__) /* Added by T.H., modified by K.Y. for mips */
+/* Use functions taken from LTTTypes.h */
+extern __inline__ int ltt_set_bit(int nr, void * addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+  unsigned char old;
+
+  p += nr>>3;
+  old = *p;
+  *p |= mask;
+
+  return ((old & mask) != 0);
+}
+
+extern __inline__ int ltt_clear_bit(int nr, void * addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+  unsigned char old;
+
+  p += nr>>3;
+  old = *p;
+  *p &= ~mask;
+
+  return ((old & mask) != 0);
+}
+
+extern __inline__ int ltt_test_bit(int nr,void *addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+   
+  p += nr>>3;
+                
+  return ((*p & mask) != 0);
+}
+#else /* For non-powerpc, non-s390 and non-mips processors we can use the kernel functions. */
+#define ltt_set_bit    set_bit
+#define ltt_clear_bit  clear_bit
+#define ltt_test_bit   test_bit
+#endif /* if defined(__s390__) || defined(__mips__) */
+#endif /* ifdef __powerpc__ */
+
+/* Function prototypes */
+int     trace
+          (uint8_t,
+	   void*);
+void    tracer_switch_buffers
+          (struct timeval);
+int     tracer_ioctl
+          (struct inode*,
+	   struct file*,
+	   unsigned int,
+	   unsigned long);
+int     tracer_mmap
+	  (struct file*,
+	   struct vm_area_struct*);
+int     tracer_open
+          (struct inode*,
+           struct file*);
+int     tracer_release
+          (struct inode*,
+	   struct file*);
+int     tracer_fsync
+          (struct file*,
+	   struct dentry*,
+	   int);
+#ifdef MODULE
+void    tracer_exit
+          (void);
+#endif
+int     tracer_set_buffer_size
+          (int);
+int     tracer_set_default_config
+          (void);
+int     tracer_init
+          (void);
+#endif /* _TRACER_H */
diff -Nurp linux-2.4.22-clean/fs/buffer.c linux-2.4.22-adeos-ltt/fs/buffer.c
--- linux-2.4.22-clean/fs/buffer.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/buffer.c	2003-11-21 23:21:08.000000000 -0800
@@ -48,6 +48,8 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -153,6 +155,7 @@ void __wait_on_buffer(struct buffer_head
 	get_bh(bh);
 	add_wait_queue(&bh->b_wait, &wait);
 	do {
+    TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_BUF_WAIT_START, 0, 0, NULL);
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!buffer_locked(bh))
 			break;
@@ -173,6 +176,7 @@ void __wait_on_buffer(struct buffer_head
 		schedule();
 	} while (buffer_locked(bh));
 	tsk->state = TASK_RUNNING;
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_BUF_WAIT_END, 0, 0, NULL);
 	remove_wait_queue(&bh->b_wait, &wait);
 	put_bh(bh);
 }
diff -Nurp linux-2.4.22-clean/fs/exec.c linux-2.4.22-adeos-ltt/fs/exec.c
--- linux-2.4.22-clean/fs/exec.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/exec.c	2003-11-21 23:21:08.000000000 -0800
@@ -40,6 +40,8 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
@@ -914,6 +916,11 @@ int do_execve(char * filename, char ** a
 	if (IS_ERR(file))
 		return retval;
 
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_EXEC,
+			  0,
+			  file->f_dentry->d_name.len,
+			  file->f_dentry->d_name.name);
+
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
 	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); 
 
diff -Nurp linux-2.4.22-clean/fs/ioctl.c linux-2.4.22-adeos-ltt/fs/ioctl.c
--- linux-2.4.22-clean/fs/ioctl.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/ioctl.c	2003-11-21 23:21:08.000000000 -0800
@@ -8,6 +8,8 @@
 #include <linux/smp_lock.h>
 #include <linux/file.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
@@ -56,6 +58,10 @@ asmlinkage long sys_ioctl(unsigned int f
 	if (!filp)
 		goto out;
 	error = 0;
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_IOCTL,
+			  fd,
+			  cmd,
+			  NULL);
 	lock_kernel();
 	switch (cmd) {
 		case FIOCLEX:
diff -Nurp linux-2.4.22-clean/fs/open.c linux-2.4.22-adeos-ltt/fs/open.c
--- linux-2.4.22-clean/fs/open.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/open.c	2003-11-21 23:21:08.000000000 -0800
@@ -16,6 +16,8 @@
 #include <linux/tty.h>
 #include <linux/iobuf.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
@@ -799,6 +801,10 @@ asmlinkage long sys_open(const char * fi
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
 				goto out_error;
+			TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_OPEN,
+					  fd,
+					  f->f_dentry->d_name.len,
+					  f->f_dentry->d_name.name); 
 			fd_install(fd, f);
 		}
 out:
@@ -865,6 +871,10 @@ asmlinkage long sys_close(unsigned int f
 	filp = files->fd[fd];
 	if (!filp)
 		goto out_unlock;
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_CLOSE,
+			  fd,
+			  0,
+			  NULL);
 	files->fd[fd] = NULL;
 	FD_CLR(fd, files->close_on_exec);
 	__put_unused_fd(files, fd);
diff -Nurp linux-2.4.22-clean/fs/read_write.c linux-2.4.22-adeos-ltt/fs/read_write.c
--- linux-2.4.22-clean/fs/read_write.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/read_write.c	2003-11-21 23:21:08.000000000 -0800
@@ -27,6 +27,8 @@
 #include <linux/smp_lock.h>
 #include <linux/dnotify.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 struct file_operations generic_ro_fops = {
@@ -121,6 +123,10 @@ asmlinkage off_t sys_lseek(unsigned int 
 		if (res != (loff_t)retval)
 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
 	}
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_SEEK,
+			  fd,
+			  offset,
+			  NULL);
 	fput(file);
 bad:
 	return retval;
@@ -146,6 +152,11 @@ asmlinkage long sys_llseek(unsigned int 
 	offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
 			origin);
 
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_SEEK,
+			  fd,
+			  offset,
+			  NULL);
+
 	retval = (int)offset;
 	if (offset >= 0) {
 		retval = -EFAULT;
@@ -173,8 +184,13 @@ asmlinkage ssize_t sys_read(unsigned int
 			if (!ret) {
 				ssize_t (*read)(struct file *, char *, size_t, loff_t *);
 				ret = -EINVAL;
-				if (file->f_op && (read = file->f_op->read) != NULL)
+				if (file->f_op && (read = file->f_op->read) != NULL) {
+				 	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_READ,
+							  fd,
+							  count,
+							  NULL); 
 					ret = read(file, buf, count, &file->f_pos);
+				}
 			}
 		}
 		if (ret > 0)
@@ -199,8 +215,13 @@ asmlinkage ssize_t sys_write(unsigned in
 			if (!ret) {
 				ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
 				ret = -EINVAL;
-				if (file->f_op && (write = file->f_op->write) != NULL)
+				if (file->f_op && (write = file->f_op->write) != NULL) {
+				        TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_WRITE,
+							  fd, 
+							  count,
+							  NULL);
 					ret = write(file, buf, count, &file->f_pos);
+				}
 			}
 		}
 		if (ret > 0)
@@ -337,6 +358,10 @@ asmlinkage ssize_t sys_readv(unsigned lo
 	file = fget(fd);
 	if (!file)
 		goto bad_file;
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_READ,
+			  fd,
+			  count,
+			  NULL);
 	if (file->f_op && (file->f_mode & FMODE_READ) &&
 	    (file->f_op->readv || file->f_op->read))
 		ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
@@ -357,6 +382,10 @@ asmlinkage ssize_t sys_writev(unsigned l
 	file = fget(fd);
 	if (!file)
 		goto bad_file;
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_WRITE,
+			  fd,
+			  count,
+			  NULL);
 	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
 	    (file->f_op->writev || file->f_op->write))
 		ret = do_readv_writev(VERIFY_READ, file, vector, count);
@@ -392,6 +421,12 @@ asmlinkage ssize_t sys_pread(unsigned in
 		goto out;
 	if (pos < 0)
 		goto out;
+
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_READ,
+			  fd,
+			  count,
+			  NULL);
+
 	ret = read(file, buf, count, &pos);
 	if (ret > 0)
 		dnotify_parent(file->f_dentry, DN_ACCESS);
@@ -424,6 +459,11 @@ asmlinkage ssize_t sys_pwrite(unsigned i
 	if (pos < 0)
 		goto out;
 
+	TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_WRITE,
+			  fd,
+			  count,
+			  NULL);
+
 	ret = write(file, buf, count, &pos);
 	if (ret > 0)
 		dnotify_parent(file->f_dentry, DN_MODIFY);
diff -Nurp linux-2.4.22-clean/fs/select.c linux-2.4.22-adeos-ltt/fs/select.c
--- linux-2.4.22-clean/fs/select.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.22-adeos-ltt/fs/select.c	2003-11-21 23:21:08.000000000 -0800
@@ -20,6 +20,8 @@
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/file.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
@@ -193,6 +195,10 @@ int do_select(int n, fd_set_bits *fds, l
 			file = fget(i);
 			mask = POLLNVAL;
 			if (file) {
+				TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_SELECT,
+						  i /*  The fd*/,
+						  __timeout,
+						  NULL);
 				mask = DEFAULT_POLLMASK;
 				if (file->f_op && file->f_op->poll)
 					mask = file->f_op->poll(file, wait);
@@ -367,6 +373,10 @@ static void do_pollfd(unsigned int num, 
 			struct file * file = fget(fd);
 			mask = POLLNVAL;
 			if (file != NULL) {
+			        TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_POLL,
+						  fd,
+						  0,
+						  NULL);
 				mask = DEFAULT_POLLMASK;
 				if (file->f_op && file->f_op->poll)
 					mask = file->f_op->poll(file, *pwait);
diff -Nurp linux-2.4.22-clean/include/asm-i386/adeos.h linux-2.4.22-adeos-ltt/include/asm-i386/adeos.h
--- linux-2.4.22-clean/include/asm-i386/adeos.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/include/asm-i386/adeos.h	2003-11-21 23:53:48.000000000 -0800
@@ -0,0 +1,415 @@
+/*
+ *   include/asm-i386/adeos.h
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __I386_ADEOS_H
+#define __I386_ADEOS_H
+
+struct task_struct;
+
+#include <asm/irq.h>
+#include <asm/siginfo.h>
+#include <asm/ptrace.h>
+#include <asm/bitops.h>
+#include <linux/list.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+
+#define ADEOS_ARCH_STRING "x86"
+
+#ifdef CONFIG_SMP
+
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+
+extern int smp_num_cpus;
+
+#define ADEOS_NR_CPUS          NR_CPUS
+#define ADEOS_CRITICAL_VECTOR  0xf1 /* Used by adeos_critical_enter/exit() */
+#define ADEOS_CRITICAL_IPI     (ADEOS_CRITICAL_VECTOR - FIRST_EXTERNAL_VECTOR)
+#define ADEOS_SERVICE_VECTOR   0xf9
+#define ADEOS_SERVICE_IPI      (ADEOS_SERVICE_VECTOR - FIRST_EXTERNAL_VECTOR)
+
+static __inline int adeos_smp_apic_id(void) {
+    return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
+}
+
+/* Cannot include asm/smpboot.h safely, so we define here the little
+   we need to know about CPU/apicid mappings. */
+
+#ifdef CONFIG_MULTIQUAD
+extern volatile int logical_apicid_2_cpu[];
+#define adeos_processor_id()   (smp_num_cpus > 1 ? logical_apicid_2_cpu[adeos_smp_apic_id()] : 0)
+#else /* !CONFIG_MULTIQUAD */		/* use physical IDs to bootstrap */
+extern volatile int physical_apicid_2_cpu[];
+#define adeos_processor_id()   (smp_num_cpus > 1 ? physical_apicid_2_cpu[adeos_smp_apic_id()] : 0)
+#endif /* CONFIG_MULTIQUAD */
+
+#define adeos_declare_cpuid    int cpuid = adeos_processor_id()
+#define adeos_reload_cpuid()   do { cpuid = adeos_processor_id(); } while(0)
+
+#else  /* !CONFIG_SMP */
+
+#define ADEOS_NR_CPUS          1
+#define adeos_processor_id()   0
+/* Array references using this index should be optimized out. */
+#define adeos_declare_cpuid  const int cpuid = 0
+#define adeos_reload_cpuid()  /* nop */
+
+#endif /* CONFIG_SMP */
+
+ /* IDT fault vectors */
+#define ADEOS_NR_FAULTS         32
+/* Pseudo-vectors used for kernel events */
+#define ADEOS_FIRST_KEVENT      ADEOS_NR_FAULTS
+#define ADEOS_SYSCALL_PROLOGUE  (ADEOS_FIRST_KEVENT)
+#define ADEOS_SYSCALL_EPILOGUE  (ADEOS_FIRST_KEVENT + 1)
+#define ADEOS_SCHEDULE_HEAD     (ADEOS_FIRST_KEVENT + 2)
+#define ADEOS_SCHEDULE_TAIL     (ADEOS_FIRST_KEVENT + 3)
+#define ADEOS_ENTER_PROCESS     (ADEOS_FIRST_KEVENT + 4)
+#define ADEOS_EXIT_PROCESS      (ADEOS_FIRST_KEVENT + 5)
+#define ADEOS_SIGNAL_PROCESS    (ADEOS_FIRST_KEVENT + 6)
+#define ADEOS_RENICE_PROCESS    (ADEOS_FIRST_KEVENT + 7)
+#define ADEOS_USER_EVENT        (ADEOS_FIRST_KEVENT + 8)
+#define ADEOS_LAST_KEVENT       (ADEOS_USER_EVENT)
+
+#define ADEOS_NR_EVENTS         (ADEOS_LAST_KEVENT + 1)
+
+typedef struct adevinfo {
+
+    unsigned domid;
+    unsigned event;
+    void *evdata;
+
+    int propagate;		/* Private */
+
+} adevinfo_t;
+
+typedef struct adsysinfo {
+
+    int ncpus;			/* Number of CPUs on board */
+
+    unsigned long long cpufreq;	/* CPU frequency (in Hz) */
+
+    /* Arch-dependent block */
+
+    struct {
+	unsigned tmirq;		/* Timer tick IRQ */
+    } archdep;
+
+} adsysinfo_t;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+/* We must cover the whole IRQ space (224 external vectors for x86) to
+   map the local timer interrupt (#207). */
+#define IPIPE_NR_XIRQS   224
+#else /* !CONFIG_X86_LOCAL_APIC */
+#define IPIPE_NR_XIRQS   NR_IRQS
+#endif /* CONFIG_X86_LOCAL_APIC */
+/* Number of virtual IRQs */
+#define IPIPE_NR_VIRQS   32
+/* First virtual IRQ # */
+#define IPIPE_VIRQ_BASE   IPIPE_NR_XIRQS
+/* Total number of IRQs (external + virtual) */
+#define IPIPE_NR_IRQS     (IPIPE_NR_XIRQS + IPIPE_NR_VIRQS)
+/* Number of indirect words needed to map the whole IRQ space. */
+#define IPIPE_IRQ_IWORDS  ((IPIPE_NR_IRQS + 31) / 32)
+
+typedef struct adomain {
+
+    /* -- Section: offset-based references are made on these fields
+       from inline assembly code. Please don't move or reorder. */
+    void (*dswitch)(void);	/* Domain switch hook */
+    int *esp[ADEOS_NR_CPUS];	/* Domain stack pointers */
+    /* -- End of section. */
+
+    int *estackbase[ADEOS_NR_CPUS];
+
+    unsigned domid;
+
+    const char *name;
+
+    int priority;
+
+    struct adcpudata {
+	volatile unsigned long status;
+	volatile unsigned long irq_pending_hi;
+	volatile unsigned long irq_pending_lo[IPIPE_IRQ_IWORDS];
+	volatile unsigned irq_hits[IPIPE_NR_IRQS];
+	adevinfo_t event_info;
+    } cpudata[ADEOS_NR_CPUS];
+
+    struct {
+	int (*acknowledge)(unsigned irq);
+	void (*handler)(unsigned irq);
+	unsigned long control;
+    } irqs[IPIPE_NR_IRQS];
+
+    struct {
+	void (*handler)(adevinfo_t *evinfo);
+    } events[ADEOS_NR_EVENTS];
+
+    int ptd_keymax;
+    int ptd_keycount;
+    unsigned long ptd_keymap;
+    void (*ptd_setfun)(int, void *);
+    void *(*ptd_getfun)(int);
+
+    struct adomain *m_link;	/* Link in mutex sleep queue */
+
+    struct list_head p_link;	/* Link in pipeline */
+
+} adomain_t;
+
+typedef struct admutex {
+
+    spinlock_t lock;
+
+    adomain_t *sleepq, /* Pending domains queue */
+	      *owner;	/* Domain owning the mutex */
+#ifdef CONFIG_SMP
+    volatile int owncpu;
+#define ADEOS_MUTEX_UNLOCKED { SPIN_LOCK_UNLOCKED, NULL, NULL, -1 }
+#else  /* !CONFIG_SMP */
+#define ADEOS_MUTEX_UNLOCKED { SPIN_LOCK_UNLOCKED, NULL, NULL }
+#endif /* CONFIG_SMP */
+
+} admutex_t;
+
+#define __clear_bit(nr,addr) clear_bit(nr,addr)
+#define __test_bit(nr,addr)  test_bit(nr,addr)
+
+/* The following macros must be used hw interrupts off. */
+
+#define __adeos_set_irq_bit(adp,cpuid,irq) \
+do { \
+    if (!test_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) { \
+        __set_bit(irq & 0x1f,&(adp)->cpudata[cpuid].irq_pending_lo[irq >> 5]); \
+        __set_bit(irq >> 5,&(adp)->cpudata[cpuid].irq_pending_hi); \
+       } \
+} while(0)
+
+#define __adeos_clear_pend(adp,cpuid,irq) \
+do { \
+    __clear_bit(irq & 0x1f,&(adp)->cpudata[cpuid].irq_pending_lo[irq >> 5]); \
+    if (&(adp)->cpudata[cpuid].irq_pending_lo[irq >> 5] == 0) \
+        __clear_bit(irq >> 5,&(adp)->cpudata[cpuid].irq_pending_hi); \
+} while(0)
+
+#define __adeos_lock_irq(adp,cpuid,irq) \
+do { \
+    if (!test_and_set_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) \
+	__adeos_clear_pend(adp,cpuid,irq); \
+} while(0)
+
+#define __adeos_unlock_irq(adp,irq) \
+do { \
+    int __cpuid; \
+    if (test_and_clear_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) \
+      for (__cpuid = 0; __cpuid < smp_num_cpus; __cpuid++) \
+         if ((adp)->cpudata[__cpuid].irq_hits[irq] > 0) { \
+           set_bit(irq & 0x1f,&(adp)->cpudata[__cpuid].irq_pending_lo[irq >> 5]); \
+           set_bit(irq >> 5,&(adp)->cpudata[__cpuid].irq_pending_hi); \
+         } \
+} while(0)
+
+#define __adeos_clear_irq(adp,irq) \
+do { \
+    int __cpuid; \
+    clear_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control); \
+    for (__cpuid = 0; __cpuid < smp_num_cpus; __cpuid++) { \
+       (adp)->cpudata[__cpuid].irq_hits[irq] = 0; \
+       __adeos_clear_pend(adp,__cpuid,irq); \
+    } \
+} while(0)
+
+#define adeos_virtual_irq_p(irq) ((irq) >= IPIPE_VIRQ_BASE && \
+				  (irq) < IPIPE_NR_IRQS)
+
+#define adeos_hw_save_flags_and_sti(x)	__asm__ __volatile__("pushfl ; popl %0 ; sti":"=g" (x): /* no input */ :"memory")
+#define adeos_hw_cli() 			__asm__ __volatile__("cli": : :"memory")
+#define adeos_hw_sti()			__asm__ __volatile__("sti": : :"memory")
+#define adeos_hw_local_irq_save(x)    __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
+#define adeos_hw_local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
+#define adeos_hw_local_irq_flags(x)   __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
+#define adeos_hw_test_iflag(x)        ((x) & (1<<9))
+#define adeos_hw_irqs_disabled()	\
+({					\
+	unsigned long flags;		\
+	adeos_hw_local_irq_flags(flags);	\
+	!adeos_hw_test_iflag(flags);	\
+})
+
+#ifdef CONFIG_PREEMPT
+#define adeos_spin_lock(x)    _raw_spin_lock(x)
+#define adeos_spin_unlock(x)  _raw_spin_unlock(x)
+#define adeos_spin_trylock(x) _raw_spin_trylock(x)
+#define __adeos_bump_count   "movl %%esp, %%ebx\n\t" \
+	                     "andl $-8192, %%ebx\n\t" \
+			     "incl 4(%%ebx)\n\t"
+#define __adeos_bump_count_noarg  "movl %esp, %ebx\n\t" \
+	                          "andl $-8192, %ebx\n\t" \
+			          "incl 4(%ebx)\n\t"
+#else /* !CONFIG_PREEMPT */
+#define adeos_spin_lock(x)    spin_lock(x)
+#define adeos_spin_unlock(x)  spin_unlock(x)
+#define adeos_spin_trylock(x) spin_trylock(x)
+#define __adeos_bump_count
+#define __adeos_bump_count_noarg
+#endif /* CONFIG_PREEMPT */
+
+#define adeos_spin_lock_irqsave(x,flags)      do { adeos_hw_local_irq_save(flags); adeos_spin_lock(x); } while (0)
+#define adeos_spin_unlock_irqrestore(x,flags) do { adeos_spin_unlock(x); adeos_hw_local_irq_restore(flags); } while (0)
+#define adeos_spin_lock_disable(x)            do { adeos_hw_cli(); adeos_spin_lock(x); } while (0)
+#define adeos_spin_unlock_enable(x)           do { adeos_spin_unlock(x); adeos_hw_sti(); } while (0)
+
+/* Private interface -- Internal use only */
+
+struct adattr;
+
+void __adeos_init(void);
+
+void __adeos_init_domain(adomain_t *adp,
+			 struct adattr *attr);
+
+void __adeos_cleanup_domain(adomain_t *adp);
+
+void __adeos_send_IPI_allbutself(int vector);
+
+void __adeos_send_IPI_other(int cpu,
+			    int vector);
+
+#ifdef CONFIG_SMP
+
+/*
+ * __adeos_switch_to() -- Switch domain contexts. The current domain
+ * is switched out while the domain pointed by "adp" is switched
+ * in. The current cpu identifier which is always known from callers
+ * is also passed to save a few cycles.
+ * This code works out the following tasks:
+ * - build a resume frame for the suspended domain,
+ * - save it's stack pointer,
+ * - load the incoming domain's stack pointer,
+ * - update the global domain descriptor pointer,
+ * - then finally activate the resume frame of the incoming domain.
+ *
+ * SMP version also provides for safe CPU migration (i.e. the domain
+ * may be switched back in on behalf of a different CPU than the one
+ * which switched it out).
+ */
+
+static inline void __adeos_switch_to (adomain_t *adp, int cpuid) {
+
+    __asm__ __volatile__( \
+	"pushl %%ecx\n\t" \
+	"pushl %%ebx\n\t" \
+	"pushl %%ebp\n\t" \
+	"pushl %%edi\n\t" \
+	"pushl %%esi\n\t" \
+	"pushfl\n\t" \
+	"cli\n\t" \
+	"movl %%eax, %%ecx\n\t" \
+	"leal " __stringify(adp_cpu_current) "(,%%eax,4),%%eax\n\t" \
+	"xchg (%%eax), %%edx\n\t" \
+	"pushl %%edx\n\t" \
+	"pushl $1f\n\t" \
+	"sall $2,%%ecx\n\t" \
+	"addl $4,%%ecx\n\t" \
+	"movl %%esp, (%%ecx,%%edx)\n\t" \
+	"movl (%%eax), %%eax\n\t" \
+	"movl (%%ecx,%%eax), %%esp\n\t" \
+	"ret\n\t" \
+	  /* Call domain switch hook (if any) */
+"1:	 popl %%eax\n\t" \
+	"movl (%%eax), %%eax\n\t" \
+	"popfl\n\t" \
+	"testl %%eax,%%eax\n\t" \
+	"je 2f\n\t" \
+	"call *%%eax\n\t" \
+	  /* Domain resume point */
+"2:	 popl %%esi\n\t" \
+	"popl %%edi\n\t" \
+	"popl %%ebp\n\t" \
+	"popl %%ebx\n\t" \
+	"popl %%ecx\n\t" \
+	: /* no output */ \
+	: "a" (cpuid), "d" (adp));
+}
+
+unsigned long __adeos_set_irq_affinity(unsigned irq,
+				       unsigned long cpumask);
+
+#else /* !CONFIG_SMP */
+
+static inline void __adeos_switch_to (adomain_t *adp, int cpuid) {
+
+    __asm__ __volatile__( \
+	"pushl %%edx\n\t" \
+	"pushl %%ecx\n\t" \
+	"pushl %%ebx\n\t" \
+	"pushl %%ebp\n\t" \
+	"pushl %%edi\n\t" \
+	"pushl %%esi\n\t" \
+	"pushfl\n\t" \
+	"cli\n\t" \
+	"movl " __stringify(adp_cpu_current)", %%edx\n\t" \
+	"pushl %%edx\n\t" \
+	"pushl $1f\n\t" \
+	"movl %%esp, 4(%%edx)\n\t" \
+	"movl 4(%%eax), %%esp\n\t" \
+	"movl %%eax, " __stringify(adp_cpu_current)"\n\t" \
+	"ret\n\t" \
+	  /* Call domain switch hook (if any) */
+"1:      popl %%eax\n\t" \
+	"movl (%%eax),%%eax\n\t" \
+	"popfl\n\t" \
+	"testl %%eax,%%eax\n\t" \
+	"je 2f\n\t" \
+	"call *%%eax\n\t" \
+	  /* Domain resume point */
+"2:	 popl %%esi\n\t" \
+	"popl %%edi\n\t" \
+	"popl %%ebp\n\t" \
+	"popl %%ebx\n\t" \
+	"popl %%ecx\n\t" \
+	"popl %%edx\n\t" \
+	: /* no output */ \
+        : "a" (adp));
+}
+
+#endif /* CONFIG_SMP */
+
+void __adeos_enable_pipeline(void);
+
+void __adeos_disable_pipeline(void);
+
+void __adeos_init_stage(adomain_t *adp);
+
+void __adeos_sync_stage(void);
+
+int __adeos_ack_system_irq(unsigned irq);
+
+int __adeos_handle_irq(struct pt_regs regs);
+
+extern struct pt_regs __adeos_tick_regs;
+
+extern int __adeos_tick_irq;
+
+#endif /* !__I386_ADEOS_H */
diff -Nurp linux-2.4.22-clean/include/asm-i386/hw_irq.h linux-2.4.22-adeos-ltt/include/asm-i386/hw_irq.h
--- linux-2.4.22-clean/include/asm-i386/hw_irq.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/include/asm-i386/hw_irq.h	2003-11-21 23:53:48.000000000 -0800
@@ -56,7 +56,12 @@
  * levels. (0x80 is the syscall vector)
  */
 #define FIRST_DEVICE_VECTOR	0x31
+#ifdef CONFIG_ADEOS_CORE
+/* Reserve 16 more vectors for domains. */
+#define FIRST_SYSTEM_VECTOR	0xdf
+#else /* !CONFIG_ADEOS_CORE */
 #define FIRST_SYSTEM_VECTOR	0xef
+#endif /* CONFIG_ADEOS_CORE */
 
 extern int irq_vector[NR_IRQS];
 #define IO_APIC_VECTOR(irq)	irq_vector[irq]
diff -Nurp linux-2.4.22-clean/include/asm-i386/pgalloc.h linux-2.4.22-adeos-ltt/include/asm-i386/pgalloc.h
--- linux-2.4.22-clean/include/asm-i386/pgalloc.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/include/asm-i386/pgalloc.h	2003-11-21 23:53:48.000000000 -0800
@@ -139,6 +139,42 @@ static __inline__ void pte_free_slow(pte
 	free_page((unsigned long)pte);
 }
 
+#ifdef CONFIG_ADEOS_CORE
+
+/* Non-root Adeos domains cannot might not cope with on-demand
+   mappings for I/O or vmalloc'ed memory, so fall back to a brute
+   force instantaneous kernel global mapping of these areas. */
+
+static inline void set_pgdir(unsigned long address, pgd_t entry) {
+
+	struct task_struct *p;
+	pgd_t *pgd;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		if (!p->mm)
+			continue;
+		*pgd_offset(p->mm,address) = entry;
+	}
+	read_unlock(&tasklist_lock);
+#ifdef CONFIG_SMP
+	{
+	int cpu;
+	/* To pgd_alloc/pgd_free, one holds the page table lock and so
+	   does our callee, so we can modify pgd caches of other CPUs
+	   as well. -jj +rpm*/
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		for (pgd = (pgd_t *)cpu_data[cpu].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+			pgd[address >> PGDIR_SHIFT] = entry;
+	}
+#else /* !CONFIG_SMP */
+	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+	       pgd[address >> PGDIR_SHIFT] = entry;
+#endif /* CONFIG_SMP */
+}
+
+#endif /* CONFIG_ADEOS_CORE */
+
 #define pte_free(pte)		pte_free_fast(pte)
 #define pgd_free(pgd)		free_pgd_slow(pgd)
 #define pgd_alloc(mm)		get_pgd_fast()
diff -Nurp linux-2.4.22-clean/include/asm-i386/system.h linux-2.4.22-adeos-ltt/include/asm-i386/system.h
--- linux-2.4.22-clean/include/asm-i386/system.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/include/asm-i386/system.h	2003-11-21 23:53:48.000000000 -0800
@@ -12,6 +12,34 @@
 struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
 extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
+#ifdef CONFIG_ADEOS_CORE
+#define prepare_to_switch(prev,next) \
+do { \
+    struct { struct task_struct *prev, *next; } arg = { (prev), (next) }; \
+    __adeos_schedule_head(&arg); \
+    adeos_hw_cli(); \
+} while(0)
+#define switch_to(prev,next,last) do {					\
+	asm volatile("pushl %%esi\n\t"					\
+		     "pushl %%edi\n\t"					\
+		     "pushl %%ebp\n\t"					\
+		     "movl %%esp,%0\n\t"	/* save ESP */		\
+		     "movl %3,%%esp\n\t"	/* restore ESP */	\
+		     "movl $1f,%1\n\t"		/* save EIP */		\
+		     "pushl %4\n\t"		/* restore EIP */	\
+		     "jmp __switch_to\n"				\
+		     "1:\t"						\
+		     "popl %%ebp\n\t"					\
+		     "popl %%edi\n\t"					\
+		     "popl %%esi\n\t"					\
+		     "sti\n\t"						\
+		     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\
+		      "=b" (last)					\
+		     :"m" (next->thread.esp),"m" (next->thread.eip),	\
+		      "a" (prev), "d" (next),				\
+		      "b" (prev));					\
+} while (0)
+#else /* !CONFIG_ADEOS_CORE */
 #define prepare_to_switch()	do { } while(0)
 #define switch_to(prev,next,last) do {					\
 	asm volatile("pushl %%esi\n\t"					\
@@ -32,6 +60,7 @@ extern void FASTCALL(__switch_to(struct 
 		      "a" (prev), "d" (next),				\
 		      "b" (prev));					\
 } while (0)
+#endif /* CONFIG_ADEOS_CORE */
 
 #define _set_base(addr,base) do { unsigned long __pr; \
 __asm__ __volatile__ ("movw %%dx,%1\n\t" \
@@ -316,6 +345,40 @@ static inline unsigned long __cmpxchg(vo
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 /* interrupt control.. */
+
+#ifdef CONFIG_ADEOS_CORE
+
+extern inline void __adeos_stall_root(void);
+
+extern inline void __adeos_unstall_root(void);
+
+extern inline unsigned long __adeos_test_root(void);
+
+extern inline unsigned long __adeos_test_and_stall_root(void);
+
+void FASTCALL(__adeos_restore_root(unsigned long flags));
+
+#define __save_flags(x)		((x) = __adeos_test_root())
+#define __restore_flags(x) 	__adeos_restore_root(x)
+#define __cli() 		__adeos_stall_root()
+#define __sti()			__adeos_unstall_root()
+/* used in the idle loop; sti takes one instruction cycle to complete */
+#define safe_halt()		__asm__ __volatile__("call "__stringify(__adeos_unstall_root)"; hlt": : :"memory")
+
+#define __save_and_cli(x)	do { __save_flags(x); __cli(); } while(0);
+#define __save_and_sti(x)	do { __save_flags(x); __sti(); } while(0);
+
+/* For spinlocks etc */
+#define local_irq_save(x)	((x) = __adeos_test_and_stall_root())
+#define local_irq_set(x)	__save_and_sti(x)
+#define local_irq_restore(x)	__adeos_restore_root(x)
+#define local_irq_disable()	__adeos_stall_root()
+#define local_irq_enable()	__adeos_unstall_root()
+
+#define irqs_disabled()		__adeos_test_root()
+
+#else /* !CONFIG_ADEOS_CORE */
+
 #define __save_flags(x)		__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
 #define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
 #define __cli() 		__asm__ __volatile__("cli": : :"memory")
@@ -339,6 +402,8 @@ static inline unsigned long __cmpxchg(vo
 #define local_irq_disable()	__cli()
 #define local_irq_enable()	__sti()
 
+#endif /* CONFIG_ADEOS_CORE */
+
 #ifdef CONFIG_SMP
 
 extern void __global_cli(void);
diff -Nurp linux-2.4.22-clean/include/asm-mips/mipsregs.h linux-2.4.22-adeos-ltt/include/asm-mips/mipsregs.h
--- linux-2.4.22-clean/include/asm-mips/mipsregs.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-adeos-ltt/include/asm-mips/mipsregs.h	2003-11-21 23:21:08.000000000 -0800
@@ -510,6 +510,9 @@
 
 #ifndef __ASSEMBLY__
 
+#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE)
+#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2))
+
 /*
  * Functions to access the r10k performance counter and control registers
  */
diff -Nurp linux-2.4.22-clean/include/linux/adeos.h linux-2.4.22-adeos-ltt/include/linux/adeos.h
--- linux-2.4.22-clean/include/linux/adeos.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/include/linux/adeos.h	2003-11-21 23:53:48.000000000 -0800
@@ -0,0 +1,371 @@
+/*
+ *   include/linux/adeos.h
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LINUX_ADEOS_H
+#define __LINUX_ADEOS_H
+
+#include <linux/kernel.h>
+#include <asm/adeos.h>
+
+#define ADEOS_VERSION_PREFIX  "2.4r9/"
+#define ADEOS_VERSION_STRING  (ADEOS_VERSION_PREFIX ADEOS_ARCH_STRING)
+#define ADEOS_RELEASE_NUMBER  0x020409ff
+
+#define ADEOS_ROOT_PRI       100
+#define ADEOS_ROOT_ID        0
+#define ADEOS_ROOT_NPTDKEYS  4	/* Must be <= 32 */
+
+#define ADEOS_OTHER_CPUS   (-1)
+#define ADEOS_RESET_TIMER  0x1
+
+#define IPIPE_STALL_FLAG   0	/* Stalls a pipeline stage */
+#define IPIPE_SYNC_FLAG    1	/* IRQ sync is undergoing */
+#define IPIPE_XPEND_FLAG   2	/* Exception notification is pending */
+#define IPIPE_SLEEP_FLAG   3	/* Domain has suspended itself */
+
+#define IPIPE_HANDLE_FLAG    0
+#define IPIPE_PASS_FLAG      1
+#define IPIPE_CALLASM_FLAG   2
+#define IPIPE_ENABLE_FLAG    3
+#define IPIPE_DYNAMIC_FLAG   IPIPE_HANDLE_FLAG
+#define IPIPE_EXCLUSIVE_FLAG 4
+#define IPIPE_STICKY_FLAG    5
+#define IPIPE_SYSTEM_FLAG    6
+#define IPIPE_LOCK_FLAG      7
+
+#define IPIPE_HANDLE_MASK    (1 << IPIPE_HANDLE_FLAG)
+#define IPIPE_PASS_MASK      (1 << IPIPE_PASS_FLAG)
+#define IPIPE_CALLASM_MASK   (1 << IPIPE_CALLASM_FLAG)
+#define IPIPE_ENABLE_MASK    (1 << IPIPE_ENABLE_FLAG)
+#define IPIPE_DYNAMIC_MASK   IPIPE_HANDLE_MASK
+#define IPIPE_EXCLUSIVE_MASK (1 << IPIPE_EXCLUSIVE_FLAG)
+#define IPIPE_STICKY_MASK    (1 << IPIPE_STICKY_FLAG)
+#define IPIPE_SYSTEM_MASK    (1 << IPIPE_SYSTEM_FLAG)
+#define IPIPE_LOCK_MASK      (1 << IPIPE_LOCK_FLAG)
+
+#define IPIPE_DEFAULT_MASK  (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK)
+
+typedef struct adattr {
+
+    unsigned domid;		/* Domain identifier -- Magic value set by caller */
+    const char *name;		/* Domain name -- Warning: won't be dup'ed! */
+    int priority;		/* Priority in interrupt pipeline */
+    void (*entry)(int);		/* Domain entry point */
+    int estacksz;		/* Stack size for entry context -- 0 means unspec */
+    void (*dswitch)(void);	/* Handler called each time the domain is switched in */
+    int nptdkeys;		/* Max. number of per-thread data keys */
+    void (*ptdset)(int,void *);	/* Routine to set pt values */
+    void *(*ptdget)(int);	/* Routine to get pt values */
+
+} adattr_t;
+
+extern adomain_t *adp_cpu_current[],
+                 *adp_root;
+
+#if defined(CONFIG_ADEOS_MODULE) || defined(CONFIG_X86_IO_APIC)
+extern int adp_pipelined;
+#else  /* !CONFIG_ADEOS_MODULE && !CONFIG_X86_IO_APIC */
+#define adp_pipelined 1		/* Testing this should be optimized out. */
+#endif /* CONFIG_ADEOS_MODULE || CONFIG_X86_IO_APIC */
+
+extern int __adeos_event_monitors[];
+
+#define adp_current (adp_cpu_current[adeos_processor_id()])
+
+/* Private interface */
+
+#ifdef CONFIG_PROC_FS
+void __adeos_init_proc(void);
+#endif /* CONFIG_PROC_FS */
+
+void __adeos_takeover(void);
+
+int __adeos_handle_event(unsigned event,
+			 void *evdata);
+
+void __adeos_dump_state(void);
+
+static inline void __adeos_schedule_head(void *evdata) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_SCHEDULE_HEAD] > 0))
+	__adeos_handle_event(ADEOS_SCHEDULE_HEAD,evdata);
+}
+
+static inline int __adeos_schedule_tail(void *evdata) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_SCHEDULE_TAIL] > 0))
+	return __adeos_handle_event(ADEOS_SCHEDULE_TAIL,evdata);
+
+    return 0;
+}
+
+static inline void __adeos_enter_process(void) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_ENTER_PROCESS] > 0))
+	__adeos_handle_event(ADEOS_ENTER_PROCESS,NULL);
+}
+
+static inline void __adeos_exit_process(void *evdata) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_EXIT_PROCESS] > 0))
+	__adeos_handle_event(ADEOS_EXIT_PROCESS,evdata);
+}
+
+static inline int __adeos_signal_process(void *evdata) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_SIGNAL_PROCESS] > 0))
+	return __adeos_handle_event(ADEOS_SIGNAL_PROCESS,evdata);
+
+    return 0;
+}
+
+static inline int __adeos_renice_process(void *evdata) {
+
+    if (unlikely(__adeos_event_monitors[ADEOS_RENICE_PROCESS] > 0))
+	return __adeos_handle_event(ADEOS_RENICE_PROCESS,evdata);
+
+    return 0;
+}
+
+extern inline void __adeos_stall_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+    else
+	adeos_hw_cli();
+}
+
+extern inline void __adeos_unstall_root (void)
+
+{
+    adeos_hw_sti();	/* Absolutely needed. */
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+
+	clear_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+
+	if (adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage();
+	}
+}
+
+extern inline unsigned long __adeos_test_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	return test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+
+    return adeos_hw_irqs_disabled();
+}
+
+extern inline unsigned long __adeos_test_and_stall_root (void)
+
+{
+    unsigned long flags;
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	return test_and_set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+
+    adeos_hw_local_irq_save(flags);
+
+    return !adeos_hw_test_iflag(flags);
+}
+
+void FASTCALL(__adeos_restore_root(unsigned long flags));
+
+/* Public interface */
+
+int adeos_register_domain(adomain_t *adp,
+			  adattr_t *attr);
+
+int adeos_unregister_domain(adomain_t *adp);
+
+void adeos_renice_domain(adomain_t *adp,
+			 int newpri);
+
+void adeos_suspend_domain(void);
+
+int adeos_virtualize_irq(unsigned irq,
+			 void (*handler)(unsigned irq),
+			 int (*acknowledge)(unsigned irq),
+			 unsigned modemask);
+
+int adeos_control_irq(unsigned irq,
+		      unsigned clrmask,
+		      unsigned setmask);
+
+unsigned long adeos_set_irq_affinity(unsigned irq,
+				     unsigned long cpumask);
+unsigned adeos_alloc_irq(void);
+
+int adeos_free_irq(unsigned irq);
+
+int FASTCALL(adeos_trigger_irq(unsigned irq));
+
+int FASTCALL(adeos_propagate_irq(unsigned irq));
+
+int FASTCALL(adeos_schedule_irq(unsigned irq));
+
+int FASTCALL(adeos_trigger_ipi(int cpuid));
+
+static inline void adeos_stall_pipeline_from (adomain_t *adp) {
+
+    adeos_declare_cpuid;
+    set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+static inline void adeos_stall_pipeline (void) {
+
+    adeos_stall_pipeline_from(adp_current);
+}
+
+void FASTCALL(adeos_unstall_pipeline_from(adomain_t *adp));
+
+static inline void adeos_unstall_pipeline (void) {
+
+    adeos_declare_cpuid;
+
+    clear_bit(IPIPE_STALL_FLAG,&adp_current->cpudata[cpuid].status);
+
+    if (unlikely(adp_current->cpudata[cpuid].irq_pending_hi != 0))
+	__adeos_sync_stage();
+}
+
+static inline unsigned long adeos_test_pipeline_from (adomain_t *adp) {
+
+    return test_bit(IPIPE_STALL_FLAG,&adp->cpudata[adeos_processor_id()].status);
+}
+
+static inline unsigned long adeos_test_pipeline_remote (adomain_t *adp, int cpuid) {
+
+    return test_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+static inline unsigned long adeos_test_pipeline (void) {
+
+    return adeos_test_pipeline_from(adp_current);
+}
+
+static inline unsigned long adeos_test_and_stall_pipeline_from (adomain_t *adp) {
+    
+    return test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[adeos_processor_id()].status);
+}
+
+static inline unsigned long adeos_test_and_stall_pipeline_remote (adomain_t *adp, int cpuid) {
+    
+    return test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+static inline unsigned long adeos_test_and_stall_pipeline (void) {
+    
+    return adeos_test_and_stall_pipeline_from(adp_current);
+}
+
+static inline void adeos_restore_pipeline_from (adomain_t *adp, unsigned long flags) {
+
+    if (flags)
+	set_bit(IPIPE_STALL_FLAG,&adp->cpudata[adeos_processor_id()].status);
+    else
+	adeos_unstall_pipeline_from(adp);
+}
+
+static inline void adeos_restore_pipeline (unsigned long flags) {
+
+    adeos_declare_cpuid;
+    adomain_t *adp = adp_cpu_current[cpuid];
+
+    if (flags)
+	set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    else
+	{
+	clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+	if (unlikely(adp->cpudata[cpuid].irq_pending_hi != 0))
+	    __adeos_sync_stage();
+	}
+}
+
+static inline void adeos_restore_pipeline_nosync (adomain_t *adp, unsigned long flags, int cpuid) {
+
+    if (flags)
+	set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    else
+	clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+static inline void adeos_restore_pipeline_remote (adomain_t *adp, unsigned long flags, int cpuid) {
+
+    adeos_restore_pipeline_nosync(adp,flags,cpuid);
+}
+
+int adeos_catch_event_from(adomain_t *adp,
+			   unsigned event,
+			   void (*handler)(adevinfo_t *));
+
+static inline int adeos_catch_event (unsigned event, void (*handler)(adevinfo_t *)) {
+    return adeos_catch_event_from(adp_current,event,handler);
+}
+
+static inline void adeos_propagate_event(adevinfo_t *evinfo) {
+
+    evinfo->propagate = 1;
+}
+
+void (*adeos_hook_dswitch(void (*handler)(void)))(void);
+
+void adeos_init_attr(adattr_t *attr);
+
+int adeos_get_sysinfo(adsysinfo_t *sysinfo);
+
+int adeos_tune_timer(unsigned long ns,
+		     int flags);
+
+int adeos_alloc_ptdkey(void);
+
+int adeos_free_ptdkey(int key);
+
+int adeos_set_ptd(int key,
+		  void *value);
+
+void *adeos_get_ptd(int key);
+
+unsigned long adeos_critical_enter(void (*syncfn)(void));
+
+void adeos_critical_exit(unsigned long flags);
+
+unsigned long FASTCALL(adeos_lock_mutex(admutex_t *mutex));
+
+void FASTCALL(adeos_unlock_mutex(admutex_t *mutex,
+				 unsigned long flags));
+
+#endif /* !__LINUX_ADEOS_H */
diff -Nurp linux-2.4.22-clean/include/linux/sched.h linux-2.4.22-adeos-ltt/include/linux/sched.h
--- linux-2.4.22-clean/include/linux/sched.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/include/linux/sched.h	2003-11-21 23:53:48.000000000 -0800
@@ -125,6 +125,10 @@ struct completion;
 
 #include <linux/spinlock.h>
 
+#ifdef CONFIG_ADEOS_CORE
+#include <linux/adeos.h>
+#endif /* CONFIG_ADEOS_CORE */
+
 /*
  * This serializes "schedule()" and also protects
  * the run-queue from deletions/modifications (but
@@ -415,6 +419,10 @@ struct task_struct {
 
 /* journalling filesystem info */
 	void *journal_info;
+
+#ifdef CONFIG_ADEOS_CORE
+        void *ptd[ADEOS_ROOT_NPTDKEYS];
+#endif /* CONFIG_ADEOS_CORE */
 };
 
 /*
@@ -468,6 +476,51 @@ extern struct exec_domain	default_exec_d
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
+#ifdef CONFIG_ADEOS_CORE
+#define INIT_TASK(tsk)	\
+{									\
+    state:		0,						\
+    flags:		0,						\
+    sigpending:		0,						\
+    addr_limit:		KERNEL_DS,					\
+    exec_domain:	&default_exec_domain,				\
+    lock_depth:		-1,						\
+    counter:		DEF_COUNTER,					\
+    nice:		DEF_NICE,					\
+    policy:		SCHED_OTHER,					\
+    mm:			NULL,						\
+    active_mm:		&init_mm,					\
+    cpus_runnable:	~0UL,						\
+    cpus_allowed:	~0UL,						\
+    run_list:		LIST_HEAD_INIT(tsk.run_list),			\
+    next_task:		&tsk,						\
+    prev_task:		&tsk,						\
+    p_opptr:		&tsk,						\
+    p_pptr:		&tsk,						\
+    thread_group:	LIST_HEAD_INIT(tsk.thread_group),		\
+    wait_chldexit:	__WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\
+    real_timer:		{						\
+	function:		it_real_fn				\
+    },									\
+    cap_effective:	CAP_INIT_EFF_SET,				\
+    cap_inheritable:	CAP_INIT_INH_SET,				\
+    cap_permitted:	CAP_FULL_SET,					\
+    keep_capabilities:	0,						\
+    rlim:		INIT_RLIMITS,					\
+    user:		INIT_USER,					\
+    comm:		"swapper",					\
+    thread:		INIT_THREAD,					\
+    fs:			&init_fs,					\
+    files:		&init_files,					\
+    sigmask_lock:	SPIN_LOCK_UNLOCKED,				\
+    sig:		&init_signals,					\
+    pending:		{ NULL, &tsk.pending.head, {{0}}},		\
+    blocked:		{{0}},						\
+    alloc_lock:		SPIN_LOCK_UNLOCKED,				\
+    journal_info:	NULL,						\
+    ptd:                { [ 0 ... ADEOS_ROOT_NPTDKEYS - 1] = 0 },       \
+}
+#else /* !CONFIG_ADEOS_CORE */
 #define INIT_TASK(tsk)	\
 {									\
     state:		0,						\
@@ -510,6 +563,7 @@ extern struct exec_domain	default_exec_d
     alloc_lock:		SPIN_LOCK_UNLOCKED,				\
     journal_info:	NULL,						\
 }
+#endif /* CONFIG_ADEOS_CORE */
 
 
 #ifndef INIT_TASK_SIZE
diff -Nurp linux-2.4.22-clean/include/linux/trace.h linux-2.4.22-adeos-ltt/include/linux/trace.h
--- linux-2.4.22-clean/include/linux/trace.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/include/linux/trace.h	2003-11-21 23:53:48.000000000 -0800
@@ -0,0 +1,437 @@
+/*
+ * linux/include/linux/trace.h
+ *
+ * Copyright (C) 1999, Karim Yaghmour
+ *
+ * This contains the necessary definitions for tracing the
+ * the system.
+ */
+
+#ifndef _LINUX_TRACE_H
+#define _LINUX_TRACE_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+/* Is kernel tracing enabled */
+#if defined(CONFIG_TRACE) || defined(CONFIG_TRACE_MODULE)
+
+/* Structure packing within the trace */
+#if LTT_UNPACKED_STRUCTS
+#define LTT_PACKED_STRUCT
+#else  /* if LTT_UNPACKED_STRUCTS */
+#define LTT_PACKED_STRUCT __attribute__ ((packed))
+#endif /* if LTT_UNPACKED_STRUCTS */
+
+/* The prototype of the tracer call (EventID, *EventStruct) */
+typedef int (*tracer_call) (uint8_t, void*);
+
+/* This structure contains all the information needed to be known
+   about the tracing module. */
+struct tracer
+{
+  /* The tracing routine itself */
+  tracer_call trace;
+
+  /* Fetch of eip origin of syscall */
+  int         fetch_syscall_eip_use_depth;  /* Use the given depth */
+  int         fetch_syscall_eip_use_bounds; /* Find eip in bounds */
+  int         syscall_eip_depth;            /* Call depth at which eip is fetched */
+  void*       syscall_lower_eip_bound;      /* Lower eip bound */
+  void*       syscall_upper_eip_bound;      /* Higher eip bound */
+};
+
+/* Maximal size a custom event can have */
+#define CUSTOM_EVENT_MAX_SIZE        8192
+
+/* String length limits for custom events creation */
+#define CUSTOM_EVENT_TYPE_STR_LEN      20
+#define CUSTOM_EVENT_DESC_STR_LEN     100
+#define CUSTOM_EVENT_FORM_STR_LEN     256
+#define CUSTOM_EVENT_FINAL_STR_LEN    200
+
+/* Type of custom event formats */
+#define CUSTOM_EVENT_FORMAT_TYPE_NONE   0
+#define CUSTOM_EVENT_FORMAT_TYPE_STR    1
+#define CUSTOM_EVENT_FORMAT_TYPE_HEX    2
+#define CUSTOM_EVENT_FORMAT_TYPE_XML    3
+#define CUSTOM_EVENT_FORMAT_TYPE_IBM    4
+
+/* Global trace flags */
+extern unsigned int syscall_entry_trace_active;
+extern unsigned int syscall_exit_trace_active;
+
+/* The functions to the tracer management code */
+int register_tracer
+       (tracer_call   /* The tracer function */);
+int unregister_tracer
+       (tracer_call   /* The tracer function */);
+int trace_set_config
+       (tracer_call   /* The tracer function */,
+	int           /* Use depth to fetch eip */,
+	int           /* Use bounds to fetch eip */,
+	int           /* Detph to fetch eip */,
+	void*         /* Lower bound eip address */,
+	void*         /* Upper bound eip address */);
+int trace_register_callback
+       (tracer_call   /* The callback to add */,
+	uint8_t       /* The event ID targeted */);
+int trace_unregister_callback
+       (tracer_call   /* The callback to remove */,
+	uint8_t       /* The event ID targeted */);
+int trace_get_config
+       (int*          /* Use depth to fetch eip */,
+	int*          /* Use bounds to fetch eip */,
+	int*          /* Detph to fetch eip */,
+	void**        /* Lower bound eip address */,
+	void**        /* Upper bound eip address */);
+int  trace_create_event
+       (char*         /* String describing event type */,
+	char*         /* String to format standard event description */,
+	int           /* Type of formatting used to log event data */,
+	char*         /* Data specific to format */);
+int  trace_create_owned_event
+       (char*         /* String describing event type */,
+	char*         /* String to format standard event description */,
+	int           /* Type of formatting used to log event data */,
+	char*         /* Data specific to format */,
+	pid_t         /* PID of event's owner */);
+void trace_destroy_event
+       (int           /* The event ID given by trace_create_event() */);
+void trace_destroy_owners_events
+       (pid_t         /* The PID of the process' who's events are to be deleted */);
+void trace_reregister_custom_events
+       (void);
+int  trace_std_formatted_event
+       (int           /* The event ID given by trace_create_event() */,
+	...           /* The parameters to be printed out in the event string */);
+int  trace_raw_event
+       (int           /* The event ID given by trace_create_event() */,
+	int           /* The size of the raw data */,
+	void*         /* Pointer to the raw event data */);
+int  trace_event
+       (uint8_t       /* Event ID (as defined in this header file) */,
+	void*         /* Structure describing the event */);
+
+/* Generic macros */
+#define TRACE_EVENT(ID, DATA) trace_event(ID, DATA)
+
+/* Traced events */
+#define TRACE_EV_START           0    /* This is to mark the trace's start */
+#define TRACE_EV_SYSCALL_ENTRY   1    /* Entry in a given system call */
+#define TRACE_EV_SYSCALL_EXIT    2    /* Exit from a given system call */
+#define TRACE_EV_TRAP_ENTRY      3    /* Entry in a trap */
+#define TRACE_EV_TRAP_EXIT       4    /* Exit from a trap */
+#define TRACE_EV_IRQ_ENTRY       5    /* Entry in an irq */
+#define TRACE_EV_IRQ_EXIT        6    /* Exit from an irq */
+#define TRACE_EV_SCHEDCHANGE     7    /* Scheduling change */
+#define TRACE_EV_KERNEL_TIMER    8    /* The kernel timer routine has been called */
+#define TRACE_EV_SOFT_IRQ        9    /* Hit key part of soft-irq management */
+#define TRACE_EV_PROCESS        10    /* Hit key part of process management */
+#define TRACE_EV_FILE_SYSTEM    11    /* Hit key part of file system */
+#define TRACE_EV_TIMER          12    /* Hit key part of timer management */
+#define TRACE_EV_MEMORY         13    /* Hit key part of memory management */
+#define TRACE_EV_SOCKET         14    /* Hit key part of socket communication */
+#define TRACE_EV_IPC            15    /* Hit key part of System V IPC */
+#define TRACE_EV_NETWORK        16    /* Hit key part of network communication */
+
+#define TRACE_EV_BUFFER_START   17    /* Mark the begining of a trace buffer */
+#define TRACE_EV_BUFFER_END     18    /* Mark the ending of a trace buffer */
+#define TRACE_EV_NEW_EVENT      19    /* New event type */
+#define TRACE_EV_CUSTOM         20    /* Custom event */
+
+#define TRACE_EV_CHANGE_MASK    21    /* Change in event mask */
+
+/* Number of traced events */
+#define TRACE_EV_MAX           TRACE_EV_CHANGE_MASK
+
+/* Structures and macros for events */
+/*  TRACE_SYSCALL_ENTRY */
+typedef struct _trace_syscall_entry
+{
+  uint8_t   syscall_id;   /* Syscall entry number in entry.S */
+  uint32_t  address;      /* Address from which call was made */
+} LTT_PACKED_STRUCT trace_syscall_entry;
+
+/*  TRACE_TRAP_ENTRY */
+#ifndef __s390__
+typedef struct _trace_trap_entry
+{
+  uint16_t  trap_id;  /* Trap number */
+  uint32_t  address;  /* Address where trap occured */
+} LTT_PACKED_STRUCT trace_trap_entry;
+#else
+typedef uint64_t trapid_t;
+typedef struct _trace_trap_entry
+{
+  trapid_t  trap_id;  /* Trap number */
+  uint32_t  address;  /* Address where trap occured */
+} LTT_PACKED_STRUCT trace_trap_entry;
+#endif
+#define TRACE_TRAP_ENTRY(ID, EIP) \
+           do \
+           {\
+           trace_trap_entry trap_event;\
+           trap_event.trap_id = ID;\
+           trap_event.address = EIP;\
+           trace_event(TRACE_EV_TRAP_ENTRY, &trap_event);\
+	   } while(0)
+
+/*  TRACE_TRAP_EXIT */
+#define TRACE_TRAP_EXIT()  trace_event(TRACE_EV_TRAP_EXIT, NULL)
+
+/*  TRACE_IRQ_ENTRY */
+typedef struct _trace_irq_entry
+{
+  uint8_t  irq_id;      /* IRQ number */
+  uint8_t  kernel;      /* Are we executing kernel code */
+} LTT_PACKED_STRUCT trace_irq_entry;
+#define TRACE_IRQ_ENTRY(ID, KERNEL) \
+           do \
+           {\
+           trace_irq_entry irq_entry;\
+           irq_entry.irq_id = ID;\
+           irq_entry.kernel = KERNEL;\
+           trace_event(TRACE_EV_IRQ_ENTRY, &irq_entry);\
+           } while(0)
+
+/*  TRACE_IRQ_EXIT */
+#define TRACE_IRQ_EXIT()  trace_event(TRACE_EV_IRQ_EXIT, NULL)
+
+/*  TRACE_SCHEDCHANGE */ 
+typedef struct _trace_schedchange
+{
+  uint32_t  out;         /* Outgoing process */
+  uint32_t  in;          /* Incoming process */
+  uint32_t  out_state;   /* Outgoing process' state */
+} LTT_PACKED_STRUCT trace_schedchange;
+#define TRACE_SCHEDCHANGE(OUT, IN) \
+           do \
+           {\
+           trace_schedchange sched_event;\
+           sched_event.out       = OUT->pid;\
+           sched_event.in        = (uint32_t) IN;\
+           sched_event.out_state = OUT->state; \
+           trace_event(TRACE_EV_SCHEDCHANGE, &sched_event);\
+           } while(0)
+
+/*  TRACE_SOFT_IRQ */
+#define TRACE_EV_SOFT_IRQ_BOTTOM_HALF        1  /* Conventional bottom-half */
+#define TRACE_EV_SOFT_IRQ_SOFT_IRQ           2  /* Real soft-irq */
+#define TRACE_EV_SOFT_IRQ_TASKLET_ACTION     3  /* Tasklet action */
+#define TRACE_EV_SOFT_IRQ_TASKLET_HI_ACTION  4  /* Tasklet hi-action */
+typedef struct _trace_soft_irq
+{
+  uint8_t   event_sub_id;     /* Soft-irq event Id */
+  uint32_t  event_data;       /* Data associated with event */
+} LTT_PACKED_STRUCT trace_soft_irq;
+#define TRACE_SOFT_IRQ(ID, DATA) \
+           do \
+           {\
+           trace_soft_irq soft_irq_event;\
+           soft_irq_event.event_sub_id = ID;\
+           soft_irq_event.event_data   = DATA;\
+           trace_event(TRACE_EV_SOFT_IRQ, &soft_irq_event);\
+	   } while(0)
+
+/*  TRACE_PROCESS */
+#define TRACE_EV_PROCESS_KTHREAD     1  /* Creation of a kernel thread */
+#define TRACE_EV_PROCESS_FORK        2  /* A fork or clone occured */
+#define TRACE_EV_PROCESS_EXIT        3  /* An exit occured */
+#define TRACE_EV_PROCESS_WAIT        4  /* A wait occured */
+#define TRACE_EV_PROCESS_SIGNAL      5  /* A signal has been sent */
+#define TRACE_EV_PROCESS_WAKEUP      6  /* Wake up a process */
+typedef struct _trace_process
+{
+  uint8_t   event_sub_id;    /* Process event ID */
+  uint32_t  event_data1;     /* Data associated with event */
+  uint32_t  event_data2; 
+} LTT_PACKED_STRUCT trace_process;
+#define TRACE_PROCESS(ID, DATA1, DATA2) \
+           do \
+           {\
+           trace_process proc_event;\
+           proc_event.event_sub_id = ID;\
+           proc_event.event_data1 = DATA1;\
+           proc_event.event_data2 = DATA2;\
+           trace_event(TRACE_EV_PROCESS, &proc_event);\
+           } while(0)
+
+/*  TRACE_FILE_SYSTEM */
+#define TRACE_EV_FILE_SYSTEM_BUF_WAIT_START  1  /* Starting to wait for a data buffer */
+#define TRACE_EV_FILE_SYSTEM_BUF_WAIT_END    2  /* End to wait for a data buffer */
+#define TRACE_EV_FILE_SYSTEM_EXEC            3  /* An exec occured */
+#define TRACE_EV_FILE_SYSTEM_OPEN            4  /* An open occured */
+#define TRACE_EV_FILE_SYSTEM_CLOSE           5  /* A close occured */
+#define TRACE_EV_FILE_SYSTEM_READ            6  /* A read occured */
+#define TRACE_EV_FILE_SYSTEM_WRITE           7  /* A write occured */
+#define TRACE_EV_FILE_SYSTEM_SEEK            8  /* A seek occured */
+#define TRACE_EV_FILE_SYSTEM_IOCTL           9  /* An ioctl occured */
+#define TRACE_EV_FILE_SYSTEM_SELECT         10  /* A select occured */
+#define TRACE_EV_FILE_SYSTEM_POLL           11  /* A poll occured */
+typedef struct _trace_file_system
+{
+  uint8_t   event_sub_id;    /* File system event ID */
+  uint32_t  event_data1;     /* Event data */
+  uint32_t  event_data2;     /* Event data 2 */
+  char*     file_name;       /* Name of file operated on */
+} LTT_PACKED_STRUCT trace_file_system;
+#define TRACE_FILE_SYSTEM(ID, DATA1, DATA2, FILE_NAME) \
+           do \
+           {\
+           trace_file_system fs_event;\
+           fs_event.event_sub_id = ID;\
+           fs_event.event_data1  = DATA1;\
+           fs_event.event_data2  = DATA2;\
+           fs_event.file_name    = (char*)FILE_NAME;\
+           trace_event(TRACE_EV_FILE_SYSTEM, &fs_event);\
+           } while(0)
+
+/*  TRACE_TIMER */
+#define TRACE_EV_TIMER_EXPIRED      1  /* Timer expired */
+#define TRACE_EV_TIMER_SETITIMER    2  /* Setting itimer occurred */
+#define TRACE_EV_TIMER_SETTIMEOUT   3  /* Setting sched timeout occurred */
+typedef struct _trace_timer
+{
+  uint8_t   event_sub_id;    /* Timer event ID */
+  uint8_t   event_sdata;     /* Short data */
+  uint32_t  event_data1;     /* Data associated with event */
+  uint32_t  event_data2;     
+} LTT_PACKED_STRUCT trace_timer;
+#define TRACE_TIMER(ID, SDATA, DATA1, DATA2) \
+           do \
+           {\
+           trace_timer timer_event;\
+           timer_event.event_sub_id = ID;\
+           timer_event.event_sdata  = SDATA;\
+           timer_event.event_data1  = DATA1;\
+           timer_event.event_data2  = DATA2;\
+           trace_event(TRACE_EV_TIMER, &timer_event);\
+	   } while(0)
+
+/*  TRACE_MEMORY */
+#define TRACE_EV_MEMORY_PAGE_ALLOC        1  /* Allocating pages */
+#define TRACE_EV_MEMORY_PAGE_FREE         2  /* Freing pages */
+#define TRACE_EV_MEMORY_SWAP_IN           3  /* Swaping pages in */
+#define TRACE_EV_MEMORY_SWAP_OUT          4  /* Swaping pages out */
+#define TRACE_EV_MEMORY_PAGE_WAIT_START   5  /* Start to wait for page */
+#define TRACE_EV_MEMORY_PAGE_WAIT_END     6  /* End to wait for page */
+typedef struct _trace_memory
+{
+  uint8_t        event_sub_id;    /* Memory event ID */
+  unsigned long  event_data;      /* Data associated with event */
+} LTT_PACKED_STRUCT trace_memory;
+#define TRACE_MEMORY(ID, DATA) \
+           do \
+           {\
+           trace_memory memory_event;\
+           memory_event.event_sub_id = ID;\
+           memory_event.event_data   = DATA;\
+           trace_event(TRACE_EV_MEMORY, &memory_event);\
+           } while(0)
+
+/*  TRACE_SOCKET */
+#define TRACE_EV_SOCKET_CALL     1  /* A socket call occured */
+#define TRACE_EV_SOCKET_CREATE   2  /* A socket has been created */
+#define TRACE_EV_SOCKET_SEND     3  /* Data was sent to a socket */
+#define TRACE_EV_SOCKET_RECEIVE  4  /* Data was read from a socket */
+typedef struct _trace_socket
+{
+  uint8_t   event_sub_id;    /* Socket event ID */
+  uint32_t  event_data1;     /* Data associated with event */
+  uint32_t  event_data2;     /* Data associated with event */
+} LTT_PACKED_STRUCT trace_socket;
+#define TRACE_SOCKET(ID, DATA1, DATA2) \
+           do \
+           {\
+           trace_socket socket_event;\
+           socket_event.event_sub_id = ID;\
+           socket_event.event_data1  = DATA1;\
+           socket_event.event_data2  = DATA2;\
+           trace_event(TRACE_EV_SOCKET, &socket_event);\
+           } while(0)
+
+/*  TRACE_IPC */
+#define TRACE_EV_IPC_CALL            1  /* A System V IPC call occured */
+#define TRACE_EV_IPC_MSG_CREATE      2  /* A message queue has been created */
+#define TRACE_EV_IPC_SEM_CREATE      3  /* A semaphore was created */
+#define TRACE_EV_IPC_SHM_CREATE      4  /* A shared memory segment has been created */
+typedef struct _trace_ipc
+{
+  uint8_t   event_sub_id;    /* IPC event ID */
+  uint32_t  event_data1;     /* Data associated with event */
+  uint32_t  event_data2;     /* Data associated with event */
+} LTT_PACKED_STRUCT trace_ipc;
+#define TRACE_IPC(ID, DATA1, DATA2) \
+           do \
+           {\
+           trace_ipc ipc_event;\
+           ipc_event.event_sub_id = ID;\
+           ipc_event.event_data1  = DATA1;\
+           ipc_event.event_data2  = DATA2;\
+           trace_event(TRACE_EV_IPC, &ipc_event);\
+           } while(0)
+
+/*  TRACE_NETWORK */
+#define TRACE_EV_NETWORK_PACKET_IN   1  /* A packet came in */
+#define TRACE_EV_NETWORK_PACKET_OUT  2  /* A packet was sent */
+typedef struct _trace_network
+{
+  uint8_t  event_sub_id;   /* Network event ID */
+  uint32_t event_data;     /* Event data */
+} LTT_PACKED_STRUCT trace_network;
+#define TRACE_NETWORK(ID, DATA) \
+           do \
+           {\
+           trace_network net_event;\
+           net_event.event_sub_id = ID;\
+           net_event.event_data   = DATA;\
+           trace_event(TRACE_EV_NETWORK, &net_event);\
+           } while(0)
+
+/* Custom declared events */
+/* ***WARNING*** These structures should never be used as is, use the provided custom event creation
+                 and logging functions. */
+typedef struct _trace_new_event
+{
+  /* Basics */
+  uint32_t         id;                               /* Custom event ID */
+  char             type[CUSTOM_EVENT_TYPE_STR_LEN];  /* Event type description */
+  char             desc[CUSTOM_EVENT_DESC_STR_LEN];  /* Detailed event description */
+
+  /* Custom formatting */
+  uint32_t         format_type;                       /* Type of formatting */
+  char             form[CUSTOM_EVENT_FORM_STR_LEN];   /* Data specific to format */
+} LTT_PACKED_STRUCT trace_new_event;
+typedef struct _trace_custom
+{
+  uint32_t          id;         /* Event ID */
+  uint32_t          data_size;  /* Size of data recorded by event */
+  void*             data;       /* Data recorded by event */
+} LTT_PACKED_STRUCT trace_custom;
+
+/* TRACE_CHANGE_MASK */
+typedef uint64_t trace_event_mask;    /* The event mask type */
+typedef struct _trace_change_mask
+{
+  trace_event_mask          mask;       /* Event mask */
+} LTT_PACKED_STRUCT trace_change_mask;
+
+#else /* Kernel is configured without tracing */
+#define TRACE_EVENT(ID, DATA)
+#define TRACE_TRAP_ENTRY(ID, EIP)
+#define TRACE_TRAP_EXIT()
+#define TRACE_IRQ_ENTRY(ID, KERNEL)
+#define TRACE_IRQ_EXIT()
+#define TRACE_SCHEDCHANGE(OUT, IN)
+#define TRACE_SOFT_IRQ(ID, DATA)
+#define TRACE_PROCESS(ID, DATA1, DATA2)
+#define TRACE_FILE_SYSTEM(ID, DATA1, DATA2, FILE_NAME)
+#define TRACE_TIMER(ID, SDATA, DATA1, DATA2)
+#define TRACE_MEMORY(ID, DATA)
+#define TRACE_SOCKET(ID, DATA1, DATA2)
+#define TRACE_IPC(ID, DATA1, DATA2)
+#define TRACE_NETWORK(ID, DATA)
+#endif /* defined(CONFIG_TRACE) || defined(CONFIG_TRACE_MODULE) */
+
+#endif /* _LINUX_TRACE_H */
diff -Nurp linux-2.4.22-clean/init/main.c linux-2.4.22-adeos-ltt/init/main.c
--- linux-2.4.22-clean/init/main.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/init/main.c	2003-11-21 23:25:36.000000000 -0800
@@ -364,6 +364,9 @@ asmlinkage void __init start_kernel(void
 	parse_options(command_line);
 	trap_init();
 	init_IRQ();
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_init();
+#endif /* CONFIG_ADEOS_CORE */
 	sched_init();
 	softirq_init();
 	time_init();
@@ -436,6 +439,9 @@ asmlinkage void __init start_kernel(void
 	 *	make syscalls (and thus be locked).
 	 */
 	smp_init();
+#if defined(CONFIG_ADEOS) && defined(CONFIG_X86_IO_APIC)
+	__adeos_takeover();
+#endif /* CONFIG_ADEOS && CONFIG_X86_IO_APIC */
 	rest_init();
 }
 
diff -Nurp linux-2.4.22-clean/ipc/msg.c linux-2.4.22-adeos-ltt/ipc/msg.c
--- linux-2.4.22-clean/ipc/msg.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/ipc/msg.c	2003-11-21 23:21:08.000000000 -0800
@@ -25,6 +25,8 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+#include <linux/trace.h>
+
 /* sysctl: */
 int msg_ctlmax = MSGMAX;
 int msg_ctlmnb = MSGMNB;
@@ -326,6 +328,7 @@ asmlinkage long sys_msgget (key_t key, i
 		msg_unlock(id);
 	}
 	up(&msg_ids.sem);
+	TRACE_IPC(TRACE_EV_IPC_MSG_CREATE, ret, msgflg);
 	return ret;
 }
 
diff -Nurp linux-2.4.22-clean/ipc/sem.c linux-2.4.22-adeos-ltt/ipc/sem.c
--- linux-2.4.22-clean/ipc/sem.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/ipc/sem.c	2003-11-21 23:21:08.000000000 -0800
@@ -66,6 +66,7 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+#include <linux/trace.h>
 
 #define sem_lock(id)	((struct sem_array*)ipc_lock(&sem_ids,id))
 #define sem_unlock(id)	ipc_unlock(&sem_ids,id)
@@ -182,6 +183,7 @@ asmlinkage long sys_semget (key_t key, i
 	}
 
 	up(&sem_ids.sem);
+	TRACE_IPC(TRACE_EV_IPC_SEM_CREATE, err, semflg);
 	return err;
 }
 
diff -Nurp linux-2.4.22-clean/ipc/shm.c linux-2.4.22-adeos-ltt/ipc/shm.c
--- linux-2.4.22-clean/ipc/shm.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.22-adeos-ltt/ipc/shm.c	2003-11-21 23:21:08.000000000 -0800
@@ -26,6 +26,8 @@
 
 #include "util.h"
 
+#include <linux/trace.h>
+
 struct shmid_kernel /* private to the kernel */
 {	
 	struct kern_ipc_perm	shm_perm;
@@ -254,6 +256,7 @@ asmlinkage long sys_shmget (key_t key, s
 		shm_unlock(id);
 	}
 	up(&shm_ids.sem);
+	TRACE_IPC(TRACE_EV_IPC_SHM_CREATE, err, shmflg);
 	return err;
 }
 
diff -Nurp linux-2.4.22-clean/kernel/adeos.c linux-2.4.22-adeos-ltt/kernel/adeos.c
--- linux-2.4.22-clean/kernel/adeos.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/kernel/adeos.c	2003-11-21 23:25:36.000000000 -0800
@@ -0,0 +1,504 @@
+/*
+ *   linux/kernel/adeos.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Architecture-independent ADEOS core support.
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+
+/* The pre-defined domain slot for the root domain. */
+static adomain_t adeos_root_domain;
+
+/* A constant pointer to the root domain. */
+adomain_t *adp_root = &adeos_root_domain;
+
+/* A pointer to the current domain. */
+adomain_t *adp_cpu_current[ADEOS_NR_CPUS] = { [ 0 ... ADEOS_NR_CPUS - 1] = &adeos_root_domain };
+
+#if defined(CONFIG_ADEOS_MODULE) || defined(CONFIG_X86_IO_APIC)
+/* A global flag telling whether Adeos pipelining is engaged. */
+int adp_pipelined = 0;
+#endif /* CONFIG_ADEOS_MODULE || CONFIG_X86_IO_APIC */
+
+/* The spinlock protecting from races while modifying the pipeline. */
+spinlock_t __adeos_pipelock = SPIN_LOCK_UNLOCKED;
+
+/* The pipeline data structure. Enqueues adomain_t objects by priority. */
+struct list_head __adeos_pipeline;
+
+/* An array of global counters tracking domains monitoring events. */
+int __adeos_event_monitors[ADEOS_NR_EVENTS] = { [ 0 ... ADEOS_NR_EVENTS - 1] = 0 };
+
+/* The allocated VIRQ map. */
+unsigned long __adeos_virtual_irq_map = 0;
+
+static void __adeos_set_root_ptd (int key, void *value) {
+
+    current->ptd[key] = value;
+}
+
+static void *__adeos_get_root_ptd (int key) {
+
+    return current->ptd[key];
+}
+
+/* adeos_init() -- Initialization routine of the ADEOS layer. Called
+   by the host kernel early during the boot procedure. */
+
+void __adeos_init (void)
+
+{
+    adomain_t *adp = &adeos_root_domain;
+
+    /*
+      A lightweight registration code for the root domain. Current
+      assumptions are:
+      - We are running on the boot CPU, and secondary CPUs are still
+      lost in space.
+      - adeos_root_domain has been zero'ed.
+    */
+
+    INIT_LIST_HEAD(&__adeos_pipeline);
+
+    adp->name = "Linux";
+    adp->domid = ADEOS_ROOT_ID;
+    adp->priority = ADEOS_ROOT_PRI;
+    adp->ptd_setfun = &__adeos_set_root_ptd;
+    adp->ptd_getfun = &__adeos_get_root_ptd;
+    adp->ptd_keymax = ADEOS_ROOT_NPTDKEYS;
+
+    __adeos_init_stage(adp);
+
+    INIT_LIST_HEAD(&adp->p_link);
+    list_add_tail(&adp->p_link,&__adeos_pipeline);
+
+    printk("ADEOS %s: Root domain %s registered.\n",
+	   ADEOS_VERSION_STRING,
+	   adp->name);
+
+#if defined(CONFIG_ADEOS) && !defined(CONFIG_X86_IO_APIC)
+    __adeos_takeover();
+#endif /* CONFIG_ADEOS && !CONFIG_X86_IO_APIC */
+}
+
+/* adeos_handle_event() -- Adeos' generic event handler. This routine
+calls the per-domain handlers registered for a given
+exception/event. Each domain before the one which raised the event in
+the pipeline will get a chance to process the event. The latter will
+eventually be allowed to process its own event too if a valid handler
+exists for it.  Handler executions are always scheduled by the domain
+which raised the event for the prioritary domains wanting to be
+notified of such event.  Note: evdata might be NULL. */
+
+int __adeos_handle_event (unsigned event, void *evdata)
+
+{
+    struct list_head *pos, *npos;
+    unsigned long flags;
+    adeos_declare_cpuid;
+    adevinfo_t evinfo;
+    int propagate = 1;
+
+    adeos_hw_local_irq_save(flags);
+
+    list_for_each_safe(pos,npos,&__adeos_pipeline) {
+
+    	adomain_t *adp = list_entry(pos,adomain_t,p_link);
+
+	if (adp->events[event].handler != NULL)
+	    {
+	    if (adp == adp_cpu_current[cpuid])
+		{
+		evinfo.domid = adp->domid;
+		evinfo.event = event;
+		evinfo.evdata = evdata;
+		evinfo.propagate = 0;
+		adp->events[event].handler(&evinfo);
+		propagate = evinfo.propagate;
+		break;
+		}
+
+	    adp->cpudata[cpuid].event_info.domid = adp_cpu_current[cpuid]->domid;
+	    adp->cpudata[cpuid].event_info.event = event;
+	    adp->cpudata[cpuid].event_info.evdata = evdata;
+	    adp->cpudata[cpuid].event_info.propagate = 0;
+	    set_bit(IPIPE_XPEND_FLAG,&adp->cpudata[cpuid].status);
+
+	    /* Let the prioritary domain process the event. */
+
+	    __adeos_switch_to(adp,cpuid);
+
+#ifdef CONFIG_SMP
+	    adeos_reload_cpuid();	/* Processor might have changed. */
+#endif /* CONFIG_SMP */
+
+	    if (!adp->cpudata[cpuid].event_info.propagate)
+		{
+		propagate = 0;
+		break;
+		}
+	    }
+
+	if (adp == adp_cpu_current[cpuid])
+	    break;
+    }
+
+    adeos_hw_local_irq_restore(flags);
+
+    if (!test_bit(IPIPE_STALL_FLAG,&adp_cpu_current[cpuid]->cpudata[cpuid].status) &&
+	adp_cpu_current[cpuid]->cpudata[cpuid].irq_pending_hi != 0)
+	__adeos_sync_stage();
+
+    return !propagate;
+}
+
+void __adeos_stall_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+    else
+	adeos_hw_cli();
+}
+
+void __adeos_unstall_root (void)
+
+{
+    adeos_hw_sti();	/* Absolutely needed. */
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+
+	clear_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+
+	if (adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage();
+	}
+}
+
+unsigned long __adeos_test_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	return test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+
+    return adeos_hw_irqs_disabled();
+}
+
+unsigned long __adeos_test_and_stall_root (void)
+
+{
+    unsigned long flags;
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	return test_and_set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+
+    adeos_hw_local_irq_save(flags);
+
+    return !adeos_hw_test_iflag(flags);
+}
+
+void __adeos_restore_root (unsigned long flags)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+
+	if (flags)
+	    set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	else
+	    {
+	    clear_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+
+	    if (adp_root->cpudata[cpuid].irq_pending_hi != 0)
+		__adeos_sync_stage();
+	    }
+	}
+    else if (flags)
+	adeos_hw_cli();
+    else
+	adeos_hw_sti();
+}
+
+/* adeos_suspend_domain() -- tell the ADEOS layer that the current
+   domain is now dormant. The calling domain is switched out, while
+   the next domain with work in progress or pending in the pipeline is
+   switched in. */
+
+void adeos_suspend_domain (void)
+
+{
+    struct adcpudata *cpudata;
+    adomain_t *adp, *nadp;
+    struct list_head *ln;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    adp = nadp = adp_cpu_current[cpuid];
+    cpudata = &adp->cpudata[cpuid];
+
+    adeos_hw_local_irq_save(flags);
+
+    for (;;)
+	{
+	ln = nadp->p_link.next;
+
+	if (ln == &__adeos_pipeline)	/* End of pipeline reached? */
+	    {
+	    /* Caller should loop on its idle task on return. */
+	    adeos_hw_local_irq_restore(flags);
+	    return;
+	    }
+
+	nadp = list_entry(ln,adomain_t,p_link);
+
+	/* Make sure the domain was preempted (i.e. not sleeping) or
+	   has some event to process before switching to it. */
+
+	if (!test_bit(IPIPE_SLEEP_FLAG,&nadp->cpudata[cpuid].status) ||
+	    (!test_bit(IPIPE_STALL_FLAG,&nadp->cpudata[cpuid].status) &&
+	     nadp->cpudata[cpuid].irq_pending_hi != 0) ||
+	    test_bit(IPIPE_XPEND_FLAG,&nadp->cpudata[cpuid].status))
+	    break;
+	}
+
+    /* A suspending domain implicitely unstalls the pipeline. */
+    clear_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+    /* Mark the outgoing domain as aslept (i.e. not preempted). */
+    set_bit(IPIPE_SLEEP_FLAG,&cpudata->status);
+
+    /* Suspend the calling domain, switching to the next one. */
+    __adeos_switch_to(nadp,cpuid);
+
+    /* Clear the sleep bit for the incoming domain (on the initial processor). */
+    clear_bit(IPIPE_SLEEP_FLAG,&cpudata->status);
+
+#ifdef CONFIG_SMP
+    adeos_reload_cpuid();	/* Processor might have changed. */
+    cpudata = &adp->cpudata[cpuid];
+#endif /* CONFIG_SMP */
+
+    /* Now, we are back into the calling domain. Flush the interrupt
+       log and fire the event interposition handler if needed.  Note
+       that a domain might be switched in because it was preempted or
+       has an event to process, even with a stalled stage. However, we
+       still ensure that interrupts won't be dispatched in the latter
+       case. */
+
+    if (!test_bit(IPIPE_STALL_FLAG,&cpudata->status) &&
+	cpudata->irq_pending_hi != 0)
+	{
+	__adeos_sync_stage();
+#ifdef CONFIG_SMP
+	adeos_reload_cpuid();	/* Processor might have changed. */
+	cpudata = &adp->cpudata[cpuid];
+#endif /* CONFIG_SMP */
+	}
+
+    /* Caution: CPU migration is allowed in SMP-mode on behalf of an
+       event handler provided that the current domain raised
+       it. Otherwise, it's not. */
+
+    if (test_and_clear_bit(IPIPE_XPEND_FLAG,&cpudata->status))
+	adp->events[cpudata->event_info.event].handler(&cpudata->event_info);
+
+    adeos_hw_local_irq_restore(flags);
+
+    /* Return to the point of suspension in the calling domain. */
+}
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry *adeos_proc_entry;
+
+static int __adeos_read_proc (char *page,
+			      char **start,
+			      off_t off,
+			      int count,
+			      int *eof,
+			      void *data)
+{
+    unsigned long flags, ctlbits;
+    struct list_head *pos;
+    unsigned irq, _irq;
+    char *p = page;
+    int len;
+
+    adeos_hw_local_irq_save(flags);
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+    	adomain_t *adp = list_entry(pos,adomain_t,p_link);
+
+	p += sprintf(p,"%8s: priority=%d, id=0x%.8x, ptdkeys=%d/%d\n",
+		     adp->name,
+		     adp->priority,
+		     adp->domid,
+		     adp->ptd_keycount,
+		     adp->ptd_keymax);
+	irq = 0;
+
+	while (irq < IPIPE_NR_IRQS)
+	    {
+	    ctlbits = (adp->irqs[irq].control & (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK|IPIPE_STICKY_MASK));
+
+	    if (adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map))
+		{
+		irq++;
+		continue;
+		}
+
+	    /* Attempt to group consecutive IRQ numbers having the
+	       same virtualization settings in a single line. */
+
+	    _irq = irq;
+
+	    while (++_irq < IPIPE_NR_IRQS)
+		{
+		if (adeos_virtual_irq_p(_irq) != adeos_virtual_irq_p(irq) ||
+		    (adeos_virtual_irq_p(_irq) && !test_bit(_irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)) ||
+		    ctlbits != (adp->irqs[_irq].control & (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK|IPIPE_STICKY_MASK)))
+		    break;
+		}
+
+	    if (_irq == irq + 1)
+		p += sprintf(p,"\tirq%u: ",irq);
+	    else
+		p += sprintf(p,"\tirq%u-%u: ",irq,_irq - 1);
+
+	    /* Statuses are as follows:
+	       o "accepted" means handled _and_ passed down the
+	       pipeline.
+	       o "grabbed" means handled, but the interrupt might be
+	       terminated _or_ passed down the pipeline depending on
+	       what the domain handler asks for to Adeos.
+	       o "passed" means unhandled by the domain but passed
+	       down the pipeline.
+	       o "discarded" means unhandled and _not_ passed down the
+	       pipeline. The interrupt merely disappears from the
+	       current domain down to the end of the pipeline. */
+
+	    if (ctlbits & IPIPE_HANDLE_MASK)
+		{
+		if (ctlbits & IPIPE_PASS_MASK)
+		    p += sprintf(p,"accepted");
+		else
+		    p += sprintf(p,"grabbed");
+		}
+	    else if (ctlbits & IPIPE_PASS_MASK)
+		p += sprintf(p,"passed");
+	    else
+		p += sprintf(p,"discarded");
+
+	    if (ctlbits & IPIPE_STICKY_MASK)
+		p += sprintf(p,", sticky");
+
+	    if (adeos_virtual_irq_p(irq))
+		p += sprintf(p,", virtual");
+
+	    p += sprintf(p,"\n");
+
+	    irq = _irq;
+	    }
+    }
+
+    adeos_hw_local_irq_restore(flags);
+
+#ifdef CONFIG_ADEOS_MODULE
+    p += sprintf(p,"\nInterrupt pipelining: %s\n",adp_pipelined ? "active" : "stopped");
+#else /* !CONFIG_ADEOS_MODULE */
+    p += sprintf(p,"\nInterrupt pipelining: permanent\n");
+#endif /* CONFIG_ADEOS_MODULE */
+
+    len = p - page;
+
+    if (len <= off + count)
+	*eof = 1;
+
+    *start = page + off;
+
+    len -= off;
+
+    if (len > count)
+	len = count;
+
+    if (len < 0)
+	len = 0;
+
+    return len;
+}
+
+void __adeos_init_proc (void) {
+
+    adeos_proc_entry = create_proc_read_entry("adeos",
+					      0444,
+					      NULL,
+					      &__adeos_read_proc,
+					      NULL);
+}
+
+#endif /* CONFIG_PROC_FS */
+
+void __adeos_dump_state (void)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+    int cpuid;
+
+    printk("ADEOS STATE: current domain=%s on CPU #%d [stackbase=%p]\n",
+	   adp_current->name,
+	   adeos_processor_id(),
+	   adp_current->estackbase[adeos_processor_id()]);
+
+    adeos_hw_local_irq_save(flags);
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+        adomain_t *adp = list_entry(pos,adomain_t,p_link);
+
+        for (cpuid = 0; cpuid < smp_num_cpus; cpuid++)
+            printk("%8s[cpuid=%d]: priority=%d, status=0x%lx, pending_hi=0x%lx\n",
+                   adp->name,
+                   cpuid,
+                   adp->priority,
+                   adp->cpudata[cpuid].status,
+                   adp->cpudata[cpuid].irq_pending_hi);
+    }
+
+    adeos_hw_local_irq_restore(flags);
+}
diff -Nurp linux-2.4.22-clean/kernel/exit.c linux-2.4.22-adeos-ltt/kernel/exit.c
--- linux-2.4.22-clean/kernel/exit.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/kernel/exit.c	2003-11-21 23:25:36.000000000 -0800
@@ -17,6 +17,8 @@
 #include <linux/acct.h>
 #endif
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
@@ -439,8 +441,13 @@ fake_volatile:
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
 #endif
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_exit_process(tsk);
+#endif /* CONFIG_ADEOS_CORE */
 	__exit_mm(tsk);
 
+	TRACE_PROCESS(TRACE_EV_PROCESS_EXIT, 0, 0);
+
 	lock_kernel();
 	sem_exit();
 	__exit_files(tsk);
@@ -498,6 +505,8 @@ asmlinkage long sys_wait4(pid_t pid,unsi
 	if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
 		return -EINVAL;
 
+	TRACE_PROCESS(TRACE_EV_PROCESS_WAIT, pid, 0);
+
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
 	flag = 0;
diff -Nurp linux-2.4.22-clean/kernel/fork.c linux-2.4.22-adeos-ltt/kernel/fork.c
--- linux-2.4.22-clean/kernel/fork.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/fork.c	2003-11-21 23:25:36.000000000 -0800
@@ -23,6 +23,8 @@
 #include <linux/personality.h>
 #include <linux/compiler.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -233,7 +235,13 @@ static struct mm_struct * mm_init(struct
 	atomic_set(&mm->mm_count, 1);
 	init_rwsem(&mm->mmap_sem);
 	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_lock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	mm->pgd = pgd_alloc(mm);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_unlock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	mm->def_flags = 0;
 	if (mm->pgd)
 		return mm;
@@ -265,7 +273,14 @@ struct mm_struct * mm_alloc(void)
 inline void __mmdrop(struct mm_struct *mm)
 {
 	BUG_ON(mm == &init_mm);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_sti();
+	adeos_spin_lock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	pgd_free(mm->pgd);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_unlock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	destroy_context(mm);
 	free_mm(mm);
 }
@@ -806,9 +821,21 @@ int do_fork(unsigned long clone_flags, u
 	nr_threads++;
 	write_unlock_irq(&tasklist_lock);
 
+#ifdef CONFIG_ADEOS_CORE
+	{
+	int k;
+
+	for (k = 0; k < ADEOS_ROOT_NPTDKEYS; k++)
+	    p->ptd[k] = NULL;
+	}
+#endif /* CONFIG_ADEOS_CORE */
+
 	if (p->ptrace & PT_PTRACED)
 		send_sig(SIGSTOP, p, 1);
 
+	/* Trace the event  */
+	TRACE_PROCESS(TRACE_EV_PROCESS_FORK, retval, 0);
+
 	wake_up_process(p);		/* do this last */
 	++total_forks;
 	if (clone_flags & CLONE_VFORK)
diff -Nurp linux-2.4.22-clean/kernel/itimer.c linux-2.4.22-adeos-ltt/kernel/itimer.c
--- linux-2.4.22-clean/kernel/itimer.c	2000-06-29 10:07:36.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/itimer.c	2003-11-21 23:21:08.000000000 -0800
@@ -10,6 +10,8 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 /*
@@ -95,6 +97,8 @@ void it_real_fn(unsigned long __data)
 	struct task_struct * p = (struct task_struct *) __data;
 	unsigned long interval;
 
+	TRACE_TIMER(TRACE_EV_TIMER_EXPIRED, 0, 0, 0);
+
 	send_sig(SIGALRM, p, 1);
 	interval = p->it_real_incr;
 	if (interval) {
@@ -114,6 +118,7 @@ int do_setitimer(int which, struct itime
 	j = tvtojiffies(&value->it_value);
 	if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
 		return k;
+	TRACE_TIMER(TRACE_EV_TIMER_SETITIMER, which, i, j);
 	switch (which) {
 		case ITIMER_REAL:
 			del_timer_sync(&current->real_timer);
diff -Nurp linux-2.4.22-clean/kernel/ksyms.c linux-2.4.22-adeos-ltt/kernel/ksyms.c
--- linux-2.4.22-clean/kernel/ksyms.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/ksyms.c	2003-11-21 23:25:36.000000000 -0800
@@ -58,6 +58,49 @@
 #include <linux/kmod.h>
 #endif
 
+#ifdef CONFIG_ADEOS_CORE
+EXPORT_SYMBOL(adeos_suspend_domain);
+#if defined(CONFIG_ADEOS_MODULE) || defined(CONFIG_X86_IO_APIC)
+EXPORT_SYMBOL(adp_pipelined);
+#endif /* CONFIG_ADEOS_MODULE || CONFIG_X86_IO_APIC */
+EXPORT_SYMBOL(adp_cpu_current);
+EXPORT_SYMBOL(adp_root);
+EXPORT_SYMBOL(__adeos_init_stage);
+EXPORT_SYMBOL(__adeos_handle_event);
+EXPORT_SYMBOL(__adeos_unstall_root);
+EXPORT_SYMBOL(__adeos_stall_root);
+EXPORT_SYMBOL(__adeos_restore_root);
+EXPORT_SYMBOL(__adeos_test_and_stall_root);
+EXPORT_SYMBOL(__adeos_test_root);
+EXPORT_SYMBOL(__adeos_dump_state);
+extern struct list_head __adeos_pipeline;
+EXPORT_SYMBOL(__adeos_pipeline);
+extern spinlock_t __adeos_pipelock;
+EXPORT_SYMBOL(__adeos_pipelock);
+extern unsigned long __adeos_virtual_irq_map;
+EXPORT_SYMBOL(__adeos_virtual_irq_map);
+EXPORT_SYMBOL(__adeos_event_monitors);
+/* The following are convenience exports which are needed by some
+   Adeos domains loaded as kernel modules. */
+EXPORT_SYMBOL_NOVERS(__mmdrop);
+EXPORT_SYMBOL_NOVERS(do_fork);
+EXPORT_SYMBOL_NOVERS(do_exit);
+ssize_t sys_read(unsigned fd,char *buf,size_t count);
+EXPORT_SYMBOL_NOVERS(sys_read);
+ssize_t sys_write(unsigned fd,const char *buf,size_t count);
+EXPORT_SYMBOL_NOVERS(sys_write);
+ssize_t sys_pread(unsigned fd,char *buf,size_t count,loff_t pos);
+EXPORT_SYMBOL_NOVERS(sys_pread);
+ssize_t sys_pwrite(unsigned fd,const char *buf,size_t count,loff_t pos);
+EXPORT_SYMBOL_NOVERS(sys_pwrite);
+long sys_fsync(unsigned fd);
+EXPORT_SYMBOL_NOVERS(sys_fsync);
+long sys_fdatasync(unsigned fd);
+EXPORT_SYMBOL_NOVERS(sys_fdatasync);
+long sys_open(const char *filename,int flags,int mode);
+EXPORT_SYMBOL_NOVERS(sys_open);
+#endif /* CONFIG_ADEOS_CORE */
+
 extern void set_device_ro(kdev_t dev,int flag);
 
 extern void *sys_call_table;
diff -Nurp linux-2.4.22-clean/kernel/Makefile linux-2.4.22-adeos-ltt/kernel/Makefile
--- linux-2.4.22-clean/kernel/Makefile	2001-09-16 21:22:40.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/Makefile	2003-11-21 23:28:32.000000000 -0800
@@ -9,7 +9,7 @@
 
 O_TARGET := kernel.o
 
-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
+export-objs = adeos.o signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o trace.o
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
@@ -19,6 +19,11 @@ obj-y     = sched.o dma.o fork.o exec_do
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_ADEOS_CORE) += adeos.o
+
+ifdef CONFIG_TRACE
+obj-y += trace.o
+endif
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Nurp linux-2.4.22-clean/kernel/printk.c linux-2.4.22-adeos-ltt/kernel/printk.c
--- linux-2.4.22-clean/kernel/printk.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/printk.c	2003-11-21 23:25:36.000000000 -0800
@@ -29,6 +29,17 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_ADEOS_CORE
+#undef spin_lock_irq
+#define	spin_lock_irq(lock)                 adeos_spin_lock_disable(lock)
+#undef spin_unlock_irq
+#define	spin_unlock_irq(lock)               adeos_spin_unlock_enable(lock)
+#undef spin_lock_irqsave
+#define	spin_lock_irqsave(lock, flags)      adeos_spin_lock_irqsave(lock,flags)
+#undef spin_unlock_irqrestore
+#define spin_unlock_irqrestore(lock, flags) adeos_spin_unlock_irqrestore(lock,flags)
+#endif /* CONFIG_ADEOS_CORE */
+
 #if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
 #define LOG_BUF_LEN	(65536)
 #elif defined(CONFIG_ARCH_S390)
diff -Nurp linux-2.4.22-clean/kernel/sched.c linux-2.4.22-adeos-ltt/kernel/sched.c
--- linux-2.4.22-clean/kernel/sched.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/sched.c	2003-11-21 23:25:36.000000000 -0800
@@ -30,6 +30,8 @@
 #include <linux/prefetch.h>
 #include <linux/compiler.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
@@ -351,6 +353,8 @@ static inline int try_to_wake_up(struct 
 	unsigned long flags;
 	int success = 0;
 
+	TRACE_PROCESS(TRACE_EV_PROCESS_WAKEUP, p->pid, p->state);
+
 	/*
 	 * We want the common case fall through straight, thus the goto.
 	 */
@@ -376,6 +380,7 @@ static void process_timeout(unsigned lon
 {
 	struct task_struct * p = (struct task_struct *) __data;
 
+	TRACE_TIMER(TRACE_EV_TIMER_EXPIRED, 0, 0, 0);
 	wake_up_process(p);
 }
 
@@ -440,6 +445,8 @@ signed long schedule_timeout(signed long
 		}
 	}
 
+	TRACE_TIMER(TRACE_EV_TIMER_SETTIMEOUT, 0, timeout, 0);
+
 	expire = timeout + jiffies;
 
 	init_timer(&timer);
@@ -532,6 +539,9 @@ needs_resched:
 asmlinkage void schedule_tail(struct task_struct *prev)
 {
 	__schedule_tail(prev);
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_enter_process();
+#endif /* CONFIG_ADEOS_CORE */
 }
 
 /*
@@ -551,6 +561,10 @@ asmlinkage void schedule(void)
 	struct list_head *tmp;
 	int this_cpu, c;
 
+#ifdef CONFIG_ADEOS_CORE
+	if (adp_current != adp_root) /* Let's be helpful and conservative. */
+	    return;
+#endif /* CONFIG_ADEOS_CORE */
 
 	spin_lock_prefetch(&runqueue_lock);
 
@@ -668,7 +682,11 @@ repeat_schedule:
 	 * but prev is set to (the just run) 'last' process by switch_to().
 	 * This might sound slightly confusing but makes tons of sense.
 	 */
+#ifdef CONFIG_ADEOS_CORE
+	prepare_to_switch(prev,next);
+#else /* !CONFIG_ADEOS_CORE */
 	prepare_to_switch();
+#endif /* CONFIG_ADEOS_CORE */
 	{
 		struct mm_struct *mm = next->mm;
 		struct mm_struct *oldmm = prev->active_mm;
@@ -688,11 +706,27 @@ repeat_schedule:
 		}
 	}
 
+	TRACE_SCHEDCHANGE(prev, next);
+
 	/*
 	 * This just switches the register state and the
 	 * stack.
 	 */
 	switch_to(prev, next, prev);
+#ifdef CONFIG_ADEOS_CORE
+	if (__adeos_schedule_tail(prev) > 0)
+	    {
+#ifdef CONFIG_PREEMPT
+	    /* Decrement the preemption count even as part of a
+	       truncated scheduling tail. We cannot use
+	       preempt_enable_no_resched() here since we might be
+	       running on behalf of a non-root domain, recycling the
+	       root domain code and stack context. */
+	    current->preempt_count--;
+#endif /* CONFIG_PREEMPT */
+	    return;
+	    }
+#endif /* CONFIG_ADEOS_CORE */
 	__schedule_tail(prev);
 
 same_process:
@@ -989,6 +1023,13 @@ static int setscheduler(pid_t pid, int p
 		goto out_unlock;
 
 	retval = 0;
+#ifdef CONFIG_ADEOS_CORE
+	{
+	struct { struct task_struct *task; int policy; struct sched_param *param; } evdata = { p, policy, &lp };
+	if (__adeos_renice_process(&evdata))
+	    goto out_unlock;
+	}
+#endif /* CONFIG_ADEOS_CORE */
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
 
diff -Nurp linux-2.4.22-clean/kernel/signal.c linux-2.4.22-adeos-ltt/kernel/signal.c
--- linux-2.4.22-clean/kernel/signal.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/signal.c	2003-11-21 23:25:36.000000000 -0800
@@ -14,6 +14,8 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 /*
@@ -554,6 +556,17 @@ printk("SIG queue (%s:%d): %d ", t->comm
 	if (!sig || !t->sig)
 		goto out_nolock;
 
+#ifdef CONFIG_ADEOS_CORE
+	/* If some domain handler in the pipeline doesn't ask for
+	   propagation, return success pretending that 'sig' was
+	   delivered. */
+	{
+	struct { struct task_struct *task; int sig; } evdata = { t, sig };
+	if (__adeos_signal_process(&evdata))
+	    goto out_nolock;
+	}
+#endif /* CONFIG_ADEOS_CORE */
+
 	spin_lock_irqsave(&t->sigmask_lock, flags);
 	handle_stop_signal(sig, t);
 
@@ -570,6 +583,8 @@ printk("SIG queue (%s:%d): %d ", t->comm
 	if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig))
 		goto out;
 
+	TRACE_PROCESS(TRACE_EV_PROCESS_SIGNAL, sig, t->pid);
+
 	ret = deliver_signal(sig, info, t);
 out:
 	spin_unlock_irqrestore(&t->sigmask_lock, flags);
diff -Nurp linux-2.4.22-clean/kernel/softirq.c linux-2.4.22-adeos-ltt/kernel/softirq.c
--- linux-2.4.22-clean/kernel/softirq.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/kernel/softirq.c	2003-11-21 23:21:08.000000000 -0800
@@ -17,6 +17,8 @@
 #include <linux/init.h>
 #include <linux/tqueue.h>
 
+#include <linux/trace.h>
+
 /*
    - No shared variables, all the data are CPU local.
    - If a softirq needs serialization, let it serialize itself
@@ -86,8 +88,10 @@ restart:
 		h = softirq_vec;
 
 		do {
-			if (pending & 1)
+		        if (pending & 1) {
+		                TRACE_SOFT_IRQ(TRACE_EV_SOFT_IRQ_SOFT_IRQ, (h - softirq_vec));
 				h->action(h);
+			}
 			h++;
 			pending >>= 1;
 		} while (pending);
@@ -192,6 +196,9 @@ static void tasklet_action(struct softir
 			if (!atomic_read(&t->count)) {
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
 					BUG();
+
+				TRACE_SOFT_IRQ(TRACE_EV_SOFT_IRQ_TASKLET_ACTION, (unsigned long) (t->func));
+
 				t->func(t->data);
 				tasklet_unlock(t);
 				continue;
@@ -226,6 +233,9 @@ static void tasklet_hi_action(struct sof
 			if (!atomic_read(&t->count)) {
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
 					BUG();
+
+				TRACE_SOFT_IRQ(TRACE_EV_SOFT_IRQ_TASKLET_HI_ACTION, (unsigned long) (t->func));
+
 				t->func(t->data);
 				tasklet_unlock(t);
 				continue;
@@ -295,8 +305,10 @@ static void bh_action(unsigned long nr)
 	if (!hardirq_trylock(cpu))
 		goto resched_unlock;
 
-	if (bh_base[nr])
+	if (bh_base[nr]){
+	        TRACE_SOFT_IRQ(TRACE_EV_SOFT_IRQ_BOTTOM_HALF, (nr));
 		bh_base[nr]();
+	}
 
 	hardirq_endlock(cpu);
 	spin_unlock(&global_bh_lock);
diff -Nurp linux-2.4.22-clean/kernel/sysctl.c linux-2.4.22-adeos-ltt/kernel/sysctl.c
--- linux-2.4.22-clean/kernel/sysctl.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/kernel/sysctl.c	2003-11-21 23:25:36.000000000 -0800
@@ -338,6 +338,9 @@ void __init sysctl_init(void)
 #ifdef CONFIG_PROC_FS
 	register_proc_table(root_table, proc_sys_root);
 	init_irq_proc();
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_init_proc();
+#endif /* CONFIG_ADEOS_CORE */
 #endif
 }
 
diff -Nurp linux-2.4.22-clean/kernel/timer.c linux-2.4.22-adeos-ltt/kernel/timer.c
--- linux-2.4.22-clean/kernel/timer.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/kernel/timer.c	2003-11-21 23:21:08.000000000 -0800
@@ -23,6 +23,8 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
+#include <linux/trace.h>
+
 #include <asm/uaccess.h>
 
 /*
@@ -692,6 +694,7 @@ static inline void update_times(void)
 
 void timer_bh(void)
 {
+	TRACE_EVENT(TRACE_EV_KERNEL_TIMER, NULL);
 	update_times();
 	run_timer_list();
 }
diff -Nurp linux-2.4.22-clean/kernel/trace.c linux-2.4.22-adeos-ltt/kernel/trace.c
--- linux-2.4.22-clean/kernel/trace.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-adeos-ltt/kernel/trace.c	2003-11-21 23:21:08.000000000 -0800
@@ -0,0 +1,699 @@
+/*
+ * linux/kernel/trace.c
+ *
+ * (C) Copyright 1999, 2000, 2001, 2002 - Karim Yaghmour (karym@opersys.com)
+ *
+ * This code is distributed under the GPL license
+ *
+ * Tracing management
+ *
+ */
+
+#include <linux/init.h>     /* For __init */
+#include <linux/trace.h>    /* Tracing definitions */
+#include <linux/errno.h>    /* Miscellaneous error codes */
+#include <linux/stddef.h>   /* NULL */
+#include <linux/slab.h>     /* kmalloc() */
+#include <linux/module.h>   /* EXPORT_SYMBOL */
+#include <linux/sched.h>    /* pid_t */
+
+/* Global variables */
+unsigned int syscall_entry_trace_active = 0;
+unsigned int syscall_exit_trace_active = 0;
+
+/* Local variables */
+static int        tracer_registered = 0;   /* Is there a tracer registered */
+struct tracer *   tracer = NULL;           /* The registered tracer */
+
+/* Registration lock */
+rwlock_t tracer_register_lock = RW_LOCK_UNLOCKED;
+
+/* Trace callback table entry */
+struct trace_callback_table_entry
+{
+  tracer_call                         callback;    /* The callback function */
+
+  struct trace_callback_table_entry*  next;        /* Next entry */
+};
+
+/* Trace callback table */
+struct trace_callback_table_entry trace_callback_table[TRACE_EV_MAX];
+
+/* Custom event description */
+struct custom_event_desc
+{
+  /* The event itself */
+  trace_new_event              event;
+
+  /* PID of event owner, if any */
+  pid_t                        owner_pid;
+
+  /* List links */
+  struct custom_event_desc*    next;
+  struct custom_event_desc*    prev;
+};
+
+/* Next event ID to be used */
+int next_event_id;
+
+/* Circular list of custom events */
+struct custom_event_desc  custom_events_head;
+struct custom_event_desc* custom_events;
+
+/* Circular list lock */
+rwlock_t custom_list_lock = RW_LOCK_UNLOCKED;
+
+/****************************************************
+ * Register the tracer to the kernel
+ * Return values :
+ *   0, all is OK
+ *   -EBUSY, there already is a registered tracer
+ *   -ENOMEM, couldn't allocate memory
+ ****************************************************/
+int register_tracer(tracer_call pm_trace_function)
+{
+  unsigned long    l_flags;   /* Flags for irqsave */
+
+  /* Is there a tracer already registered */
+  if(tracer_registered == 1)
+    return -EBUSY;
+
+  /* Allocate memory for the tracer */
+  if((tracer = (struct tracer *) kmalloc(sizeof(struct tracer), GFP_ATOMIC)) == NULL)
+    /* We couldn't allocate any memory */
+    return -ENOMEM;
+
+  /* Lock registration variables */
+  write_lock_irqsave(&tracer_register_lock, l_flags);
+
+  /* There is a tracer registered */
+  tracer_registered = 1;
+
+  /* Set the tracer to the one being passed by the caller */
+  tracer->trace = pm_trace_function;
+
+  /* Unlock registration variables */
+  write_unlock_irqrestore(&tracer_register_lock, l_flags);
+
+  /* Initialize the tracer settings */
+  tracer->fetch_syscall_eip_use_bounds = 0;
+  tracer->fetch_syscall_eip_use_depth  = 0;
+
+  /* Tell the caller that everything went fine */
+  return 0;
+}
+
+/***************************************************
+ * Unregister the currently registered tracer
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEDIUM, there isn't a registered tracer
+ *   -ENXIO, unregestering wrong tracer
+ ***************************************************/
+int unregister_tracer(tracer_call pm_trace_function)
+{
+  unsigned long    l_flags;   /* Flags for irqsave */
+
+  /* Is there a tracer already registered */
+  if(tracer_registered == 0)
+    /* Nothing to unregister */
+    return -ENOMEDIUM;
+
+  /* Lock registration variables */
+  write_lock_irqsave(&tracer_register_lock, l_flags);
+
+  /* Is it the tracer that was registered */
+  if(tracer->trace == pm_trace_function)
+    /* There isn't any tracer in here */
+    tracer_registered = 0;
+  else
+    {
+    /* Unlock registration variables */
+    write_unlock_irqrestore(&tracer_register_lock, l_flags);
+
+    /* We're done here */
+    return -ENXIO;
+    }
+
+  /* Free the memory used by the tracing structure */
+  kfree(tracer);
+  tracer = NULL;
+
+  /* Unlock registration variables */
+  write_unlock_irqrestore(&tracer_register_lock, l_flags);
+
+  /* Tell the caller that everything went OK */
+  return 0;
+}
+
+/*******************************************************
+ * Set the tracing configuration
+ * Parameters :
+ *   pm_trace_function, the trace function.
+ *   pm_fetch_syscall_use_depth, Use depth to fetch eip
+ *   pm_fetch_syscall_use_bounds, Use bounds to fetch eip
+ *   pm_syscall_eip_depth, Detph to fetch eip
+ *   pm_syscall_lower_bound, Lower bound eip address
+ *   pm_syscall_upper_bound, Upper bound eip address
+ * Return values : 
+ *   0, all is OK 
+ *   -ENOMEDIUM, there isn't a registered tracer
+ *   -ENXIO, wrong tracer
+ *   -EINVAL, invalid configuration
+ *******************************************************/
+int trace_set_config(tracer_call pm_trace_function,
+		     int         pm_fetch_syscall_use_depth,
+		     int         pm_fetch_syscall_use_bounds,
+		     int         pm_syscall_eip_depth,
+		     void*       pm_syscall_lower_bound,
+		     void*       pm_syscall_upper_bound)
+{
+  /* Is there a tracer already registered */
+  if(tracer_registered == 0)
+    return -ENOMEDIUM;
+
+  /* Is it the tracer that was registered */
+  if(tracer->trace != pm_trace_function)
+    return -ENXIO;
+
+  /* Is this a valid configuration */
+  if((pm_fetch_syscall_use_depth && pm_fetch_syscall_use_bounds)
+   ||(pm_syscall_lower_bound > pm_syscall_upper_bound)
+   ||(pm_syscall_eip_depth < 0))
+    return -EINVAL;
+
+  /* Set the configuration */
+  tracer->fetch_syscall_eip_use_depth  = pm_fetch_syscall_use_depth;
+  tracer->fetch_syscall_eip_use_bounds = pm_fetch_syscall_use_bounds;
+  tracer->syscall_eip_depth = pm_syscall_eip_depth;
+  tracer->syscall_lower_eip_bound = pm_syscall_lower_bound;
+  tracer->syscall_upper_eip_bound = pm_syscall_upper_bound;
+
+  /* Tell the caller that everything was OK */
+  return 0;
+}
+
+/*******************************************************
+ * Get the tracing configuration
+ * Parameters :
+ *   pm_fetch_syscall_use_depth, Use depth to fetch eip
+ *   pm_fetch_syscall_use_bounds, Use bounds to fetch eip
+ *   pm_syscall_eip_depth, Detph to fetch eip
+ *   pm_syscall_lower_bound, Lower bound eip address
+ *   pm_syscall_upper_bound, Upper bound eip address
+ * Return values :
+ *   0, all is OK 
+ *   -ENOMEDIUM, there isn't a registered tracer
+ *******************************************************/
+int trace_get_config(int*        pm_fetch_syscall_use_depth,
+		     int*        pm_fetch_syscall_use_bounds,
+		     int*        pm_syscall_eip_depth,
+		     void**      pm_syscall_lower_bound,
+		     void**      pm_syscall_upper_bound)
+{
+  /* Is there a tracer already registered */
+  if(tracer_registered == 0)
+    return -ENOMEDIUM;
+
+  /* Get the configuration */
+  *pm_fetch_syscall_use_depth  = tracer->fetch_syscall_eip_use_depth;
+  *pm_fetch_syscall_use_bounds = tracer->fetch_syscall_eip_use_bounds;
+  *pm_syscall_eip_depth = tracer->syscall_eip_depth;
+  *pm_syscall_lower_bound = tracer->syscall_lower_eip_bound;
+  *pm_syscall_upper_bound = tracer->syscall_upper_eip_bound;
+
+  /* Tell the caller that everything was OK */
+  return 0;
+}
+
+/*******************************************************
+ * Register a callback function to be called on occurence
+ * of given event
+ * Parameters :
+ *   pm_trace_function, the callback function.
+ *   pm_event_id, the event ID to be monitored.
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEM, unable to allocate memory for callback
+ *******************************************************/
+int trace_register_callback(tracer_call pm_trace_function,
+			    uint8_t     pm_event_id)
+{
+  struct trace_callback_table_entry*  p_tct_entry;
+
+  /* Search for an empty entry in the callback table */
+  for(p_tct_entry = &(trace_callback_table[pm_event_id - 1]);
+      p_tct_entry->next != NULL;
+      p_tct_entry = p_tct_entry->next);
+
+  /* Allocate a new callback */
+  if((p_tct_entry->next = kmalloc(sizeof(struct trace_callback_table_entry), GFP_ATOMIC)) == NULL)
+    return -ENOMEM;
+
+  /* Setup the new callback */
+  p_tct_entry->next->callback = pm_trace_function;
+  p_tct_entry->next->next     = NULL;
+
+  /* Tell the caller everything is ok */
+  return 0;
+}
+
+/*******************************************************
+ * UnRegister a callback function.
+ * Parameters :
+ *   pm_trace_function, the callback function.
+ *   pm_event_id, the event ID that had to be monitored.
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEDIUM, no such callback resigtered
+ *******************************************************/
+int trace_unregister_callback(tracer_call pm_trace_function,
+			      uint8_t     pm_event_id)
+{
+  struct trace_callback_table_entry*  p_tct_entry;  /* Pointer to trace callback table entry */
+  struct trace_callback_table_entry*  p_temp_entry; /* Pointer to trace callback table entry */
+
+  /* Search for the callback in the callback table */
+  for(p_tct_entry = &(trace_callback_table[pm_event_id - 1]);
+      ((p_tct_entry->next != NULL) && (p_tct_entry->next->callback != pm_trace_function));
+      p_tct_entry = p_tct_entry->next);
+
+  /* Did we find anything */
+  if(p_tct_entry == NULL)
+    return -ENOMEDIUM;
+
+  /* Free the callback entry */
+  p_temp_entry = p_tct_entry->next->next;
+  kfree(p_tct_entry->next);
+  p_tct_entry->next = p_temp_entry;
+
+  /* Tell the caller everything is ok */
+  return 0;
+}
+
+/*******************************************************
+ * Create a new traceable event type
+ * Parameters :
+ *   pm_event_type, string describing event type
+ *   pm_event_desc, string used for standard formatting
+ *   pm_format_type, type of formatting used to log event
+ *                 data
+ *   pm_format_data, data specific to format
+ *   pm_owner_pid, PID of event's owner (0 if none)
+ * Return values :
+ *   New Event ID if all is OK
+ *   -ENOMEM, Unable to allocate new event
+ *******************************************************/
+int _trace_create_event(char*            pm_event_type,
+			char*            pm_event_desc,
+			int              pm_format_type,
+			char*            pm_format_data,
+			pid_t            pm_owner_pid)
+{
+  struct custom_event_desc* p_new_event;          /* Newly created event */
+
+  /* Create event */
+  if((p_new_event = (struct custom_event_desc*) kmalloc(sizeof(struct custom_event_desc), GFP_ATOMIC)) == NULL)
+    return -ENOMEM;
+
+  /* Initialize event properties */
+  p_new_event->event.type[0] = '\0';
+  p_new_event->event.desc[0] = '\0';
+  p_new_event->event.form[0] = '\0';
+
+  /* Set basic event properties */
+  if(pm_event_type != NULL)
+    strncpy(p_new_event->event.type, pm_event_type, CUSTOM_EVENT_TYPE_STR_LEN);
+  if(pm_event_desc != NULL)
+    strncpy(p_new_event->event.desc, pm_event_desc, CUSTOM_EVENT_DESC_STR_LEN);
+  if(pm_format_data != NULL)
+    strncpy(p_new_event->event.form, pm_format_data, CUSTOM_EVENT_FORM_STR_LEN);
+
+  /* Ensure that strings are bound */
+  p_new_event->event.type[CUSTOM_EVENT_TYPE_STR_LEN - 1] = '\0';
+  p_new_event->event.desc[CUSTOM_EVENT_DESC_STR_LEN - 1] = '\0';
+  p_new_event->event.form[CUSTOM_EVENT_FORM_STR_LEN - 1] = '\0';
+
+  /* Set format type */
+  p_new_event->event.format_type = pm_format_type;
+
+  /* Give the new event a unique event ID */
+  p_new_event->event.id = next_event_id;
+  next_event_id++;
+
+  /* Set event's owner */
+  p_new_event->owner_pid = pm_owner_pid;
+
+  /* Insert new event in event list */
+  write_lock(&custom_list_lock);
+  p_new_event->next = custom_events;
+  p_new_event->prev = custom_events->prev;
+  custom_events->prev->next = p_new_event;
+  custom_events->prev = p_new_event;
+  write_unlock(&custom_list_lock);
+
+  /* Log the event creation event */
+  trace_event(TRACE_EV_NEW_EVENT, &(p_new_event->event));
+
+  /* Return new event ID */
+  return p_new_event->event.id;
+}
+int trace_create_event(char*            pm_event_type,
+		       char*            pm_event_desc,
+		       int              pm_format_type,
+		       char*            pm_format_data)
+{
+  return _trace_create_event(pm_event_type, pm_event_desc, pm_format_type, pm_format_data, 0);
+}
+int trace_create_owned_event(char*            pm_event_type,
+			     char*            pm_event_desc,
+			     int              pm_format_type,
+			     char*            pm_format_data,
+			     pid_t            pm_owner_pid)
+{
+  return _trace_create_event(pm_event_type, pm_event_desc, pm_format_type, pm_format_data, pm_owner_pid);
+}
+
+/*******************************************************
+ * Destroy a created event type
+ * Parameters :
+ *   pm_event_id, the Id returned by trace_create_event()
+ * Return values :
+ *   NONE
+ *******************************************************/
+void trace_destroy_event(int pm_event_id)
+{
+  struct custom_event_desc*   p_event_desc;   /* Generic event description pointer */
+
+  /* Lock the table for writting */
+  write_lock(&custom_list_lock);
+
+  /* Go through the event description list */
+  for(p_event_desc = custom_events->next;
+      p_event_desc != custom_events;
+      p_event_desc = p_event_desc->next)
+    if(p_event_desc->event.id == pm_event_id)
+      break;
+
+  /* If we found something */
+  if(p_event_desc != custom_events)
+    {
+    /* Remove the event fromt the list */
+    p_event_desc->next->prev = p_event_desc->prev;
+    p_event_desc->prev->next = p_event_desc->next;
+
+    /* Free the memory used by this event */
+    kfree(p_event_desc);
+    }
+
+  /* Unlock the table for writting */
+  write_unlock(&custom_list_lock);
+}
+
+/*******************************************************
+ * Destroy an owner's events
+ * Parameters :
+ *   pm_owner_pid, the PID of the owner who's events are to
+ *               be deleted.
+ * Return values :
+ *   NONE
+ *******************************************************/
+void trace_destroy_owners_events(pid_t pm_owner_pid)
+{
+  struct custom_event_desc*   p_temp_event;   /* Temporary event */
+  struct custom_event_desc*   p_event_desc;   /* Generic event description pointer */
+
+  /* Lock the table for writting */
+  write_lock(&custom_list_lock);
+
+  /* Start at the first event in the list */
+  p_event_desc = custom_events->next;
+
+  /* Go through the event description list */
+  while(p_event_desc != custom_events)
+    {
+    /* Keep pointer to next event */
+    p_temp_event = p_event_desc->next;
+
+    /* Does this event belong to the same owner */
+    if(p_event_desc->owner_pid == pm_owner_pid)
+      {
+      /* Remove the event fromt the list */
+      p_event_desc->next->prev = p_event_desc->prev;
+      p_event_desc->prev->next = p_event_desc->next;
+
+      /* Free the memory used by this event */
+      kfree(p_event_desc);
+      }
+
+    /* Go to next event */
+    p_event_desc = p_temp_event;
+    }
+
+  /* Unlock the table for writting */
+  write_unlock(&custom_list_lock);
+}
+
+/*******************************************************
+ * Relog the declarations of custom events. This is
+ * necessary to make sure that even though the event
+ * creation might not have taken place during a trace,
+ * that all custom events be part of all traces. Hence,
+ * if a custom event occurs during a trace, we can be
+ * sure that it's definition is part of the trace.
+ * Parameters :
+ *    NONE
+ * Return values :
+ *    NONE
+ *******************************************************/
+void trace_reregister_custom_events(void)
+{
+  struct custom_event_desc*   p_event_desc;   /* Generic event description pointer */
+
+  /* Lock the table for reading */
+  read_lock(&custom_list_lock);
+
+  /* Go through the event description list */
+  for(p_event_desc = custom_events->next;
+      p_event_desc != custom_events;
+      p_event_desc = p_event_desc->next)
+    /* Log the event creation event */
+    trace_event(TRACE_EV_NEW_EVENT, &(p_event_desc->event));
+
+  /* Unlock the table for reading */
+  read_unlock(&custom_list_lock);
+}
+
+/*******************************************************
+ * Trace a formatted event
+ * Parameters :
+ *   pm_event_id, the event Id provided upon creation
+ *   ..., printf-like data that will be used to fill the
+ *        event string.
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEDIUM, there isn't a registered tracer or this
+ *               event doesn't exist.
+ *   -EBUSY, tracing hasn't started yet
+ *******************************************************/
+int trace_std_formatted_event(int pm_event_id, ...)
+{
+  int                         l_string_size;   /* Size of the string outputed by vsprintf() */
+  char                        l_string[CUSTOM_EVENT_FINAL_STR_LEN];  /* Final formatted string */
+  va_list                     l_var_arg_list;  /* Variable argument list */
+  trace_custom                l_custom;        /* Custom event */
+  struct custom_event_desc*   p_event_desc;    /* Generic event description pointer */
+
+  /* Lock the table for reading */
+  read_lock(&custom_list_lock);
+
+  /* Go through the event description list */
+  for(p_event_desc = custom_events->next;
+      p_event_desc != custom_events;
+      p_event_desc = p_event_desc->next)
+    if(p_event_desc->event.id == pm_event_id)
+      break;
+
+  /* If we haven't found anything */
+  if(p_event_desc == custom_events)
+    {
+    /* Unlock the table for reading */
+    read_unlock(&custom_list_lock);
+
+    /* No such thing */
+    return -ENOMEDIUM;
+    }
+
+  /* Set custom event Id */
+  l_custom.id = pm_event_id;
+
+  /* Initialize variable argument list access */
+  va_start(l_var_arg_list, pm_event_id);
+
+  /* Print the description out to the temporary buffer */
+  l_string_size = vsprintf(l_string, p_event_desc->event.desc, l_var_arg_list);
+
+  /* Unlock the table for reading */
+  read_unlock(&custom_list_lock);
+
+  /* Facilitate return to caller */
+  va_end(l_var_arg_list);
+
+  /* Set the size of the event */
+  l_custom.data_size = (uint32_t) (l_string_size + 1);
+
+  /* Set the pointer to the event data */
+  l_custom.data = l_string;
+
+  /* Log the custom event */
+  return trace_event(TRACE_EV_CUSTOM, &l_custom);
+}
+
+/*******************************************************
+ * Trace a raw event
+ * Parameters :
+ *   pm_event_id, the event Id provided upon creation
+ *   pm_event_size, the size of the data provided
+ *   pm_event_data, data buffer describing event
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEDIUM, there isn't a registered tracer or this
+ *               event doesn't exist.
+ *   -EBUSY, tracing hasn't started yet
+ *******************************************************/
+int trace_raw_event(int pm_event_id, int pm_event_size, void* pm_event_data)
+{
+  trace_custom                l_custom;        /* Custom event */
+  struct custom_event_desc*   p_event_desc;    /* Generic event description pointer */
+
+  /* Lock the table for reading */
+  read_lock(&custom_list_lock);
+
+  /* Go through the event description list */
+  for(p_event_desc = custom_events->next;
+      p_event_desc != custom_events;
+      p_event_desc = p_event_desc->next)
+    if(p_event_desc->event.id == pm_event_id)
+      break;
+
+  /* Unlock the table for reading */
+  read_unlock(&custom_list_lock);
+
+  /* If we haven't found anything */
+  if(p_event_desc == custom_events)
+    /* No such thing */
+    return -ENOMEDIUM;
+
+  /* Set custom event Id */
+  l_custom.id = pm_event_id;
+
+  /* Set the data size */
+  if(pm_event_size <= CUSTOM_EVENT_MAX_SIZE)
+    l_custom.data_size = (uint32_t) pm_event_size;
+  else
+    l_custom.data_size = (uint32_t) CUSTOM_EVENT_MAX_SIZE;
+
+  /* Set the pointer to the event data */
+  l_custom.data = pm_event_data;
+
+  /* Log the custom event */
+  return trace_event(TRACE_EV_CUSTOM, &l_custom);
+}
+
+/*******************************************************
+ * Trace an event
+ * Parameters :
+ *   pm_event_id, the event's ID (check out trace.h)
+ *   pm_event_struct, the structure describing the event
+ * Return values :
+ *   0, all is OK
+ *   -ENOMEDIUM, there isn't a registered tracer
+ *   -EBUSY, tracing hasn't started yet
+ *******************************************************/
+int trace_event(uint8_t  pm_event_id, 
+       	        void*    pm_event_struct)
+{
+  int                                 l_ret_value; /* The return value */
+  struct trace_callback_table_entry*  p_tct_entry; /* Pointer to trace callback table entry */
+
+  /* Lock registration variables */
+  read_lock(&tracer_register_lock);
+
+  /* Is there a tracer registered */
+  if(tracer_registered != 1)
+    l_ret_value = -ENOMEDIUM;
+  else
+    /* Call the tracer */
+    l_ret_value = tracer->trace(pm_event_id, pm_event_struct);
+
+  /* Unlock registration variables */
+  read_unlock(&tracer_register_lock);
+
+  /* Is this a native event */
+  if(pm_event_id <= TRACE_EV_MAX)
+    {
+    /* Are there any callbacks to call */
+    if(trace_callback_table[pm_event_id - 1].next != NULL)
+      {
+      /* Call all the callbacks linked to this event */
+      for(p_tct_entry = trace_callback_table[pm_event_id - 1].next;
+	  p_tct_entry != NULL;
+	  p_tct_entry = p_tct_entry->next)
+	p_tct_entry->callback(pm_event_id, pm_event_struct);
+      }
+    }
+
+  /* Give the return value */
+  return l_ret_value;
+}
+
+/*******************************************************
+ * Initialize trace facility
+ * Parameters :
+ *    NONE
+ * Return values :
+ *    NONE
+ *******************************************************/
+static int __init trace_init(void)
+{
+  int i;  /* Generic index */
+
+  /* Initialize callback table */
+  for(i = 0; i < TRACE_EV_MAX; i++)
+    {
+    trace_callback_table[i].callback = NULL;
+    trace_callback_table[i].next     = NULL;
+    }
+
+  /* Next event ID to be used */
+  next_event_id = TRACE_EV_MAX + 1;
+
+  /* Initialize custom events list */
+  custom_events = &custom_events_head;
+  custom_events->next = custom_events;
+  custom_events->prev = custom_events;
+
+  /* Everything is OK */
+  return 0;
+}
+
+module_init(trace_init);
+
+/* Export symbols so that can be visible from outside this file */
+EXPORT_SYMBOL(register_tracer);
+EXPORT_SYMBOL(unregister_tracer);
+EXPORT_SYMBOL(trace_set_config);
+EXPORT_SYMBOL(trace_get_config);
+EXPORT_SYMBOL(trace_register_callback);
+EXPORT_SYMBOL(trace_unregister_callback);
+EXPORT_SYMBOL(trace_create_event);
+EXPORT_SYMBOL(trace_create_owned_event);
+EXPORT_SYMBOL(trace_destroy_event);
+EXPORT_SYMBOL(trace_destroy_owners_events);
+EXPORT_SYMBOL(trace_reregister_custom_events);
+EXPORT_SYMBOL(trace_std_formatted_event);
+EXPORT_SYMBOL(trace_raw_event);
+EXPORT_SYMBOL(trace_event);
+
+EXPORT_SYMBOL(syscall_entry_trace_active);
+EXPORT_SYMBOL(syscall_exit_trace_active);
diff -Nurp linux-2.4.22-clean/Makefile linux-2.4.22-adeos-ltt/Makefile
--- linux-2.4.22-clean/Makefile	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/Makefile	2003-11-21 23:29:15.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 22
-EXTRAVERSION =
+EXTRAVERSION = -adeos-ltt
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -74,7 +74,7 @@ endif
 # images.  Uncomment if you want to place them anywhere other than root.
 #
 
-#export	INSTALL_PATH=/boot
+export	INSTALL_PATH=/boot
 
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
@@ -135,6 +135,7 @@ DRIVERS-y :=
 DRIVERS-m :=
 DRIVERS-  :=
 
+DRIVERS-$(CONFIG_ADEOS) += drivers/adeos/adeos.o
 DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
 DRIVERS-y += drivers/char/char.o \
@@ -194,6 +195,7 @@ DRIVERS-$(CONFIG_BLUEZ) += drivers/bluet
 DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
 DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
 DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
+DRIVERS-$(CONFIG_TRACE) += drivers/trace/trace_driver.o
 
 DRIVERS := $(DRIVERS-y)
 
diff -Nurp linux-2.4.22-clean/mm/filemap.c linux-2.4.22-adeos-ltt/mm/filemap.c
--- linux-2.4.22-clean/mm/filemap.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/mm/filemap.c	2003-11-21 23:21:08.000000000 -0800
@@ -24,6 +24,8 @@
 #include <linux/mm.h>
 #include <linux/iobuf.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/mman.h>
@@ -857,10 +859,12 @@ void ___wait_on_page(struct page *page)
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!PageLocked(page))
 			break;
+ 		TRACE_MEMORY(TRACE_EV_MEMORY_PAGE_WAIT_START, 0);
 		sync_page(page);
 		schedule();
 	} while (PageLocked(page));
 	__set_task_state(tsk, TASK_RUNNING);
+ 	TRACE_MEMORY(TRACE_EV_MEMORY_PAGE_WAIT_END, 0);
 	remove_wait_queue(waitqueue, &wait);
 }
 
diff -Nurp linux-2.4.22-clean/mm/memory.c linux-2.4.22-adeos-ltt/mm/memory.c
--- linux-2.4.22-clean/mm/memory.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/mm/memory.c	2003-11-21 23:21:08.000000000 -0800
@@ -46,6 +46,8 @@
 #include <linux/pagemap.h>
 #include <linux/module.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
@@ -1126,6 +1128,7 @@ static int do_swap_page(struct mm_struct
 	spin_unlock(&mm->page_table_lock);
 	page = lookup_swap_cache(entry);
 	if (!page) {
+	        TRACE_MEMORY(TRACE_EV_MEMORY_SWAP_IN, address);
 		swapin_readahead(entry);
 		page = read_swap_cache_async(entry);
 		if (!page) {
diff -Nurp linux-2.4.22-clean/mm/page_alloc.c linux-2.4.22-adeos-ltt/mm/page_alloc.c
--- linux-2.4.22-clean/mm/page_alloc.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/mm/page_alloc.c	2003-11-21 23:21:08.000000000 -0800
@@ -22,6 +22,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/trace.h>
+
 int nr_swap_pages;
 int nr_active_pages;
 int nr_inactive_pages;
@@ -106,6 +108,9 @@ static void __free_pages_ok (struct page
 		BUG();
 	if (PageActive(page))
 		BUG();
+
+	TRACE_MEMORY(TRACE_EV_MEMORY_PAGE_FREE, order);
+
 	page->flags &= ~((1<<PG_referenced) | (1<<PG_dirty));
 
 	if (current->flags & PF_FREE_PAGES)
@@ -432,6 +437,7 @@ unsigned long __get_free_pages(unsigned 
 	page = alloc_pages(gfp_mask, order);
 	if (!page)
 		return 0;
+	TRACE_MEMORY(TRACE_EV_MEMORY_PAGE_ALLOC, order);
 	return (unsigned long) page_address(page);
 }
 
diff -Nurp linux-2.4.22-clean/mm/swap_state.c linux-2.4.22-adeos-ltt/mm/swap_state.c
--- linux-2.4.22-clean/mm/swap_state.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-adeos-ltt/mm/swap_state.c	2003-11-21 23:21:08.000000000 -0800
@@ -15,6 +15,8 @@
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
+#include <linux/trace.h>
+
 #include <asm/pgtable.h>
 
 /*
@@ -27,6 +29,9 @@ static int swap_writepage(struct page *p
 		UnlockPage(page);
 		return 0;
 	}
+
+	TRACE_MEMORY(TRACE_EV_MEMORY_SWAP_OUT, (unsigned long) page);
+
 	rw_swap_page(WRITE, page);
 	return 0;
 }
diff -Nurp linux-2.4.22-clean/mm/vmalloc.c linux-2.4.22-adeos-ltt/mm/vmalloc.c
--- linux-2.4.22-clean/mm/vmalloc.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/mm/vmalloc.c	2003-11-21 23:25:36.000000000 -0800
@@ -165,6 +165,9 @@ static inline int __vmalloc_area_pages (
 	dir = pgd_offset_k(address);
 	spin_lock(&init_mm.page_table_lock);
 	do {
+#ifdef CONFIG_ADEOS_CORE
+		pgd_t olddir = *dir;
+#endif /* CONFIG_ADEOS_CORE */
 		pmd_t *pmd;
 		
 		pmd = pmd_alloc(&init_mm, dir, address);
@@ -176,6 +179,11 @@ static inline int __vmalloc_area_pages (
 		if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot, pages))
 			break;
 
+#ifdef CONFIG_ADEOS_CORE
+		if (pgd_val(olddir) != pgd_val(*dir))
+		    set_pgdir(address,*dir);
+#endif /* CONFIG_ADEOS_CORE */
+
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 
diff -Nurp linux-2.4.22-clean/net/core/dev.c linux-2.4.22-adeos-ltt/net/core/dev.c
--- linux-2.4.22-clean/net/core/dev.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/net/core/dev.c	2003-11-21 23:21:08.000000000 -0800
@@ -104,6 +104,9 @@
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
 #include <net/iw_handler.h>
 #endif	/* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
+
+#include <linux/trace.h>
+
 #ifdef CONFIG_PLIP
 extern int plip_init(void);
 #endif
@@ -1066,6 +1069,8 @@ int dev_queue_xmit(struct sk_buff *skb)
 			return -ENOMEM;
 	}
 
+	TRACE_NETWORK(TRACE_EV_NETWORK_PACKET_OUT, skb->protocol);
+
 	/* Grab device queue */
 	spin_lock_bh(&dev->queue_lock);
 	q = dev->qdisc;
@@ -1470,6 +1475,8 @@ int netif_receive_skb(struct sk_buff *sk
 	skb_bond(skb);
 
 	netdev_rx_stat[smp_processor_id()].total++;
+ 
+  TRACE_NETWORK(TRACE_EV_NETWORK_PACKET_IN, skb->protocol);
 
 #ifdef CONFIG_NET_FASTROUTE
 	if (skb->pkt_type == PACKET_FASTROUTE) {
diff -Nurp linux-2.4.22-clean/net/socket.c linux-2.4.22-adeos-ltt/net/socket.c
--- linux-2.4.22-clean/net/socket.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-adeos-ltt/net/socket.c	2003-11-21 23:21:08.000000000 -0800
@@ -75,6 +75,8 @@
 #include <linux/module.h>
 #include <linux/highmem.h>
 
+#include <linux/trace.h>
+
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 #include <linux/kmod.h>
 #endif
@@ -502,6 +504,8 @@ int sock_sendmsg(struct socket *sock, st
 	int err;
 	struct scm_cookie scm;
 
+	TRACE_SOCKET(TRACE_EV_SOCKET_SEND, sock->type, size);
+
 	err = scm_send(sock, msg, &scm);
 	if (err >= 0) {
 		err = sock->ops->sendmsg(sock, msg, size, &scm);
@@ -516,6 +520,8 @@ int sock_recvmsg(struct socket *sock, st
 
 	memset(&scm, 0, sizeof(scm));
 
+	TRACE_SOCKET(TRACE_EV_SOCKET_RECEIVE, sock->type, size);
+
 	size = sock->ops->recvmsg(sock, msg, size, flags, &scm);
 	if (size >= 0)
 		scm_recv(sock, msg, &scm, flags);
@@ -911,6 +917,8 @@ asmlinkage long sys_socket(int family, i
 	if (retval < 0)
 		goto out_release;
 
+	TRACE_SOCKET(TRACE_EV_SOCKET_CREATE, retval, type);
+
 out:
 	/* It may be already another descriptor 8) Not kernel problem. */
 	return retval;
@@ -1548,6 +1556,8 @@ asmlinkage long sys_socketcall(int call,
 		
 	a0=a[0];
 	a1=a[1];
+
+	TRACE_SOCKET(TRACE_EV_SOCKET_CALL, call, a0);
 	
 	switch(call) 
 	{
