Hello ! The attached patch incorporates preemption enable/disable in some parts of the kernel. I have tested this on the Broadcom Sibyte. Please review ... Thanks Manish Lachwani Index: linux-2.6.8.1/arch/mips/kernel/signal32.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/kernel/signal32.c +++ linux-2.6.8.1/arch/mips/kernel/signal32.c @@ -295,6 +295,8 @@ err |= __get_user(current->used_math, &sc->sc_used_math); + preempt_disable(); + if (current->used_math) { /* restore fpu context if we have used it before */ own_fpu(); @@ -304,6 +306,8 @@ lose_fpu(); } + preempt_enable(); + return err; } @@ -489,12 +493,16 @@ * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. */ + preempt_disable(); + if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } err |= save_fp_context32(sc); + preempt_enable(); + out: return err; } Index: linux-2.6.8.1/arch/mips/mm/c-sb1.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/mm/c-sb1.c +++ linux-2.6.8.1/arch/mips/mm/c-sb1.c @@ -197,10 +197,14 @@ if (!(vma->vm_flags & VM_EXEC)) return; + preempt_disable(); + addr &= PAGE_MASK; args.vma = vma; args.addr = addr; on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); + + preempt_enable(); } #else void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr) @@ -243,7 +247,9 @@ static void sb1___flush_cache_all(void) { + preempt_disable(); on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); + preempt_enable(); } #else void sb1___flush_cache_all(void) @@ -291,9 +297,13 @@ { struct flush_icache_range_args args; + preempt_disable(); + args.start = start; args.end = end; on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); + + preempt_enable(); } #else void sb1_flush_icache_range(unsigned long start, unsigned long end) @@ -348,9 +358,14 @@ if (!(vma->vm_flags & VM_EXEC)) return; + + preempt_disable(); + args.vma = vma; args.page = page; on_each_cpu(sb1_flush_icache_page_ipi, (void *) &args, 1, 1); + + preempt_enable(); } #else void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page) @@ -377,7 +392,9 @@ static void sb1_flush_cache_sigtramp(unsigned long addr) { + preempt_disable(); on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); + preempt_enable(); } #else void sb1_flush_cache_sigtramp(unsigned long addr) Index: linux-2.6.8.1/arch/mips/mm/tlb-sb1.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/mm/tlb-sb1.c +++ linux-2.6.8.1/arch/mips/mm/tlb-sb1.c @@ -286,10 +286,17 @@ these entries, we just bump the asid. */ void local_flush_tlb_mm(struct mm_struct *mm) { - int cpu = smp_processor_id(); + int cpu; + + preempt_disable(); + + cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { drop_mmu_context(mm, cpu); } + + preempt_enable(); } /* Stolen from mips32 routines */ Index: linux-2.6.8.1/arch/mips/kernel/traps.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/kernel/traps.c +++ linux-2.6.8.1/arch/mips/kernel/traps.c @@ -411,6 +411,8 @@ goto sig; } + preempt_disable(); + if (ll_task == NULL || ll_task == current) { ll_bit = 1; } else { @@ -418,6 +420,8 @@ } ll_task = current; + preempt_enable(); + regs->regs[(opcode & RT) >> 16] = value; compute_return_epc(regs); @@ -450,12 +454,18 @@ signal = SIGBUS; goto sig; } + + preempt_disable(); + if (ll_bit == 0 || ll_task != current) { regs->regs[reg] = 0; + preempt_enable(); compute_return_epc(regs); return; } + preempt_enable(); + if (put_user(regs->regs[reg], vaddr)) { signal = SIGSEGV; goto sig; @@ -515,6 +525,8 @@ if (fcr31 & FPU_CSR_UNI_X) { int sig; + preempt_disable(); + /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... @@ -540,6 +552,8 @@ /* Restore the hardware register state */ restore_fp(current); + preempt_enable(); + /* If something went wrong, signal */ if (sig) force_sig(sig, current); @@ -659,6 +673,8 @@ break; case 1: + preempt_disable(); + own_fpu(); if (current->used_math) { /* Using the FPU again. */ restore_fp(current); @@ -674,6 +690,8 @@ force_sig(sig, current); } + preempt_enable(); + return; case 2: Index: linux-2.6.8.1/arch/mips/kernel/process.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/kernel/process.c +++ linux-2.6.8.1/arch/mips/kernel/process.c @@ -99,10 +99,14 @@ childksp = (unsigned long)ti + THREAD_SIZE - 32; + preempt_disable(); + if (is_fpu_owner()) { save_fp(p); } + preempt_enable(); + /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; Index: linux-2.6.8.1/arch/mips/kernel/signal.c =================================================================== --- linux-2.6.8.1.orig/arch/mips/kernel/signal.c +++ linux-2.6.8.1/arch/mips/kernel/signal.c @@ -178,6 +178,8 @@ err |= __get_user(current->used_math, &sc->sc_used_math); + preempt_disable(); + if (current->used_math) { /* restore fpu context if we have used it before */ own_fpu(); @@ -187,6 +189,8 @@ lose_fpu(); } + preempt_enable(); + return err; } @@ -320,12 +324,16 @@ * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. */ + preempt_disable(); + if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } err |= save_fp_context(sc); + preempt_enable(); + out: return err; }