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