Changes in / [22c3444:62b20f1] in mainline
- Location:
- kernel
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/include/interrupt.h
r22c3444 r62b20f1 72 72 73 73 typedef struct istate { 74 /* 75 * The strange order of the GPRs is given by the requirement to use the 76 * istate structure for both regular interrupts and exceptions as well 77 * as for syscall handler which use this order as an optimization. 78 */ 79 uint32_t edx; 80 uint32_t ecx; 81 uint32_t ebx; 82 uint32_t esi; 83 uint32_t edi; 84 uint32_t ebp; 74 85 uint32_t eax; 75 uint32_t ebx;76 uint32_t ecx;77 uint32_t edx;78 uint32_t edi;79 uint32_t esi;80 uint32_t ebp;81 86 82 87 uint32_t ebp_frame; /* imitation of frame pointer linkage */ -
kernel/arch/ia32/src/asm.S
r22c3444 r62b20f1 164 164 .endm 165 165 166 /* 167 * The SYSENTER syscall mechanism can be used for syscalls with 168 * four or fewer arguments. To pass these four arguments, we 169 * use four registers: EDX, ECX, EBX, ESI. The syscall number 170 * is passed in EAX. We use EDI to remember the return address 171 * and EBP to remember the stack. The INT-based syscall mechanism 172 * can actually handle six arguments plus the syscall number 173 * entirely in registers. 174 */ 175 .global sysenter_handler 176 sysenter_handler: 177 sti 178 pushl %ebp /* remember user stack */ 179 pushl %edi /* remember return user address */ 180 181 xorl %ebp, %ebp /* stop stack traces here */ 182 183 pushl %gs /* remember TLS */ 184 185 pushl %eax /* syscall number */ 186 subl $8, %esp /* unused sixth and fifth argument */ 187 pushl %esi /* fourth argument */ 188 pushl %ebx /* third argument */ 189 pushl %ecx /* second argument */ 190 pushl %edx /* first argument */ 191 192 movw $16, %ax 193 movw %ax, %ds 194 movw %ax, %es 195 196 cld 197 call syscall_handler 198 addl $28, %esp /* remove arguments from stack */ 199 200 pop %gs /* restore TLS */ 201 202 pop %edx /* prepare return EIP for SYSEXIT */ 203 pop %ecx /* prepare userspace ESP for SYSEXIT */ 204 205 sysexit /* return to userspace */ 206 207 #define ISTATE_OFFSET_EAX 0 208 #define ISTATE_OFFSET_EBX 4 209 #define ISTATE_OFFSET_ECX 8 210 #define ISTATE_OFFSET_EDX 12 211 #define ISTATE_OFFSET_EDI 16 212 #define ISTATE_OFFSET_ESI 20 213 #define ISTATE_OFFSET_EBP 24 166 #define ISTATE_OFFSET_EDX 0 167 #define ISTATE_OFFSET_ECX 4 168 #define ISTATE_OFFSET_EBX 8 169 #define ISTATE_OFFSET_ESI 12 170 #define ISTATE_OFFSET_EDI 16 171 #define ISTATE_OFFSET_EBP 20 172 #define ISTATE_OFFSET_EAX 24 214 173 #define ISTATE_OFFSET_EBP_FRAME 28 215 174 #define ISTATE_OFFSET_EIP_FRAME 32 … … 231 190 #define ISTATE_SOFT_SIZE 52 232 191 192 /* 193 * Size of the entire istate structure including the error word and the 194 * hardware-saved part. 195 */ 196 #define ISTATE_REAL_SIZE (ISTATE_SOFT_SIZE + 24) 197 198 /* 199 * The SYSENTER syscall mechanism can be used for syscalls with 200 * four or fewer arguments. To pass these four arguments, we 201 * use four registers: EDX, ECX, EBX, ESI. The syscall number 202 * is passed in EAX. We use EDI to remember the return address 203 * and EBP to remember the stack. The INT-based syscall mechanism 204 * can actually handle six arguments plus the syscall number 205 * entirely in registers. 206 */ 207 .global sysenter_handler 208 sysenter_handler: 209 sti 210 subl $(ISTATE_REAL_SIZE), %esp 211 212 /* 213 * Save the return address and the userspace stack in the istate 214 * structure on locations that would normally be taken by them. 215 */ 216 movl %ebp, ISTATE_OFFSET_ESP(%esp) 217 movl %edi, ISTATE_OFFSET_EIP(%esp) 218 219 /* 220 * Push syscall arguments onto the stack 221 */ 222 movl %eax, ISTATE_OFFSET_EAX(%esp) 223 movl %ebx, ISTATE_OFFSET_EBX(%esp) 224 movl %ecx, ISTATE_OFFSET_ECX(%esp) 225 movl %edx, ISTATE_OFFSET_EDX(%esp) 226 movl %esi, ISTATE_OFFSET_ESI(%esp) 227 movl %edi, ISTATE_OFFSET_EDI(%esp) /* observability; not needed */ 228 movl %ebp, ISTATE_OFFSET_EBP(%esp) /* observability; not needed */ 229 230 /* 231 * Fake up the stack trace linkage. 232 */ 233 movl %edi, ISTATE_OFFSET_EIP_FRAME(%esp) 234 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 235 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 236 237 /* 238 * Save TLS. 239 */ 240 movl %gs, %edx 241 movl %edx, ISTATE_OFFSET_GS(%esp) 242 243 /* 244 * Switch to kernel selectors. 245 */ 246 movw $16, %ax 247 movw %ax, %ds 248 movw %ax, %es 249 250 cld 251 call syscall_handler 252 253 /* 254 * Restore TLS. 255 */ 256 movl ISTATE_OFFSET_GS(%esp), %edx 257 movl %edx, %gs 258 259 /* 260 * Prepare return address and userspace stack for SYSEXIT. 261 */ 262 movl ISTATE_OFFSET_EIP(%esp), %edx 263 movl ISTATE_OFFSET_ESP(%esp), %ecx 264 265 addl $(ISTATE_REAL_SIZE), %esp 266 267 sysexit /* return to userspace */ 268 233 269 /** Declare interrupt handlers 234 270 * … … 245 281 .ifeq \i - 0x30 246 282 /* Syscall handler */ 247 pushl %ds 248 pushl %es 249 pushl %fs 250 pushl %gs 251 283 subl $(ISTATE_SOFT_SIZE + 4), %esp 284 252 285 /* 253 286 * Push syscall arguments onto the stack … … 257 290 * first and preserved registers next. An optimized 258 291 * libc syscall wrapper can make use of this setup. 292 * The istate structure is arranged in the way to support 293 * this idea. 259 294 * 260 295 */ 261 pushl %eax 262 pushl %ebp 263 pushl %edi 264 pushl %esi 265 pushl %ebx 266 pushl %ecx 267 pushl %edx 268 269 /* We must fill the data segment registers */ 270 movw $16, %ax 271 movw %ax, %ds 272 movw %ax, %es 273 274 xorl %ebp, %ebp 296 movl %eax, ISTATE_OFFSET_EAX(%esp) 297 movl %ebx, ISTATE_OFFSET_EBX(%esp) 298 movl %ecx, ISTATE_OFFSET_ECX(%esp) 299 movl %edx, ISTATE_OFFSET_EDX(%esp) 300 movl %edi, ISTATE_OFFSET_EDI(%esp) 301 movl %esi, ISTATE_OFFSET_ESI(%esp) 302 movl %ebp, ISTATE_OFFSET_EBP(%esp) 303 304 /* 305 * Save the selector registers. 306 */ 307 movl %gs, %ecx 308 movl %fs, %edx 309 310 movl %ecx, ISTATE_OFFSET_GS(%esp) 311 movl %edx, ISTATE_OFFSET_FS(%esp) 312 313 movl %es, %ecx 314 movl %ds, %edx 315 316 movl %ecx, ISTATE_OFFSET_ES(%esp) 317 movl %edx, ISTATE_OFFSET_DS(%esp) 318 319 /* 320 * Switch to kernel selectors. 321 */ 322 movl $16, %eax 323 movl %eax, %ds 324 movl %eax, %es 325 326 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 327 movl ISTATE_OFFSET_EIP(%esp), %eax 328 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 329 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 275 330 276 331 cld … … 279 334 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 280 335 call syscall_handler 281 cli 282 283 movl 20(%esp), %ebp /* restore EBP */ 284 addl $28, %esp /* clean-up of parameters */ 285 286 popl %gs 287 popl %fs 288 popl %es 289 popl %ds 290 336 291 337 CLEAR_NT_FLAG 338 339 /* 340 * Restore the selector registers. 341 */ 342 movl ISTATE_OFFSET_GS(%esp), %ecx 343 movl ISTATE_OFFSET_FS(%esp), %edx 344 345 movl %ecx, %gs 346 movl %edx, %fs 347 348 movl ISTATE_OFFSET_ES(%esp), %ecx 349 movl ISTATE_OFFSET_DS(%esp), %edx 350 351 movl %ecx, %es 352 movl %edx, %ds 353 354 /* 355 * Restore the preserved registers the handler cloberred itself 356 * (i.e. EBP). 357 */ 358 movl ISTATE_OFFSET_EBP(%esp), %ebp 359 360 addl $(ISTATE_SOFT_SIZE + 4), %esp 292 361 iret 362 293 363 .else 294 364 /* -
kernel/generic/src/interrupt/interrupt.c
r22c3444 r62b20f1 163 163 { 164 164 fault_if_from_uspace(istate, "Unhandled exception %u.", n); 165 panic ("Unhandled exception %u.", n);165 panic_badtrap(istate, n, "Unhandled exception %u.", n); 166 166 } 167 167
Note:
See TracChangeset
for help on using the changeset viewer.