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 ------=_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 --- /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 +#include +#include +#include + +/* 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 #include #include - +#include +#include + ;; 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 = ¤t->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 = ¤t->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 _