Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/smp/apic.c

    r99718a2e rd99c1d2  
    5353 * Advanced Programmable Interrupt Controller for SMP systems.
    5454 * Tested on:
    55  *    Bochs 2.0.2 - Bochs 2.2.6 with 2-8 CPUs
    56  *    Simics 2.0.28 - Simics 2.2.19 2-15 CPUs
    57  *    VMware Workstation 5.5 with 2 CPUs
    58  *    QEMU 0.8.0 with 2-15 CPUs
    59  *    ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs
    60  *    ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs
    61  *    MSI K7D Master-L with 2x 2100MHz Athlon MP CPUs
    62  *
     55 *      Bochs 2.0.2 - Bochs 2.2.6 with 2-8 CPUs
     56 *      Simics 2.0.28 - Simics 2.2.19 2-15 CPUs
     57 *      VMware Workstation 5.5 with 2 CPUs
     58 *      QEMU 0.8.0 with 2-15 CPUs
     59 *      ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs
     60 *      ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs
     61 *      MSI K7D Master-L with 2x 2100MHz Athlon MP CPUs
    6362 */
    6463
     
    7069 * optimize the code too much and accesses to l_apic and io_apic, that must
    7170 * always be 32-bit, would use byte oriented instructions.
    72  *
    7371 */
    7472volatile uint32_t *l_apic = (uint32_t *) 0xfee00000;
     
    7674
    7775uint32_t apic_id_mask = 0;
    78 uint8_t bsp_l_apic = 0;
    79 
    8076static irq_t l_apic_timer_irq;
    8177
     
    8379
    8480#ifdef LAPIC_VERBOSE
    85 static const char *delmod_str[] = {
     81static char *delmod_str[] = {
    8682        "Fixed",
    8783        "Lowest Priority",
     
    9490};
    9591
    96 static const char *destmod_str[] = {
     92static char *destmod_str[] = {
    9793        "Physical",
    9894        "Logical"
    9995};
    10096
    101 static const char *trigmod_str[] = {
     97static char *trigmod_str[] = {
    10298        "Edge",
    10399        "Level"
    104100};
    105101
    106 static const char *mask_str[] = {
     102static char *mask_str[] = {
    107103        "Unmasked",
    108104        "Masked"
    109105};
    110106
    111 static const char *delivs_str[] = {
     107static char *delivs_str[] = {
    112108        "Idle",
    113109        "Send Pending"
    114110};
    115111
    116 static const char *tm_mode_str[] = {
     112static char *tm_mode_str[] = {
    117113        "One-shot",
    118114        "Periodic"
    119115};
    120116
    121 static const char *intpol_str[] = {
     117static char *intpol_str[] = {
    122118        "Polarity High",
    123119        "Polarity Low"
     
    127123/** APIC spurious interrupt handler.
    128124 *
    129  * @param n      Interrupt vector.
     125 * @param n Interrupt vector.
    130126 * @param istate Interrupted state.
    131  *
    132  */
    133 static void apic_spurious(unsigned int n __attribute__((unused)),
    134     istate_t *istate __attribute__((unused)))
     127 */
     128static void apic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
    135129{
    136130#ifdef CONFIG_DEBUG
     
    151145         * irq->lock so we just unlock it and then lock it again.
    152146         */
    153         irq_spinlock_unlock(&irq->lock, false);
     147        spinlock_unlock(&irq->lock);
    154148        clock();
    155         irq_spinlock_lock(&irq->lock, false);
    156 }
    157 
    158 /** Get Local APIC ID.
    159  *
    160  * @return Local APIC ID.
    161  *
    162  */
    163 static uint8_t l_apic_id(void)
    164 {
    165         l_apic_id_t idreg;
    166        
    167         idreg.value = l_apic[L_APIC_ID];
    168         return idreg.apic_id;
     149        spinlock_lock(&irq->lock);
    169150}
    170151
     
    172153void apic_init(void)
    173154{
    174         exc_register(VECTOR_APIC_SPUR, "apic_spurious", false,
    175             (iroutine_t) apic_spurious);
    176        
     155        io_apic_id_t idreg;
     156       
     157        exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious);
     158
    177159        enable_irqs_function = io_apic_enable_irqs;
    178160        disable_irqs_function = io_apic_disable_irqs;
     
    197179        for (i = 0; i < IRQ_COUNT; i++) {
    198180                int pin;
    199                
     181       
    200182                if ((pin = smp_irq_to_pin(i)) != -1)
    201183                        io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI);
     
    205187         * Ensure that io_apic has unique ID.
    206188         */
    207         io_apic_id_t idreg;
    208        
    209189        idreg.value = io_apic_read(IOAPICID);
    210         if ((1 << idreg.apic_id) & apic_id_mask) {  /* See if IO APIC ID is used already */
     190        if ((1 << idreg.apic_id) & apic_id_mask) {      /* see if IO APIC ID is used already */
    211191                for (i = 0; i < APIC_ID_COUNT; i++) {
    212192                        if (!((1 << i) & apic_id_mask)) {
     
    217197                }
    218198        }
    219        
     199
    220200        /*
    221201         * Configure the BSP's lapic.
    222202         */
    223203        l_apic_init();
    224         l_apic_debug();
    225        
    226         bsp_l_apic = l_apic_id();
     204
     205        l_apic_debug();
    227206}
    228207
     
    232211 *
    233212 * @return 0 on error, 1 on success.
    234  *
    235213 */
    236214int apic_poll_errors(void)
     
    254232        if (esr.illegal_register_address)
    255233                printf("Illegal Register Address\n");
    256        
     234
    257235        return !esr.err_bitmap;
    258236}
     
    263241 *
    264242 * @return 0 on failure, 1 on success.
    265  *
    266243 */
    267244int l_apic_broadcast_custom_ipi(uint8_t vector)
    268245{
    269246        icr_t icr;
    270        
     247
    271248        icr.lo = l_apic[ICRlo];
    272249        icr.delmod = DELMOD_FIXED;
     
    276253        icr.trigger_mode = TRIGMOD_LEVEL;
    277254        icr.vector = vector;
    278        
     255
    279256        l_apic[ICRlo] = icr.lo;
    280        
     257
    281258        icr.lo = l_apic[ICRlo];
    282259        if (icr.delivs == DELIVS_PENDING) {
     
    285262#endif
    286263        }
    287        
     264
    288265        return apic_poll_errors();
    289266}
     
    294271 *
    295272 * @return 0 on failure, 1 on success.
    296  *
    297273 */
    298274int l_apic_send_init_ipi(uint8_t apicid)
    299275{
     276        icr_t icr;
     277        int i;
     278
    300279        /*
    301280         * Read the ICR register in and zero all non-reserved fields.
    302281         */
    303         icr_t icr;
    304        
    305282        icr.lo = l_apic[ICRlo];
    306283        icr.hi = l_apic[ICRhi];
     
    316293        l_apic[ICRhi] = icr.hi;
    317294        l_apic[ICRlo] = icr.lo;
    318        
     295
    319296        /*
    320297         * According to MP Specification, 20us should be enough to
     
    322299         */
    323300        delay(20);
    324        
     301
    325302        if (!apic_poll_errors())
    326303                return 0;
    327        
     304
    328305        icr.lo = l_apic[ICRlo];
    329306        if (icr.delivs == DELIVS_PENDING) {
     
    332309#endif
    333310        }
    334        
     311
    335312        icr.delmod = DELMOD_INIT;
    336313        icr.destmod = DESTMOD_PHYS;
     
    340317        icr.vector = 0;
    341318        l_apic[ICRlo] = icr.lo;
    342        
     319
    343320        /*
    344321         * Wait 10ms as MP Specification specifies.
    345322         */
    346323        delay(10000);
    347        
     324
    348325        if (!is_82489DX_apic(l_apic[LAVR])) {
    349326                /*
    350327                 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
    351328                 */
    352                 unsigned int i;
    353                 for (i = 0; i < 2; i++) {
     329                for (i = 0; i<2; i++) {
    354330                        icr.lo = l_apic[ICRlo];
    355331                        icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */
     
    370346void l_apic_init(void)
    371347{
     348        lvt_error_t error;
     349        lvt_lint_t lint;
     350        tpr_t tpr;
     351        svr_t svr;
     352        icr_t icr;
     353        tdcr_t tdcr;
     354        lvt_tm_t tm;
     355        ldr_t ldr;
     356        dfr_t dfr;
     357        uint32_t t1, t2;
     358
    372359        /* Initialize LVT Error register. */
    373         lvt_error_t error;
    374        
    375360        error.value = l_apic[LVT_Err];
    376361        error.masked = true;
    377362        l_apic[LVT_Err] = error.value;
    378        
     363
    379364        /* Initialize LVT LINT0 register. */
    380         lvt_lint_t lint;
    381        
    382365        lint.value = l_apic[LVT_LINT0];
    383366        lint.masked = true;
    384367        l_apic[LVT_LINT0] = lint.value;
    385        
     368
    386369        /* Initialize LVT LINT1 register. */
    387370        lint.value = l_apic[LVT_LINT1];
    388371        lint.masked = true;
    389372        l_apic[LVT_LINT1] = lint.value;
    390        
     373
    391374        /* Task Priority Register initialization. */
    392         tpr_t tpr;
    393        
    394375        tpr.value = l_apic[TPR];
    395376        tpr.pri_sc = 0;
     
    398379       
    399380        /* Spurious-Interrupt Vector Register initialization. */
    400         svr_t svr;
    401        
    402381        svr.value = l_apic[SVR];
    403382        svr.vector = VECTOR_APIC_SPUR;
     
    405384        svr.focus_checking = true;
    406385        l_apic[SVR] = svr.value;
    407        
     386
    408387        if (CPU->arch.family >= 6)
    409388                enable_l_apic_in_msr();
    410389       
    411390        /* Interrupt Command Register initialization. */
    412         icr_t icr;
    413        
    414391        icr.lo = l_apic[ICRlo];
    415392        icr.delmod = DELMOD_INIT;
     
    421398       
    422399        /* Timer Divide Configuration Register initialization. */
    423         tdcr_t tdcr;
    424        
    425400        tdcr.value = l_apic[TDCR];
    426401        tdcr.div_value = DIVIDE_1;
    427402        l_apic[TDCR] = tdcr.value;
    428        
     403
    429404        /* Program local timer. */
    430         lvt_tm_t tm;
    431        
    432405        tm.value = l_apic[LVT_Tm];
    433406        tm.vector = VECTOR_CLK;
     
    435408        tm.masked = false;
    436409        l_apic[LVT_Tm] = tm.value;
    437        
     410
    438411        /*
    439412         * Measure and configure the timer to generate timer
    440413         * interrupt with period 1s/HZ seconds.
    441414         */
    442         uint32_t t1 = l_apic[CCRT];
     415        t1 = l_apic[CCRT];
    443416        l_apic[ICRT] = 0xffffffff;
    444        
    445         while (l_apic[CCRT] == t1);
    446        
     417
     418        while (l_apic[CCRT] == t1)
     419                ;
     420               
    447421        t1 = l_apic[CCRT];
    448         delay(1000000 / HZ);
    449         uint32_t t2 = l_apic[CCRT];
    450        
    451         l_apic[ICRT] = t1 - t2;
     422        delay(1000000/HZ);
     423        t2 = l_apic[CCRT];
     424       
     425        l_apic[ICRT] = t1-t2;
    452426       
    453427        /* Program Logical Destination Register. */
    454         ASSERT(CPU->id < 8);
    455         ldr_t ldr;
    456        
     428        ASSERT(CPU->id < 8)
    457429        ldr.value = l_apic[LDR];
    458430        ldr.id = (uint8_t) (1 << CPU->id);
     
    460432       
    461433        /* Program Destination Format Register for Flat mode. */
    462         dfr_t dfr;
    463        
    464434        dfr.value = l_apic[DFR];
    465435        dfr.model = MODEL_FLAT;
     
    477447{
    478448#ifdef LAPIC_VERBOSE
    479         printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n",
    480             CPU->id, l_apic_id());
    481        
    482449        lvt_tm_t tm;
     450        lvt_lint_t lint;
     451        lvt_error_t error;     
     452       
     453        printf("LVT on cpu%d, LAPIC ID: %d\n", CPU->id, l_apic_id());
     454
    483455        tm.value = l_apic[LVT_Tm];
    484         printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n",
    485             tm.vector, delivs_str[tm.delivs], mask_str[tm.masked],
    486             tm_mode_str[tm.mode]);
    487        
    488         lvt_lint_t lint;
     456        printf("LVT Tm: vector=%hhd, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]);
    489457        lint.value = l_apic[LVT_LINT0];
    490         printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
    491             tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
    492             intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
    493             mask_str[lint.masked]);
    494        
    495         lint.value = l_apic[LVT_LINT1];
    496         printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
    497             tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
    498             intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
    499             mask_str[lint.masked]);
    500        
    501         lvt_error_t error;
     458        printf("LVT LINT0: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]);
     459        lint.value = l_apic[LVT_LINT1];
     460        printf("LVT LINT1: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]); 
    502461        error.value = l_apic[LVT_Err];
    503         printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
    504             delivs_str[error.delivs], mask_str[error.masked]);
     462        printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]);
    505463#endif
    506464}
    507465
     466/** Get Local APIC ID.
     467 *
     468 * @return Local APIC ID.
     469 */
     470uint8_t l_apic_id(void)
     471{
     472        l_apic_id_t idreg;
     473       
     474        idreg.value = l_apic[L_APIC_ID];
     475        return idreg.apic_id;
     476}
     477
    508478/** Read from IO APIC register.
    509479 *
     
    511481 *
    512482 * @return Content of the addressed IO APIC register.
    513  *
    514483 */
    515484uint32_t io_apic_read(uint8_t address)
     
    526495 *
    527496 * @param address IO APIC register address.
    528  * @param val     Content to be written to the addressed IO APIC register.
    529  *
    530  */
    531 void io_apic_write(uint8_t address, uint32_t val)
     497 * @param x Content to be written to the addressed IO APIC register.
     498 */
     499void io_apic_write(uint8_t address, uint32_t x)
    532500{
    533501        io_regsel_t regsel;
     
    536504        regsel.reg_addr = address;
    537505        io_apic[IOREGSEL] = regsel.value;
    538         io_apic[IOWIN] = val;
     506        io_apic[IOWIN] = x;
    539507}
    540508
    541509/** Change some attributes of one item in I/O Redirection Table.
    542510 *
    543  * @param pin   IO APIC pin number.
    544  * @param dest  Interrupt destination address.
    545  * @param vec  Interrupt vector to trigger.
     511 * @param pin IO APIC pin number.
     512 * @param dest Interrupt destination address.
     513 * @param v Interrupt vector to trigger.
    546514 * @param flags Flags.
    547  *
    548  */
    549 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec,
    550     unsigned int flags)
    551 {
    552         unsigned int dlvr;
     515 */
     516void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t v, int flags)
     517{
     518        io_redirection_reg_t reg;
     519        int dlvr = DELMOD_FIXED;
    553520       
    554521        if (flags & LOPRI)
    555522                dlvr = DELMOD_LOWPRI;
    556         else
    557                 dlvr = DELMOD_FIXED;
    558        
    559         io_redirection_reg_t reg;
     523
    560524        reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    561525        reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1));
     
    566530        reg.intpol = POLARITY_HIGH;
    567531        reg.delmod = dlvr;
    568         reg.intvec = vec;
    569        
     532        reg.intvec = v;
     533
    570534        io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
    571535        io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi);
     
    575539 *
    576540 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
    577  *
    578541 */
    579542void io_apic_disable_irqs(uint16_t irqmask)
    580543{
     544        io_redirection_reg_t reg;
    581545        unsigned int i;
     546        int pin;
     547       
    582548        for (i = 0; i < 16; i++) {
    583549                if (irqmask & (1 << i)) {
     
    586552                         * mapping for the respective IRQ number.
    587553                         */
    588                         int pin = smp_irq_to_pin(i);
     554                        pin = smp_irq_to_pin(i);
    589555                        if (pin != -1) {
    590                                 io_redirection_reg_t reg;
    591                                
    592556                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    593557                                reg.masked = true;
     
    602566 *
    603567 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
    604  *
    605568 */
    606569void io_apic_enable_irqs(uint16_t irqmask)
    607570{
    608571        unsigned int i;
     572        int pin;
     573        io_redirection_reg_t reg;       
     574       
    609575        for (i = 0; i < 16; i++) {
    610576                if (irqmask & (1 << i)) {
     
    613579                         * mapping for the respective IRQ number.
    614580                         */
    615                         int pin = smp_irq_to_pin(i);
     581                        pin = smp_irq_to_pin(i);
    616582                        if (pin != -1) {
    617                                 io_redirection_reg_t reg;
    618                                
    619583                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    620584                                reg.masked = false;
Note: See TracChangeset for help on using the changeset viewer.