summaryrefslogtreecommitdiff
path: root/core/minute-ia/switch.S
diff options
context:
space:
mode:
Diffstat (limited to 'core/minute-ia/switch.S')
-rw-r--r--core/minute-ia/switch.S81
1 files changed, 27 insertions, 54 deletions
diff --git a/core/minute-ia/switch.S b/core/minute-ia/switch.S
index 1fdcc61bb8..c5098b9003 100644
--- a/core/minute-ia/switch.S
+++ b/core/minute-ia/switch.S
@@ -9,6 +9,8 @@
#include "registers.h"
#include "task_defs.h"
+#include "irq_handler_common.S"
+
.text
.extern current_task
@@ -17,6 +19,7 @@
.global __task_start
.global __switchto
.global default_int_handler
+.global sw_irq_handler
# Start the task scheduling. Start current_task (hook_task)
# This function is not an ISR but imitates the sequence.
@@ -67,72 +70,43 @@ default_int_handler:
ASM_LOCK_PREFIX subl $1, __in_isr
popa
iret
+.endfunc
+
+.align 4
+.func sw_irq_handler
+sw_irq_handler:
+ pusha
+ ASM_LOCK_PREFIX addl $1, __in_isr
+
+ # Call sw irq handler with irq number(%ecx) from task_trigger_irq.
+ # Pass 0 for both desched and resched since we don't need to deschedule
+ # our current task (and idle task can always be rescheduled)
+ irq_handler_common $0 $0 %ecx
+
+ # Indicate completion of servicing the interrupt to LAPIC.
+ # No IOAPIC EOI needed as this is SW triggered.
+ movl $0x00, LAPIC_EOI_REG
+ # Decrement ISR counter and restore general purpose registers.
+ ASM_LOCK_PREFIX subl $1, __in_isr
+ popa
+ iret
.endfunc
+
# Switches from one task to another if ready.
# __schedule triggers software interrupt ISH_TS_VECTOR, which is handled by
# __switchto
.align 4
.func __switchto
__switchto:
-
- # Save current task
pusha
ASM_LOCK_PREFIX addl $1, __in_isr
- movl %esp, %eax
- movl $stack_end, %esp # use system stack
- push %eax # push sp of preempted context
-
# __schedule() copies 'resched' to %ecx and 'desched' to %edx before
- # triggering ISH_TS_VECTOR
- #
- # Push %ecx and %edx into stack to pass them as function parameters
- # to switch_handler(desched, resched). After call, we clean up stack
- # pointer. Note, we do this now before task_start_irq has a chance
- # to clobber these caller-saved registers.
- push %ecx
- push %edx
-
-#ifdef CONFIG_TASK_PROFILING
- push $ISH_TS_VECTOR
- call task_start_irq_handler
- addl $0x4, %esp
-#endif
-
- # Stack is already set up from previous pushes
- call switch_handler
- addl $0x8, %esp # Clean up stack
- pop %esp # restore sp of preempted context
-
- test %eax, %eax # Check if task switch required
- jz 1f
-
- movl current_task, %eax
-
-#ifdef CONFIG_FPU
- movl USE_FPU_OFFSET(%eax), %ebx
- test %ebx, %ebx
- jz 2f
- fnsave FPU_CTX_OFFSET(%eax) # Save current FPU context(current->fp_ctx)
- 2:
-#endif
-
- # Save SP of current task and switch to new task
- movl %esp, (%eax)
- movl next_task, %eax
- movl %eax, current_task
- movl (%eax), %esp
-
-#ifdef CONFIG_FPU
- movl USE_FPU_OFFSET(%eax), %ebx
- test %ebx, %ebx
- jz 1f
- frstor FPU_CTX_OFFSET(%eax) # Restore next FPU context
-#endif
-
- 1:
+ # triggering ISH_TS_VECTOR.
+ # Call sw_irq with an invalid IRQ so it will skip calling a routine
+ irq_handler_common %edx %ecx $CONFIG_IRQ_COUNT
# Indicate completion of servicing the interrupt to LAPIC.
# No IOAPIC EOI needed as this is SW triggered.
@@ -142,5 +116,4 @@ __switchto:
ASM_LOCK_PREFIX subl $1, __in_isr
popa
iret
-
.endfunc