

This is a multi-part message in MIME format.

------=_NextPart_000_0047_01C4C57D.AF9D9320
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit

Added profiler.
Optimized MMU refill handling.
Improved multiple interrupt handling.

Signed-off-by: Mikael Starvik <starvik@axis.com>

------=_NextPart_000_0047_01C4C57D.AF9D9320
Content-Type: application/octet-stream;
	name="cris269_6.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="cris269_6.patch"

../linux/arch/cris/arch-v10/kernel/entry.S =
lx25/arch/cris/arch-v10/kernel/entry.S
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 /dev/null                                     |    0 
 25-akpm/arch/cris/arch-v10/kernel/crisksyms.c |   17 +++
 25-akpm/arch/cris/arch-v10/kernel/entry.S     |  139 ++++++++++++++++----------
 25-akpm/arch/cris/arch-v10/kernel/irq.c       |   33 +-----
 25-akpm/arch/cris/arch-v10/kernel/kgdb.c      |    7 -
 25-akpm/arch/cris/arch-v10/kernel/process.c   |   24 ++--
 25-akpm/arch/cris/arch-v10/kernel/ptrace.c    |   44 ++++++--
 25-akpm/arch/cris/arch-v10/kernel/signal.c    |   28 ++---
 25-akpm/arch/cris/arch-v10/kernel/time.c      |    9 -
 25-akpm/arch/cris/arch-v10/mm/fault.c         |  104 ++++---------------
 25-akpm/arch/cris/arch-v10/mm/tlb.c           |   20 ++-
 arch/cris/arch-v10/kernel/head.S              |    0 
 arch/cris/arch-v10/kernel/setup.c             |    0 
 13 files changed, 230 insertions(+), 195 deletions(-)

diff -puN /dev/null arch/cris/arch-v10/kernel/crisksyms.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/cris/arch-v10/kernel/crisksyms.c	Mon Nov  8 14:19:32 2004
@@ -0,0 +1,17 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/arch/svinto.h>
+
+/* Export shadow registers for the CPU I/O pins */
+EXPORT_SYMBOL(genconfig_shadow);
+EXPORT_SYMBOL(port_pa_data_shadow);
+EXPORT_SYMBOL(port_pa_dir_shadow);
+EXPORT_SYMBOL(port_pb_data_shadow);
+EXPORT_SYMBOL(port_pb_dir_shadow);
+EXPORT_SYMBOL(port_pb_config_shadow);
+EXPORT_SYMBOL(port_g_data_shadow);
+
+/* Cache flush functions */
+EXPORT_SYMBOL(flush_etrax_cache);
+EXPORT_SYMBOL(prepare_rx_descriptor);
diff -puN arch/cris/arch-v10/kernel/entry.S~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/entry.S
--- 25/arch/cris/arch-v10/kernel/entry.S~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/entry.S	Mon Nov  8 14:19:32 2004
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.18 2004/05/11 12:28:25 starvik Exp $
+/* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $
  *
  *  linux/arch/cris/entry.S
  *
@@ -7,6 +7,23 @@
  *  Authors:	Bjorn Wesen (bjornw@axis.com)
  *
  *  $Log: entry.S,v $
+ *  Revision 1.23  2004/10/19 13:07:37  starvik
+ *  Merge of Linux 2.6.9
+ *
+ *  Revision 1.22  2004/06/21 10:29:55  starvik
+ *  Merge of Linux 2.6.7
+ *
+ *  Revision 1.21  2004/06/09 05:30:27  starvik
+ *  Clean up multiple interrupt handling.
+ *    Prevent interrupts from interrupting each other.
+ *    Handle all active interrupts.
+ *
+ *  Revision 1.20  2004/06/08 08:55:32  starvik
+ *  Removed unused code
+ *
+ *  Revision 1.19  2004/06/04 11:56:15  starvik
+ *  Implemented page table lookup for refills in assembler for improved performance.
+ *
  *  Revision 1.18  2004/05/11 12:28:25  starvik
  *  Merge of Linux 2.6.6
  *
@@ -238,7 +255,9 @@
 #include <asm/errno.h>
 #include <asm/thread_info.h>
 #include <asm/arch/offset.h>
-		
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
 	;; functions exported from this file
 	
 	.globl system_call
@@ -539,11 +558,63 @@ resume:	
 	;; It needs to stack the CPU status and overall is different
 	;; from the other interrupt handlers.
 
-mmu_bus_fault:	
-	sbfs	[$sp=$sp-16]	; push the internal CPU status
+mmu_bus_fault:
+	;; For refills we try to do a quick page table lookup. If it is
+	;; a real fault we let the mm subsystem handle it.
+
 	;; the first longword in the sbfs frame was the interrupted PC
 	;; which fits nicely with the "IRP" slot in pt_regs normally used to
-	;; contain the return address. used by Oops to print kernel errors..
+	;; contain the return address. used by Oops to print kernel errors.
+	sbfs	[$sp=$sp-16]	; push the internal CPU status
+	push	$dccr
+	di
+	subq	2*4, $sp
+	movem	$r1, [$sp]
+	move.d  [R_MMU_CAUSE], $r1
+	;; ETRAX 100LX TR89 bugfix: if the second half of an unaligned
+	;; write causes a MMU-fault, it will not be restarted correctly.
+	;; This could happen if a write crosses a page-boundary and the
+	;; second page is not yet COW'ed or even loaded. The workaround
+	;; is to clear the unaligned bit in the CPU status record, so
+	;; that the CPU will rerun both the first and second halves of
+	;; the instruction. This will not have any sideeffects unless
+	;; the first half goes to any device or memory that can't be
+	;; written twice, and which is mapped through the MMU.
+	;;
+	;; We only need to do this for writes.
+	btstq	8, $r1		   ; Write access?
+	bpl	1f
+	nop
+	move.d	[$sp+16], $r0	   ; Clear unaligned bit in csrinstr
+	and.d	~(1<<5), $r0
+	move.d	$r0, [$sp+16]
+1:	btstq	12, $r1		   ; Refill?
+	bpl	2f
+	lsrq	PMD_SHIFT, $r1     ; Get PMD index into PGD (bit 24-31)
+	move.d  [current_pgd], $r0 ; PGD for the current process
+	move.d	[$r0+$r1.d], $r0   ; Get PMD
+	beq	2f
+	nop
+	and.w	PAGE_MASK, $r0	   ; Remove PMD flags
+	move.d  [R_MMU_CAUSE], $r1
+	lsrq	PAGE_SHIFT, $r1
+	and.d	0x7ff, $r1         ; Get PTE index into PMD (bit 13-24)
+	move.d	[$r0+$r1.d], $r1   ; Get PTE
+	beq	2f
+	nop
+	;; Store in TLB
+	move.d  $r1, [R_TLB_LO]
+	;; Return
+	movem	[$sp+], $r1
+	pop	$dccr
+	rbf	[$sp+]		; return by popping the CPU status
+
+2:	; PMD or PTE missing, let the mm subsystem fix it up.
+	movem	[$sp+], $r1
+	pop	$dccr
+
+	; Ok, not that easy, pass it on to the mm subsystem
+	; The MMU status record is now on the stack
 	push	$srp		; make a stackframe similar to pt_regs
 	push	$dccr
 	push	$mof
@@ -556,7 +627,7 @@ mmu_bus_fault:	
 
 	move.d	$sp, $r10	; pt_regs argument to handle_mmu_bus_fault
 		
-	jsr	handle_mmu_bus_fault  ; in arch/cris/mm/fault.c
+	jsr	handle_mmu_bus_fault  ; in arch/cris/arch-v10/mm/fault.c
 
 	;; now we need to return through the normal path, we cannot just
 	;; do the RBFexit since we might have killed off the running
@@ -569,48 +640,20 @@ mmu_bus_fault:	
 	nop
 		
 	;; special handlers for breakpoint and NMI
-#if 0			
 hwbreakpoint:
 	push	$dccr
 	di
 	push	$r10
 	push	$r11
-	push	$r12
-	push	$r13
-	clearf	b
-	move	$brp,$r11
-	move.d	[hw_bp_msg],$r10
-	jsr	printk
-	setf	b
-	pop	$r13
-	pop	$r12
-	pop	$r11
-	pop	$r10
-	pop	$dccr
-	retb
-	nop
-#else
-hwbreakpoint:
-	push	$dccr
-	di
-#if 1
-	push	$r10
-	push	$r11
 	move.d	[hw_bp_trig_ptr],$r10
-	move.d	[$r10],$r11
-	cmp.d	42,$r11
-	beq	1f
-	nop
 	move	$brp,$r11
 	move.d	$r11,[$r10+]
 	move.d	$r10,[hw_bp_trig_ptr]
 1:	pop	$r11
 	pop	$r10
-#endif
 	pop	$dccr
 	retb
 	nop
-#endif
 	
 IRQ1_interrupt:
 
@@ -719,29 +762,23 @@ multiple_interrupt:
 	push	$r10		; push orig_r10
 	clear.d [$sp=$sp-4]	; frametype == 0, normal frame
 	
-	move.d	irq_shortcuts + 8, $r1
 	moveq	2, $r2		; first bit we care about is the timer0 irq
 	move.d	[R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq
+	move.d	$r0, [R_VECT_MASK_CLR] ; Block all active IRQs
 1:	
 	btst	$r2, $r0	; check for the irq given by bit r2
-	bmi	_do_shortcut	; actually do the shortcut
-	nop
+	bpl	2f
+	move.d  $r2, $r10	; First argument to do_IRQ
+	move.d  $sp, $r11	; second argument to do_IRQ
+	jsr	do_IRQ
+2:
 	addq	1, $r2		; next vector bit
-	addq	4, $r1		; next vector
 	cmp.b	32, $r2
 	bne	1b	; process all irq's up to and including number 31
-	nop
-	
-	;; strange, we didn't get any set vector bits.. oh well, just return
+	moveq	0, $r9  ; make ret_from_intr realise we came from an ir
 	
-	ba	_Rexit
-	nop
-
-_do_shortcut:
-	test.d	[$r1]
-	beq	_Rexit
-	nop
-	jump	[$r1]		; jump to the irq handlers shortcut
+	move.d	$r0, [R_VECT_MASK_SET] ;  Unblock all the IRQs
+	jump    ret_from_intr
 
 do_sigtrap:
 	;; 
@@ -1079,7 +1116,9 @@ sys_call_table:	
 	.long sys_mq_timedreceive	/* 280 */
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
-		
+	.long sys_ni_syscall		/* reserved for kexec */
+	.long sys_waitid
+
         /*
          * NOTE!! This doesn't have to be exact - we just have
          * to make sure we have _enough_ of the "sys_ni_syscall"
diff -puN arch/cris/arch-v10/kernel/head.S~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/head.S
diff -puN arch/cris/arch-v10/kernel/irq.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/irq.c
--- 25/arch/cris/arch-v10/kernel/irq.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/irq.c	Mon Nov  8 14:19:32 2004
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.1 2002/12/11 15:42:02 starvik Exp $
+/* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $
  *
  *	linux/arch/cris/kernel/irq.c
  *
@@ -23,12 +23,8 @@ irqvectptr irq_shortcuts[NR_IRQS]; /* ve
  */
 
 void
-set_int_vector(int n, irqvectptr addr, irqvectptr saddr)
+set_int_vector(int n, irqvectptr addr)
 {
-	/* remember the shortcut entry point, after the prologue */
-
-	irq_shortcuts[n] = saddr;
-
 	etrax_irv->v[n + 0x20] = (irqvectptr)addr;
 }
 
@@ -106,17 +102,6 @@ static void (*interrupt[NR_IRQS])(void) 
 	IRQ31_interrupt
 };
 
-static void (*sinterrupt[NR_IRQS])(void) = {
-	NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt,
-	sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt,
-	sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt,
-	sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,	
-	sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,	
-	sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,	
-	sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
-	sIRQ31_interrupt
-};
-
 static void (*bad_interrupt[NR_IRQS])(void) = {
         NULL, NULL,
 	NULL, bad_IRQ3_interrupt,
@@ -137,12 +122,12 @@ static void (*bad_interrupt[NR_IRQS])(vo
 
 void arch_setup_irq(int irq)
 {
-  set_int_vector(irq, interrupt[irq], sinterrupt[irq]);
+  set_int_vector(irq, interrupt[irq]);
 }
 
 void arch_free_irq(int irq)
 {
-  set_int_vector(irq, bad_interrupt[irq], 0);
+  set_int_vector(irq, bad_interrupt[irq]);
 }
 
 void weird_irq(void);
@@ -187,20 +172,20 @@ init_IRQ(void)
         
 	/* set all etrax irq's to the bad handlers */
 	for (i = 2; i < NR_IRQS; i++)
-		set_int_vector(i, bad_interrupt[i], 0);
+		set_int_vector(i, bad_interrupt[i]);
         
 	/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
 
-	set_int_vector(15, multiple_interrupt, 0);
+	set_int_vector(15, multiple_interrupt);
 	
 	/* 0 and 1 which are special breakpoint/NMI traps */
 
-	set_int_vector(0, hwbreakpoint, 0);
-	set_int_vector(1, IRQ1_interrupt, 0);
+	set_int_vector(0, hwbreakpoint);
+	set_int_vector(1, IRQ1_interrupt);
 
 	/* and irq 14 which is the mmu bus fault handler */
 
-	set_int_vector(14, mmu_bus_fault, 0);
+	set_int_vector(14, mmu_bus_fault);
 
 	/* setup the system-call trap, which is reached by BREAK 13 */
 
diff -puN arch/cris/arch-v10/kernel/kgdb.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/kgdb.c
--- 25/arch/cris/arch-v10/kernel/kgdb.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/kgdb.c	Mon Nov  8 14:19:32 2004
@@ -18,6 +18,9 @@
 *! Jul 21 1999  Bjorn Wesen     eLinux port
 *!
 *! $Log: kgdb.c,v $
+*! Revision 1.5  2004/10/07 13:59:08  starvik
+*! Corrected call to set_int_vector
+*!
 *! Revision 1.4  2003/04/09 05:20:44  starvik
 *! Merge of Linux 2.5.67
 *!
@@ -68,7 +71,7 @@
 *!
 *!---------------------------------------------------------------------------
 *!
-*! $Id: kgdb.c,v 1.4 2003/04/09 05:20:44 starvik Exp $
+*! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $
 *!
 *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
 *!
@@ -1557,7 +1560,7 @@ kgdb_init(void)
 	/* could initialize debug port as well but it's done in head.S already... */
 
         /* breakpoint handler is now set in irq.c */
-	set_int_vector(8, kgdb_handle_serial, 0);
+	set_int_vector(8, kgdb_handle_serial);
 	
 	enableDebugIRQ();
 }
diff -puN arch/cris/arch-v10/kernel/process.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/process.c
--- 25/arch/cris/arch-v10/kernel/process.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/process.c	Mon Nov  8 14:19:32 2004
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.6 2004/05/11 12:28:25 starvik Exp $
+/* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $
  * 
  *  linux/arch/cris/kernel/process.c
  *
@@ -34,6 +34,15 @@ void default_idle(void)
 #endif
 }
 
+/*
+ * Free current thread data structures etc..
+ */
+
+void exit_thread(void)
+{
+	/* Nothing needs to be done.  */
+}
+
 /* if the watchdog is enabled, we can simply disable interrupts and go
  * into an eternal loop, and the watchdog will reset the CPU after 0.1s
  * if on the other hand the watchdog wasn't enabled, we just enable it and wait
@@ -122,6 +131,8 @@ int copy_thread(int nr, unsigned long cl
         
 	*childregs = *regs;  /* struct copy of pt_regs */
         
+        p->set_child_tid = p->clear_child_tid = NULL;
+
         childregs->r10 = 0;  /* child returns 0 after a fork/clone */
 	
 	/* put the switch stack right below the pt_regs */
@@ -212,13 +223,6 @@ asmlinkage int sys_execve(const char *fn
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-
-#define first_sched	((unsigned long)__sched_text_start)
-#define last_sched	((unsigned long)__sched_text_end)
-
 unsigned long get_wchan(struct task_struct *p)
 {
 #if 0
@@ -239,8 +243,8 @@ unsigned long get_wchan(struct task_stru
                 if (ebp < stack_page || ebp > 8184+stack_page)
                         return 0;
                 eip = *(unsigned long *) (ebp+4);
-                if (eip < first_sched || eip >= last_sched)
-                        return eip;
+		if (!in_sched_functions(eip))
+			return eip;
                 ebp = *(unsigned long *) ebp;
         } while (count++ < 16);
 #endif
diff -puN arch/cris/arch-v10/kernel/ptrace.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/ptrace.c
--- 25/arch/cris/arch-v10/kernel/ptrace.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/ptrace.c	Mon Nov  8 14:19:32 2004
@@ -23,8 +23,37 @@
  */
 #define DCCR_MASK 0x0000001f     /* XNZVC */
 
-extern inline long get_reg(struct task_struct *, unsigned int);
-extern inline long put_reg(struct task_struct *, unsigned int, unsigned long);
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+inline long get_reg(struct task_struct *task, unsigned int regno)
+{
+	/* USP is a special case, it's not in the pt_regs struct but
+	 * in the tasks thread struct
+	 */
+
+	if (regno == PT_USP)
+		return task->thread.usp;
+	else if (regno < PT_MAX)
+		return ((unsigned long *)user_regs(task->thread_info))[regno];
+	else
+		return 0;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+inline int put_reg(struct task_struct *task, unsigned int regno,
+			  unsigned long data)
+{
+	if (regno == PT_USP)
+		task->thread.usp = data;
+	else if (regno < PT_MAX)
+		((unsigned long *)user_regs(task->thread_info))[regno] = data;
+	else
+		return -1;
+	return 0;
+}
 
 /*
  * Called by kernel/ptrace.c when detaching.
@@ -50,6 +79,7 @@ sys_ptrace(long request, long pid, long 
 {
 	struct task_struct *child;
 	int ret;
+	unsigned long __user *datap = (unsigned long __user *)data;
 
 	lock_kernel();
 	ret = -EPERM;
@@ -102,7 +132,7 @@ sys_ptrace(long request, long pid, long 
 			if (copied != sizeof(tmp))
 				break;
 			
-			ret = put_user(tmp,(unsigned long *) data);
+			ret = put_user(tmp,datap);
 			break;
 		}
 
@@ -115,7 +145,7 @@ sys_ptrace(long request, long pid, long 
 				break;
 
 			tmp = get_reg(child, addr >> 2);
-			ret = put_user(tmp, (unsigned long *)data);
+			ret = put_user(tmp, datap);
 			break;
 		}
 		
@@ -176,7 +206,7 @@ sys_ptrace(long request, long pid, long 
 		case PTRACE_KILL:
 			ret = 0;
 			
-			if (child->exit_state == EXIT_ZOMBIE)
+			if (child->state == TASK_ZOMBIE)
 				break;
 			
 			child->exit_code = SIGKILL;
@@ -213,7 +243,7 @@ sys_ptrace(long request, long pid, long 
 			for (i = 0; i <= PT_MAX; i++) {
 				tmp = get_reg(child, i);
 				
-				if (put_user(tmp, (unsigned long *) data)) {
+				if (put_user(tmp, datap)) {
 					ret = -EFAULT;
 					goto out_tsk;
 				}
@@ -231,7 +261,7 @@ sys_ptrace(long request, long pid, long 
 			unsigned long tmp;
 			
 			for (i = 0; i <= PT_MAX; i++) {
-				if (get_user(tmp, (unsigned long *) data)) {
+				if (get_user(tmp, datap)) {
 					ret = -EFAULT;
 					goto out_tsk;
 				}
diff -puN arch/cris/arch-v10/kernel/setup.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/setup.c
diff -puN arch/cris/arch-v10/kernel/signal.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/signal.c
--- 25/arch/cris/arch-v10/kernel/signal.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/signal.c	Mon Nov  8 14:19:32 2004
@@ -264,7 +264,6 @@ asmlinkage int sys_rt_sigreturn(long r10
 {
 	struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp();
 	sigset_t set;
-	stack_t st;
 
         /*
          * Since we stacked the signal on a dword boundary,
@@ -288,11 +287,8 @@ asmlinkage int sys_rt_sigreturn(long r10
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT)
 		goto badframe;
-	/* It is more difficult to avoid calling this function than to
-	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, rdusp());
 
 	return regs->r10;
 
@@ -388,9 +384,9 @@ static void setup_frame(int sig, struct 
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
 		/* This is movu.w __NR_sigreturn, r9; break 13; */
-		err |= __put_user(0x9c5f,         (short *)(frame->retcode+0));
-		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
-		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
+		err |= __put_user(0x9c5f,         (short __user*)(frame->retcode+0));
+		err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2));
+		err |= __put_user(0xe93d,         (short __user*)(frame->retcode+4));
 	}
 
 	if (err)
@@ -448,9 +444,9 @@ static void setup_rt_frame(int sig, stru
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
 		/* This is movu.w __NR_rt_sigreturn, r9; break 13; */
-		err |= __put_user(0x9c5f,            (short *)(frame->retcode+0));
-		err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode+2));
-		err |= __put_user(0xe93d,            (short *)(frame->retcode+4));
+		err |= __put_user(0x9c5f,            (short __user*)(frame->retcode+0));
+		err |= __put_user(__NR_rt_sigreturn, (short __user*)(frame->retcode+2));
+		err |= __put_user(0xe93d,            (short __user*)(frame->retcode+4));
 	}
 
 	if (err)
@@ -482,10 +478,9 @@ give_sigsegv:
 
 extern inline void
 handle_signal(int canrestart, unsigned long sig,
-	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+	      siginfo_t *info, struct k_sigaction *ka,
+              sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Are we from a system call? */
 	if (canrestart) {
 		/* If so, check system call restarting.. */
@@ -547,6 +542,7 @@ int do_signal(int canrestart, sigset_t *
 {
 	siginfo_t info;
 	int signr;
+        struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -560,10 +556,10 @@ int do_signal(int canrestart, sigset_t *
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(canrestart, signr, &info, oldset, regs);
+		handle_signal(canrestart, signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff -puN arch/cris/arch-v10/kernel/time.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/kernel/time.c
--- 25/arch/cris/arch-v10/kernel/time.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/kernel/time.c	Mon Nov  8 14:19:32 2004
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.3 2004/06/01 05:38:42 starvik Exp $
+/* $Id: time.c,v 1.5 2004/09/29 06:12:46 starvik Exp $
  *
  *  linux/arch/cris/arch-v10/kernel/time.c
  *
@@ -200,6 +200,8 @@ static long last_rtc_update = 0;
 
 //static unsigned short myjiff; /* used by our debug routine print_timestamp */
 
+extern void cris_do_profile(struct pt_regs *regs);
+
 static inline irqreturn_t
 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -227,10 +229,9 @@ timer_interrupt(int irq, void *dev_id, s
 	/* call the real timer interrupt handler */
 
 	do_timer(regs);
-#ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
-#endif
 	
+        cris_do_profile(regs); /* Save profiling information */
+
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
diff -puN arch/cris/arch-v10/mm/fault.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/mm/fault.c
--- 25/arch/cris/arch-v10/mm/fault.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/mm/fault.c	Mon Nov  8 14:19:32 2004
@@ -40,23 +40,25 @@ void
 handle_mmu_bus_fault(struct pt_regs *regs)
 {
 	int cause;
-#ifdef DEBUG
 	int select;
+#ifdef DEBUG
 	int index;
 	int page_id;
 	int acc, inv;
 #endif
-	int miss, we, writeac;
+	pgd_t* pgd = (pgd_t*)current_pgd;
 	pmd_t *pmd;
 	pte_t pte;
+	int miss, we, writeac;
 	unsigned long address;
+	unsigned long flags;
 
 	cause = *R_MMU_CAUSE;
 
 	address = cause & PAGE_MASK; /* get faulting address */
+	select = *R_TLB_SELECT;
 
 #ifdef DEBUG
-	select = *R_TLB_SELECT;
 	page_id = IO_EXTRACT(R_MMU_CAUSE,  page_id,   cause);
 	acc     = IO_EXTRACT(R_MMU_CAUSE,  acc_excp,  cause);
 	inv     = IO_EXTRACT(R_MMU_CAUSE,  inv_excp,  cause);  
@@ -66,85 +68,31 @@ handle_mmu_bus_fault(struct pt_regs *reg
 	we      = IO_EXTRACT(R_MMU_CAUSE,  we_excp,   cause);
 	writeac = IO_EXTRACT(R_MMU_CAUSE,  wr_rd,     cause);
 
-	/* ETRAX 100LX TR89 bugfix: if the second half of an unaligned
-	 * write causes a MMU-fault, it will not be restarted correctly.
-	 * This could happen if a write crosses a page-boundary and the
-	 * second page is not yet COW'ed or even loaded. The workaround
-	 * is to clear the unaligned bit in the CPU status record, so 
-	 * that the CPU will rerun both the first and second halves of
-	 * the instruction. This will not have any sideeffects unless
-	 * the first half goes to any device or memory that can't be
-	 * written twice, and which is mapped through the MMU.
-	 *
-	 * We only need to do this for writes.
-	 */
-
-	if(writeac)
-		regs->csrinstr &= ~(1 << 5);
-	
 	D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n",
 		 regs->irp, address, miss, inv, we, acc, index, page_id));
 
-	/* for a miss, we need to reload the TLB entry */
-
-	if (miss) {
-		/* see if the pte exists at all
-		 * refer through current_pgd, dont use mm->pgd
-		 */
-
-		pmd = (pmd_t *)(current_pml4 + pgd_index(address));
-		if (pmd_none(*pmd)) {
-			do_page_fault(address, regs, 0, writeac);
-			return;
-		}
-		if (pmd_bad(*pmd)) {
-			printk("bad pgdir entry 0x%lx at 0x%p\n", *(unsigned long*)pmd, pmd);
-			pmd_clear(pmd);
-			return;
-		}
-		pte = *pte_offset_kernel(pmd, address);
-		if (!pte_present(pte)) {
-			do_page_fault(address, regs, 0, writeac);
-			return;
-		}
-
-#ifdef DEBUG
-		printk(" found pte %lx pg %p ", pte_val(pte), pte_page(pte));
-		if (pte_val(pte) & _PAGE_SILENT_WRITE)
-			printk("Silent-W ");
-		if (pte_val(pte) & _PAGE_KERNEL)
-			printk("Kernel ");
-		if (pte_val(pte) & _PAGE_SILENT_READ)
-			printk("Silent-R ");
-		if (pte_val(pte) & _PAGE_GLOBAL)
-			printk("Global ");
-		if (pte_val(pte) & _PAGE_PRESENT)
-			printk("Present ");
-		if (pte_val(pte) & _PAGE_ACCESSED)
-			printk("Accessed ");
-		if (pte_val(pte) & _PAGE_MODIFIED)
-			printk("Modified ");
-		if (pte_val(pte) & _PAGE_READ)
-			printk("Readable ");
-		if (pte_val(pte) & _PAGE_WRITE)
-			printk("Writeable ");
-		printk("\n");
-#endif
-
-		/* load up the chosen TLB entry
-		 * this assumes the pte format is the same as the TLB_LO layout.
-		 *
-		 * the write to R_TLB_LO also writes the vpn and page_id fields from
-		 * R_MMU_CAUSE, which we in this case obviously want to keep
-		 */
-
-		*R_TLB_LO = pte_val(pte);
-
-		return;
-	}
-
 	/* leave it to the MM system fault handler */
-	do_page_fault(address, regs, 1, we);
+	if (miss)
+		do_page_fault(address, regs, 0, writeac);
+        else
+		do_page_fault(address, regs, 1, we);
+
+        /* Reload TLB with new entry to avoid an extra miss exception.
+	 * do_page_fault may have flushed the TLB so we have to restore
+	 * the MMU registers.
+	 */
+	local_save_flags(flags);
+	local_irq_disable();
+	pmd = (pmd_t *)(pgd + pgd_index(address));
+	if (pmd_none(*pmd))
+		return;
+	pte = *pte_offset_kernel(pmd, address);
+	if (!pte_present(pte))
+		return;
+	*R_TLB_SELECT = select;
+	*R_TLB_HI = cause;
+	*R_TLB_LO = pte_val(pte);
+	local_irq_restore(flags);
 }
 
 /* Called from arch/cris/mm/fault.c to find fixup code. */
diff -puN arch/cris/arch-v10/mm/tlb.c~cris-architecture-update-core-kernel-updates arch/cris/arch-v10/mm/tlb.c
--- 25/arch/cris/arch-v10/mm/tlb.c~cris-architecture-update-core-kernel-updates	Mon Nov  8 14:19:32 2004
+++ 25-akpm/arch/cris/arch-v10/mm/tlb.c	Mon Nov  8 14:19:32 2004
@@ -65,7 +65,7 @@ void
 flush_tlb_mm(struct mm_struct *mm)
 {
 	int i;
-	int page_id = mm->context;
+	int page_id = mm->context.page_id;
 	unsigned long flags;
 
 	D(printk("tlb: flush mm context %d (%p)\n", page_id, mm));
@@ -103,7 +103,7 @@ flush_tlb_page(struct vm_area_struct *vm
 	       unsigned long addr)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	int page_id = mm->context;
+	int page_id = mm->context.page_id;
 	int i;
 	unsigned long flags;
 
@@ -147,7 +147,7 @@ flush_tlb_range(struct vm_area_struct *v
 		unsigned long end)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	int page_id = mm->context;
+	int page_id = mm->context.page_id;
 	int i;
 	unsigned long flags;
 
@@ -208,6 +208,18 @@ dump_tlb_all(void)
 }
 #endif
 
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context.page_id = NO_CONTEXT;
+	return 0;
+}
+
 /* called in schedule() just before actually doing the switch_to */
 
 void 
@@ -231,6 +243,6 @@ switch_mm(struct mm_struct *prev, struct
 	
 	D(printk("switching mmu_context to %d (%p)\n", next->context, next));
 
-	*R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context);
+	*R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context.page_id);
 }
 
diff -L linux/arch/cris/arch-v10/kernel/crisksyms.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/entry.S -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/head.S -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/irq.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/kgdb.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/process.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/ptrace.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/setup.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/signal.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/kernel/time.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/mm/fault.c -puN /dev/null /dev/null
diff -L linux/arch/cris/arch-v10/mm/tlb.c -puN /dev/null /dev/null
_
