Changeset bd48f4c in mainline for kernel/arch/ia32/src/asm.S


Ignore:
Timestamp:
2010-07-12T10:53:30Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bd11d3e
Parents:
c40e6ef (diff), bee2d4c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rc40e6ef rbd48f4c  
    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
    39 .global interrupt_handlers
    4046.global memsetb
    4147.global memsetw
     
    4551.global memcpy_to_uspace
    4652.global memcpy_to_uspace_failover_address
    47 
    48 
    49 # Wrapper for generic memsetb
     53.global early_putchar
     54
     55/* Wrapper for generic memsetb */
    5056memsetb:
    5157        jmp _memsetb
    5258
    53 # Wrapper for generic memsetw
     59/* Wrapper for generic memsetw */
    5460memsetw:
    5561        jmp _memsetw
    5662
    57 
    58 #define MEMCPY_DST      4
    59 #define MEMCPY_SRC      8
    60 #define MEMCPY_SIZE     12
     63#define MEMCPY_DST   4
     64#define MEMCPY_SRC   8
     65#define MEMCPY_SIZE  12
    6166
    6267/** Copy memory to/from userspace.
     
    6873 * or copy_to_uspace().
    6974 *
    70  * @param MEMCPY_DST(%esp)      Destination address.
    71  * @param MEMCPY_SRC(%esp)      Source address.
    72  * @param MEMCPY_SIZE(%esp)     Size.
     75 * @param MEMCPY_DST(%esp)  Destination address.
     76 * @param MEMCPY_SRC(%esp)  Source address.
     77 * @param MEMCPY_SIZE(%esp) Size.
    7378 *
    7479 * @return MEMCPY_DST(%esp) on success and 0 on failure.
     80 *
    7581 */
    7682memcpy:
    7783memcpy_from_uspace:
    7884memcpy_to_uspace:
    79         movl %edi, %edx                 /* save %edi */
    80         movl %esi, %eax                 /* save %esi */
     85        movl %edi, %edx  /* save %edi */
     86        movl %esi, %eax  /* save %esi */
    8187       
    8288        movl MEMCPY_SIZE(%esp), %ecx
    83         shrl $2, %ecx                   /* size / 4 */
     89        shrl $2, %ecx  /* size / 4 */
    8490       
    8591        movl MEMCPY_DST(%esp), %edi
    8692        movl MEMCPY_SRC(%esp), %esi
    8793       
    88         rep movsl                       /* copy whole words */
    89 
     94        /* Copy whole words */
     95        rep movsl
     96       
    9097        movl MEMCPY_SIZE(%esp), %ecx
    91         andl $3, %ecx                   /* size % 4 */
     98        andl $3, %ecx  /* size % 4 */
    9299        jz 0f
    93100       
    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        
     101        /* Copy the rest byte by byte */
     102        rep movsb
     103       
     104        0:
     105       
     106                movl %edx, %edi
     107                movl %eax, %esi
     108               
     109                /* MEMCPY_DST(%esp), success */
     110                movl MEMCPY_DST(%esp), %eax
     111                ret
     112
    102113/*
    103114 * We got here from as_page_fault() after the memory operations
     
    108119        movl %edx, %edi
    109120        movl %eax, %esi
    110         xorl %eax, %eax                 /* return 0, failure */
     121       
     122        /* Return 0, failure */
     123        xorl %eax, %eax
    111124        ret
    112125
    113 ## Turn paging on
    114 #
    115 # Enable paging and write-back caching in CR0.
    116 #
     126/** Turn paging on
     127 *
     128 * Enable paging and write-back caching in CR0.
     129 *
     130 */
    117131paging_on:
    118132        movl %cr0, %edx
    119         orl $(1 << 31), %edx            # paging on
    120         # clear Cache Disable and not Write Though
     133        orl $(1 << 31), %edx  /* paging on */
     134       
     135        /* Clear Cache Disable and not Write Though */
    121136        andl $~((1 << 30) | (1 << 29)), %edx
    122         movl %edx,%cr0
     137        movl %edx, %cr0
    123138        jmp 0f
    124 0:
    125         ret
    126 
    127 
    128 ## Enable local APIC
    129 #
    130 # Enable local APIC in MSR.
    131 #
     139       
     140        0:
     141                ret
     142
     143/** Enable local APIC
     144 *
     145 * Enable local APIC in MSR.
     146 *
     147 */
    132148enable_l_apic_in_msr:
    133149        movl $0x1b, %ecx
     
    138154        ret
    139155
    140 # Clear nested flag
    141 # overwrites %ecx
     156/** Clear nested flag
     157 *
     158 */
    142159.macro CLEAR_NT_FLAG
    143160        pushfl
    144         pop %ecx
    145         and $0xffffbfff, %ecx
    146         push %ecx
     161        andl $0xffffbfff, (%esp)
    147162        popfl
    148 .endm   
     163.endm
     164
     165#define ISTATE_OFFSET_EDX         0
     166#define ISTATE_OFFSET_ECX         4
     167#define ISTATE_OFFSET_EBX         8
     168#define ISTATE_OFFSET_ESI         12
     169#define ISTATE_OFFSET_EDI         16
     170#define ISTATE_OFFSET_EBP         20
     171#define ISTATE_OFFSET_EAX         24
     172#define ISTATE_OFFSET_EBP_FRAME   28
     173#define ISTATE_OFFSET_EIP_FRAME   32
     174#define ISTATE_OFFSET_GS          36
     175#define ISTATE_OFFSET_FS          40
     176#define ISTATE_OFFSET_ES          44
     177#define ISTATE_OFFSET_DS          48
     178#define ISTATE_OFFSET_ERROR_WORD  52
     179#define ISTATE_OFFSET_EIP         56
     180#define ISTATE_OFFSET_CS          60
     181#define ISTATE_OFFSET_EFLAGS      64
     182#define ISTATE_OFFSET_ESP         68
     183#define ISTATE_OFFSET_SS          72
     184
     185/*
     186 * Size of the istate structure without the hardware-saved part
     187 * and without the error word.
     188 */
     189#define ISTATE_SOFT_SIZE  52
     190
     191/*
     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)
    149196
    150197/*
     
    160207sysenter_handler:
    161208        sti
    162         pushl %ebp      # remember user stack
    163         pushl %edi      # remember return user address
    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 
     209        subl $(ISTATE_REAL_SIZE), %esp
     210
     211        /*
     212         * Save the return address and the userspace stack in the istate
     213         * structure on locations that would normally be taken by them.
     214         */
     215        movl %ebp, ISTATE_OFFSET_ESP(%esp)
     216        movl %edi, ISTATE_OFFSET_EIP(%esp)
     217
     218        /*
     219         * Push syscall arguments onto the stack
     220         */
     221        movl %eax, ISTATE_OFFSET_EAX(%esp)
     222        movl %ebx, ISTATE_OFFSET_EBX(%esp)
     223        movl %ecx, ISTATE_OFFSET_ECX(%esp)
     224        movl %edx, ISTATE_OFFSET_EDX(%esp)
     225        movl %esi, ISTATE_OFFSET_ESI(%esp)
     226        movl %edi, ISTATE_OFFSET_EDI(%esp)      /* observability; not needed */
     227        movl %ebp, ISTATE_OFFSET_EBP(%esp)      /* observability; not needed */
     228       
     229        /*
     230         * Fake up the stack trace linkage.
     231         */
     232        movl %edi, ISTATE_OFFSET_EIP_FRAME(%esp)
     233        movl $0, ISTATE_OFFSET_EBP_FRAME(%esp)
     234        leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
     235
     236        /*
     237         * Save TLS.
     238         */
     239        movl %gs, %edx
     240        movl %edx, ISTATE_OFFSET_GS(%esp)
     241
     242        /*
     243         * Switch to kernel selectors.
     244         */
    174245        movw $16, %ax
    175246        movw %ax, %ds
    176247        movw %ax, %es
    177 
     248       
    178249        cld
    179250        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 ## Declare interrupt handlers
    191 #
    192 # Declare interrupt handlers for n interrupt
    193 # vectors starting at vector i.
    194 #
    195 # The handlers setup data segment registers
    196 # and call exc_dispatch().
    197 #
    198 #define INTERRUPT_ALIGN 64
    199 .macro handler i n
    200        
    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
     251       
     252        /*
     253         * Restore TLS.
     254         */
     255        movl ISTATE_OFFSET_GS(%esp), %edx
     256        movl %edx, %gs
     257       
     258        /*
     259         * Prepare return address and userspace stack for SYSEXIT.
     260         */
     261        movl ISTATE_OFFSET_EIP(%esp), %edx
     262        movl ISTATE_OFFSET_ESP(%esp), %ecx
     263
     264        addl $(ISTATE_REAL_SIZE), %esp
     265       
     266        sysexit   /* return to userspace */
     267
     268/** Declare interrupt handlers
     269 *
     270 * Declare interrupt handlers for n interrupt
     271 * vectors starting at vector i.
     272 *
     273 */
     274
     275.macro handler i
     276.global int_\i
     277int_\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
    226327               
    227328                cld
    228329                sti
    229                 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
     330               
     331                /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
    230332                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                
     333                       
    239334                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
    240358                iret
     359               
    241360        .else
    242361                /*
    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.
     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.
    247367                 */
    248368                .iflt \i - 32
    249369                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
    250370                                /*
    251                                  * With error word, do nothing
     371                                 * Exception with error word: do nothing
    252372                                 */
    253373                        .else
    254374                                /*
    255                                  * Version without error word
     375                                 * Exception without error word: fake up one
    256376                                 */
    257                                 subl $4, %esp
     377                                pushl $0
    258378                        .endif
    259379                .else
    260380                        /*
    261                          * Version without error word
     381                         * Interrupt: fake up one
    262382                         */
    263                         subl $4, %esp
     383                        pushl $0
    264384                .endif
    265385               
    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
     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
    283425                xorl %ebp, %ebp
    284426               
    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
     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               
    310473        .endif
    311474.endm
    312475
    313 # keep in sync with pm.h !!!
    314 IDT_ITEMS = 64
    315 .align INTERRUPT_ALIGN
     476#define LIST_0_63 \
     477        0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\
     478        28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,\
     479        53,54,55,56,57,58,59,60,61,62,63
     480
    316481interrupt_handlers:
    317 h_start:
    318         handler 0 IDT_ITEMS
    319 h_end:
    320 
    321 .data
    322 .global interrupt_handler_size
    323 
    324 interrupt_handler_size: .long (h_end - h_start) / IDT_ITEMS
     482.irp cnt, LIST_0_63
     483        handler \cnt
     484.endr
     485
     486/** Print Unicode character to EGA display.
     487 *
     488 * If CONFIG_EGA is undefined or CONFIG_FB is defined
     489 * then this function does nothing.
     490 *
     491 * Since the EGA can only display Extended ASCII (usually
     492 * ISO Latin 1) characters, some of the Unicode characters
     493 * can be displayed in a wrong way. Only newline and backspace
     494 * are interpreted, all other characters (even unprintable) are
     495 * printed verbatim.
     496 *
     497 * @param %ebp+0x08 Unicode character to be printed.
     498 *
     499 */
     500early_putchar:
     501       
     502#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
     503       
     504        /* Prologue, save preserved registers */
     505        pushl %ebp
     506        movl %esp, %ebp
     507        pushl %ebx
     508        pushl %esi
     509        pushl %edi
     510       
     511        movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
     512        xorl %eax, %eax
     513       
     514        /* Read bits 8 - 15 of the cursor address */
     515        movw $0x3d4, %dx
     516        movb $0xe, %al
     517        outb %al, %dx
     518       
     519        movw $0x3d5, %dx
     520        inb %dx, %al
     521        shl $8, %ax
     522       
     523        /* Read bits 0 - 7 of the cursor address */
     524        movw $0x3d4, %dx
     525        movb $0xf, %al
     526        outb %al, %dx
     527       
     528        movw $0x3d5, %dx
     529        inb %dx, %al
     530       
     531        /* Sanity check for the cursor on screen */
     532        cmp $2000, %ax
     533        jb early_putchar_cursor_ok
     534       
     535                movw $1998, %ax
     536       
     537        early_putchar_cursor_ok:
     538       
     539        movw %ax, %bx
     540        shl $1, %eax
     541        addl %eax, %edi
     542       
     543        movl 0x08(%ebp), %eax
     544       
     545        cmp $0x0a, %al
     546        jne early_putchar_backspace
     547       
     548                /* Interpret newline */
     549               
     550                movw %bx, %ax  /* %bx -> %dx:%ax */
     551                xorw %dx, %dx
     552               
     553                movw $80, %cx
     554                idivw %cx, %ax  /* %dx = %bx % 80 */
     555               
     556                /* %bx <- %bx + 80 - (%bx % 80) */
     557                addw %cx, %bx
     558                subw %dx, %bx
     559               
     560                jmp early_putchar_skip
     561       
     562        early_putchar_backspace:
     563       
     564                cmp $0x08, %al
     565                jne early_putchar_print
     566               
     567                /* Interpret backspace */
     568               
     569                cmp $0x0000, %bx
     570                je early_putchar_skip
     571               
     572                dec %bx
     573                jmp early_putchar_skip
     574       
     575        early_putchar_print:
     576       
     577                /* Print character */
     578               
     579                movb $0x0e, %ah  /* black background, yellow foreground */
     580                stosw
     581                inc %bx
     582       
     583        early_putchar_skip:
     584       
     585        /* Sanity check for the cursor on the last line */
     586        cmp $2000, %bx
     587        jb early_putchar_no_scroll
     588       
     589                /* Scroll the screen (24 rows) */
     590                movl $(PA2KA(0xb80a0)), %esi
     591                movl $(PA2KA(0xb8000)), %edi
     592                movl $960, %ecx
     593                rep movsl
     594               
     595                /* Clear the 24th row */
     596                xorl %eax, %eax
     597                movl $40, %ecx
     598                rep stosl
     599               
     600                /* Go to row 24 */
     601                movw $1920, %bx
     602       
     603        early_putchar_no_scroll:
     604       
     605        /* Write bits 8 - 15 of the cursor address */
     606        movw $0x3d4, %dx
     607        movb $0xe, %al
     608        outb %al, %dx
     609       
     610        movw $0x3d5, %dx
     611        movb %bh, %al
     612        outb %al, %dx
     613       
     614        /* Write bits 0 - 7 of the cursor address */
     615        movw $0x3d4, %dx
     616        movb $0xf, %al
     617        outb %al, %dx
     618       
     619        movw $0x3d5, %dx
     620        movb %bl, %al
     621        outb %al, %dx
     622       
     623        /* Epilogue, restore preserved registers */
     624        popl %edi
     625        popl %esi
     626        popl %ebx
     627        leave
     628       
     629#endif
     630       
     631        ret
     632
Note: See TracChangeset for help on using the changeset viewer.