Ignore:
File:
1 edited

Legend:

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

    racc7ce4 r84afc7b  
    3333 */
    3434
    35 #include <typedefs.h>
     35#include <arch/types.h>
    3636#include <arch/smp/apic.h>
    3737#include <arch/smp/ap.h>
     
    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  *
    73  */
    74 volatile uint32_t *l_apic = (uint32_t *) UINT32_C(0xfee00000);
    75 volatile uint32_t *io_apic = (uint32_t *) UINT32_C(0xfec00000);
     71 */
     72volatile uint32_t *l_apic = (uint32_t *) 0xfee00000;
     73volatile uint32_t *io_apic = (uint32_t *) 0xfec00000;
    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;
    179161        eoi_function = l_apic_eoi;
    180         irqs_info = "apic";
    181162       
    182163        /*
     
    185166         * Other interrupts will be forwarded to the lowest priority CPU.
    186167         */
    187         io_apic_disable_irqs(0xffffU);
     168        io_apic_disable_irqs(0xffff);
    188169       
    189170        irq_initialize(&l_apic_timer_irq);
     
    198179        for (i = 0; i < IRQ_COUNT; i++) {
    199180                int pin;
    200                
     181       
    201182                if ((pin = smp_irq_to_pin(i)) != -1)
    202183                        io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI);
     
    206187         * Ensure that io_apic has unique ID.
    207188         */
    208         io_apic_id_t idreg;
    209        
    210189        idreg.value = io_apic_read(IOAPICID);
    211         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 */
    212191                for (i = 0; i < APIC_ID_COUNT; i++) {
    213192                        if (!((1 << i) & apic_id_mask)) {
     
    218197                }
    219198        }
    220        
     199
    221200        /*
    222201         * Configure the BSP's lapic.
    223202         */
    224203        l_apic_init();
    225         l_apic_debug();
    226        
    227         bsp_l_apic = l_apic_id();
     204
     205        l_apic_debug();
    228206}
    229207
     
    233211 *
    234212 * @return 0 on error, 1 on success.
    235  *
    236213 */
    237214int apic_poll_errors(void)
     
    255232        if (esr.illegal_register_address)
    256233                printf("Illegal Register Address\n");
    257        
     234
    258235        return !esr.err_bitmap;
    259236}
     
    264241 *
    265242 * @return 0 on failure, 1 on success.
    266  *
    267243 */
    268244int l_apic_broadcast_custom_ipi(uint8_t vector)
    269245{
    270246        icr_t icr;
    271        
     247
    272248        icr.lo = l_apic[ICRlo];
    273249        icr.delmod = DELMOD_FIXED;
     
    277253        icr.trigger_mode = TRIGMOD_LEVEL;
    278254        icr.vector = vector;
    279        
     255
    280256        l_apic[ICRlo] = icr.lo;
    281        
     257
    282258        icr.lo = l_apic[ICRlo];
    283259        if (icr.delivs == DELIVS_PENDING) {
     
    286262#endif
    287263        }
    288        
     264
    289265        return apic_poll_errors();
    290266}
     
    295271 *
    296272 * @return 0 on failure, 1 on success.
    297  *
    298273 */
    299274int l_apic_send_init_ipi(uint8_t apicid)
    300275{
     276        icr_t icr;
     277        int i;
     278
    301279        /*
    302280         * Read the ICR register in and zero all non-reserved fields.
    303281         */
    304         icr_t icr;
    305        
    306282        icr.lo = l_apic[ICRlo];
    307283        icr.hi = l_apic[ICRhi];
     
    317293        l_apic[ICRhi] = icr.hi;
    318294        l_apic[ICRlo] = icr.lo;
    319        
     295
    320296        /*
    321297         * According to MP Specification, 20us should be enough to
     
    323299         */
    324300        delay(20);
    325        
     301
    326302        if (!apic_poll_errors())
    327303                return 0;
    328        
     304
    329305        icr.lo = l_apic[ICRlo];
    330306        if (icr.delivs == DELIVS_PENDING) {
     
    333309#endif
    334310        }
    335        
     311
    336312        icr.delmod = DELMOD_INIT;
    337313        icr.destmod = DESTMOD_PHYS;
     
    341317        icr.vector = 0;
    342318        l_apic[ICRlo] = icr.lo;
    343        
     319
    344320        /*
    345321         * Wait 10ms as MP Specification specifies.
    346322         */
    347323        delay(10000);
    348        
     324
    349325        if (!is_82489DX_apic(l_apic[LAVR])) {
    350326                /*
    351327                 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
    352328                 */
    353                 unsigned int i;
    354                 for (i = 0; i < 2; i++) {
     329                for (i = 0; i<2; i++) {
    355330                        icr.lo = l_apic[ICRlo];
    356331                        icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */
     
    371346void l_apic_init(void)
    372347{
     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
    373359        /* Initialize LVT Error register. */
    374         lvt_error_t error;
    375        
    376360        error.value = l_apic[LVT_Err];
    377361        error.masked = true;
    378362        l_apic[LVT_Err] = error.value;
    379        
     363
    380364        /* Initialize LVT LINT0 register. */
    381         lvt_lint_t lint;
    382        
    383365        lint.value = l_apic[LVT_LINT0];
    384366        lint.masked = true;
    385367        l_apic[LVT_LINT0] = lint.value;
    386        
     368
    387369        /* Initialize LVT LINT1 register. */
    388370        lint.value = l_apic[LVT_LINT1];
    389371        lint.masked = true;
    390372        l_apic[LVT_LINT1] = lint.value;
    391        
     373
    392374        /* Task Priority Register initialization. */
    393         tpr_t tpr;
    394        
    395375        tpr.value = l_apic[TPR];
    396376        tpr.pri_sc = 0;
     
    399379       
    400380        /* Spurious-Interrupt Vector Register initialization. */
    401         svr_t svr;
    402        
    403381        svr.value = l_apic[SVR];
    404382        svr.vector = VECTOR_APIC_SPUR;
     
    406384        svr.focus_checking = true;
    407385        l_apic[SVR] = svr.value;
    408        
     386
    409387        if (CPU->arch.family >= 6)
    410388                enable_l_apic_in_msr();
    411389       
    412390        /* Interrupt Command Register initialization. */
    413         icr_t icr;
    414        
    415391        icr.lo = l_apic[ICRlo];
    416392        icr.delmod = DELMOD_INIT;
     
    422398       
    423399        /* Timer Divide Configuration Register initialization. */
    424         tdcr_t tdcr;
    425        
    426400        tdcr.value = l_apic[TDCR];
    427401        tdcr.div_value = DIVIDE_1;
    428402        l_apic[TDCR] = tdcr.value;
    429        
     403
    430404        /* Program local timer. */
    431         lvt_tm_t tm;
    432        
    433405        tm.value = l_apic[LVT_Tm];
    434406        tm.vector = VECTOR_CLK;
     
    436408        tm.masked = false;
    437409        l_apic[LVT_Tm] = tm.value;
    438        
     410
    439411        /*
    440412         * Measure and configure the timer to generate timer
    441413         * interrupt with period 1s/HZ seconds.
    442414         */
    443         uint32_t t1 = l_apic[CCRT];
     415        t1 = l_apic[CCRT];
    444416        l_apic[ICRT] = 0xffffffff;
    445        
    446         while (l_apic[CCRT] == t1);
    447        
     417
     418        while (l_apic[CCRT] == t1)
     419                ;
     420               
    448421        t1 = l_apic[CCRT];
    449         delay(1000000 / HZ);
    450         uint32_t t2 = l_apic[CCRT];
    451        
    452         l_apic[ICRT] = t1 - t2;
     422        delay(1000000/HZ);
     423        t2 = l_apic[CCRT];
     424       
     425        l_apic[ICRT] = t1-t2;
    453426       
    454427        /* Program Logical Destination Register. */
    455         ASSERT(CPU->id < 8);
    456         ldr_t ldr;
    457        
     428        ASSERT(CPU->id < 8)
    458429        ldr.value = l_apic[LDR];
    459430        ldr.id = (uint8_t) (1 << CPU->id);
     
    461432       
    462433        /* Program Destination Format Register for Flat mode. */
    463         dfr_t dfr;
    464        
    465434        dfr.value = l_apic[DFR];
    466435        dfr.model = MODEL_FLAT;
     
    478447{
    479448#ifdef LAPIC_VERBOSE
    480         printf("LVT on cpu%u, LAPIC ID: %" PRIu8 "\n",
    481             CPU->id, l_apic_id());
    482        
    483449        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
    484455        tm.value = l_apic[LVT_Tm];
    485         printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n",
    486             tm.vector, delivs_str[tm.delivs], mask_str[tm.masked],
    487             tm_mode_str[tm.mode]);
    488        
    489         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]);
    490457        lint.value = l_apic[LVT_LINT0];
    491         printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
    492             tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
    493             intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
    494             mask_str[lint.masked]);
    495        
    496         lint.value = l_apic[LVT_LINT1];
    497         printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
    498             tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
    499             intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
    500             mask_str[lint.masked]);
    501        
    502         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]); 
    503461        error.value = l_apic[LVT_Err];
    504         printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
    505             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]);
    506463#endif
    507464}
    508465
     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
    509478/** Read from IO APIC register.
    510479 *
     
    512481 *
    513482 * @return Content of the addressed IO APIC register.
    514  *
    515483 */
    516484uint32_t io_apic_read(uint8_t address)
     
    527495 *
    528496 * @param address IO APIC register address.
    529  * @param val     Content to be written to the addressed IO APIC register.
    530  *
    531  */
    532 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)
    533500{
    534501        io_regsel_t regsel;
     
    537504        regsel.reg_addr = address;
    538505        io_apic[IOREGSEL] = regsel.value;
    539         io_apic[IOWIN] = val;
     506        io_apic[IOWIN] = x;
    540507}
    541508
    542509/** Change some attributes of one item in I/O Redirection Table.
    543510 *
    544  * @param pin   IO APIC pin number.
    545  * @param dest  Interrupt destination address.
    546  * @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.
    547514 * @param flags Flags.
    548  *
    549  */
    550 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec,
    551     unsigned int flags)
    552 {
    553         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;
    554520       
    555521        if (flags & LOPRI)
    556522                dlvr = DELMOD_LOWPRI;
    557         else
    558                 dlvr = DELMOD_FIXED;
    559        
    560         io_redirection_reg_t reg;
     523
    561524        reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    562525        reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1));
     
    567530        reg.intpol = POLARITY_HIGH;
    568531        reg.delmod = dlvr;
    569         reg.intvec = vec;
    570        
     532        reg.intvec = v;
     533
    571534        io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
    572535        io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi);
     
    576539 *
    577540 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
    578  *
    579541 */
    580542void io_apic_disable_irqs(uint16_t irqmask)
    581543{
     544        io_redirection_reg_t reg;
    582545        unsigned int i;
     546        int pin;
     547       
    583548        for (i = 0; i < 16; i++) {
    584549                if (irqmask & (1 << i)) {
     
    587552                         * mapping for the respective IRQ number.
    588553                         */
    589                         int pin = smp_irq_to_pin(i);
     554                        pin = smp_irq_to_pin(i);
    590555                        if (pin != -1) {
    591                                 io_redirection_reg_t reg;
    592                                
    593556                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    594557                                reg.masked = true;
     
    603566 *
    604567 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
    605  *
    606568 */
    607569void io_apic_enable_irqs(uint16_t irqmask)
    608570{
    609571        unsigned int i;
     572        int pin;
     573        io_redirection_reg_t reg;       
     574       
    610575        for (i = 0; i < 16; i++) {
    611576                if (irqmask & (1 << i)) {
     
    614579                         * mapping for the respective IRQ number.
    615580                         */
    616                         int pin = smp_irq_to_pin(i);
     581                        pin = smp_irq_to_pin(i);
    617582                        if (pin != -1) {
    618                                 io_redirection_reg_t reg;
    619                                
    620583                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    621584                                reg.masked = false;
Note: See TracChangeset for help on using the changeset viewer.