This patch is complement to 030304-a.rml-preempt-2.4.21.no-arch.patch, covering mips32 part. Together these patches add preemptible kernel capability. Patch is created against linux-mips.org CVS tree linux_2_4 brach on 030304. Jun diff -Nru linux/arch/mips/kernel/time.c.orig linux/arch/mips/kernel/time.c --- linux/arch/mips/kernel/time.c.orig Mon Dec 2 16:56:03 2002 +++ linux/arch/mips/kernel/time.c Tue Mar 4 14:02:07 2003 @@ -28,6 +28,7 @@ #include #include #include +#include /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) @@ -416,6 +417,8 @@ { int cpu = smp_processor_id(); + preempt_disable(); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; @@ -426,12 +429,30 @@ if (softirq_pending(cpu)) do_softirq(); + +#if defined(CONFIG_PREEMPT) + for(;;) { + db_assert(intr_off()); + db_assert(!in_interrupt()); + + preempt_enable_no_resched(); + if (preempt_is_disabled() || !need_resched()) + break; + + preempt_disable(); + __sti(); + preempt_schedule(); + __cli(); + } +#endif } asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) { int cpu = smp_processor_id(); + preempt_disable(); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; @@ -442,6 +463,22 @@ if (softirq_pending(cpu)) do_softirq(); + +#if defined(CONFIG_PREEMPT) + for(;;) { + db_assert(intr_off()); + db_assert(!in_interrupt()); + + preempt_enable_no_resched(); + if (preempt_is_disabled() || !need_resched()) + break; + + preempt_disable(); + __sti(); + preempt_schedule(); + __cli(); + } +#endif } /* diff -Nru linux/arch/mips/kernel/traps.c.orig linux/arch/mips/kernel/traps.c --- linux/arch/mips/kernel/traps.c.orig Thu Feb 13 11:34:55 2003 +++ linux/arch/mips/kernel/traps.c Tue Mar 4 13:45:42 2003 @@ -128,12 +128,14 @@ goto sig; } + preempt_disable(); if (ll_task == NULL || ll_task == current) { ll_bit = 1; } else { ll_bit = 0; } ll_task = current; + preempt_enable(); regs->regs[(opcode & RT) >> 16] = value; compute_return_epc(regs); @@ -170,10 +172,13 @@ signal = SIGBUS; goto sig; } + preempt_disable(); if (ll_bit == 0 || ll_task != current) { regs->regs[reg] = 0; + preempt_enable(); goto sig; } + preempt_enable(); if (put_user(regs->regs[reg], vaddr)) signal = SIGSEGV; @@ -517,6 +522,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... @@ -542,6 +549,8 @@ /* Restore the hardware register state */ restore_fp(current); + preempt_enable(); + /* If something went wrong, signal */ if (sig) force_sig(sig, current); @@ -684,6 +693,8 @@ die_if_kernel("do_cpu invoked from kernel context!", regs); + preempt_disable(); + own_fpu(); if (current->used_math) { /* Using the FPU again. */ restore_fp(current); @@ -698,6 +709,8 @@ force_sig(sig, current); } + preempt_enable(); + return; bad_cid: diff -Nru linux/arch/mips/kernel/irq.c.orig linux/arch/mips/kernel/irq.c --- linux/arch/mips/kernel/irq.c.orig Mon Aug 12 20:29:54 2002 +++ linux/arch/mips/kernel/irq.c Tue Mar 4 13:45:42 2003 @@ -24,6 +24,7 @@ #include #include #include +#include /* * Controller mappings for all interrupt sources: @@ -215,8 +216,9 @@ __save_flags(flags); if (flags & ST0_IE) { - int cpu = smp_processor_id(); + int cpu; __cli(); + cpu = smp_processor_id(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -226,6 +228,11 @@ { int cpu = smp_processor_id(); + /* + * [JSUN] FIXME: what if we are preempted here and migrate to + * another CPU? + */ + if (!local_irq_count(cpu)) release_irqlock(cpu); __sti(); @@ -245,6 +252,11 @@ unsigned long flags; int cpu = smp_processor_id(); + /* + * [JSUN] FIXME: what if we are preempted here and migrate to + * another CPU? + */ + __save_flags(flags); local_enabled = (flags & ST0_IE); /* default to local */ @@ -294,6 +306,7 @@ int status; int cpu = smp_processor_id(); + db_assert(intr_off()); irq_enter(cpu, irq); status = 1; /* Force the "do bottom halves" bit */ @@ -361,6 +374,8 @@ void disable_irq(unsigned int irq) { + preempt_disable(); + disable_irq_nosync(irq); if (!local_irq_count(smp_processor_id())) { @@ -368,6 +383,8 @@ barrier(); } while (irq_desc[irq].status & IRQ_INPROGRESS); } + + preempt_enable(); } /** @@ -429,6 +446,8 @@ struct irqaction * action; unsigned int status; + preempt_disable(); + kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); @@ -490,6 +509,23 @@ if (softirq_pending(cpu)) do_softirq(); + +#if defined(CONFIG_PREEMPT) + for(;;) { + preempt_enable_no_resched(); + if (preempt_is_disabled() || !need_resched()) + break; + + db_assert(intr_off()); + db_assert(!in_interrupt()); + + preempt_disable(); + __sti(); + preempt_schedule(); + __cli(); + } +#endif + return 1; } diff -Nru linux/arch/mips/kernel/process.c.orig linux/arch/mips/kernel/process.c --- linux/arch/mips/kernel/process.c.orig Wed Jan 29 15:33:03 2003 +++ linux/arch/mips/kernel/process.c Tue Mar 4 13:45:42 2003 @@ -78,9 +78,11 @@ childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; + preempt_disable(); if (is_fpu_owner()) { save_fp(p); } + preempt_enable(); /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; diff -Nru linux/arch/mips/kernel/signal.c.orig linux/arch/mips/kernel/signal.c --- linux/arch/mips/kernel/signal.c.orig Thu Nov 7 14:05:33 2002 +++ linux/arch/mips/kernel/signal.c Tue Mar 4 13:45:42 2003 @@ -214,6 +214,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(); @@ -223,6 +225,8 @@ loose_fpu(); } + preempt_enable(); + return err; } @@ -351,6 +355,8 @@ if (!current->used_math) goto out; + preempt_disable(); + /* * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. @@ -361,6 +367,8 @@ } err |= save_fp_context(sc); + preempt_enable(); + out: return err; } diff -Nru linux/arch/mips/kernel/smp.c.orig linux/arch/mips/kernel/smp.c --- linux/arch/mips/kernel/smp.c.orig Mon Dec 2 16:56:03 2002 +++ linux/arch/mips/kernel/smp.c Tue Mar 4 13:45:42 2003 @@ -158,6 +158,8 @@ if (!cpus) return 0; + db_assert(preempt_is_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); @@ -247,8 +249,10 @@ void flush_tlb_all(void) { + preempt_disable(); smp_call_function(flush_tlb_all_ipi, 0, 1, 1); local_flush_tlb_all(); + preempt_enable(); } static void flush_tlb_mm_ipi(void *mm) @@ -271,6 +275,7 @@ void flush_tlb_mm(struct mm_struct *mm) { + preempt_disable(); if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); } else { @@ -280,6 +285,7 @@ cpu_context(i, mm) = 0; } local_flush_tlb_mm(mm); + preempt_enable(); } struct flush_tlb_data { @@ -298,6 +304,7 @@ void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { + preempt_disable(); if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { struct flush_tlb_data fd; @@ -312,6 +319,7 @@ cpu_context(i, mm) = 0; } local_flush_tlb_range(mm, start, end); + preempt_enable(); } static void flush_tlb_page_ipi(void *info) @@ -323,6 +331,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { + preempt_disable(); if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) { struct flush_tlb_data fd; @@ -336,6 +345,7 @@ cpu_context(i, vma->vm_mm) = 0; } local_flush_tlb_page(vma, page); + preempt_enable(); } EXPORT_SYMBOL(smp_num_cpus); diff -Nru linux/arch/mips/mm/tlb-sb1.c.orig linux/arch/mips/mm/tlb-sb1.c --- linux/arch/mips/mm/tlb-sb1.c.orig Thu Feb 13 11:34:55 2003 +++ linux/arch/mips/mm/tlb-sb1.c Tue Mar 4 13:45:42 2003 @@ -180,17 +180,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { unsigned long flags; - -#ifdef CONFIG_SMP - /* - * This variable is eliminated from cpu_context() if SMP isn't defined, - * so conditional it to get rid of silly "unused variable" compiler - * complaints - */ - int cpu = smp_processor_id(); -#endif + int cpu; local_irq_save(flags); + cpu = smp_processor_id(); if (cpu_context(cpu, vma->vm_mm) != 0) { int oldpid, newpid, idx; newpid = cpu_asid(cpu, vma->vm_mm); @@ -217,10 +210,13 @@ 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 */ diff -Nru linux/arch/mips/mm/fault.c.orig linux/arch/mips/mm/fault.c --- linux/arch/mips/mm/fault.c.orig Wed Jan 29 15:33:03 2003 +++ linux/arch/mips/mm/fault.c Tue Mar 4 13:45:42 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #define development_version (LINUX_VERSION_CODE & 0x100) @@ -254,6 +255,7 @@ pmd_t *pmd, *pmd_k; pte_t *pte_k; + db_assert(preempt_is_disabled() || intr_off()); pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; pgd_k = init_mm.pgd + offset; diff -Nru linux/arch/mips/config-shared.in.orig linux/arch/mips/config-shared.in --- linux/arch/mips/config-shared.in.orig Tue Mar 4 12:21:51 2003 +++ linux/arch/mips/config-shared.in Tue Mar 4 13:45:42 2003 @@ -804,6 +804,7 @@ define_bool CONFIG_HOTPLUG_PCI n fi +bool 'Preemptible Kernel' CONFIG_PREEMPT bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL diff -Nru linux/include/asm-mips/smplock.h.orig linux/include/asm-mips/smplock.h --- linux/include/asm-mips/smplock.h.orig Tue Mar 4 12:18:54 2003 +++ linux/include/asm-mips/smplock.h Tue Mar 4 14:02:39 2003 @@ -8,12 +8,21 @@ #ifndef __ASM_SMPLOCK_H #define __ASM_SMPLOCK_H +#include #include #include extern spinlock_t kernel_flag; +#ifdef CONFIG_SMP #define kernel_locked() spin_is_locked(&kernel_flag) +#else +#ifdef CONFIG_PREEMPT +#define kernel_locked() preempt_get_count() +#else +#define kernel_locked() 1 +#endif +#endif /* * Release global kernel lock and global interrupt lock @@ -45,8 +54,14 @@ */ extern __inline__ void lock_kernel(void) { +#ifdef CONFIG_PREEMPT + if (current->lock_depth == -1) + spin_lock(&kernel_flag); + ++current->lock_depth; +#else if (!++current->lock_depth) spin_lock(&kernel_flag); +#endif } extern __inline__ void unlock_kernel(void) diff -Nru linux/include/asm-mips/softirq.h.orig linux/include/asm-mips/softirq.h --- linux/include/asm-mips/softirq.h.orig Thu Dec 12 10:39:28 2002 +++ linux/include/asm-mips/softirq.h Tue Mar 4 14:02:39 2003 @@ -10,11 +10,20 @@ #ifndef _ASM_SOFTIRQ_H #define _ASM_SOFTIRQ_H +/* + * [jsun] For preemptible kernel, we need to include these files because many + * (driver) code include "interrupt.h" without including "sched.h". In + * those cases compiling will fail. + */ +#include +#include + #include #include static inline void cpu_bh_disable(int cpu) { + preempt_disable(); local_bh_count(cpu)++; barrier(); } @@ -23,6 +32,7 @@ { barrier(); local_bh_count(cpu)--; + preempt_enable(); } @@ -36,6 +46,7 @@ cpu = smp_processor_id(); \ if (!--local_bh_count(cpu) && softirq_pending(cpu)) \ do_softirq(); \ + preempt_enable(); \ } while (0) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) diff -Nru linux/include/asm-mips/system.h.orig linux/include/asm-mips/system.h --- linux/include/asm-mips/system.h.orig Tue Mar 4 12:18:54 2003 +++ linux/include/asm-mips/system.h Tue Mar 4 13:51:03 2003 @@ -338,4 +338,18 @@ #define die_if_kernel(msg, regs) \ __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__) +extern __inline__ int intr_on(void) +{ + unsigned long flags; + save_flags(flags); + return flags & 1; +} + +extern __inline__ int intr_off(void) +{ + return ! intr_on(); +} + +#define irqs_disabled() intr_off() + #endif /* _ASM_SYSTEM_H */ diff -Nru linux/include/asm-mips/pgalloc.h.orig linux/include/asm-mips/pgalloc.h --- linux/include/asm-mips/pgalloc.h.orig Thu Dec 12 10:39:28 2002 +++ linux/include/asm-mips/pgalloc.h Tue Mar 4 14:02:39 2003 @@ -11,6 +11,7 @@ #include #include +#include #include /* TLB flushing: @@ -84,20 +85,26 @@ { unsigned long *ret; + preempt_disable(); if((ret = pgd_quicklist) != NULL) { pgd_quicklist = (unsigned long *)(*ret); ret[0] = ret[1]; pgtable_cache_size--; - } else + preempt_enable(); + } else { + preempt_enable(); ret = (unsigned long *)get_pgd_slow(); + } return (pgd_t *)ret; } extern __inline__ void free_pgd_fast(pgd_t *pgd) { + preempt_disable(); *(unsigned long *)pgd = (unsigned long) pgd_quicklist; pgd_quicklist = (unsigned long *) pgd; pgtable_cache_size++; + preempt_enable(); } extern __inline__ void free_pgd_slow(pgd_t *pgd) @@ -109,19 +116,23 @@ { unsigned long *ret; + preempt_disable(); if((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); ret[0] = ret[1]; pgtable_cache_size--; } + preempt_enable(); return (pte_t *)ret; } extern __inline__ void free_pte_fast(pte_t *pte) { + preempt_disable(); *(unsigned long *)pte = (unsigned long) pte_quicklist; pte_quicklist = (unsigned long *) pte; pgtable_cache_size++; + preempt_enable(); } extern __inline__ void free_pte_slow(pte_t *pte) diff -Nru linux/include/asm-mips/fpu.h.orig linux/include/asm-mips/fpu.h --- linux/include/asm-mips/fpu.h.orig Thu Dec 12 10:42:56 2002 +++ linux/include/asm-mips/fpu.h Tue Mar 4 14:08:34 2003 @@ -122,11 +122,14 @@ static inline unsigned long long *get_fpu_regs(struct task_struct *tsk) { + preempt_disable(); if(mips_cpu.options & MIPS_CPU_FPU) { if ((tsk == current) && is_fpu_owner()) _save_fp(current); + preempt_enable(); return (unsigned long long *)&tsk->thread.fpu.hard.fp_regs[0]; } else { + preempt_enable(); return (unsigned long long *)tsk->thread.fpu.soft.regs; } } diff -Nru linux/include/asm-mips/hardirq.h.orig linux/include/asm-mips/hardirq.h --- linux/include/asm-mips/hardirq.h.orig Thu Dec 12 10:39:28 2002 +++ linux/include/asm-mips/hardirq.h Tue Mar 4 14:02:39 2003 @@ -27,11 +27,16 @@ /* * Are we in an interrupt context? Either doing bottom half - * or hardware interrupt processing? + * or hardware interrupt processing? Note the preempt check, + * this is both a bugfix and an optimization. If we are + * preemptible, we cannot be in an interrupt. */ -#define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) -#define in_irq() (local_irq_count(smp_processor_id()) != 0) +#define in_interrupt() (preempt_is_disabled() && \ + ({unsigned long __cpu = smp_processor_id(); \ + (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })) + +#define in_irq() (preempt_is_disabled() && \ + (local_irq_count(smp_processor_id()) != 0)) #ifndef CONFIG_SMP @@ -43,6 +48,8 @@ #define synchronize_irq() barrier(); +#define release_irqlock(cpu) do { } while (0) + #else #include diff -Nru linux/include/asm-mips/highmem.h.orig linux/include/asm-mips/highmem.h --- linux/include/asm-mips/highmem.h.orig Thu Dec 12 10:39:30 2002 +++ linux/include/asm-mips/highmem.h Tue Mar 4 14:02:39 2003 @@ -78,6 +78,7 @@ enum fixed_addresses idx; unsigned long vaddr; + preempt_disable(); if (page < highmem_start_page) return page_address(page); @@ -92,6 +93,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) { + preempt_enable(); } #endif /* __KERNEL__ */ diff -Nru linux/include/asm-mips/spinlock.h.orig linux/include/asm-mips/spinlock.h --- linux/include/asm-mips/spinlock.h.orig Mon Aug 5 16:53:37 2002 +++ linux/include/asm-mips/spinlock.h Tue Mar 4 14:00:40 2003 @@ -31,12 +31,12 @@ * We make no fairness assumptions. They have a cost. */ -static inline void spin_lock(spinlock_t *lock) +static inline void _raw_spin_lock(spinlock_t *lock) { unsigned int tmp; __asm__ __volatile__( - ".set\tnoreorder\t\t\t# spin_lock\n" + ".set\tnoreorder\t\t\t# _raw_spin_lock\n" "1:\tll\t%1, %2\n\t" "bnez\t%1, 1b\n\t" " li\t%1, 1\n\t" @@ -49,10 +49,10 @@ : "memory"); } -static inline void spin_unlock(spinlock_t *lock) +static inline void _raw_spin_unlock(spinlock_t *lock) { __asm__ __volatile__( - ".set\tnoreorder\t\t\t# spin_unlock\n\t" + ".set\tnoreorder\t\t\t# _raw_spin_unlock\n\t" "sync\n\t" "sw\t$0, %0\n\t" ".set\treorder" @@ -61,7 +61,7 @@ : "memory"); } -#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) +#define _raw_spin_trylock(lock) (!test_and_set_bit(0,(lock))) /* * Read-write spinlocks, allowing multiple readers but only one writer. @@ -80,12 +80,12 @@ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) -static inline void read_lock(rwlock_t *rw) +static inline void _raw_read_lock(rwlock_t *rw) { unsigned int tmp; __asm__ __volatile__( - ".set\tnoreorder\t\t\t# read_lock\n" + ".set\tnoreorder\t\t\t# _raw_read_lock\n" "1:\tll\t%1, %2\n\t" "bltz\t%1, 1b\n\t" " addu\t%1, 1\n\t" @@ -101,12 +101,12 @@ /* Note the use of sub, not subu which will make the kernel die with an overflow exception if we ever try to unlock an rwlock that is already unlocked or is being held by a writer. */ -static inline void read_unlock(rwlock_t *rw) +static inline void _raw_read_unlock(rwlock_t *rw) { unsigned int tmp; __asm__ __volatile__( - ".set\tnoreorder\t\t\t# read_unlock\n" + ".set\tnoreorder\t\t\t# _raw_read_unlock\n" "1:\tll\t%1, %2\n\t" "sub\t%1, 1\n\t" "sc\t%1, %0\n\t" @@ -118,12 +118,12 @@ : "memory"); } -static inline void write_lock(rwlock_t *rw) +static inline void _raw_write_lock(rwlock_t *rw) { unsigned int tmp; __asm__ __volatile__( - ".set\tnoreorder\t\t\t# write_lock\n" + ".set\tnoreorder\t\t\t# _raw_write_lock\n" "1:\tll\t%1, %2\n\t" "bnez\t%1, 1b\n\t" " lui\t%1, 0x8000\n\t" @@ -136,10 +136,10 @@ : "memory"); } -static inline void write_unlock(rwlock_t *rw) +static inline void _raw_write_unlock(rwlock_t *rw) { __asm__ __volatile__( - ".set\tnoreorder\t\t\t# write_unlock\n\t" + ".set\tnoreorder\t\t\t# _raw_write_unlock\n\t" "sync\n\t" "sw\t$0, %0\n\t" ".set\treorder" diff -Nru linux/include/asm-mips/pgtable.h.orig linux/include/asm-mips/pgtable.h --- linux/include/asm-mips/pgtable.h.orig Thu Dec 12 10:39:28 2002 +++ linux/include/asm-mips/pgtable.h Tue Mar 4 13:51:03 2003 @@ -45,21 +45,20 @@ #define flush_dcache_page(page) do { } while (0) -#define flush_cache_all() _flush_cache_all() -#define __flush_cache_all() ___flush_cache_all() -#define flush_cache_mm(mm) _flush_cache_mm(mm) -#define flush_cache_range(mm,start,end) _flush_cache_range(mm,start,end) -#define flush_cache_page(vma,page) _flush_cache_page(vma, page) -#define flush_page_to_ram(page) _flush_page_to_ram(page) +#define flush_cache_all() do { preempt_disable(); _flush_cache_all(); preempt_enable(); } while (0) +#define __flush_cache_all() do { preempt_disable(); ___flush_cache_all(); preempt_enable(); } while (0) +#define flush_cache_mm(mm) do { preempt_disable(); _flush_cache_mm(mm); preempt_enable(); } while (0) +#define flush_cache_range(mm,start,end) do { preempt_disable(); _flush_cache_range(mm,start,end); preempt_enable(); } while (0) +#define flush_cache_page(vma,page) do { preempt_disable(); _flush_cache_page(vma, page); preempt_enable(); } while (0) +#define flush_page_to_ram(page) do { preempt_disable(); _flush_page_to_ram(page); preempt_enable(); } while (0) -#define flush_icache_range(start, end) _flush_icache_range(start,end) -#define flush_icache_user_range(vma, page, addr, len) \ - _flush_icache_page((vma), (page)) -#define flush_icache_page(vma, page) _flush_icache_page(vma, page) +#define flush_icache_range(start, end) do { preempt_disable(); _flush_icache_range(start,end); preempt_enable(); } while (0) +#define flush_icache_user_range(vma, page, addr, len) do { preempt_disable(); _flush_icache_page((vma), (page)); preempt_enable(); } while (0) +#define flush_icache_page(vma, page) do { preempt_disable(); _flush_icache_page(vma, page); preempt_enable(); } while (0) -#define flush_cache_sigtramp(addr) _flush_cache_sigtramp(addr) +#define flush_cache_sigtramp(addr) do { preempt_disable(); _flush_cache_sigtramp(addr); preempt_enable(); } while (0) #ifdef CONFIG_VTAG_ICACHE -#define flush_icache_all() _flush_icache_all() +#define flush_icache_all() do { preempt_disable(); _flush_icache_all(); preempt_enable(); } while (0) #else #define flush_icache_all() do { } while(0) #endif