Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset ed7998b in mainline


Ignore:
Timestamp:
2010-07-07T20:29:31Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial
Children:
62b20f1, 676afa2
Parents:
0737078
Message:

Rewrite the SYSENTER syscall handler to use istate_t for parameter passing and
preserving registers.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/asm.S

    r0737078 red7998b  
    163163        popfl
    164164.endm
    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 */
    206165
    207166#define ISTATE_OFFSET_EDX         0
     
    231190#define ISTATE_SOFT_SIZE  52
    232191
     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
     208sysenter_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
    233269/** Declare interrupt handlers
    234270 *
Note: See TracChangeset for help on using the changeset viewer.