Ignore:
File:
1 edited

Legend:

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

    r84afc7b racc7ce4  
    3333 */
    3434
    35 #include <arch/types.h>
     35#include <typedefs.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
     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.
    71  */
    72 volatile uint32_t *l_apic = (uint32_t *) 0xfee00000;
    73 volatile uint32_t *io_apic = (uint32_t *) 0xfec00000;
     72 *
     73 */
     74volatile uint32_t *l_apic = (uint32_t *) UINT32_C(0xfee00000);
     75volatile uint32_t *io_apic = (uint32_t *) UINT32_C(0xfec00000);
    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;
    161179        eoi_function = l_apic_eoi;
     180        irqs_info = "apic";
    162181       
    163182        /*
     
    166185         * Other interrupts will be forwarded to the lowest priority CPU.
    167186         */
    168         io_apic_disable_irqs(0xffff);
     187        io_apic_disable_irqs(0xffffU);
    169188       
    170189        irq_initialize(&l_apic_timer_irq);
     
    179198        for (i = 0; i < IRQ_COUNT; i++) {
    180199                int pin;
    181        
     200               
    182201                if ((pin = smp_irq_to_pin(i)) != -1)
    183202                        io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI);
     
    187206         * Ensure that io_apic has unique ID.
    188207         */
     208        io_apic_id_t idreg;
     209       
    189210        idreg.value = io_apic_read(IOAPICID);
    190         if ((1 << idreg.apic_id) & apic_id_mask) {      /* see if IO APIC ID is used already */
     211        if ((1 << idreg.apic_id) & apic_id_mask) {  /* See if IO APIC ID is used already */
    191212                for (i = 0; i < APIC_ID_COUNT; i++) {
    192213                        if (!((1 << i) & apic_id_mask)) {
     
    197218                }
    198219        }
    199 
     220       
    200221        /*
    201222         * Configure the BSP's lapic.
    202223         */
    203224        l_apic_init();
    204 
    205         l_apic_debug();
     225        l_apic_debug();
     226       
     227        bsp_l_apic = l_apic_id();
    206228}
    207229
     
    211233 *
    212234 * @return 0 on error, 1 on success.
     235 *
    213236 */
    214237int apic_poll_errors(void)
     
    232255        if (esr.illegal_register_address)
    233256                printf("Illegal Register Address\n");
    234 
     257       
    235258        return !esr.err_bitmap;
    236259}
     
    241264 *
    242265 * @return 0 on failure, 1 on success.
     266 *
    243267 */
    244268int l_apic_broadcast_custom_ipi(uint8_t vector)
    245269{
    246270        icr_t icr;
    247 
     271       
    248272        icr.lo = l_apic[ICRlo];
    249273        icr.delmod = DELMOD_FIXED;
     
    253277        icr.trigger_mode = TRIGMOD_LEVEL;
    254278        icr.vector = vector;
    255 
     279       
    256280        l_apic[ICRlo] = icr.lo;
    257 
     281       
    258282        icr.lo = l_apic[ICRlo];
    259283        if (icr.delivs == DELIVS_PENDING) {
     
    262286#endif
    263287        }
    264 
     288       
    265289        return apic_poll_errors();
    266290}
     
    271295 *
    272296 * @return 0 on failure, 1 on success.
     297 *
    273298 */
    274299int l_apic_send_init_ipi(uint8_t apicid)
    275300{
     301        /*
     302         * Read the ICR register in and zero all non-reserved fields.
     303         */
    276304        icr_t icr;
    277         int i;
    278 
    279         /*
    280          * Read the ICR register in and zero all non-reserved fields.
    281          */
     305       
    282306        icr.lo = l_apic[ICRlo];
    283307        icr.hi = l_apic[ICRhi];
     
    293317        l_apic[ICRhi] = icr.hi;
    294318        l_apic[ICRlo] = icr.lo;
    295 
     319       
    296320        /*
    297321         * According to MP Specification, 20us should be enough to
     
    299323         */
    300324        delay(20);
    301 
     325       
    302326        if (!apic_poll_errors())
    303327                return 0;
    304 
     328       
    305329        icr.lo = l_apic[ICRlo];
    306330        if (icr.delivs == DELIVS_PENDING) {
     
    309333#endif
    310334        }
    311 
     335       
    312336        icr.delmod = DELMOD_INIT;
    313337        icr.destmod = DESTMOD_PHYS;
     
    317341        icr.vector = 0;
    318342        l_apic[ICRlo] = icr.lo;
    319 
     343       
    320344        /*
    321345         * Wait 10ms as MP Specification specifies.
    322346         */
    323347        delay(10000);
    324 
     348       
    325349        if (!is_82489DX_apic(l_apic[LAVR])) {
    326350                /*
    327351                 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
    328352                 */
    329                 for (i = 0; i<2; i++) {
     353                unsigned int i;
     354                for (i = 0; i < 2; i++) {
    330355                        icr.lo = l_apic[ICRlo];
    331356                        icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */
     
    346371void l_apic_init(void)
    347372{
     373        /* Initialize LVT Error register. */
    348374        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. */
     375       
    360376        error.value = l_apic[LVT_Err];
    361377        error.masked = true;
    362378        l_apic[LVT_Err] = error.value;
    363 
     379       
    364380        /* Initialize LVT LINT0 register. */
     381        lvt_lint_t lint;
     382       
    365383        lint.value = l_apic[LVT_LINT0];
    366384        lint.masked = true;
    367385        l_apic[LVT_LINT0] = lint.value;
    368 
     386       
    369387        /* Initialize LVT LINT1 register. */
    370388        lint.value = l_apic[LVT_LINT1];
    371389        lint.masked = true;
    372390        l_apic[LVT_LINT1] = lint.value;
    373 
     391       
    374392        /* Task Priority Register initialization. */
     393        tpr_t tpr;
     394       
    375395        tpr.value = l_apic[TPR];
    376396        tpr.pri_sc = 0;
     
    379399       
    380400        /* Spurious-Interrupt Vector Register initialization. */
     401        svr_t svr;
     402       
    381403        svr.value = l_apic[SVR];
    382404        svr.vector = VECTOR_APIC_SPUR;
     
    384406        svr.focus_checking = true;
    385407        l_apic[SVR] = svr.value;
    386 
     408       
    387409        if (CPU->arch.family >= 6)
    388410                enable_l_apic_in_msr();
    389411       
    390412        /* Interrupt Command Register initialization. */
     413        icr_t icr;
     414       
    391415        icr.lo = l_apic[ICRlo];
    392416        icr.delmod = DELMOD_INIT;
     
    398422       
    399423        /* Timer Divide Configuration Register initialization. */
     424        tdcr_t tdcr;
     425       
    400426        tdcr.value = l_apic[TDCR];
    401427        tdcr.div_value = DIVIDE_1;
    402428        l_apic[TDCR] = tdcr.value;
    403 
     429       
    404430        /* Program local timer. */
     431        lvt_tm_t tm;
     432       
    405433        tm.value = l_apic[LVT_Tm];
    406434        tm.vector = VECTOR_CLK;
     
    408436        tm.masked = false;
    409437        l_apic[LVT_Tm] = tm.value;
    410 
     438       
    411439        /*
    412440         * Measure and configure the timer to generate timer
    413441         * interrupt with period 1s/HZ seconds.
    414442         */
     443        uint32_t t1 = l_apic[CCRT];
     444        l_apic[ICRT] = 0xffffffff;
     445       
     446        while (l_apic[CCRT] == t1);
     447       
    415448        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;
     449        delay(1000000 / HZ);
     450        uint32_t t2 = l_apic[CCRT];
     451       
     452        l_apic[ICRT] = t1 - t2;
    426453       
    427454        /* Program Logical Destination Register. */
    428         ASSERT(CPU->id < 8)
     455        ASSERT(CPU->id < 8);
     456        ldr_t ldr;
     457       
    429458        ldr.value = l_apic[LDR];
    430459        ldr.id = (uint8_t) (1 << CPU->id);
     
    432461       
    433462        /* Program Destination Format Register for Flat mode. */
     463        dfr_t dfr;
     464       
    434465        dfr.value = l_apic[DFR];
    435466        dfr.model = MODEL_FLAT;
     
    447478{
    448479#ifdef LAPIC_VERBOSE
     480        printf("LVT on cpu%u, LAPIC ID: %" PRIu8 "\n",
     481            CPU->id, l_apic_id());
     482       
    449483        lvt_tm_t tm;
     484        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       
    450489        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]);
    457490        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]); 
     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;
    461503        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]);
     504        printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
     505            delivs_str[error.delivs], mask_str[error.masked]);
    463506#endif
    464507}
    465508
    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 
    478509/** Read from IO APIC register.
    479510 *
     
    481512 *
    482513 * @return Content of the addressed IO APIC register.
     514 *
    483515 */
    484516uint32_t io_apic_read(uint8_t address)
     
    495527 *
    496528 * @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)
     529 * @param val     Content to be written to the addressed IO APIC register.
     530 *
     531 */
     532void io_apic_write(uint8_t address, uint32_t val)
    500533{
    501534        io_regsel_t regsel;
     
    504537        regsel.reg_addr = address;
    505538        io_apic[IOREGSEL] = regsel.value;
    506         io_apic[IOWIN] = x;
     539        io_apic[IOWIN] = val;
    507540}
    508541
    509542/** Change some attributes of one item in I/O Redirection Table.
    510543 *
    511  * @param pin IO APIC pin number.
    512  * @param dest Interrupt destination address.
    513  * @param v Interrupt vector to trigger.
     544 * @param pin   IO APIC pin number.
     545 * @param dest  Interrupt destination address.
     546 * @param vec  Interrupt vector to trigger.
    514547 * @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;
     548 *
     549 */
     550void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec,
     551    unsigned int flags)
     552{
     553        unsigned int dlvr;
    520554       
    521555        if (flags & LOPRI)
    522556                dlvr = DELMOD_LOWPRI;
    523 
     557        else
     558                dlvr = DELMOD_FIXED;
     559       
     560        io_redirection_reg_t reg;
    524561        reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    525562        reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1));
     
    530567        reg.intpol = POLARITY_HIGH;
    531568        reg.delmod = dlvr;
    532         reg.intvec = v;
    533 
     569        reg.intvec = vec;
     570       
    534571        io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
    535572        io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi);
     
    539576 *
    540577 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
     578 *
    541579 */
    542580void io_apic_disable_irqs(uint16_t irqmask)
    543581{
    544         io_redirection_reg_t reg;
    545582        unsigned int i;
    546         int pin;
    547        
    548583        for (i = 0; i < 16; i++) {
    549584                if (irqmask & (1 << i)) {
     
    552587                         * mapping for the respective IRQ number.
    553588                         */
    554                         pin = smp_irq_to_pin(i);
     589                        int pin = smp_irq_to_pin(i);
    555590                        if (pin != -1) {
     591                                io_redirection_reg_t reg;
     592                               
    556593                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    557594                                reg.masked = true;
     
    566603 *
    567604 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
     605 *
    568606 */
    569607void io_apic_enable_irqs(uint16_t irqmask)
    570608{
    571609        unsigned int i;
    572         int pin;
    573         io_redirection_reg_t reg;       
    574        
    575610        for (i = 0; i < 16; i++) {
    576611                if (irqmask & (1 << i)) {
     
    579614                         * mapping for the respective IRQ number.
    580615                         */
    581                         pin = smp_irq_to_pin(i);
     616                        int pin = smp_irq_to_pin(i);
    582617                        if (pin != -1) {
     618                                io_redirection_reg_t reg;
     619                               
    583620                                reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
    584621                                reg.masked = false;
Note: See TracChangeset for help on using the changeset viewer.