Changeset 89c57b6 in mainline for kernel/arch/amd64/src/asm.S


Ignore:
Timestamp:
2011-04-13T14:45:41Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
88634420
Parents:
cefb126 (diff), 17279ead (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/amd64/src/asm.S

    rcefb126 r89c57b6  
    2727 */
    2828
    29 #define IREGISTER_SPACE  80
    30 
    31 #define IOFFSET_RAX  0x00
    32 #define IOFFSET_RCX  0x08
    33 #define IOFFSET_RDX  0x10
    34 #define IOFFSET_RSI  0x18
    35 #define IOFFSET_RDI  0x20
    36 #define IOFFSET_R8   0x28
    37 #define IOFFSET_R9   0x30
    38 #define IOFFSET_R10  0x38
    39 #define IOFFSET_R11  0x40
    40 #define IOFFSET_RBP  0x48
    41 
    42 /**
    43  * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
    44  * has no error word  and 1 means interrupt with error word
    45  *
    46  */
    47 #define ERROR_WORD_INTERRUPT_LIST  0x00027D00
    48 
    4929#include <arch/pm.h>
    5030#include <arch/mm/page.h>
     
    5737.global read_efer_flag
    5838.global set_efer_flag
    59 .global memsetb
    60 .global memsetw
    61 .global memcpy
    6239.global memcpy_from_uspace
    6340.global memcpy_to_uspace
     
    6643.global early_putchar
    6744
    68 /* Wrapper for generic memsetb */
    69 memsetb:
    70         jmp _memsetb
    71 
    72 /* Wrapper for generic memsetw */
    73 memsetw:
    74         jmp _memsetw
    75 
    7645#define MEMCPY_DST   %rdi
    7746#define MEMCPY_SRC   %rsi
     
    9463 *
    9564 */
    96 memcpy:
    9765memcpy_from_uspace:
    9866memcpy_to_uspace:
     
    11583memcpy_from_uspace_failover_address:
    11684memcpy_to_uspace_failover_address:
    117         xorq %rax, %rax         /* return 0, failure */
     85        xorl %eax, %eax         /* return 0, failure */
    11886        ret
    11987
     
    163131
    164132set_efer_flag:
    165         movq $0xc0000080, %rcx
     133        movl $0xc0000080, %ecx
    166134        rdmsr
    167135        btsl %edi, %eax
     
    170138
    171139read_efer_flag:
    172         movq $0xc0000080, %rcx
     140        movl $0xc0000080, %ecx
    173141        rdmsr
    174142        ret
    175143
    176 /** Push all volatile general purpose registers on stack
    177  *
     144#define ISTATE_OFFSET_RAX               0
     145#define ISTATE_OFFSET_RBX               8
     146#define ISTATE_OFFSET_RCX               16
     147#define ISTATE_OFFSET_RDX               24
     148#define ISTATE_OFFSET_RSI               32
     149#define ISTATE_OFFSET_RDI               40
     150#define ISTATE_OFFSET_RBP               48
     151#define ISTATE_OFFSET_R8                56
     152#define ISTATE_OFFSET_R9                64
     153#define ISTATE_OFFSET_R10               72
     154#define ISTATE_OFFSET_R11               80
     155#define ISTATE_OFFSET_R12               88     
     156#define ISTATE_OFFSET_R13               96
     157#define ISTATE_OFFSET_R14               104
     158#define ISTATE_OFFSET_R15               112
     159#define ISTATE_OFFSET_ALIGNMENT         120
     160#define ISTATE_OFFSET_RBP_FRAME         128
     161#define ISTATE_OFFSET_RIP_FRAME         136
     162#define ISTATE_OFFSET_ERROR_WORD        144
     163#define ISTATE_OFFSET_RIP               152
     164#define ISTATE_OFFSET_CS                160
     165#define ISTATE_OFFSET_RFLAGS            168
     166#define ISTATE_OFFSET_RSP               176
     167#define ISTATE_OFFSET_SS                184
     168
     169/*
     170 * Size of the istate structure without the hardware-saved part and without the
     171 * error word.
    178172 */
    179 .macro save_all_gpr
    180         movq %rax, IOFFSET_RAX(%rsp)
    181         movq %rcx, IOFFSET_RCX(%rsp)
    182         movq %rdx, IOFFSET_RDX(%rsp)
    183         movq %rsi, IOFFSET_RSI(%rsp)
    184         movq %rdi, IOFFSET_RDI(%rsp)
    185         movq %r8, IOFFSET_R8(%rsp)
    186         movq %r9, IOFFSET_R9(%rsp)
    187         movq %r10, IOFFSET_R10(%rsp)
    188         movq %r11, IOFFSET_R11(%rsp)
    189         movq %rbp, IOFFSET_RBP(%rsp)
    190 .endm
    191 
    192 .macro restore_all_gpr
    193         movq IOFFSET_RAX(%rsp), %rax
    194         movq IOFFSET_RCX(%rsp), %rcx
    195         movq IOFFSET_RDX(%rsp), %rdx
    196         movq IOFFSET_RSI(%rsp), %rsi
    197         movq IOFFSET_RDI(%rsp), %rdi
    198         movq IOFFSET_R8(%rsp), %r8
    199         movq IOFFSET_R9(%rsp), %r9
    200         movq IOFFSET_R10(%rsp), %r10
    201         movq IOFFSET_R11(%rsp), %r11
    202         movq IOFFSET_RBP(%rsp), %rbp
    203 .endm
    204 
    205 #define INTERRUPT_ALIGN  128
    206 
    207 /** Declare interrupt handlers
    208  *
    209  * Declare interrupt handlers for n interrupt
    210  * vectors starting at vector i.
    211  *
    212  * The handlers call exc_dispatch().
     173#define ISTATE_SOFT_SIZE        144
     174
     175/**
     176 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
     177 * has no error word  and 1 means interrupt with error word
    213178 *
    214179 */
    215 .macro handler i n
    216        
     180#define ERROR_WORD_INTERRUPT_LIST  0x00027D00
     181
     182.macro handler i
     183.global int_\i
     184int_\i:
     185
    217186        /*
    218187         * Choose between version with error code and version without error
    219          * code. Both versions have to be of the same size. amd64 assembly is,
    220          * however, a little bit tricky. For instance, subq $0x80, %rsp and
    221          * subq $0x78, %rsp can result in two instructions with different
    222          * op-code lengths.
    223          * Therefore we align the interrupt handlers.
     188         * code.
    224189         */
    225190       
     
    229194                         * Version with error word.
    230195                         */
    231                         subq $IREGISTER_SPACE, %rsp
     196                        subq $ISTATE_SOFT_SIZE, %rsp
    232197                .else
    233198                        /*
    234                          * Version without error word,
     199                         * Version without error word.
    235200                         */
    236                         subq $(IREGISTER_SPACE + 8), %rsp
     201                        subq $(ISTATE_SOFT_SIZE + 8), %rsp
    237202                .endif
    238203        .else
    239204                /*
    240                  * Version without error word,
     205                 * Version without error word.
    241206                 */
    242                 subq $(IREGISTER_SPACE + 8), %rsp
     207                subq $(ISTATE_SOFT_SIZE + 8), %rsp
    243208        .endif
    244209       
    245         save_all_gpr
     210        /*
     211         * Save the general purpose registers.
     212         */
     213        movq %rax, ISTATE_OFFSET_RAX(%rsp)
     214        movq %rbx, ISTATE_OFFSET_RBX(%rsp)
     215        movq %rcx, ISTATE_OFFSET_RCX(%rsp)
     216        movq %rdx, ISTATE_OFFSET_RDX(%rsp)
     217        movq %rsi, ISTATE_OFFSET_RSI(%rsp)
     218        movq %rdi, ISTATE_OFFSET_RDI(%rsp)
     219        movq %rbp, ISTATE_OFFSET_RBP(%rsp)
     220        movq %r8, ISTATE_OFFSET_R8(%rsp)
     221        movq %r9, ISTATE_OFFSET_R9(%rsp)
     222        movq %r10, ISTATE_OFFSET_R10(%rsp)
     223        movq %r11, ISTATE_OFFSET_R11(%rsp)
     224        movq %r12, ISTATE_OFFSET_R12(%rsp)
     225        movq %r13, ISTATE_OFFSET_R13(%rsp)
     226        movq %r14, ISTATE_OFFSET_R14(%rsp)
     227        movq %r15, ISTATE_OFFSET_R15(%rsp)
     228
     229        /*
     230         * Imitate a regular stack frame linkage.
     231         * Stop stack traces here if we came from userspace.
     232         */
     233        xorl %edx, %edx
     234        cmpq $(GDT_SELECTOR(KTEXT_DES)), ISTATE_OFFSET_CS(%rsp)
     235        cmovnzq %rdx, %rbp
     236
     237        movq %rbp, ISTATE_OFFSET_RBP_FRAME(%rsp)
     238        movq ISTATE_OFFSET_RIP(%rsp), %rax
     239        movq %rax, ISTATE_OFFSET_RIP_FRAME(%rsp)
     240        leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp
     241
     242        movq $(\i), %rdi   /* pass intnum in the first argument */
     243        movq %rsp, %rsi    /* pass istate address in the second argument */
     244       
    246245        cld
    247        
    248         /*
    249          * Stop stack traces here if we came from userspace.
    250          */
    251         movq %cs, %rax
    252         xorq %rdx, %rdx
    253         cmpq %rax, IREGISTER_SPACE+16(%rsp)
    254         cmovneq %rdx, %rbp
    255 
    256         movq $(\i), %rdi   /* %rdi - first argument */
    257         movq %rsp, %rsi    /* %rsi - pointer to istate */
    258        
     246
    259247        /* Call exc_dispatch(i, istate) */
    260248        call exc_dispatch
    261        
    262         restore_all_gpr
     249
     250        /*
     251         * Restore all scratch registers and the preserved registers we have
     252         * clobbered in this handler (i.e. RBP).
     253         */
     254        movq ISTATE_OFFSET_RAX(%rsp), %rax
     255        movq ISTATE_OFFSET_RCX(%rsp), %rcx
     256        movq ISTATE_OFFSET_RDX(%rsp), %rdx
     257        movq ISTATE_OFFSET_RSI(%rsp), %rsi
     258        movq ISTATE_OFFSET_RDI(%rsp), %rdi
     259        movq ISTATE_OFFSET_RBP(%rsp), %rbp
     260        movq ISTATE_OFFSET_R8(%rsp), %r8
     261        movq ISTATE_OFFSET_R9(%rsp), %r9
     262        movq ISTATE_OFFSET_R10(%rsp), %r10
     263        movq ISTATE_OFFSET_R11(%rsp), %r11
    263264       
    264265        /* $8 = Skip error word */
    265         addq $(IREGISTER_SPACE + 8), %rsp
     266        addq $(ISTATE_SOFT_SIZE + 8), %rsp
    266267        iretq
    267        
    268         .align INTERRUPT_ALIGN
    269         .if (\n - \i) - 1
    270                 handler "(\i + 1)", \n
    271         .endif
    272268.endm
    273269
    274 .align INTERRUPT_ALIGN
     270#define LIST_0_63 \
     271        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,\
     272        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,\
     273        53,54,55,56,57,58,59,60,61,62,63
     274
    275275interrupt_handlers:
    276         h_start:
    277                 handler 0 IDT_ITEMS
    278         h_end:
     276.irp cnt, LIST_0_63
     277        handler \cnt
     278.endr
    279279
    280280/** Low-level syscall handler
     
    309309        movq %gs:8, %rsp  /* set this thread's kernel RSP */
    310310       
    311         /* Switch back to remain consistent */
     311        /*
     312         * Note that the space needed for the imitated istate structure has been
     313         * preallocated for us in thread_create_arch() and set in
     314         * before_thread_runs_arch().
     315         */
     316
     317        /*
     318         * Save the general purpose registers and push the 7th argument (syscall
     319         * number) onto the stack. Note that the istate structure has a layout
     320         * which supports this.
     321         */
     322        movq %rax, ISTATE_OFFSET_RAX(%rsp)  /* 7th argument, passed on stack */
     323        movq %rbx, ISTATE_OFFSET_RBX(%rsp)  /* observability */
     324        movq %rcx, ISTATE_OFFSET_RCX(%rsp)  /* userspace RIP */
     325        movq %rdx, ISTATE_OFFSET_RDX(%rsp)  /* 3rd argument, observability */
     326        movq %rsi, ISTATE_OFFSET_RSI(%rsp)  /* 2nd argument, observability */
     327        movq %rdi, ISTATE_OFFSET_RDI(%rsp)  /* 1st argument, observability */
     328        movq %rbp, ISTATE_OFFSET_RBP(%rsp)  /* need to preserve userspace RBP */
     329        movq %r8, ISTATE_OFFSET_R8(%rsp)    /* 5th argument, observability */
     330        movq %r9, ISTATE_OFFSET_R9(%rsp)    /* 6th argument, observability */
     331        movq %r10, ISTATE_OFFSET_R10(%rsp)  /* 4th argument, observability */
     332        movq %r11, ISTATE_OFFSET_R11(%rsp)  /* low 32 bits userspace RFLAGS */
     333        movq %r12, ISTATE_OFFSET_R12(%rsp)  /* observability */
     334        movq %r13, ISTATE_OFFSET_R13(%rsp)  /* observability */
     335        movq %r14, ISTATE_OFFSET_R14(%rsp)  /* observability */
     336        movq %r15, ISTATE_OFFSET_R15(%rsp)  /* observability */
     337
     338        /*
     339         * Save the return address and the userspace stack on locations that
     340         * would normally be taken by them.
     341         */
     342        movq %gs:0, %rax
     343        movq %rax, ISTATE_OFFSET_RSP(%rsp)
     344        movq %rcx, ISTATE_OFFSET_RIP(%rsp)
     345
     346        /*
     347         * Imitate a regular stack frame linkage.
     348         */
     349        movq $0, ISTATE_OFFSET_RBP_FRAME(%rsp)
     350        movq %rcx, ISTATE_OFFSET_RIP_FRAME(%rsp)
     351        leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp
     352
     353        /* Switch back to normal %gs */
    312354        swapgs
    313355        sti
    314356       
    315         pushq %rcx
    316         pushq %r11
    317         pushq %rbp
    318        
    319         xorq %rbp, %rbp  /* stop the stack traces here */
    320        
    321357        /* Copy the 4th argument where it is expected  */
    322358        movq %r10, %rcx
    323         pushq %rax
    324        
     359
     360        /*
     361         * Call syscall_handler() with the 7th argument passed on stack.
     362         */
    325363        call syscall_handler
    326364       
    327         addq $8, %rsp
    328        
    329         popq %rbp
    330         popq %r11
    331         popq %rcx
    332        
    333365        cli
    334         swapgs
    335        
    336         /* Restore the user RSP */
    337         movq %gs:0, %rsp
    338         swapgs
    339        
     366       
     367        /*
     368         * Restore registers needed for return via the SYSRET instruction and
     369         * the clobbered preserved registers (i.e. RBP).
     370         */
     371        movq ISTATE_OFFSET_RBP(%rsp), %rbp
     372        movq ISTATE_OFFSET_RCX(%rsp), %rcx
     373        movq ISTATE_OFFSET_R11(%rsp), %r11
     374        movq ISTATE_OFFSET_RSP(%rsp), %rsp
     375
     376        /*
     377         * Clear the rest of the scratch registers to prevent information leak.
     378         * The 32-bit XOR on the low GPRs actually clears the entire 64-bit
     379         * register and the instruction is shorter.
     380         */
     381        xorl %edx, %edx
     382        xorl %esi, %esi
     383        xorl %edi, %edi
     384        xorq %r8, %r8
     385        xorq %r9, %r9
     386        xorq %r10, %r10
     387
    340388        sysretq
    341389
     
    347395 * Since the EGA can only display Extended ASCII (usually
    348396 * ISO Latin 1) characters, some of the Unicode characters
    349  * can be displayed in a wrong way. Only the newline character
    350  * is interpreted, all other characters (even unprintable) are
     397 * can be displayed in a wrong way. Only newline and backspace
     398 * are interpreted, all other characters (even unprintable) are
    351399 * printed verbatim.
    352400 *
     
    365413        movq %rdi, %rsi
    366414        movq $(PA2KA(0xb8000)), %rdi  /* base of EGA text mode memory */
    367         xorq %rax, %rax
     415        xorl %eax, %eax
    368416       
    369417        /* Read bits 8 - 15 of the cursor address */
     
    399447       
    400448        cmp $0x0a, %al
    401         jne early_putchar_print
     449        jne early_putchar_backspace
    402450       
    403451                /* Interpret newline */
     
    413461                subw %dx, %bx
    414462               
    415                 jmp early_putchar_newline
     463                jmp early_putchar_skip
     464       
     465        early_putchar_backspace:
     466       
     467                cmp $0x08, %al
     468                jne early_putchar_print
     469               
     470                /* Interpret backspace */
     471               
     472                cmp $0x0000, %bx
     473                je early_putchar_skip
     474               
     475                dec %bx
     476                jmp early_putchar_skip
    416477       
    417478        early_putchar_print:
     
    423484                inc %bx
    424485       
    425         early_putchar_newline:
     486        early_putchar_skip:
    426487       
    427488        /* Sanity check for the cursor on the last line */
     
    432493                movq $(PA2KA(0xb80a0)), %rsi
    433494                movq $(PA2KA(0xb8000)), %rdi
    434                 movq $1920, %rcx
    435                 rep movsw
     495                movl $480, %ecx
     496                rep movsq
    436497               
    437498                /* Clear the 24th row */
    438                 xorq %rax, %rax
    439                 movq $80, %rcx
    440                 rep stosw
     499                xorl %eax, %eax
     500                movl $20, %ecx
     501                rep stosq
    441502               
    442503                /* Go to row 24 */
     
    471532        ret
    472533
    473 .data
    474 .global interrupt_handler_size
    475 
    476 interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Note: See TracChangeset for help on using the changeset viewer.