diff options
Diffstat (limited to 'arch/parisc/kernel/entry.S')
-rw-r--r-- | arch/parisc/kernel/entry.S | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6d17c0a3431b..7c95d7663c29 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -1014,14 +1014,21 @@ intr_restore: | |||
1014 | nop | 1014 | nop |
1015 | nop | 1015 | nop |
1016 | 1016 | ||
1017 | #ifndef CONFIG_PREEMPT | ||
1018 | # define intr_do_preempt intr_restore | ||
1019 | #endif /* !CONFIG_PREEMPT */ | ||
1020 | |||
1017 | .import schedule,code | 1021 | .import schedule,code |
1018 | intr_do_resched: | 1022 | intr_do_resched: |
1019 | /* Only do reschedule if we are returning to user space */ | 1023 | /* Only call schedule on return to userspace. If we're returning |
1024 | * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise | ||
1025 | * we jump back to intr_restore. | ||
1026 | */ | ||
1020 | LDREG PT_IASQ0(%r16), %r20 | 1027 | LDREG PT_IASQ0(%r16), %r20 |
1021 | CMPIB= 0,%r20,intr_restore /* backward */ | 1028 | CMPIB= 0, %r20, intr_do_preempt |
1022 | nop | 1029 | nop |
1023 | LDREG PT_IASQ1(%r16), %r20 | 1030 | LDREG PT_IASQ1(%r16), %r20 |
1024 | CMPIB= 0,%r20,intr_restore /* backward */ | 1031 | CMPIB= 0, %r20, intr_do_preempt |
1025 | nop | 1032 | nop |
1026 | 1033 | ||
1027 | #ifdef CONFIG_64BIT | 1034 | #ifdef CONFIG_64BIT |
@@ -1037,6 +1044,32 @@ intr_do_resched: | |||
1037 | #endif | 1044 | #endif |
1038 | ldo R%intr_check_sig(%r2), %r2 | 1045 | ldo R%intr_check_sig(%r2), %r2 |
1039 | 1046 | ||
1047 | /* preempt the current task on returning to kernel | ||
1048 | * mode from an interrupt, iff need_resched is set, | ||
1049 | * and preempt_count is 0. otherwise, we continue on | ||
1050 | * our merry way back to the current running task. | ||
1051 | */ | ||
1052 | #ifdef CONFIG_PREEMPT | ||
1053 | .import preempt_schedule_irq,code | ||
1054 | intr_do_preempt: | ||
1055 | rsm PSW_SM_I, %r0 /* disable interrupts */ | ||
1056 | |||
1057 | /* current_thread_info()->preempt_count */ | ||
1058 | mfctl %cr30, %r1 | ||
1059 | LDREG TI_PRE_COUNT(%r1), %r19 | ||
1060 | CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */ | ||
1061 | nop /* prev insn branched backwards */ | ||
1062 | |||
1063 | /* check if we interrupted a critical path */ | ||
1064 | LDREG PT_PSW(%r16), %r20 | ||
1065 | bb,<,n %r20, 31 - PSW_SM_I, intr_restore | ||
1066 | nop | ||
1067 | |||
1068 | BL preempt_schedule_irq, %r2 | ||
1069 | nop | ||
1070 | |||
1071 | b intr_restore /* ssm PSW_SM_I done by intr_restore */ | ||
1072 | #endif /* CONFIG_PREEMPT */ | ||
1040 | 1073 | ||
1041 | .import do_signal,code | 1074 | .import do_signal,code |
1042 | intr_do_signal: | 1075 | intr_do_signal: |