Ignore:
File:
1 edited

Legend:

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

    reee047c rb8230b9  
    142142.macro CLEAR_NT_FLAG
    143143        pushfl
    144         andl $0xffffbfff, (%esp)
     144        pop %ecx
     145        and $0xffffbfff, %ecx
     146        push %ecx
    145147        popfl
    146148.endm   
     
    161163        pushl %edi      # remember return user address
    162164
    163         xorl %ebp, %ebp # stop stack traces here
    164 
    165165        pushl %gs       # remember TLS
    166166
     
    188188
    189189
    190 #define ISTATE_OFFSET_EAX               0
    191 #define ISTATE_OFFSET_EBX               4
    192 #define ISTATE_OFFSET_ECX               8
    193 #define ISTATE_OFFSET_EDX               12
    194 #define ISTATE_OFFSET_EDI               16
    195 #define ISTATE_OFFSET_ESI               20
    196 #define ISTATE_OFFSET_EBP               24
    197 #define ISTATE_OFFSET_EBP_FRAME         28
    198 #define ISTATE_OFFSET_EIP_FRAME         32
    199 #define ISTATE_OFFSET_GS                36
    200 #define ISTATE_OFFSET_FS                40
    201 #define ISTATE_OFFSET_ES                44
    202 #define ISTATE_OFFSET_DS                48
    203 #define ISTATE_OFFSET_ERROR_WORD        52
    204 #define ISTATE_OFFSET_EIP               56
    205 #define ISTATE_OFFSET_CS                60
    206 #define ISTATE_OFFSET_EFLAGS            64
    207 #define ISTATE_OFFSET_ESP               68
    208 #define ISTATE_OFFSET_SS                72
    209 
    210 /*
    211  * Size of the istate structure without the hardware-saved part and without the
    212  * error word.
    213  */
    214 #define ISTATE_SOFT_SIZE                52
    215 
    216190## Declare interrupt handlers
    217191#
     
    222196# and call exc_dispatch().
    223197#
    224 #define INTERRUPT_ALIGN 256
     198#define INTERRUPT_ALIGN 64
    225199.macro handler i n
    226200       
    227 .ifeq \i - 0x30     # Syscall handler
    228         pushl %ds
    229         pushl %es
    230         pushl %fs
    231         pushl %gs
    232                
    233         #
    234         # Push syscall arguments onto the stack
    235         #
    236         # NOTE: The idea behind the order of arguments passed in registers is to
    237         #       use all scratch registers first and preserved registers next.
    238         #       An optimized libc syscall wrapper can make use of this setup.
    239         #
    240         pushl %eax
    241         pushl %ebp
    242         pushl %edi
    243         pushl %esi
    244         pushl %ebx
    245         pushl %ecx
    246         pushl %edx
    247                
    248         # we must fill the data segment registers
    249         movw $16, %ax
    250         movw %ax, %ds
    251         movw %ax, %es
    252        
    253         xorl %ebp, %ebp
    254 
    255         cld
    256         sti
    257         # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
    258         call syscall_handler
    259         cli
    260 
    261         movl 20(%esp), %ebp     # restore EBP
    262         addl $28, %esp          # clean-up of parameters
    263                
    264         popl %gs
    265         popl %fs
    266         popl %es
    267         popl %ds
    268                
    269         CLEAR_NT_FLAG
    270         iret
    271 .else
    272         /*
    273          * This macro distinguishes between two versions of ia32 exceptions.
    274          * One version has error word and the other does not have it.
    275          * The latter version fakes the error word on the stack so that the
    276          * handlers and istate_t can be the same for both types.
    277          */
    278 .iflt \i - 32
    279 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
    280         #
    281         # Exception with error word: do nothing
    282         #
    283 .else
    284         #
    285         # Exception without error word: fake up one
    286         #
    287         pushl $0
    288 .endif
    289 .else
    290         #
    291         # Interrupt: fake up one
    292         #
    293         pushl $0
    294 .endif
    295                
    296         subl $ISTATE_SOFT_SIZE, %esp
    297 
    298         #
    299         # Save the general purpose registers.
    300         #
    301         movl %eax, ISTATE_OFFSET_EAX(%esp)
    302         movl %ebx, ISTATE_OFFSET_EBX(%esp)
    303         movl %ecx, ISTATE_OFFSET_ECX(%esp)
    304         movl %edx, ISTATE_OFFSET_EDX(%esp)
    305         movl %edi, ISTATE_OFFSET_EDI(%esp)
    306         movl %esi, ISTATE_OFFSET_ESI(%esp)
    307         movl %ebp, ISTATE_OFFSET_EBP(%esp)
    308        
    309         #
    310         # Save the selector registers.
    311         #
    312         movl %gs, %eax
    313         movl %fs, %ebx
    314         movl %es, %ecx
    315         movl %ds, %edx
    316 
    317         movl %eax, ISTATE_OFFSET_GS(%esp)
    318         movl %ebx, ISTATE_OFFSET_FS(%esp)
    319         movl %ecx, ISTATE_OFFSET_ES(%esp)
    320         movl %edx, ISTATE_OFFSET_DS(%esp)
    321 
    322         #
    323         # Switch to kernel selectors.
    324         #
    325         movl $16, %eax
    326         movl %eax, %ds
    327         movl %eax, %es
    328                
    329         #
    330         # Imitate a regular stack frame linkage.
    331         # Stop stack traces here if we came from userspace.
    332         #
    333         cmpl $8, ISTATE_OFFSET_CS(%esp)
    334         jz 0f
    335         xorl %ebp, %ebp
    336 0:      movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
    337         movl ISTATE_OFFSET_EIP(%esp), %eax
    338         movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
    339         leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
    340 
    341         cld
    342 
    343         pushl %esp          # pass istate address
    344         pushl $(\i)         # pass intnum
    345         call exc_dispatch   # exc_dispatch(intnum, istate)
    346         addl $8, %esp       # Clear arguments from the stack
    347                
    348         CLEAR_NT_FLAG
    349        
    350         #
    351         # Restore the selector registers.
    352         #
    353         movl ISTATE_OFFSET_GS(%esp), %eax
    354         movl ISTATE_OFFSET_FS(%esp), %ebx
    355         movl ISTATE_OFFSET_ES(%esp), %ecx
    356         movl ISTATE_OFFSET_DS(%esp), %edx
    357 
    358         movl %eax, %gs
    359         movl %ebx, %fs
    360         movl %ecx, %es
    361         movl %edx, %ds
    362 
    363         #
    364         # Restore the scratch registers and the preserved registers the handler
    365         # cloberred itself (i.e. EBX and EBP).
    366         #
    367         movl ISTATE_OFFSET_EAX(%esp), %eax
    368         movl ISTATE_OFFSET_EBX(%esp), %ebx
    369         movl ISTATE_OFFSET_ECX(%esp), %ecx
    370         movl ISTATE_OFFSET_EDX(%esp), %edx
    371         movl ISTATE_OFFSET_EBP(%esp), %ebp
    372        
    373         addl $(ISTATE_SOFT_SIZE + 4), %esp
    374         iret
    375 .endif
    376        
    377 .align INTERRUPT_ALIGN
    378 .if (\n- \i) - 1
    379         handler "(\i + 1)", \n
    380 .endif
     201        .ifeq \i - 0x30     # Syscall handler
     202                pushl %ds
     203                pushl %es
     204                pushl %fs
     205                pushl %gs
     206               
     207                #
     208                # Push syscall arguments onto the stack
     209                #
     210                # NOTE: The idea behind the order of arguments passed in registers is to
     211                #       use all scratch registers first and preserved registers next.
     212                #       An optimized libc syscall wrapper can make use of this setup.
     213                #
     214                pushl %eax
     215                pushl %ebp
     216                pushl %edi
     217                pushl %esi
     218                pushl %ebx
     219                pushl %ecx
     220                pushl %edx
     221               
     222                # we must fill the data segment registers
     223                movw $16, %ax
     224                movw %ax, %ds
     225                movw %ax, %es
     226               
     227                cld
     228                sti
     229                # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
     230                call syscall_handler
     231                cli
     232                addl $28, %esp         # clean-up of parameters
     233               
     234                popl %gs
     235                popl %fs
     236                popl %es
     237                popl %ds
     238               
     239                CLEAR_NT_FLAG
     240                iret
     241        .else
     242                /*
     243                 * This macro distinguishes between two versions of ia32 exceptions.
     244                 * One version has error word and the other does not have it.
     245                 * The latter version fakes the error word on the stack so that the
     246                 * handlers and istate_t can be the same for both types.
     247                 */
     248                .iflt \i - 32
     249                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
     250                                /*
     251                                 * With error word, do nothing
     252                                 */
     253                        .else
     254                                /*
     255                                 * Version without error word
     256                                 */
     257                                subl $4, %esp
     258                        .endif
     259                .else
     260                        /*
     261                         * Version without error word
     262                         */
     263                        subl $4, %esp
     264                .endif
     265               
     266                pushl %ds
     267                pushl %es
     268                pushl %fs
     269                pushl %gs
     270               
     271                pushl %ebp
     272                pushl %edx
     273                pushl %ecx
     274                pushl %eax
     275               
     276                # we must fill the data segment registers
     277               
     278                movw $16, %ax
     279                movw %ax, %ds
     280                movw %ax, %es
     281               
     282                # stop stack traces here
     283                xorl %ebp, %ebp
     284               
     285                pushl %esp          # *istate
     286                pushl $(\i)         # intnum
     287                call exc_dispatch   # exc_dispatch(intnum, *istate)
     288                addl $8, %esp       # Clear arguments from stack
     289               
     290                CLEAR_NT_FLAG # Modifies %ecx
     291               
     292                popl %eax
     293                popl %ecx
     294                popl %edx
     295                popl %ebp
     296               
     297                popl %gs
     298                popl %fs
     299                popl %es
     300                popl %ds
     301               
     302                # skip error word, no matter whether real or fake
     303                addl $4, %esp
     304                iret
     305        .endif
     306       
     307        .align INTERRUPT_ALIGN
     308        .if (\n- \i) - 1
     309                handler "(\i + 1)", \n
     310        .endif
    381311.endm
    382312
Note: See TracChangeset for help on using the changeset viewer.