Ignore:
File:
1 edited

Legend:

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

    rd99c1d2 r99718a2e  
    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
     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 *
    6263 */
    6364
     
    6970 * optimize the code too much and accesses to l_apic and io_apic, that must
    7071 * always be 32-bit, would use byte oriented instructions.
     72 *
    7173 */
    7274volatile uint32_t *l_apic = (uint32_t *) 0xfee00000;
     
    7476
    7577uint32_t apic_id_mask = 0;
     78uint8_t bsp_l_apic = 0;
     79
    7680static irq_t l_apic_timer_irq;
    7781
     
    7983
    8084#ifdef LAPIC_VERBOSE
    81 static char *delmod_str[] = {
     85static const char *delmod_str[] = {
    8286        "Fixed",
    8387        "Lowest Priority",
     
    9094};
    9195
    92 static char *destmod_str[] = {
     96static const char *destmod_str[] = {
    9397        "Physical",
    9498        "Logical"
    9599};
    96100
    97 static char *trigmod_str[] = {
     101static const char *trigmod_str[] = {
    98102        "Edge",
    99103        "Level"
    100104};
    101105
    102 static char *mask_str[] = {
     106static const char *mask_str[] = {
    103107        "Unmasked",
    104108        "Masked"
    105109};
    106110
    107 static char *delivs_str[] = {
     111static const char *delivs_str[] = {
    108112        "Idle",
    109113        "Send Pending"
    110114};
    111115
    112 static char *tm_mode_str[] = {
     116static const char *tm_mode_str[] = {
    113117        "One-shot",
    114118        "Periodic"
    115119};
    116120
    117 static char *intpol_str[] = {
     121static const char *intpol_str[] = {
    118122        "Polarity High",
    119123        "Polarity Low"
     
    123127/** APIC spurious interrupt handler.
    124128 *
    125  * @param n Interrupt vector.
     129 * @param n      Interrupt vector.
    126130 * @param istate Interrupted state.
    127  */
    128 static void apic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
     131 *
     132 */
     133static void apic_spurious(unsigned int n __attribute__((unused)),
     134    istate_t *istate __attribute__((unused)))
    129135{
    130136#ifdef CONFIG_DEBUG
     
    145151         * irq->lock so we just unlock it and then lock it again.
    146152         */
    147         spinlock_unlock(&irq->lock);
     153        irq_spinlock_unlock(&irq->lock, false);
    148154        clock();
    149         spinlock_lock(&irq->lock);
     155        irq_spinlock_lock(&irq->lock, false);
     156}
     157
     158/** Get Local APIC ID.
     159 *
     160 * @return Local APIC ID.
     161 *
     162 */
     163static 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;
    150169}
    151170
     
    153172void apic_init(void)
    154173{
    155         io_apic_id_t idreg;
    156        
    157         exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious);
    158 
     174        exc_register(VECTOR_APIC_SPUR, "apic_spurious", false,
     175            (iroutine_t) apic_spurious);
     176       
    159177        enable_irqs_function = io_apic_enable_irqs;
    160178        disable_irqs_function = io_apic_disable_irqs;
     
    179197        for (i = 0; i < IRQ_COUNT; i++) {
    180198                int pin;
    181        
     199               
    182200                if ((pin = smp_irq_to_pin(i)) != -1)
    183201                        io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI);
     
    187205         * Ensure that io_apic has unique ID.
    188206         */
     207        io_apic_id_t idreg;
     208       
    189209        idreg.value = io_apic_read(IOAPICID);
    190         if ((1 << idreg.apic_id) & apic_id_mask) {      /* see if IO APIC ID is used already */
     210        if ((1 << idreg.apic_id) & apic_id_mask) {  /* See if IO APIC ID is used already */
    191211                for (i = 0; i < APIC_ID_COUNT; i++) {
    192212                        if (!((1 << i) & apic_id_mask)) {
     
    197217                }
    198218        }
    199 
     219       
    200220        /*
    201221         * Configure the BSP's lapic.
    202222         */
    203223        l_apic_init();
    204 
    205         l_apic_debug();
     224        l_apic_debug();
     225       
     226        bsp_l_apic = l_apic_id();
    206227}
    207228
     
    211232 *
    212233 * @return 0 on error, 1 on success.
     234 *
    213235 */
    214236int apic_poll_errors(void)
     
    232254        if (esr.illegal_register_address)
    233255                printf("Illegal Register Address\n");
    234 
     256       
    235257        return !esr.err_bitmap;
    236258}
     
    241263 *
    242264 * @return 0 on failure, 1 on success.
     265 *
    243266 */
    244267int l_apic_broadcast_custom_ipi(uint8_t vector)
    245268{
    246269        icr_t icr;
    247 
     270       
    248271        icr.lo = l_apic[ICRlo];
    249272        icr.delmod = DELMOD_FIXED;
     
    253276        icr.trigger_mode = TRIGMOD_LEVEL;
    254277        icr.vector = vector;
    255 
     278       
    256279        l_apic[ICRlo] = icr.lo;
    257 
     280       
    258281        icr.lo = l_apic[ICRlo];
    259282        if (icr.delivs == DELIVS_PENDING) {
     
    262285#endif
    263286        }
    264 
     287       
    265288        return apic_poll_errors();
    266289}
     
    271294 *
    272295 * @return 0 on failure, 1 on success.
     296 *
    273297 */
    274298int l_apic_send_init_ipi(uint8_t apicid)
    275299{
     300        /*
     301         * Read the ICR register in and zero all non-reserved fields.
     302         */
    276303        icr_t icr;
    277         int i;
    278 
    279         /*
    280          * Read the ICR register in and zero all non-reserved fields.
    281          */
     304       
    282305        icr.lo = l_apic[ICRlo];
    283306        icr.hi = l_apic[ICRhi];
     
    293316        l_apic[ICRhi] = icr.hi;
    294317        l_apic[ICRlo] = icr.lo;
    295 
     318       
    296319        /*
    297320         * According to MP Specification, 20us should be enough to
     
    299322         */
    300323        delay(20);
    301 
     324       
    302325        if (!apic_poll_errors())
    303326                return 0;
    304 
     327       
    305328        icr.lo = l_apic[ICRlo];
    306329        if (icr.delivs == DELIVS_PENDING) {
     
    309332#endif
    310333        }
    311 
     334       
    312335        icr.delmod = DELMOD_INIT;
    313336        icr.destmod = DESTMOD_PHYS;
     
    317340        icr.vector = 0;
    318341        l_apic[ICRlo] = icr.lo;
    319 
     342       
    320343        /*
    321344         * Wait 10ms as MP Specification specifies.
    322345         */
    323346        delay(10000);
    324 
     347       
    325348        if (!is_82489DX_apic(l_apic[LAVR])) {
    326349                /*
    327350                 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
    328351                 */
    329                 for (i = 0; i<2; i++) {
     352                unsigned int i;
     353                for (i = 0; i < 2; i++) {
    330354                        icr.lo = l_apic[ICRlo];
    331355                        icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */
     
    346370void l_apic_init(void)
    347371{
     372        /* Initialize LVT Error register. */
    348373        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 
    359         /* Initialize LVT Error register. */
     374       
    360375        error.value = l_apic[LVT_Err];
    361376        error.masked = true;
    362377        l_apic[LVT_Err] = error.value;
    363 
     378       
    364379        /* Initialize LVT LINT0 register. */
     380        lvt_lint_t lint;
     381       
    365382        lint.value = l_apic[LVT_LINT0];
    366383        lint.masked = true;
    367384        l_apic[LVT_LINT0] = lint.value;
    368 
     385       
    369386        /* Initialize LVT LINT1 register. */
    370387        lint.value = l_apic[LVT_LINT1];
    371388        lint.masked = true;
    372389        l_apic[LVT_LINT1] = lint.value;
    373 
     390       
    374391        /* Task Priority Register initialization. */
     392        tpr_t tpr;
     393       
    375394        tpr.value = l_apic[TPR];
    376395        tpr.pri_sc = 0;
     
    379398       
    380399        /* Spurious-Interrupt Vector Register initialization. */
     400        svr_t svr;
     401       
    381402        svr.value = l_apic[SVR];
    382403        svr.vector = VECTOR_APIC_SPUR;
     
    384405        svr.focus_checking = true;
    385406        l_apic[SVR] = svr.value;
    386 
     407       
    387408        if (CPU->arch.family >= 6)
    388409                enable_l_apic_in_msr();
    389410       
    390411        /* Interrupt Command Register initialization. */
     412        icr_t icr;
     413       
    391414        icr.lo = l_apic[ICRlo];
    392415        icr.delmod = DELMOD_INIT;
     
    398421       
    399422        /* Timer Divide Configuration Register initialization. */
     423        tdcr_t tdcr;
     424       
    400425        tdcr.value = l_apic[TDCR];
    401426        tdcr.div_value = DIVIDE_1;
    402427        l_apic[TDCR] = tdcr.value;
    403 
     428       
    404429        /* Program local timer. */
     430        lvt_tm_t tm;
     431       
    405432        tm.value = l_apic[LVT_Tm];
    406433        tm.vector = VECTOR_CLK;
     
    408435        tm.masked = false;
    409436        l_apic[LVT_Tm] = tm.value;
    410 
     437       
    411438        /*
    412439         * Measure and configure the timer to generate timer
    413440         * interrupt with period 1s/HZ seconds.
    414441         */
     442        uint32_t t1 = l_apic[CCRT];
     443        l_apic[ICRT] = 0xffffffff;
     444       
     445        while (l_apic[CCRT] == t1);
     446       
    415447        t1 = l_apic[CCRT];
    416         l_apic[ICRT] = 0xffffffff;
    417 
    418         while (l_apic[CCRT] == t1)
    419                 ;
    420                
    421         t1 = l_apic[CCRT];
    422         delay(1000000/HZ);
    423         t2 = l_apic[CCRT];
    424        
    425         l_apic[ICRT] = t1-t2;
     448        delay(1000000 / HZ);
     449        uint32_t t2 = l_apic[CCRT];
     450       
     451        l_apic[ICRT] = t1 - t2;
    426452       
    427453        /* Program Logical Destination Register. */
    428         ASSERT(CPU->id < 8)
     454        ASSERT(CPU->id < 8);
     455        ldr_t ldr;
     456       
    429457        ldr.value = l_apic[LDR];
    430458        ldr.id = (uint8_t) (1 << CPU->id);
     
    432460       
    433461        /* Program Destination Format Register for Flat mode. */
     462        dfr_t dfr;
     463       
    434464        dfr.value = l_apic[DFR];
    435465        dfr.model = MODEL_FLAT;
     
    447477{
    448478#ifdef LAPIC_VERBOSE
     479        printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n",
     480            CPU->id, l_apic_id());
     481       
    449482        lvt_tm_t tm;
     483        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       
    450488        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 
    455         tm.value = l_apic[LVT_Tm];
    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]);
    457489        lint.value = l_apic[LVT_LINT0];
    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]); 
     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;
    461502        error.value = l_apic[LVT_Err];
    462         printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]);
     503        printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
     504            delivs_str[error.delivs], mask_str[error.masked]);
    463505#endif
    464506}
    465507
    466 /** Get Local APIC ID.
    467  *
    468  * @return Local APIC ID.
    469  */
    470 uint8_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 
    478508/** Read from IO APIC register.
    479509 *
     
    481511 *
    482512 * @return Content of the addressed IO APIC register.
     513 *
    483514 */
    484515uint32_t io_apic_read(uint8_t address)
     
    495526 *
    496527 * @param address IO APIC register address.
    497  * @param x Content to be written to the addressed IO APIC register.
    498  */
    499 void io_apic_write(uint8_t address, uint32_t x)
     528 * @param val     Content to be written to the addressed IO APIC register.
     529 *
     530 */
     531void io_apic_write(uint8_t address, uint32_t val)
    500532{
    501533        io_regsel_t regsel;
     
    504536        regsel.reg_addr = address;
    505537        io_apic[IOREGSEL] = regsel.value;
    506         io_apic[IOWIN] = x;
     538        io_apic[IOWIN] = val;
    507539}
    508540
    509541/** Change some attributes of one item in I/O Redirection Table.
    510542 *
    511  * @param pin IO APIC pin number.
    512  * @param dest Interrupt destination address.
    513  * @param v Interrupt vector to trigger.
     543 * @param pin   IO APIC pin number.
     544 * @param dest  Interrupt destination address.
     545 * @param vec  Interrupt vector to trigger.
    514546 * @param flags Flags.
    515  */
    516 void 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;
     547 *
     548 */
     549void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec,
     550    unsigned int flags)
     551{
     552        unsigned int dlvr;
    520553       
    521554        if (flags & LOPRI)
    522555                dlvr = DELMOD_LOWPRI;
    523 
     556        else
     557                dlvr = DELMOD_FIXED;
     558       
     559        io_redirection_reg_t reg;
    524560        reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    525561        reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1));
     
    530566        reg.intpol = POLARITY_HIGH;
    531567        reg.delmod = dlvr;
    532         reg.intvec = v;
    533 
     568        reg.intvec = vec;
     569       
    534570        io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
    535571        io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi);
     
    539575 *
    540576 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
     577 *
    541578 */
    542579void io_apic_disable_irqs(uint16_t irqmask)
    543580{
    544         io_redirection_reg_t reg;
    545581        unsigned int i;
    546         int pin;
    547        
    548582        for (i = 0; i < 16; i++) {
    549583                if (irqmask & (1 << i)) {
     
    552586                         * mapping for the respective IRQ number.
    553587                         */
    554                         pin = smp_irq_to_pin(i);
     588                        int pin = smp_irq_to_pin(i);
    555589                        if (pin != -1) {
     590                                io_redirection_reg_t reg;
     591                               
    556592                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    557593                                reg.masked = true;
     
    566602 *
    567603 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
     604 *
    568605 */
    569606void io_apic_enable_irqs(uint16_t irqmask)
    570607{
    571608        unsigned int i;
    572         int pin;
    573         io_redirection_reg_t reg;       
    574        
    575609        for (i = 0; i < 16; i++) {
    576610                if (irqmask & (1 << i)) {
     
    579613                         * mapping for the respective IRQ number.
    580614                         */
    581                         pin = smp_irq_to_pin(i);
     615                        int pin = smp_irq_to_pin(i);
    582616                        if (pin != -1) {
     617                                io_redirection_reg_t reg;
     618                               
    583619                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    584620                                reg.masked = false;
Note: See TracChangeset for help on using the changeset viewer.