From 50a34dbd612925f2ec55b1781632835ef36b97d5 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 24 Mar 2006 21:24:21 -0700 Subject: [PARISC] Add PREEMPT support Signed-off-by: Kyle McMartin --- arch/parisc/Kconfig | 6 +----- arch/parisc/kernel/entry.S | 39 ++++++++++++++++++++++++++++++++++++--- include/asm-parisc/thread_info.h | 3 ++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 6b3c50964ca9e7..2fdf21989dc20a 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -177,14 +177,10 @@ config ARCH_DISCONTIGMEM_DEFAULT def_bool y depends on ARCH_DISCONTIGMEM_ENABLE +source "kernel/Kconfig.preempt" source "kernel/Kconfig.hz" source "mm/Kconfig" -config PREEMPT - bool -# bool "Preemptible Kernel" - default n - config COMPAT def_bool y depends on 64BIT diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6d17c0a3431b63..7c95d7663c2999 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1014,14 +1014,21 @@ intr_restore: nop nop +#ifndef CONFIG_PREEMPT +# define intr_do_preempt intr_restore +#endif /* !CONFIG_PREEMPT */ + .import schedule,code intr_do_resched: - /* Only do reschedule if we are returning to user space */ + /* Only call schedule on return to userspace. If we're returning + * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise + * we jump back to intr_restore. + */ LDREG PT_IASQ0(%r16), %r20 - CMPIB= 0,%r20,intr_restore /* backward */ + CMPIB= 0, %r20, intr_do_preempt nop LDREG PT_IASQ1(%r16), %r20 - CMPIB= 0,%r20,intr_restore /* backward */ + CMPIB= 0, %r20, intr_do_preempt nop #ifdef CONFIG_64BIT @@ -1037,6 +1044,32 @@ intr_do_resched: #endif ldo R%intr_check_sig(%r2), %r2 + /* preempt the current task on returning to kernel + * mode from an interrupt, iff need_resched is set, + * and preempt_count is 0. otherwise, we continue on + * our merry way back to the current running task. + */ +#ifdef CONFIG_PREEMPT + .import preempt_schedule_irq,code +intr_do_preempt: + rsm PSW_SM_I, %r0 /* disable interrupts */ + + /* current_thread_info()->preempt_count */ + mfctl %cr30, %r1 + LDREG TI_PRE_COUNT(%r1), %r19 + CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */ + nop /* prev insn branched backwards */ + + /* check if we interrupted a critical path */ + LDREG PT_PSW(%r16), %r20 + bb,<,n %r20, 31 - PSW_SM_I, intr_restore + nop + + BL preempt_schedule_irq, %r2 + nop + + b intr_restore /* ssm PSW_SM_I done by intr_restore */ +#endif /* CONFIG_PREEMPT */ .import do_signal,code intr_do_signal: diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h index ac32f140b83aa1..f2f83b04cd8b8f 100644 --- a/include/asm-parisc/thread_info.h +++ b/include/asm-parisc/thread_info.h @@ -49,7 +49,8 @@ struct thread_info { #endif /* !__ASSEMBLY */ -#define PREEMPT_ACTIVE 0x10000000 +#define PREEMPT_ACTIVE_BIT 28 +#define PREEMPT_ACTIVE (1 << PREEMPT_ACTIVE_BIT) /* * thread information flags -- cgit 1.2.3-korg