Ignore:
File:
1 edited

Legend:

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

    reee047c rb5382d4f  
    1 #
    2 # Copyright (c) 2001-2004 Jakub Jermar
    3 # All rights reserved.
    4 #
    5 # Redistribution and use in source and binary forms, with or without
    6 # modification, are permitted provided that the following conditions
    7 # are met:
    8 #
    9 # - Redistributions of source code must retain the above copyright
    10 #   notice, this list of conditions and the following disclaimer.
    11 # - Redistributions in binary form must reproduce the above copyright
    12 #   notice, this list of conditions and the following disclaimer in the
    13 #   documentation and/or other materials provided with the distribution.
    14 # - The name of the author may not be used to endorse or promote products
    15 #   derived from this software without specific prior written permission.
    16 #
    17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27 #
    28 
    29 ## very low and hardware-level functions
    30 
    31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error
    32 # word and 1 means interrupt with error word
    33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00
     1/*
     2 * Copyright (c) 2001 Jakub Jermar
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 *
     9 * - Redistributions of source code must retain the above copyright
     10 *   notice, this list of conditions and the following disclaimer.
     11 * - Redistributions in binary form must reproduce the above copyright
     12 *   notice, this list of conditions and the following disclaimer in the
     13 *   documentation and/or other materials provided with the distribution.
     14 * - The name of the author may not be used to endorse or promote products
     15 *   derived from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28
     29/** Very low and hardware-level functions
     30 *
     31 */
     32
     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
     40#include <arch/pm.h>
     41#include <arch/mm/page.h>
    3442
    3543.text
    36 
    3744.global paging_on
    3845.global enable_l_apic_in_msr
     
    4552.global memcpy_to_uspace
    4653.global memcpy_to_uspace_failover_address
    47 
    48 
    49 # Wrapper for generic memsetb
     54.global early_putchar
     55
     56/* Wrapper for generic memsetb */
    5057memsetb:
    5158        jmp _memsetb
    5259
    53 # Wrapper for generic memsetw
     60/* Wrapper for generic memsetw */
    5461memsetw:
    5562        jmp _memsetw
    5663
    57 
    58 #define MEMCPY_DST      4
    59 #define MEMCPY_SRC      8
    60 #define MEMCPY_SIZE     12
     64#define MEMCPY_DST   4
     65#define MEMCPY_SRC   8
     66#define MEMCPY_SIZE  12
    6167
    6268/** Copy memory to/from userspace.
     
    6874 * or copy_to_uspace().
    6975 *
    70  * @param MEMCPY_DST(%esp)      Destination address.
    71  * @param MEMCPY_SRC(%esp)      Source address.
    72  * @param MEMCPY_SIZE(%esp)     Size.
     76 * @param MEMCPY_DST(%esp)  Destination address.
     77 * @param MEMCPY_SRC(%esp)  Source address.
     78 * @param MEMCPY_SIZE(%esp) Size.
    7379 *
    7480 * @return MEMCPY_DST(%esp) on success and 0 on failure.
     81 *
    7582 */
    7683memcpy:
    7784memcpy_from_uspace:
    7885memcpy_to_uspace:
    79         movl %edi, %edx                 /* save %edi */
    80         movl %esi, %eax                 /* save %esi */
     86        movl %edi, %edx  /* save %edi */
     87        movl %esi, %eax  /* save %esi */
    8188       
    8289        movl MEMCPY_SIZE(%esp), %ecx
    83         shrl $2, %ecx                   /* size / 4 */
     90        shrl $2, %ecx  /* size / 4 */
    8491       
    8592        movl MEMCPY_DST(%esp), %edi
    8693        movl MEMCPY_SRC(%esp), %esi
    8794       
    88         rep movsl                       /* copy whole words */
    89 
     95        /* Copy whole words */
     96        rep movsl
     97       
    9098        movl MEMCPY_SIZE(%esp), %ecx
    91         andl $3, %ecx                   /* size % 4 */
     99        andl $3, %ecx  /* size % 4 */
    92100        jz 0f
    93101       
    94         rep movsb                       /* copy the rest byte by byte */
    95 
    96 0:
    97         movl %edx, %edi
    98         movl %eax, %esi
    99         movl MEMCPY_DST(%esp), %eax     /* MEMCPY_DST(%esp), success */
    100         ret
    101        
     102        /* Copy the rest byte by byte */
     103        rep movsb
     104       
     105        0:
     106       
     107                movl %edx, %edi
     108                movl %eax, %esi
     109               
     110                /* MEMCPY_DST(%esp), success */
     111                movl MEMCPY_DST(%esp), %eax
     112                ret
     113
    102114/*
    103115 * We got here from as_page_fault() after the memory operations
     
    108120        movl %edx, %edi
    109121        movl %eax, %esi
    110         xorl %eax, %eax                 /* return 0, failure */
     122       
     123        /* Return 0, failure */
     124        xorl %eax, %eax
    111125        ret
    112126
    113 ## Turn paging on
    114 #
    115 # Enable paging and write-back caching in CR0.
    116 #
     127/** Turn paging on
     128 *
     129 * Enable paging and write-back caching in CR0.
     130 *
     131 */
    117132paging_on:
    118133        movl %cr0, %edx
    119         orl $(1 << 31), %edx            # paging on
    120         # clear Cache Disable and not Write Though
     134        orl $(1 << 31), %edx  /* paging on */
     135       
     136        /* Clear Cache Disable and not Write Though */
    121137        andl $~((1 << 30) | (1 << 29)), %edx
    122         movl %edx,%cr0
     138        movl %edx, %cr0
    123139        jmp 0f
    124 0:
    125         ret
    126 
    127 
    128 ## Enable local APIC
    129 #
    130 # Enable local APIC in MSR.
    131 #
     140       
     141        0:
     142                ret
     143
     144/** Enable local APIC
     145 *
     146 * Enable local APIC in MSR.
     147 *
     148 */
    132149enable_l_apic_in_msr:
    133150        movl $0x1b, %ecx
     
    138155        ret
    139156
    140 # Clear nested flag
    141 # overwrites %ecx
     157/** Clear nested flag
     158 *
     159 */
    142160.macro CLEAR_NT_FLAG
    143161        pushfl
    144162        andl $0xffffbfff, (%esp)
    145163        popfl
    146 .endm   
     164.endm
    147165
    148166/*
     
    158176sysenter_handler:
    159177        sti
    160         pushl %ebp      # remember user stack
    161         pushl %edi      # remember return user address
    162 
    163         xorl %ebp, %ebp # stop stack traces here
    164 
    165         pushl %gs       # remember TLS
    166 
    167         pushl %eax      # syscall number
    168         subl $8, %esp   # unused sixth and fifth argument
    169         pushl %esi      # fourth argument
    170         pushl %ebx      # third argument
    171         pushl %ecx      # second argument
    172         pushl %edx      # first argument
    173 
     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       
    174192        movw $16, %ax
    175193        movw %ax, %ds
    176194        movw %ax, %es
    177 
     195       
    178196        cld
    179197        call syscall_handler
    180         addl $28, %esp  # remove arguments from stack
    181 
    182         pop %gs         # restore TLS
    183 
    184         pop %edx        # prepare return EIP for SYSEXIT
    185         pop %ecx        # prepare userspace ESP for SYSEXIT
    186 
    187         sysexit         # return to userspace
    188 
    189 
    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
     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
     214#define ISTATE_OFFSET_EBP_FRAME   28
     215#define ISTATE_OFFSET_EIP_FRAME   32
     216#define ISTATE_OFFSET_GS          36
     217#define ISTATE_OFFSET_FS          40
     218#define ISTATE_OFFSET_ES          44
     219#define ISTATE_OFFSET_DS          48
     220#define ISTATE_OFFSET_ERROR_WORD  52
     221#define ISTATE_OFFSET_EIP         56
     222#define ISTATE_OFFSET_CS          60
     223#define ISTATE_OFFSET_EFLAGS      64
     224#define ISTATE_OFFSET_ESP         68
     225#define ISTATE_OFFSET_SS          72
    209226
    210227/*
    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 
    216 ## Declare interrupt handlers
    217 #
    218 # Declare interrupt handlers for n interrupt
    219 # vectors starting at vector i.
    220 #
    221 # The handlers setup data segment registers
    222 # and call exc_dispatch().
    223 #
    224 #define INTERRUPT_ALIGN 256
     228 * Size of the istate structure without the hardware-saved part
     229 * and without the error word.
     230 */
     231#define ISTATE_SOFT_SIZE  52
     232
     233/** Declare interrupt handlers
     234 *
     235 * Declare interrupt handlers for n interrupt
     236 * vectors starting at vector i.
     237 *
     238 * The handlers setup data segment registers
     239 * and call exc_dispatch().
     240 *
     241 */
     242#define INTERRUPT_ALIGN  256
     243
    225244.macro handler i n
    226        
    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
     245        .ifeq \i - 0x30
     246                /* Syscall handler */
     247                pushl %ds
     248                pushl %es
     249                pushl %fs
     250                pushl %gs
     251               
     252                /*
     253                 * Push syscall arguments onto the stack
     254                 *
     255                 * NOTE: The idea behind the order of arguments passed
     256                 *       in registers is to use all scratch registers
     257                 *       first and preserved registers next. An optimized
     258                 *       libc syscall wrapper can make use of this setup.
     259                 *
     260                 */
     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
     275               
     276                cld
     277                sti
     278               
     279                /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
     280                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               
     291                CLEAR_NT_FLAG
     292                iret
     293        .else
     294                /*
     295                 * This macro distinguishes between two versions of ia32
     296                 * exceptions. One version has error word and the other
     297                 * does not have it. The latter version fakes the error
     298                 * word on the stack so that the handlers and istate_t
     299                 * can be the same for both types.
     300                 */
     301                .iflt \i - 32
     302                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
     303                                /*
     304                                 * Exception with error word: do nothing
     305                                 */
     306                        .else
     307                                /*
     308                                 * Exception without error word: fake up one
     309                                 */
     310                                pushl $0
     311                        .endif
     312                .else
     313                        /*
     314                         * Interrupt: fake up one
     315                         */
     316                        pushl $0
     317                .endif
     318               
     319                subl $ISTATE_SOFT_SIZE, %esp
     320               
     321                /*
     322                 * Save the general purpose registers.
     323                 */
     324                movl %eax, ISTATE_OFFSET_EAX(%esp)
     325                movl %ebx, ISTATE_OFFSET_EBX(%esp)
     326                movl %ecx, ISTATE_OFFSET_ECX(%esp)
     327                movl %edx, ISTATE_OFFSET_EDX(%esp)
     328                movl %edi, ISTATE_OFFSET_EDI(%esp)
     329                movl %esi, ISTATE_OFFSET_ESI(%esp)
     330                movl %ebp, ISTATE_OFFSET_EBP(%esp)
     331               
     332                /*
     333                 * Save the selector registers.
     334                 */
     335                movl %gs, %eax
     336                movl %fs, %ebx
     337                movl %es, %ecx
     338                movl %ds, %edx
     339               
     340                movl %eax, ISTATE_OFFSET_GS(%esp)
     341                movl %ebx, ISTATE_OFFSET_FS(%esp)
     342                movl %ecx, ISTATE_OFFSET_ES(%esp)
     343                movl %edx, ISTATE_OFFSET_DS(%esp)
     344               
     345                /*
     346                 * Switch to kernel selectors.
     347                 */
     348                movl $16, %eax
     349                movl %eax, %ds
     350                movl %eax, %es
     351               
     352                /*
     353                 * Imitate a regular stack frame linkage.
     354                 * Stop stack traces here if we came from userspace.
     355                 */
     356                cmpl $8, ISTATE_OFFSET_CS(%esp)
     357                jz 0f
     358                xorl %ebp, %ebp
     359               
     360                0:
     361               
     362                        movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
     363                        movl ISTATE_OFFSET_EIP(%esp), %eax
     364                        movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
     365                        leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
     366                       
     367                        cld
     368                       
     369                        pushl %esp   /* pass istate address */
     370                        pushl $(\i)  /* pass intnum */
     371                       
     372                        /* Call exc_dispatch(intnum, istate) */
     373                        call exc_dispatch
     374                       
     375                        addl $8, %esp  /* clear arguments from the stack */
     376                       
     377                        CLEAR_NT_FLAG
     378                       
     379                        /*
     380                         * Restore the selector registers.
     381                         */
     382                        movl ISTATE_OFFSET_GS(%esp), %eax
     383                        movl ISTATE_OFFSET_FS(%esp), %ebx
     384                        movl ISTATE_OFFSET_ES(%esp), %ecx
     385                        movl ISTATE_OFFSET_DS(%esp), %edx
     386                       
     387                        movl %eax, %gs
     388                        movl %ebx, %fs
     389                        movl %ecx, %es
     390                        movl %edx, %ds
     391                       
     392                        /*
     393                         * Restore the scratch registers and the preserved
     394                         * registers the handler cloberred itself
     395                         * (i.e. EBX and EBP).
     396                         */
     397                        movl ISTATE_OFFSET_EAX(%esp), %eax
     398                        movl ISTATE_OFFSET_EBX(%esp), %ebx
     399                        movl ISTATE_OFFSET_ECX(%esp), %ecx
     400                        movl ISTATE_OFFSET_EDX(%esp), %edx
     401                        movl ISTATE_OFFSET_EBP(%esp), %ebp
     402                       
     403                        addl $(ISTATE_SOFT_SIZE + 4), %esp
     404                        iret
     405               
     406        .endif
     407       
     408        .align INTERRUPT_ALIGN
     409        .if (\n - \i) - 1
     410                handler "(\i + 1)", \n
     411        .endif
    381412.endm
    382413
    383 # keep in sync with pm.h !!!
    384 IDT_ITEMS = 64
     414/* Keep in sync with pm.h! */
     415#define IDT_ITEMS  64
     416
    385417.align INTERRUPT_ALIGN
    386418interrupt_handlers:
    387 h_start:
    388         handler 0 IDT_ITEMS
    389 h_end:
     419        h_start:
     420                handler 0 IDT_ITEMS
     421        h_end:
     422
     423/** Print Unicode character to EGA display.
     424 *
     425 * If CONFIG_EGA is undefined or CONFIG_FB is defined
     426 * then this function does nothing.
     427 *
     428 * Since the EGA can only display Extended ASCII (usually
     429 * ISO Latin 1) characters, some of the Unicode characters
     430 * can be displayed in a wrong way. Only the newline character
     431 * is interpreted, all other characters (even unprintable) are
     432 * printed verbatim.
     433 *
     434 * @param %ebp+0x08 Unicode character to be printed.
     435 *
     436 */
     437early_putchar:
     438       
     439#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
     440       
     441        /* Prologue, save preserved registers */
     442        pushl %ebp
     443        movl %esp, %ebp
     444        pushl %ebx
     445        pushl %esi
     446        pushl %edi
     447       
     448        movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
     449        xorl %eax, %eax
     450       
     451        /* Read bits 8 - 15 of the cursor address */
     452        movw $0x3d4, %dx
     453        movb $0xe, %al
     454        outb %al, %dx
     455       
     456        movw $0x3d5, %dx
     457        inb %dx, %al
     458        shl $8, %ax
     459       
     460        /* Read bits 0 - 7 of the cursor address */
     461        movw $0x3d4, %dx
     462        movb $0xf, %al
     463        outb %al, %dx
     464       
     465        movw $0x3d5, %dx
     466        inb %dx, %al
     467       
     468        /* Sanity check for the cursor on screen */
     469        cmp $2000, %ax
     470        jb early_putchar_cursor_ok
     471       
     472                movw $1998, %ax
     473       
     474        early_putchar_cursor_ok:
     475       
     476        movw %ax, %bx
     477        shl $1, %eax
     478        addl %eax, %edi
     479       
     480        movl 0x08(%ebp), %eax
     481       
     482        cmp $0x0a, %al
     483        jne early_putchar_print
     484       
     485                /* Interpret newline */
     486               
     487                movw %bx, %ax  /* %bx -> %dx:%ax */
     488                xorw %dx, %dx
     489               
     490                movw $80, %cx
     491                idivw %cx, %ax  /* %dx = %bx % 80 */
     492               
     493                /* %bx <- %bx + 80 - (%bx % 80) */
     494                addw %cx, %bx
     495                subw %dx, %bx
     496               
     497                jmp early_putchar_newline
     498       
     499        early_putchar_print:
     500       
     501                /* Print character */
     502               
     503                movb $0x0e, %ah  /* black background, yellow foreground */
     504                stosw
     505                inc %bx
     506       
     507        early_putchar_newline:
     508       
     509        /* Sanity check for the cursor on the last line */
     510        cmp $2000, %bx
     511        jb early_putchar_no_scroll
     512       
     513                /* Scroll the screen (24 rows) */
     514                movl $(PA2KA(0xb80a0)), %esi
     515                movl $(PA2KA(0xb8000)), %edi
     516                movl $1920, %ecx
     517                rep movsw
     518               
     519                /* Clear the 24th row */
     520                xorl %eax, %eax
     521                movl $80, %ecx
     522                rep stosw
     523               
     524                /* Go to row 24 */
     525                movw $1920, %bx
     526       
     527        early_putchar_no_scroll:
     528       
     529        /* Write bits 8 - 15 of the cursor address */
     530        movw $0x3d4, %dx
     531        movb $0xe, %al
     532        outb %al, %dx
     533       
     534        movw $0x3d5, %dx
     535        movb %bh, %al
     536        outb %al, %dx
     537       
     538        /* Write bits 0 - 7 of the cursor address */
     539        movw $0x3d4, %dx
     540        movb $0xf, %al
     541        outb %al, %dx
     542       
     543        movw $0x3d5, %dx
     544        movb %bl, %al
     545        outb %al, %dx
     546       
     547        /* Epilogue, restore preserved registers */
     548        popl %edi
     549        popl %esi
     550        popl %ebx
     551        leave
     552       
     553#endif
     554       
     555        ret
    390556
    391557.data
Note: See TracChangeset for help on using the changeset viewer.