Ignore:
File:
1 edited

Legend:

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

    rb808660 rb8230b9  
    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>
     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
    4234
    4335.text
     36
    4437.global paging_on
    4538.global enable_l_apic_in_msr
     39.global interrupt_handlers
    4640.global memsetb
    4741.global memsetw
     
    5145.global memcpy_to_uspace
    5246.global memcpy_to_uspace_failover_address
    53 .global early_putchar
    54 
    55 /* Wrapper for generic memsetb */
     47
     48
     49# Wrapper for generic memsetb
    5650memsetb:
    5751        jmp _memsetb
    5852
    59 /* Wrapper for generic memsetw */
     53# Wrapper for generic memsetw
    6054memsetw:
    6155        jmp _memsetw
    6256
    63 #define MEMCPY_DST   4
    64 #define MEMCPY_SRC   8
    65 #define MEMCPY_SIZE  12
     57
     58#define MEMCPY_DST      4
     59#define MEMCPY_SRC      8
     60#define MEMCPY_SIZE     12
    6661
    6762/** Copy memory to/from userspace.
     
    7368 * or copy_to_uspace().
    7469 *
    75  * @param MEMCPY_DST(%esp)  Destination address.
    76  * @param MEMCPY_SRC(%esp)  Source address.
    77  * @param MEMCPY_SIZE(%esp) Size.
     70 * @param MEMCPY_DST(%esp)      Destination address.
     71 * @param MEMCPY_SRC(%esp)      Source address.
     72 * @param MEMCPY_SIZE(%esp)     Size.
    7873 *
    7974 * @return MEMCPY_DST(%esp) on success and 0 on failure.
    80  *
    8175 */
    8276memcpy:
    8377memcpy_from_uspace:
    8478memcpy_to_uspace:
    85         movl %edi, %edx  /* save %edi */
    86         movl %esi, %eax  /* save %esi */
     79        movl %edi, %edx                 /* save %edi */
     80        movl %esi, %eax                 /* save %esi */
    8781       
    8882        movl MEMCPY_SIZE(%esp), %ecx
    89         shrl $2, %ecx  /* size / 4 */
     83        shrl $2, %ecx                   /* size / 4 */
    9084       
    9185        movl MEMCPY_DST(%esp), %edi
    9286        movl MEMCPY_SRC(%esp), %esi
    9387       
    94         /* Copy whole words */
    95         rep movsl
    96        
     88        rep movsl                       /* copy whole words */
     89
    9790        movl MEMCPY_SIZE(%esp), %ecx
    98         andl $3, %ecx  /* size % 4 */
     91        andl $3, %ecx                   /* size % 4 */
    9992        jz 0f
    10093       
    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 
     94        rep movsb                       /* copy the rest byte by byte */
     95
     960:
     97        movl %edx, %edi
     98        movl %eax, %esi
     99        movl MEMCPY_DST(%esp), %eax     /* MEMCPY_DST(%esp), success */
     100        ret
     101       
    113102/*
    114103 * We got here from as_page_fault() after the memory operations
     
    119108        movl %edx, %edi
    120109        movl %eax, %esi
    121        
    122         /* Return 0, failure */
    123         xorl %eax, %eax
     110        xorl %eax, %eax                 /* return 0, failure */
    124111        ret
    125112
    126 /** Turn paging on
    127  *
    128  * Enable paging and write-back caching in CR0.
    129  *
    130  */
     113## Turn paging on
     114#
     115# Enable paging and write-back caching in CR0.
     116#
    131117paging_on:
    132118        movl %cr0, %edx
    133         orl $(1 << 31), %edx  /* paging on */
    134        
    135         /* Clear Cache Disable and not Write Though */
     119        orl $(1 << 31), %edx            # paging on
     120        # clear Cache Disable and not Write Though
    136121        andl $~((1 << 30) | (1 << 29)), %edx
    137         movl %edx, %cr0
     122        movl %edx,%cr0
    138123        jmp 0f
    139        
    140         0:
    141                 ret
    142 
    143 /** Enable local APIC
    144  *
    145  * Enable local APIC in MSR.
    146  *
    147  */
     1240:
     125        ret
     126
     127
     128## Enable local APIC
     129#
     130# Enable local APIC in MSR.
     131#
    148132enable_l_apic_in_msr:
    149133        movl $0x1b, %ecx
     
    154138        ret
    155139
    156 /** Clear nested flag
    157  *
    158  */
     140# Clear nested flag
     141# overwrites %ecx
    159142.macro CLEAR_NT_FLAG
    160143        pushfl
    161         andl $0xffffbfff, (%esp)
     144        pop %ecx
     145        and $0xffffbfff, %ecx
     146        push %ecx
    162147        popfl
    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)
     148.endm   
    196149
    197150/*
     
    207160sysenter_handler:
    208161        sti
    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          */
     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
    245174        movw $16, %ax
    246175        movw %ax, %ds
    247176        movw %ax, %es
    248        
     177
    249178        cld
    250179        call syscall_handler
    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
    277 int_\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
     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
    327226               
    328227                cld
    329228                sti
    330                
    331                 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
     229                # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
    332230                call syscall_handler
    333                        
     231                cli
     232                addl $28, %esp         # clean-up of parameters
     233               
     234                popl %gs
     235                popl %fs
     236                popl %es
     237                popl %ds
     238               
    334239                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
    358240                iret
    359                
    360241        .else
    361242                /*
    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.
     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.
    367247                 */
    368248                .iflt \i - 32
    369249                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
    370250                                /*
    371                                  * Exception with error word: do nothing
     251                                 * With error word, do nothing
    372252                                 */
    373253                        .else
    374254                                /*
    375                                  * Exception without error word: fake up one
     255                                 * Version without error word
    376256                                 */
    377                                 pushl $0
     257                                subl $4, %esp
    378258                        .endif
    379259                .else
    380260                        /*
    381                          * Interrupt: fake up one
     261                         * Version without error word
    382262                         */
    383                         pushl $0
     263                        subl $4, %esp
    384264                .endif
    385265               
    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
     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
    425283                xorl %ebp, %ebp
    426284               
    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                
     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
    473310        .endif
    474311.endm
    475312
    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 
     313# keep in sync with pm.h !!!
     314IDT_ITEMS = 64
     315.align INTERRUPT_ALIGN
    481316interrupt_handlers:
    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  */
    500 early_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 
     317h_start:
     318        handler 0 IDT_ITEMS
     319h_end:
     320
     321.data
     322.global interrupt_handler_size
     323
     324interrupt_handler_size: .long (h_end - h_start) / IDT_ITEMS
Note: See TracChangeset for help on using the changeset viewer.