[BACK]Return to vector.s CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/vector.s, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: vector.s,v 1.10 2007/04/12 20:22:58 art Exp $ */
                      2: /*     $NetBSD: vector.s,v 1.32 1996/01/07 21:29:47 mycroft Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *     notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *     notice, this list of conditions and the following disclaimer in the
                     14:  *     documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *     must display the following acknowledgement:
                     17:  *     This product includes software developed by Charles M. Hannum.
                     18:  * 4. The name of the author may not be used to endorse or promote products
                     19:  *     derived from this software without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <machine/i8259.h>
                     34: #include <dev/isa/isareg.h>
                     35:
                     36: #define MY_COUNT _C_LABEL(uvmexp)
                     37:
                     38: /*
                     39:  * Macros for interrupt entry, call to handler, and exit.
                     40:  *
                     41:  * XXX
                     42:  * The interrupt frame is set up to look like a trap frame.  This may be a
                     43:  * waste.  The only handler which needs a frame is the clock handler, and it
                     44:  * only needs a few bits.  Xdoreti() needs a trap frame for handling ASTs, but
                     45:  * it could easily convert the frame on demand.
                     46:  *
                     47:  * The direct costs of setting up a trap frame are two pushl's (error code and
                     48:  * trap number), an addl to get rid of these, and pushing and popping the
                     49:  * callee-saved registers %esi, %edi, %ebx, and %ebp twice.
                     50:  *
                     51:  * If the interrupt frame is made more flexible,  INTR can push %eax first and
                     52:  * decide the ipending case with less overhead, e.g., by avoiding loading the
                     53:  * segment registers.
                     54:  *
                     55:  * XXX
                     56:  * Should we do a cld on every system entry to avoid the requirement for
                     57:  * scattered cld's?
                     58:  */
                     59:
                     60:        .globl  _C_LABEL(isa_strayintr)
                     61:
                     62: #ifdef MULTIPROCESSOR
                     63: #define LOCK_KERNEL(ipl)       pushl ipl; call _C_LABEL(i386_intlock); addl $4,%esp
                     64: #define UNLOCK_KERNEL(ipl)     pushl ipl; call _C_LABEL(i386_intunlock); addl $4,%esp
                     65: #else
                     66: #define LOCK_KERNEL(ipl)
                     67: #define UNLOCK_KERNEL(ipl)
                     68: #endif
                     69:
                     70: #define voidop(num)
                     71:
                     72: /*
                     73:  * Normal vectors.
                     74:  *
                     75:  * We cdr down the intrhand chain, calling each handler with its appropriate
                     76:  * argument (0 meaning a pointer to the frame, for clock interrupts).
                     77:  *
                     78:  * The handler returns one of three values:
                     79:  *   0 - This interrupt wasn't for me.
                     80:  *   1 - This interrupt was for me.
                     81:  *  -1 - This interrupt might have been for me, but I don't know.
                     82:  * If there are no handlers, or they all return 0, we flag it as a `stray'
                     83:  * interrupt.  On a system with level-triggered interrupts, we could terminate
                     84:  * immediately when one of them returns 1; but this is a PC.
                     85:  *
                     86:  * On exit, we jump to Xdoreti(), to process soft interrupts and ASTs.
                     87:  */
                     88: #define        INTRSTUB(name, num, early_ack, late_ack, mask, unmask, level_mask) \
                     89: IDTVEC(resume_/**/name/**/num)                                         ;\
                     90:        push    %ebx                                                    ;\
                     91:        cli                                                             ;\
                     92:        jmp     1f                                                      ;\
                     93: IDTVEC(recurse_/**/name/**/num)                                                ;\
                     94:        pushfl                                                          ;\
                     95:        pushl   %cs                                                     ;\
                     96:        pushl   %esi                                                    ;\
                     97:        pushl   $0                      /* dummy error code */          ;\
                     98:        pushl   $T_ASTFLT               /* trap # for doing ASTs */     ;\
                     99:        movl    %ebx,%esi                                               ;\
                    100:        INTRENTRY                                                       ;\
                    101:        MAKE_FRAME                                                      ;\
                    102:        push    %esi                                                    ;\
                    103:        cli                                                             ;\
                    104:        jmp     1f                                                      ;\
                    105: _C_LABEL(Xintr_/**/name/**/num):                                       ;\
                    106:        pushl   $0                      /* dummy error code */          ;\
                    107:        pushl   $T_ASTFLT               /* trap # for doing ASTs */     ;\
                    108:        INTRENTRY                                                       ;\
                    109:        MAKE_FRAME                                                      ;\
                    110:        mask(num)                       /* mask it in hardware */       ;\
                    111:        early_ack(num)                  /* and allow other intrs */     ;\
                    112:        incl    MY_COUNT+V_INTR         /* statistical info */          ;\
                    113:        movl    _C_LABEL(iminlevel) + (num) * 4, %eax                   ;\
                    114:        movl    CPL,%ebx                                                ;\
                    115:        cmpl    %eax,%ebx                                               ;\
                    116:        jae     _C_LABEL(Xhold_/**/name/**/num)/* currently masked; hold it */;\
                    117:        pushl   %ebx                    /* cpl to restore on exit */    ;\
                    118: 1:                                                                     ;\
                    119:        movl    _C_LABEL(imaxlevel) + (num) * 4,%eax                    ;\
                    120:        movl    %eax,CPL                /* block enough for this irq */ ;\
                    121:        sti                             /* safe to take intrs now */    ;\
                    122:        movl    _C_LABEL(intrhand) + (num) * 4,%ebx     /* head of chain */ ;\
                    123:        testl   %ebx,%ebx                                               ;\
                    124:        jz      _C_LABEL(Xstray_/**/name/**/num)        /* no handlers; we're stray */  ;\
                    125:        STRAY_INITIALIZE                /* nobody claimed it yet */     ;\
                    126:        LOCK_KERNEL(IF_PPL(%esp))                                       ;\
                    127: 7:     movl    IH_ARG(%ebx),%eax       /* get handler arg */           ;\
                    128:        testl   %eax,%eax                                               ;\
                    129:        jnz     4f                                                      ;\
                    130:        movl    %esp,%eax               /* 0 means frame pointer */     ;\
                    131: 4:     pushl   %eax                                                    ;\
                    132:        call    *IH_FUN(%ebx)           /* call it */                   ;\
                    133:        addl    $4,%esp                 /* toss the arg */              ;\
                    134:        STRAY_INTEGRATE                 /* maybe he claimed it */       ;\
                    135:        orl     %eax,%eax               /* should it be counted? */     ;\
                    136:        jz      5f                      /* no, skip it */               ;\
                    137:        addl    $1,IH_COUNT(%ebx)       /* count the intrs */           ;\
                    138:        adcl    $0,IH_COUNT+4(%ebx)                                     ;\
                    139: 5:     movl    IH_NEXT(%ebx),%ebx      /* next handler in chain */     ;\
                    140:        testl   %ebx,%ebx                                               ;\
                    141:        jnz     7b                                                      ;\
                    142:        UNLOCK_KERNEL(IF_PPL(%esp))                                     ;\
                    143:        STRAY_TEST(name,num)            /* see if it's a stray */       ;\
                    144: 6:     unmask(num)                     /* unmask it in hardware */     ;\
                    145:        late_ack(num)                                                   ;\
                    146:        jmp     _C_LABEL(Xdoreti)       /* lower spl and do ASTs */     ;\
                    147: IDTVEC(stray_/**/name/**/num)                                          ;\
                    148:        pushl   $num                                                    ;\
                    149:        call    _C_LABEL(isa_strayintr)                                 ;\
                    150:        addl    $4,%esp                                                 ;\
                    151:        jmp     6b                                                      ;\
                    152: IDTVEC(hold_/**/name/**/num)                                           ;\
                    153:        orb     $IRQ_BIT(num),_C_LABEL(ipending) + IRQ_BYTE(num)        ;\
                    154:        INTRFASTEXIT
                    155:
                    156: #if defined(DEBUG)
                    157: #define        STRAY_INITIALIZE \
                    158:        xorl    %esi,%esi
                    159: #define        STRAY_INTEGRATE \
                    160:        orl     %eax,%esi
                    161: #define        STRAY_TEST(name,num) \
                    162:        testl   %esi,%esi                                               ;\
                    163:        jz      _C_LABEL(Xstray_/**/name/**/num)
                    164: #else /* !DEBUG */
                    165: #define        STRAY_INITIALIZE
                    166: #define        STRAY_INTEGRATE
                    167: #define        STRAY_TEST(name,num)
                    168: #endif /* DEBUG */
                    169:
                    170: #ifdef DDB
                    171: #define        MAKE_FRAME \
                    172:        leal    -8(%esp),%ebp
                    173: #else /* !DDB */
                    174: #define        MAKE_FRAME
                    175: #endif /* DDB */
                    176:
                    177: #define ICUADDR IO_ICU1
                    178:
                    179: INTRSTUB(legacy,0, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    180:     voidop)
                    181: INTRSTUB(legacy,1, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    182:     voidop)
                    183: INTRSTUB(legacy,2, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    184:     voidop)
                    185: INTRSTUB(legacy,3, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    186:     voidop)
                    187: INTRSTUB(legacy,4, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    188:     voidop)
                    189: INTRSTUB(legacy,5, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    190:     voidop)
                    191: INTRSTUB(legacy,6, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    192:     voidop)
                    193: INTRSTUB(legacy,7, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
                    194:     voidop)
                    195:
                    196: #undef ICUADDR
                    197: #define ICUADDR IO_ICU2
                    198:
                    199: INTRSTUB(legacy,8, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    200:     voidop)
                    201: INTRSTUB(legacy,9, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    202:     voidop)
                    203: INTRSTUB(legacy,10, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    204:     voidop)
                    205: INTRSTUB(legacy,11, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    206:     voidop)
                    207: INTRSTUB(legacy,12, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    208:     voidop)
                    209: INTRSTUB(legacy,13, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    210:     voidop)
                    211: INTRSTUB(legacy,14, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    212:     voidop)
                    213: INTRSTUB(legacy,15, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
                    214:     voidop)
                    215:
                    216: /*
                    217:  * These tables are used by the ISA configuration code.
                    218:  */
                    219: /* interrupt service routine entry points */
                    220: IDTVEC(intr)
                    221:        .long   _C_LABEL(Xintr_legacy0), _C_LABEL(Xintr_legacy1)
                    222:        .long   _C_LABEL(Xintr_legacy2), _C_LABEL(Xintr_legacy3)
                    223:        .long   _C_LABEL(Xintr_legacy4), _C_LABEL(Xintr_legacy5)
                    224:        .long   _C_LABEL(Xintr_legacy6), _C_LABEL(Xintr_legacy7)
                    225:        .long   _C_LABEL(Xintr_legacy8), _C_LABEL(Xintr_legacy9)
                    226:        .long   _C_LABEL(Xintr_legacy10), _C_LABEL(Xintr_legacy11)
                    227:        .long   _C_LABEL(Xintr_legacy12), _C_LABEL(Xintr_legacy13)
                    228:        .long   _C_LABEL(Xintr_legacy14), _C_LABEL(Xintr_legacy15)
                    229:
                    230: /*
                    231:  * These tables are used by Xdoreti() and Xspllower().
                    232:  */
                    233: /* resume points for suspended interrupts */
                    234: IDTVEC(resume)
                    235:        .long   _C_LABEL(Xresume_legacy0), _C_LABEL(Xresume_legacy1)
                    236:        .long   _C_LABEL(Xresume_legacy2), _C_LABEL(Xresume_legacy3)
                    237:        .long   _C_LABEL(Xresume_legacy4), _C_LABEL(Xresume_legacy5)
                    238:        .long   _C_LABEL(Xresume_legacy6), _C_LABEL(Xresume_legacy7)
                    239:        .long   _C_LABEL(Xresume_legacy8), _C_LABEL(Xresume_legacy9)
                    240:        .long   _C_LABEL(Xresume_legacy10), _C_LABEL(Xresume_legacy11)
                    241:        .long   _C_LABEL(Xresume_legacy12), _C_LABEL(Xresume_legacy13)
                    242:        .long   _C_LABEL(Xresume_legacy14), _C_LABEL(Xresume_legacy15)
                    243:        /* for soft interrupts */
                    244:        .long   0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                    245:        .long   _C_LABEL(Xsoftast), _C_LABEL(Xsofttty)
                    246:        .long   _C_LABEL(Xsoftnet), _C_LABEL(Xsoftclock)
                    247:        .long   0, 0
                    248: /* fake interrupts to resume from splx() */
                    249: IDTVEC(recurse)
                    250:        .long   _C_LABEL(Xrecurse_legacy0), _C_LABEL(Xrecurse_legacy1)
                    251:        .long   _C_LABEL(Xrecurse_legacy2), _C_LABEL(Xrecurse_legacy3)
                    252:        .long   _C_LABEL(Xrecurse_legacy4), _C_LABEL(Xrecurse_legacy5)
                    253:        .long   _C_LABEL(Xrecurse_legacy6), _C_LABEL(Xrecurse_legacy7)
                    254:        .long   _C_LABEL(Xrecurse_legacy8), _C_LABEL(Xrecurse_legacy9)
                    255:        .long   _C_LABEL(Xrecurse_legacy10), _C_LABEL(Xrecurse_legacy11)
                    256:        .long   _C_LABEL(Xrecurse_legacy12), _C_LABEL(Xrecurse_legacy13)
                    257:        .long   _C_LABEL(Xrecurse_legacy14), _C_LABEL(Xrecurse_legacy15)
                    258:        /* for soft interrupts */
                    259:        .long   0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                    260:        .long   _C_LABEL(Xsoftast), _C_LABEL(Xsofttty)
                    261:        .long   _C_LABEL(Xsoftnet), _C_LABEL(Xsoftclock)
                    262:        .long   0, 0

CVSweb