Ignore:
File:
1 edited

Legend:

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

    rda1bafb 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;
     
    8179
    8280#ifdef LAPIC_VERBOSE
    83 static const char *delmod_str[] = {
     81static char *delmod_str[] = {
    8482        "Fixed",
    8583        "Lowest Priority",
     
    9290};
    9391
    94 static const char *destmod_str[] = {
     92static char *destmod_str[] = {
    9593        "Physical",
    9694        "Logical"
    9795};
    9896
    99 static const char *trigmod_str[] = {
     97static char *trigmod_str[] = {
    10098        "Edge",
    10199        "Level"
    102100};
    103101
    104 static const char *mask_str[] = {
     102static char *mask_str[] = {
    105103        "Unmasked",
    106104        "Masked"
    107105};
    108106
    109 static const char *delivs_str[] = {
     107static char *delivs_str[] = {
    110108        "Idle",
    111109        "Send Pending"
    112110};
    113111
    114 static const char *tm_mode_str[] = {
     112static char *tm_mode_str[] = {
    115113        "One-shot",
    116114        "Periodic"
    117115};
    118116
    119 static const char *intpol_str[] = {
     117static char *intpol_str[] = {
    120118        "Polarity High",
    121119        "Polarity Low"
     
    125123/** APIC spurious interrupt handler.
    126124 *
    127  * @param n      Interrupt vector.
     125 * @param n Interrupt vector.
    128126 * @param istate Interrupted state.
    129  *
    130  */
    131 static void apic_spurious(int n __attribute__((unused)),
    132     istate_t *istate __attribute__((unused)))
     127 */
     128static void apic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
    133129{
    134130#ifdef CONFIG_DEBUG
     
    149145         * irq->lock so we just unlock it and then lock it again.
    150146         */
    151         irq_spinlock_unlock(&irq->lock, false);
     147        spinlock_unlock(&irq->lock);
    152148        clock();
    153         irq_spinlock_lock(&irq->lock, false);
     149        spinlock_lock(&irq->lock);
    154150}
    155151
     
    157153void apic_init(void)
    158154{
     155        io_apic_id_t idreg;
     156       
    159157        exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious);
    160        
     158
    161159        enable_irqs_function = io_apic_enable_irqs;
    162160        disable_irqs_function = io_apic_disable_irqs;
     
    181179        for (i = 0; i < IRQ_COUNT; i++) {
    182180                int pin;
    183                
     181       
    184182                if ((pin = smp_irq_to_pin(i)) != -1)
    185183                        io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI);
     
    189187         * Ensure that io_apic has unique ID.
    190188         */
    191         io_apic_id_t idreg;
    192        
    193189        idreg.value = io_apic_read(IOAPICID);
    194         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 */
    195191                for (i = 0; i < APIC_ID_COUNT; i++) {
    196192                        if (!((1 << i) & apic_id_mask)) {
     
    201197                }
    202198        }
    203        
     199
    204200        /*
    205201         * Configure the BSP's lapic.
    206202         */
    207203        l_apic_init();
    208         l_apic_debug();
     204
     205        l_apic_debug();
    209206}
    210207
     
    214211 *
    215212 * @return 0 on error, 1 on success.
    216  *
    217213 */
    218214int apic_poll_errors(void)
     
    236232        if (esr.illegal_register_address)
    237233                printf("Illegal Register Address\n");
    238        
     234
    239235        return !esr.err_bitmap;
    240236}
     
    245241 *
    246242 * @return 0 on failure, 1 on success.
    247  *
    248243 */
    249244int l_apic_broadcast_custom_ipi(uint8_t vector)
    250245{
    251246        icr_t icr;
    252        
     247
    253248        icr.lo = l_apic[ICRlo];
    254249        icr.delmod = DELMOD_FIXED;
     
    258253        icr.trigger_mode = TRIGMOD_LEVEL;
    259254        icr.vector = vector;
    260        
     255
    261256        l_apic[ICRlo] = icr.lo;
    262        
     257
    263258        icr.lo = l_apic[ICRlo];
    264259        if (icr.delivs == DELIVS_PENDING) {
     
    267262#endif
    268263        }
    269        
     264
    270265        return apic_poll_errors();
    271266}
     
    276271 *
    277272 * @return 0 on failure, 1 on success.
    278  *
    279273 */
    280274int l_apic_send_init_ipi(uint8_t apicid)
    281275{
     276        icr_t icr;
     277        int i;
     278
    282279        /*
    283280         * Read the ICR register in and zero all non-reserved fields.
    284281         */
    285         icr_t icr;
    286        
    287282        icr.lo = l_apic[ICRlo];
    288283        icr.hi = l_apic[ICRhi];
     
    298293        l_apic[ICRhi] = icr.hi;
    299294        l_apic[ICRlo] = icr.lo;
    300        
     295
    301296        /*
    302297         * According to MP Specification, 20us should be enough to
     
    304299         */
    305300        delay(20);
    306        
     301
    307302        if (!apic_poll_errors())
    308303                return 0;
    309        
     304
    310305        icr.lo = l_apic[ICRlo];
    311306        if (icr.delivs == DELIVS_PENDING) {
     
    314309#endif
    315310        }
    316        
     311
    317312        icr.delmod = DELMOD_INIT;
    318313        icr.destmod = DESTMOD_PHYS;
     
    322317        icr.vector = 0;
    323318        l_apic[ICRlo] = icr.lo;
    324        
     319
    325320        /*
    326321         * Wait 10ms as MP Specification specifies.
    327322         */
    328323        delay(10000);
    329        
     324
    330325        if (!is_82489DX_apic(l_apic[LAVR])) {
    331326                /*
    332327                 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
    333328                 */
    334                 unsigned int i;
    335                 for (i = 0; i < 2; i++) {
     329                for (i = 0; i<2; i++) {
    336330                        icr.lo = l_apic[ICRlo];
    337331                        icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */
     
    352346void l_apic_init(void)
    353347{
     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
    354359        /* Initialize LVT Error register. */
    355         lvt_error_t error;
    356        
    357360        error.value = l_apic[LVT_Err];
    358361        error.masked = true;
    359362        l_apic[LVT_Err] = error.value;
    360        
     363
    361364        /* Initialize LVT LINT0 register. */
    362         lvt_lint_t lint;
    363        
    364365        lint.value = l_apic[LVT_LINT0];
    365366        lint.masked = true;
    366367        l_apic[LVT_LINT0] = lint.value;
    367        
     368
    368369        /* Initialize LVT LINT1 register. */
    369370        lint.value = l_apic[LVT_LINT1];
    370371        lint.masked = true;
    371372        l_apic[LVT_LINT1] = lint.value;
    372        
     373
    373374        /* Task Priority Register initialization. */
    374         tpr_t tpr;
    375        
    376375        tpr.value = l_apic[TPR];
    377376        tpr.pri_sc = 0;
     
    380379       
    381380        /* Spurious-Interrupt Vector Register initialization. */
    382         svr_t svr;
    383        
    384381        svr.value = l_apic[SVR];
    385382        svr.vector = VECTOR_APIC_SPUR;
     
    387384        svr.focus_checking = true;
    388385        l_apic[SVR] = svr.value;
    389        
     386
    390387        if (CPU->arch.family >= 6)
    391388                enable_l_apic_in_msr();
    392389       
    393390        /* Interrupt Command Register initialization. */
    394         icr_t icr;
    395        
    396391        icr.lo = l_apic[ICRlo];
    397392        icr.delmod = DELMOD_INIT;
     
    403398       
    404399        /* Timer Divide Configuration Register initialization. */
    405         tdcr_t tdcr;
    406        
    407400        tdcr.value = l_apic[TDCR];
    408401        tdcr.div_value = DIVIDE_1;
    409402        l_apic[TDCR] = tdcr.value;
    410        
     403
    411404        /* Program local timer. */
    412         lvt_tm_t tm;
    413        
    414405        tm.value = l_apic[LVT_Tm];
    415406        tm.vector = VECTOR_CLK;
     
    417408        tm.masked = false;
    418409        l_apic[LVT_Tm] = tm.value;
    419        
     410
    420411        /*
    421412         * Measure and configure the timer to generate timer
    422413         * interrupt with period 1s/HZ seconds.
    423414         */
    424         uint32_t t1 = l_apic[CCRT];
     415        t1 = l_apic[CCRT];
    425416        l_apic[ICRT] = 0xffffffff;
    426        
    427         while (l_apic[CCRT] == t1);
    428        
     417
     418        while (l_apic[CCRT] == t1)
     419                ;
     420               
    429421        t1 = l_apic[CCRT];
    430         delay(1000000 / HZ);
    431         uint32_t t2 = l_apic[CCRT];
    432        
    433         l_apic[ICRT] = t1 - t2;
     422        delay(1000000/HZ);
     423        t2 = l_apic[CCRT];
     424       
     425        l_apic[ICRT] = t1-t2;
    434426       
    435427        /* Program Logical Destination Register. */
    436         ASSERT(CPU->id < 8);
    437         ldr_t ldr;
    438        
     428        ASSERT(CPU->id < 8)
    439429        ldr.value = l_apic[LDR];
    440430        ldr.id = (uint8_t) (1 << CPU->id);
     
    442432       
    443433        /* Program Destination Format Register for Flat mode. */
    444         dfr_t dfr;
    445        
    446434        dfr.value = l_apic[DFR];
    447435        dfr.model = MODEL_FLAT;
     
    459447{
    460448#ifdef LAPIC_VERBOSE
    461         printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n", CPU->id, l_apic_id());
    462        
    463449        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
    464455        tm.value = l_apic[LVT_Tm];
    465456        printf("LVT Tm: vector=%hhd, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]);
    466        
    467         lvt_lint_t lint;
    468457        lint.value = l_apic[LVT_LINT0];
    469458        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]);
    470459        lint.value = l_apic[LVT_LINT1];
    471460        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]); 
    472        
    473         lvt_error_t error;
    474461        error.value = l_apic[LVT_Err];
    475462        printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]);
     
    480467 *
    481468 * @return Local APIC ID.
    482  *
    483469 */
    484470uint8_t l_apic_id(void)
     
    495481 *
    496482 * @return Content of the addressed IO APIC register.
    497  *
    498483 */
    499484uint32_t io_apic_read(uint8_t address)
     
    510495 *
    511496 * @param address IO APIC register address.
    512  * @param val     Content to be written to the addressed IO APIC register.
    513  *
    514  */
    515 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)
    516500{
    517501        io_regsel_t regsel;
     
    520504        regsel.reg_addr = address;
    521505        io_apic[IOREGSEL] = regsel.value;
    522         io_apic[IOWIN] = val;
     506        io_apic[IOWIN] = x;
    523507}
    524508
    525509/** Change some attributes of one item in I/O Redirection Table.
    526510 *
    527  * @param pin   IO APIC pin number.
    528  * @param dest  Interrupt destination address.
    529  * @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.
    530514 * @param flags Flags.
    531  *
    532  */
    533 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec,
    534     unsigned int flags)
    535 {
    536         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;
    537520       
    538521        if (flags & LOPRI)
    539522                dlvr = DELMOD_LOWPRI;
    540         else
    541                 dlvr = DELMOD_FIXED;
    542        
    543         io_redirection_reg_t reg;
     523
    544524        reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    545525        reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1));
     
    550530        reg.intpol = POLARITY_HIGH;
    551531        reg.delmod = dlvr;
    552         reg.intvec = vec;
    553        
     532        reg.intvec = v;
     533
    554534        io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
    555535        io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi);
     
    559539 *
    560540 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
    561  *
    562541 */
    563542void io_apic_disable_irqs(uint16_t irqmask)
    564543{
     544        io_redirection_reg_t reg;
    565545        unsigned int i;
     546        int pin;
     547       
    566548        for (i = 0; i < 16; i++) {
    567549                if (irqmask & (1 << i)) {
     
    570552                         * mapping for the respective IRQ number.
    571553                         */
    572                         int pin = smp_irq_to_pin(i);
     554                        pin = smp_irq_to_pin(i);
    573555                        if (pin != -1) {
    574                                 io_redirection_reg_t reg;
    575                                
    576556                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    577557                                reg.masked = true;
     
    586566 *
    587567 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
    588  *
    589568 */
    590569void io_apic_enable_irqs(uint16_t irqmask)
    591570{
    592571        unsigned int i;
     572        int pin;
     573        io_redirection_reg_t reg;       
     574       
    593575        for (i = 0; i < 16; i++) {
    594576                if (irqmask & (1 << i)) {
     
    597579                         * mapping for the respective IRQ number.
    598580                         */
    599                         int pin = smp_irq_to_pin(i);
     581                        pin = smp_irq_to_pin(i);
    600582                        if (pin != -1) {
    601                                 io_redirection_reg_t reg;
    602                                
    603583                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    604584                                reg.masked = false;
Note: See TracChangeset for help on using the changeset viewer.