Ignore:
File:
1 edited

Legend:

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

    rb808660 r91ef7cfd  
    11/*
    2  * Copyright (c) 2001 Jakub Jermar
     2 * Copyright (c) 2010 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 
    4033#include <arch/pm.h>
     34#include <arch/cpu.h>
    4135#include <arch/mm/page.h>
    4236
     
    153147        wrmsr
    154148        ret
    155 
    156 /** Clear nested flag
    157  *
    158  */
    159 .macro CLEAR_NT_FLAG
    160         pushfl
    161         andl $0xffffbfff, (%esp)
    162         popfl
    163 .endm
    164149
    165150#define ISTATE_OFFSET_EDX         0
     
    190175
    191176/*
    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 /*
    198177 * The SYSENTER syscall mechanism can be used for syscalls with
    199178 * four or fewer arguments. To pass these four arguments, we
     
    206185.global sysenter_handler
    207186sysenter_handler:
    208         sti
    209         subl $(ISTATE_REAL_SIZE), %esp
     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         */
    210192
    211193        /*
     
    243225         * Switch to kernel selectors.
    244226         */
    245         movw $16, %ax
     227        movw $(gdtselector(KDATA_DES)), %ax
    246228        movw %ax, %ds
    247229        movw %ax, %es
    248230       
    249         cld
     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
    250246        call syscall_handler
    251247       
     
    262258        movl ISTATE_OFFSET_ESP(%esp), %ecx
    263259
    264         addl $(ISTATE_REAL_SIZE), %esp
    265        
    266260        sysexit   /* return to userspace */
    267261
    268 /** Declare interrupt handlers
    269  *
    270  * Declare interrupt handlers for n interrupt
    271  * vectors starting at vector i.
    272  *
    273  */
     262/*
     263 * This is the legacy syscall handler using the interrupt mechanism.
     264 */
     265.global int_syscall
     266int_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
    274350
    275351.macro handler i
    276352.global int_\i
    277353int_\i:
    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                
     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
     367                .else
     368                        /*
     369                         * Exception without error word: fake up one
     370                         */
     371                        subl $(ISTATE_SOFT_SIZE + 4), %esp
     372                .endif
    360373        .else
    361374                /*
    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.
     375                 * Interrupt: fake up an error word
    367376                 */
    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
    379                 .else
    380                         /*
    381                          * Interrupt: fake up one
    382                          */
    383                         pushl $0
    384                 .endif
    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                
     377                subl $(ISTATE_SOFT_SIZE + 4), %esp
    473378        .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
    474463.endm
    475464
Note: See TracChangeset for help on using the changeset viewer.