Ignore:
File:
1 edited

Legend:

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

    r91ef7cfd rb808660  
    11/*
    2  * Copyright (c) 2010 Jakub Jermar
     2 * Copyright (c) 2001 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3131 */
    3232
     33/**
     34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
     35 * has no error word  and 1 means interrupt with error word
     36 *
     37 */
     38#define ERROR_WORD_INTERRUPT_LIST  0x00027d00
     39
    3340#include <arch/pm.h>
    34 #include <arch/cpu.h>
    3541#include <arch/mm/page.h>
    3642
     
    147153        wrmsr
    148154        ret
     155
     156/** Clear nested flag
     157 *
     158 */
     159.macro CLEAR_NT_FLAG
     160        pushfl
     161        andl $0xffffbfff, (%esp)
     162        popfl
     163.endm
    149164
    150165#define ISTATE_OFFSET_EDX         0
     
    175190
    176191/*
     192 * Size of the entire istate structure including the error word and the
     193 * hardware-saved part.
     194 */
     195#define ISTATE_REAL_SIZE  (ISTATE_SOFT_SIZE + 24)
     196
     197/*
    177198 * The SYSENTER syscall mechanism can be used for syscalls with
    178199 * four or fewer arguments. To pass these four arguments, we
     
    185206.global sysenter_handler
    186207sysenter_handler:
    187 
    188         /*
    189          * Note that the space needed for the istate structure has been
    190          * preallocated on the stack by before_thread_runs_arch().
    191          */
     208        sti
     209        subl $(ISTATE_REAL_SIZE), %esp
    192210
    193211        /*
     
    225243         * Switch to kernel selectors.
    226244         */
    227         movw $(gdtselector(KDATA_DES)), %ax
     245        movw $16, %ax
    228246        movw %ax, %ds
    229247        movw %ax, %es
    230248       
    231         /*
    232          * Sanitize EFLAGS.
    233          *
    234          * SYSENTER does not clear the NT flag, which could thus proliferate
    235          * from here to the IRET instruction via a context switch and result
    236          * in crash.
    237          *
    238          * SYSENTER does not clear DF, which the ABI assumes to be cleared.
    239          *
    240          * SYSENTER clears IF, which we would like to be set for syscalls.
    241          *
    242          */
    243         pushl $(EFLAGS_IF)  /* specify EFLAGS bits that we want to set */
    244         popfl               /* set bits from the mask, clear or ignore others */
    245 
     249        cld
    246250        call syscall_handler
    247251       
     
    258262        movl ISTATE_OFFSET_ESP(%esp), %ecx
    259263
     264        addl $(ISTATE_REAL_SIZE), %esp
     265       
    260266        sysexit   /* return to userspace */
    261267
    262 /*
    263  * This is the legacy syscall handler using the interrupt mechanism.
    264  */
    265 .global int_syscall
    266 int_syscall:
    267         subl $(ISTATE_SOFT_SIZE + 4), %esp
    268 
    269         /*
    270          * Push syscall arguments onto the stack
    271          *
    272          * NOTE: The idea behind the order of arguments passed
    273          *       in registers is to use all scratch registers
    274          *       first and preserved registers next. An optimized
    275          *       libc syscall wrapper can make use of this setup.
    276          *       The istate structure is arranged in the way to support
    277          *       this idea.
    278          *
    279          */
    280         movl %eax, ISTATE_OFFSET_EAX(%esp)
    281         movl %ebx, ISTATE_OFFSET_EBX(%esp)
    282         movl %ecx, ISTATE_OFFSET_ECX(%esp)
    283         movl %edx, ISTATE_OFFSET_EDX(%esp)
    284         movl %edi, ISTATE_OFFSET_EDI(%esp)
    285         movl %esi, ISTATE_OFFSET_ESI(%esp)
    286         movl %ebp, ISTATE_OFFSET_EBP(%esp)
    287 
    288         /*
    289          * Save the selector registers.
    290          */
    291         movl %gs, %ecx
    292         movl %fs, %edx
    293 
    294         movl %ecx, ISTATE_OFFSET_GS(%esp)
    295         movl %edx, ISTATE_OFFSET_FS(%esp)
    296 
    297         movl %es, %ecx
    298         movl %ds, %edx
    299                
    300         movl %ecx, ISTATE_OFFSET_ES(%esp)
    301         movl %edx, ISTATE_OFFSET_DS(%esp)
    302 
    303         /*
    304          * Switch to kernel selectors.
    305          */
    306         movl $(gdtselector(KDATA_DES)), %eax
    307         movl %eax, %ds
    308         movl %eax, %es
    309                
    310         movl $0, ISTATE_OFFSET_EBP_FRAME(%esp)
    311         movl ISTATE_OFFSET_EIP(%esp), %eax
    312         movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
    313         leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
    314                
    315         cld
    316                
    317         /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
    318         call syscall_handler
    319                        
    320         /*
    321          * Restore the selector registers.
    322          */
    323         movl ISTATE_OFFSET_GS(%esp), %ecx
    324         movl ISTATE_OFFSET_FS(%esp), %edx
    325 
    326         movl %ecx, %gs
    327         movl %edx, %fs
    328 
    329         movl ISTATE_OFFSET_ES(%esp), %ecx
    330         movl ISTATE_OFFSET_DS(%esp), %edx
    331                        
    332         movl %ecx, %es
    333         movl %edx, %ds
    334                        
    335         /*
    336          * Restore the preserved registers the handler cloberred itself
    337          * (i.e. EBP).
    338          */
    339         movl ISTATE_OFFSET_EBP(%esp), %ebp
    340                        
    341         addl $(ISTATE_SOFT_SIZE + 4), %esp
    342         iret
    343                
    344 /**
    345  * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
    346  * has no error word  and 1 means interrupt with error word
    347  *
    348  */
    349 #define ERROR_WORD_INTERRUPT_LIST  0x00027d00
     268/** Declare interrupt handlers
     269 *
     270 * Declare interrupt handlers for n interrupt
     271 * vectors starting at vector i.
     272 *
     273 */
    350274
    351275.macro handler i
    352276.global int_\i
    353277int_\i:
    354         /*
    355          * This macro distinguishes between two versions of ia32
    356          * exceptions. One version has error word and the other
    357          * does not have it. The latter version fakes the error
    358          * word on the stack so that the handlers and istate_t
    359          * can be the same for both types.
    360          */
    361         .iflt \i - 32
    362                 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
    363                         /*
    364                          * Exception with error word.
    365                          */
    366                         subl $ISTATE_SOFT_SIZE, %esp
     278        .ifeq \i - 0x30
     279                /* Syscall handler */
     280                subl $(ISTATE_SOFT_SIZE + 4), %esp
     281
     282                /*
     283                 * Push syscall arguments onto the stack
     284                 *
     285                 * NOTE: The idea behind the order of arguments passed
     286                 *       in registers is to use all scratch registers
     287                 *       first and preserved registers next. An optimized
     288                 *       libc syscall wrapper can make use of this setup.
     289                 *       The istate structure is arranged in the way to support
     290                 *       this idea.
     291                 *
     292                 */
     293                movl %eax, ISTATE_OFFSET_EAX(%esp)
     294                movl %ebx, ISTATE_OFFSET_EBX(%esp)
     295                movl %ecx, ISTATE_OFFSET_ECX(%esp)
     296                movl %edx, ISTATE_OFFSET_EDX(%esp)
     297                movl %edi, ISTATE_OFFSET_EDI(%esp)
     298                movl %esi, ISTATE_OFFSET_ESI(%esp)
     299                movl %ebp, ISTATE_OFFSET_EBP(%esp)
     300
     301                /*
     302                 * Save the selector registers.
     303                 */
     304                movl %gs, %ecx
     305                movl %fs, %edx
     306
     307                movl %ecx, ISTATE_OFFSET_GS(%esp)
     308                movl %edx, ISTATE_OFFSET_FS(%esp)
     309
     310                movl %es, %ecx
     311                movl %ds, %edx
     312               
     313                movl %ecx, ISTATE_OFFSET_ES(%esp)
     314                movl %edx, ISTATE_OFFSET_DS(%esp)
     315
     316                /*
     317                 * Switch to kernel selectors.
     318                 */
     319                movl $16, %eax
     320                movl %eax, %ds
     321                movl %eax, %es
     322               
     323                movl $0, ISTATE_OFFSET_EBP_FRAME(%esp)
     324                movl ISTATE_OFFSET_EIP(%esp), %eax
     325                movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
     326                leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
     327               
     328                cld
     329                sti
     330               
     331                /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
     332                call syscall_handler
     333                       
     334                CLEAR_NT_FLAG
     335
     336                /*
     337                 * Restore the selector registers.
     338                 */
     339                movl ISTATE_OFFSET_GS(%esp), %ecx
     340                movl ISTATE_OFFSET_FS(%esp), %edx
     341
     342                movl %ecx, %gs
     343                movl %edx, %fs
     344
     345                movl ISTATE_OFFSET_ES(%esp), %ecx
     346                movl ISTATE_OFFSET_DS(%esp), %edx
     347                       
     348                movl %ecx, %es
     349                movl %edx, %ds
     350                       
     351                /*
     352                 * Restore the preserved registers the handler cloberred itself
     353                 * (i.e. EBP).
     354                 */
     355                movl ISTATE_OFFSET_EBP(%esp), %ebp
     356                       
     357                addl $(ISTATE_SOFT_SIZE + 4), %esp
     358                iret
     359               
     360        .else
     361                /*
     362                 * This macro distinguishes between two versions of ia32
     363                 * exceptions. One version has error word and the other
     364                 * does not have it. The latter version fakes the error
     365                 * word on the stack so that the handlers and istate_t
     366                 * can be the same for both types.
     367                 */
     368                .iflt \i - 32
     369                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
     370                                /*
     371                                 * Exception with error word: do nothing
     372                                 */
     373                        .else
     374                                /*
     375                                 * Exception without error word: fake up one
     376                                 */
     377                                pushl $0
     378                        .endif
    367379                .else
    368380                        /*
    369                          * Exception without error word: fake up one
     381                         * Interrupt: fake up one
    370382                         */
    371                         subl $(ISTATE_SOFT_SIZE + 4), %esp
     383                        pushl $0
    372384                .endif
    373         .else
    374                 /*
    375                  * Interrupt: fake up an error word
    376                  */
    377                 subl $(ISTATE_SOFT_SIZE + 4), %esp
     385               
     386                subl $ISTATE_SOFT_SIZE, %esp
     387               
     388                /*
     389                 * Save the general purpose registers.
     390                 */
     391                movl %eax, ISTATE_OFFSET_EAX(%esp)
     392                movl %ebx, ISTATE_OFFSET_EBX(%esp)
     393                movl %ecx, ISTATE_OFFSET_ECX(%esp)
     394                movl %edx, ISTATE_OFFSET_EDX(%esp)
     395                movl %edi, ISTATE_OFFSET_EDI(%esp)
     396                movl %esi, ISTATE_OFFSET_ESI(%esp)
     397                movl %ebp, ISTATE_OFFSET_EBP(%esp)
     398               
     399                /*
     400                 * Save the selector registers.
     401                 */
     402                movl %gs, %eax
     403                movl %fs, %ebx
     404                movl %es, %ecx
     405                movl %ds, %edx
     406               
     407                movl %eax, ISTATE_OFFSET_GS(%esp)
     408                movl %ebx, ISTATE_OFFSET_FS(%esp)
     409                movl %ecx, ISTATE_OFFSET_ES(%esp)
     410                movl %edx, ISTATE_OFFSET_DS(%esp)
     411               
     412                /*
     413                 * Switch to kernel selectors.
     414                 */
     415                movl $16, %eax
     416                movl %eax, %ds
     417                movl %eax, %es
     418               
     419                /*
     420                 * Imitate a regular stack frame linkage.
     421                 * Stop stack traces here if we came from userspace.
     422                 */
     423                cmpl $8, ISTATE_OFFSET_CS(%esp)
     424                jz 0f
     425                xorl %ebp, %ebp
     426               
     427                0:
     428               
     429                        movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
     430                        movl ISTATE_OFFSET_EIP(%esp), %eax
     431                        movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
     432                        leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
     433                       
     434                        cld
     435                       
     436                        pushl %esp   /* pass istate address */
     437                        pushl $(\i)  /* pass intnum */
     438                       
     439                        /* Call exc_dispatch(intnum, istate) */
     440                        call exc_dispatch
     441                       
     442                        addl $8, %esp  /* clear arguments from the stack */
     443                       
     444                        CLEAR_NT_FLAG
     445                       
     446                        /*
     447                         * Restore the selector registers.
     448                         */
     449                        movl ISTATE_OFFSET_GS(%esp), %eax
     450                        movl ISTATE_OFFSET_FS(%esp), %ebx
     451                        movl ISTATE_OFFSET_ES(%esp), %ecx
     452                        movl ISTATE_OFFSET_DS(%esp), %edx
     453                       
     454                        movl %eax, %gs
     455                        movl %ebx, %fs
     456                        movl %ecx, %es
     457                        movl %edx, %ds
     458                       
     459                        /*
     460                         * Restore the scratch registers and the preserved
     461                         * registers the handler cloberred itself
     462                         * (i.e. EBX and EBP).
     463                         */
     464                        movl ISTATE_OFFSET_EAX(%esp), %eax
     465                        movl ISTATE_OFFSET_EBX(%esp), %ebx
     466                        movl ISTATE_OFFSET_ECX(%esp), %ecx
     467                        movl ISTATE_OFFSET_EDX(%esp), %edx
     468                        movl ISTATE_OFFSET_EBP(%esp), %ebp
     469                       
     470                        addl $(ISTATE_SOFT_SIZE + 4), %esp
     471                        iret
     472               
    378473        .endif
    379        
    380         /*
    381          * Save the general purpose registers.
    382          */
    383         movl %eax, ISTATE_OFFSET_EAX(%esp)
    384         movl %ebx, ISTATE_OFFSET_EBX(%esp)
    385         movl %ecx, ISTATE_OFFSET_ECX(%esp)
    386         movl %edx, ISTATE_OFFSET_EDX(%esp)
    387         movl %edi, ISTATE_OFFSET_EDI(%esp)
    388         movl %esi, ISTATE_OFFSET_ESI(%esp)
    389         movl %ebp, ISTATE_OFFSET_EBP(%esp)
    390        
    391         /*
    392          * Save the selector registers.
    393          */
    394         movl %gs, %ecx
    395         movl %fs, %edx
    396 
    397         movl %ecx, ISTATE_OFFSET_GS(%esp)
    398         movl %edx, ISTATE_OFFSET_FS(%esp)
    399 
    400         movl %es, %ecx
    401         movl %ds, %edx
    402        
    403         movl %ecx, ISTATE_OFFSET_ES(%esp)
    404         movl %edx, ISTATE_OFFSET_DS(%esp)
    405        
    406         /*
    407          * Switch to kernel selectors.
    408          */
    409         movl $(gdtselector(KDATA_DES)), %eax
    410         movl %eax, %ds
    411         movl %eax, %es
    412        
    413         /*
    414          * Imitate a regular stack frame linkage.
    415          * Stop stack traces here if we came from userspace.
    416          */
    417         xorl %eax, %eax
    418         cmpl $(gdtselector(KTEXT_DES)), ISTATE_OFFSET_CS(%esp)
    419         cmovnzl %eax, %ebp
    420 
    421         movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
    422         movl ISTATE_OFFSET_EIP(%esp), %eax
    423         movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
    424         leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
    425                
    426         cld
    427                
    428         pushl %esp   /* pass istate address */
    429         pushl $(\i)  /* pass intnum */
    430                
    431         /* Call exc_dispatch(intnum, istate) */
    432         call exc_dispatch
    433                
    434         addl $8, %esp  /* clear arguments from the stack */
    435                
    436         /*
    437          * Restore the selector registers.
    438          */
    439         movl ISTATE_OFFSET_GS(%esp), %ecx
    440         movl ISTATE_OFFSET_FS(%esp), %edx
    441 
    442         movl %ecx, %gs
    443         movl %edx, %fs
    444 
    445         movl ISTATE_OFFSET_ES(%esp), %ecx
    446         movl ISTATE_OFFSET_DS(%esp), %edx
    447                
    448         movl %ecx, %es
    449         movl %edx, %ds
    450                
    451         /*
    452          * Restore the scratch registers and the preserved
    453          * registers the handler cloberred itself
    454          * (i.e. EBP).
    455          */
    456         movl ISTATE_OFFSET_EAX(%esp), %eax
    457         movl ISTATE_OFFSET_ECX(%esp), %ecx
    458         movl ISTATE_OFFSET_EDX(%esp), %edx
    459         movl ISTATE_OFFSET_EBP(%esp), %ebp
    460                
    461         addl $(ISTATE_SOFT_SIZE + 4), %esp
    462         iret
    463474.endm
    464475
Note: See TracChangeset for help on using the changeset viewer.