001 /* Copyright (C) 2005 David Decotigny
002 Copyright (C) 2000-2004, The KOS team
003
004 This program is free software; you can redistribute it and/or
005 modify it under the terms of the GNU General Public License
006 as published by the Free Software Foundation; either version 2
007 of the License, or (at your option) any later version.
008
009 This program is distributed in the hope that it will be useful,
010 but WITHOUT ANY WARRANTY; without even the implied warranty of
011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 GNU General Public License for more details.
013
014 You should have received a copy of the GNU General Public License
015 along with this program; if not, write to the Free Software
016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017 USA.
018 */
019 #define ASM_SOURCE 1
020
021
022 #include "segment.h"
023
024
025 .file "cpu_context_switch.S"
026
027 .text
028
029
030 /**
031 * C Function called by the routines below in order to tell the CPU
032 * where will be the kernel stack (needed by the interrupt handlers)
033 * when next_ctxt will come back into kernel mode.
034 *
035 * void sos_cpu_context_update_kernel_tss(struct sos_cpu_state *next_ctxt)
036 *
037 * @see end of cpu_context.c
038 */
039 .extern sos_cpu_context_update_kernel_tss
040
041
042 .globl sos_cpu_context_switch
043 .type sos_cpu_context_switch, @function
044 sos_cpu_context_switch:
045 // arg2= to_context -- esp+64
046 // arg1= from_context -- esp+60
047 // caller ip -- esp+56
048 pushf // (eflags) esp+52
049 pushl %cs // (cs) esp+48
050 pushl $resume_pc // (ip) esp+44
051 pushl $0 // (error code) esp+40
052 pushl %ebp // esp+36
053 pushl %edi // esp+32
054 pushl %esi // esp+28
055 pushl %edx // esp+24
056 pushl %ecx // esp+20
057 pushl %ebx // esp+16
058 pushl %eax // esp+12
059 subl $2, %esp // (alignment) esp+10
060 pushw %ss // esp+8
061 pushw %ds // esp+6
062 pushw %es // esp+4
063 pushw %fs // esp+2
064 pushw %gs // esp
065
066 /*
067 * Now that the original eax/ebx are stored, we can use them safely
068 */
069
070 /* Store the address of the saved context */
071 movl 60(%esp), %ebx
072 movl %esp, (%ebx)
073
074 /* This is the proper context switch ! We change the stack here */
075 movl 64(%esp), %esp
076
077 /* Prepare kernel TSS in case we are switching to a user thread: we
078 make sure that we will come back into the kernel at a correct
079 stack location */
080 pushl %esp /* Pass the location of the context we are
081 restoring to the function */
082 call sos_cpu_context_update_kernel_tss
083 addl $4, %esp
084
085 /* Restore the CPU context */
086 popw %gs
087 popw %fs
088 popw %es
089 popw %ds
090 popw %ss
091 addl $2,%esp
092 popl %eax
093 popl %ebx
094 popl %ecx
095 popl %edx
096 popl %esi
097 popl %edi
098 popl %ebp
099 addl $4, %esp /* Ignore "error code" */
100
101 /* This restores the eflags, the cs and the eip registers */
102 iret /* equivalent to: popfl ; ret */
103
104 resume_pc:
105 // Same context as that when sos_cpu_context_switch got called
106 // arg2= to_context -- esp+8
107 // arg1= from_context -- esp+4
108 // caller ip -- esp
109 ret
110
111
112
113 /* ------------------------- */
114 .globl sos_cpu_context_exit_to
115 .type sos_cpu_context_exit_to, @function
116 sos_cpu_context_exit_to:
117 // arg3= reclaiming_arg -- esp+12
118 // arg2= reclaiming_func -- esp+8
119 // arg1= to_context -- esp+4
120 // caller ip -- esp
121
122 /* Store the current SP in a temporary register */
123 movl %esp, %eax
124
125 /* This is the proper context switch ! We change the stack here */
126 movl 4(%eax), %esp
127
128 /* Call the reclaiming function (remember: the old frame address
129 is stored in eax) */
130 pushl 12(%eax)
131 call *8(%eax)
132 addl $4, %esp
133
134 /* Prepare kernel TSS in case we are switching to a user thread: we
135 make sure that we will come back into the kernel at a correct
136 stack location */
137 pushl %esp /* Pass the location of the context we are
138 restoring to the function */
139 call sos_cpu_context_update_kernel_tss
140 addl $4, %esp
141
142 /* Restore the CPU context */
143 popw %gs
144 popw %fs
145 popw %es
146 popw %ds
147 popw %ss
148 addl $2,%esp
149 popl %eax
150 popl %ebx
151 popl %ecx
152 popl %edx
153 popl %esi
154 popl %edi
155 popl %ebp
156 addl $4, %esp /* Ignore "error code" */
157
158 /* This restores the eflags, the cs and the eip registers */
159 iret /* equivalent to: popfl ; ret */