Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fe32163 in mainline


Ignore:
Timestamp:
2010-06-29T00:08:48Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial
Children:
c19aa612
Parents:
9a21f9d
Message:

improve support for inactive CPUs
major revision of MADT and MPS parsing code
limit the number of active CPUs on ia32 and amd64 to 8 (actually the APIC ID of all active CPUs must be in the range 0 .. 7 to avoid tripping on an assertion in APIC code)
fix off-by-one bug in MADT parsing code (missing the last entry)

Location:
kernel
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/include/smp/smp.h

    r9a21f9d rfe32163  
    2727 */
    2828
    29 /** @addtogroup ia32   
     29/** @addtogroup ia32
    3030 * @{
    3131 */
     
    4040/** SMP config opertaions interface. */
    4141struct smp_config_operations {
    42         size_t (* cpu_count)(void);             /**< Return number of detected processors. */
    43         bool (* cpu_enabled)(size_t i); /**< Check whether the processor of index i is enabled. */
    44         bool (*cpu_bootstrap)(size_t i);        /**< Check whether the processor of index i is BSP. */
    45         uint8_t (*cpu_apic_id)(size_t i);               /**< Return APIC ID of the processor of index i. */
    46         int (*irq_to_pin)(unsigned int irq);            /**< Return mapping between irq and APIC pin. */
     42        /** Check whether a processor is enabled. */
     43        bool (* cpu_enabled)(size_t);
     44       
     45        /** Check whether a processor is BSP. */
     46        bool (*cpu_bootstrap)(size_t);
     47       
     48        /** Return APIC ID of a processor. */
     49        uint8_t (*cpu_apic_id)(size_t);
     50       
     51        /** Return mapping between IRQ and APIC pin. */
     52        int (*irq_to_pin)(unsigned int);
    4753};
    4854
    49 extern int smp_irq_to_pin(unsigned int irq);
     55extern int smp_irq_to_pin(unsigned int);
    5056
    5157#endif
  • kernel/arch/ia32/src/smp/mps.c

    r9a21f9d rfe32163  
    2727 */
    2828
    29 /** @addtogroup ia32   
     29/** @addtogroup ia32
    3030 * @{
    3131 */
     
    5252 */
    5353
    54 #define FS_SIGNATURE    0x5f504d5f
    55 #define CT_SIGNATURE    0x504d4350
    56 
    57 static int mps_fs_check(uint8_t *base);
    58 static int mps_ct_check(void);
    59 
    60 static int configure_via_ct(void);
    61 static int configure_via_default(uint8_t n);
    62 
    63 static int ct_processor_entry(struct __processor_entry *pr);
    64 static void ct_bus_entry(struct __bus_entry *bus);
    65 static void ct_io_apic_entry(struct __io_apic_entry *ioa);
    66 static void ct_io_intr_entry(struct __io_intr_entry *iointr);
    67 static void ct_l_intr_entry(struct __l_intr_entry *lintr);
    68 
    69 static void ct_extended_entries(void);
     54#define FS_SIGNATURE  0x5f504d5f
     55#define CT_SIGNATURE  0x504d4350
    7056
    7157static struct mps_fs *fs;
    7258static struct mps_ct *ct;
    7359
    74 struct __processor_entry *processor_entries = NULL;
    75 struct __bus_entry *bus_entries = NULL;
    76 struct __io_apic_entry *io_apic_entries = NULL;
    77 struct __io_intr_entry *io_intr_entries = NULL;
    78 struct __l_intr_entry *l_intr_entries = NULL;
    79 
    80 unsigned int processor_entry_cnt = 0;
    81 unsigned int bus_entry_cnt = 0;
    82 unsigned int io_apic_entry_cnt = 0;
    83 unsigned int io_intr_entry_cnt = 0;
    84 unsigned int l_intr_entry_cnt = 0;
    85 
    86 /*
    87  * Implementation of IA-32 SMP configuration interface.
    88  */
    89 static size_t get_cpu_count(void);
    90 static bool is_cpu_enabled(size_t i);
    91 static bool is_bsp(size_t i);
    92 static uint8_t get_cpu_apic_id(size_t i);
    93 static int mps_irq_to_pin(unsigned int irq);
    94 
     60static struct __processor_entry *processor_entries = NULL;
     61static struct __bus_entry *bus_entries = NULL;
     62static struct __io_apic_entry *io_apic_entries = NULL;
     63static struct __io_intr_entry *io_intr_entries = NULL;
     64static struct __l_intr_entry *l_intr_entries = NULL;
     65
     66static size_t io_apic_cnt = 0;
     67
     68static size_t processor_entry_cnt = 0;
     69static size_t bus_entry_cnt = 0;
     70static size_t io_apic_entry_cnt = 0;
     71static size_t io_intr_entry_cnt = 0;
     72static size_t l_intr_entry_cnt = 0;
     73
     74static uint8_t get_cpu_apic_id(size_t i)
     75{
     76        ASSERT(i < processor_entry_cnt);
     77       
     78        return processor_entries[i].l_apic_id;
     79}
     80
     81static bool is_cpu_enabled(size_t i)
     82{
     83        ASSERT(i < processor_entry_cnt);
     84       
     85        /*
     86         * FIXME: The current local APIC driver limits usable
     87         * APIC IDs to 8.
     88         *
     89         */
     90        if (get_cpu_apic_id(i) > 7)
     91                return false;
     92       
     93        return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
     94}
     95
     96static bool is_bsp(size_t i)
     97{
     98        ASSERT(i < processor_entry_cnt);
     99       
     100        return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
     101}
     102
     103static int mps_irq_to_pin(unsigned int irq)
     104{
     105        size_t i;
     106       
     107        for (i = 0; i < io_intr_entry_cnt; i++) {
     108                if (io_intr_entries[i].src_bus_irq == irq &&
     109                    io_intr_entries[i].intr_type == 0)
     110                        return io_intr_entries[i].dst_io_apic_pin;
     111        }
     112       
     113        return -1;
     114}
     115
     116/** Implementation of IA-32 SMP configuration interface.
     117 *
     118 */
    95119struct smp_config_operations mps_config_operations = {
    96         .cpu_count = get_cpu_count,
    97120        .cpu_enabled = is_cpu_enabled,
    98121        .cpu_bootstrap = is_bsp,
     
    101124};
    102125
    103 size_t get_cpu_count(void)
    104 {
    105         return processor_entry_cnt;
    106 }
    107 
    108 bool is_cpu_enabled(size_t i)
    109 {
    110         ASSERT(i < processor_entry_cnt);
    111         return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
    112 }
    113 
    114 bool is_bsp(size_t i)
    115 {
    116         ASSERT(i < processor_entry_cnt);
    117         return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
    118 }
    119 
    120 uint8_t get_cpu_apic_id(size_t i)
    121 {
    122         ASSERT(i < processor_entry_cnt);
    123         return processor_entries[i].l_apic_id;
    124 }
    125 
    126 
    127 /*
    128  * Used to check the integrity of the MP Floating Structure.
    129  */
    130 int mps_fs_check(uint8_t *base)
     126/** Check the integrity of the MP Floating Structure.
     127 *
     128 */
     129static bool mps_fs_check(uint8_t *base)
    131130{
    132131        unsigned int i;
     
    136135                sum = (uint8_t) (sum + base[i]);
    137136       
    138         return !sum;
    139 }
    140 
    141 /*
    142  * Used to check the integrity of the MP Configuration Table.
    143  */
    144 int mps_ct_check(void)
     137        return (sum == 0);
     138}
     139
     140/** Check the integrity of the MP Configuration Table.
     141 *
     142 */
     143static bool mps_ct_check(void)
    145144{
    146145        uint8_t *base = (uint8_t *) ct;
    147146        uint8_t *ext = base + ct->base_table_length;
    148147        uint8_t sum;
    149         int i; 
    150        
    151         /* count the checksum for the base table */
    152         for (i = 0,sum = 0; i < ct->base_table_length; i++)
     148        uint16_t i;
     149       
     150        /* Compute the checksum for the base table */
     151        for (i = 0, sum = 0; i < ct->base_table_length; i++)
    153152                sum = (uint8_t) (sum + base[i]);
    154                
     153       
    155154        if (sum)
    156                 return 0;
    157                
    158         /* count the checksum for the extended table */
     155                return false;
     156       
     157        /* Compute the checksum for the extended table */
    159158        for (i = 0, sum = 0; i < ct->ext_table_length; i++)
    160159                sum = (uint8_t) (sum + ext[i]);
    161                
    162         return sum == ct->ext_table_checksum;
    163 }
    164 
    165 void mps_init(void)
    166 {
    167         uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) };
    168         unsigned int i, j, length[2] = { 1024, 64 * 1024 };
    169        
    170 
     160       
     161        return (sum == ct->ext_table_checksum);
     162}
     163
     164static void ct_processor_entry(struct __processor_entry *pr)
     165{
    171166        /*
    172          * Find MP Floating Pointer Structure
    173          * 1a. search first 1K of EBDA
    174          * 1b. if EBDA is undefined, search last 1K of base memory
    175          *  2. search 64K starting at 0xf0000
     167         * Ignore processors which are not marked enabled.
    176168         */
    177 
    178         addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024);
    179         for (i = 0; i < 2; i++) {
    180                 for (j = 0; j < length[i]; j += 16) {
    181                         if (*((uint32_t *) &addr[i][j]) ==
    182                             FS_SIGNATURE && mps_fs_check(&addr[i][j])) {
    183                                 fs = (struct mps_fs *) &addr[i][j];
    184                                 goto fs_found;
    185                         }
     169        if ((pr->cpu_flags & (1 << 0)) == 0)
     170                return;
     171       
     172        apic_id_mask |= (1 << pr->l_apic_id);
     173}
     174
     175static void ct_bus_entry(struct __bus_entry *bus __attribute__((unused)))
     176{
     177#ifdef MPSCT_VERBOSE
     178        char buf[7];
     179       
     180        memcpy((void *) buf, (void *) bus->bus_type, 6);
     181        buf[6] = 0;
     182       
     183        printf("MPS: bus=%" PRIu8 " (%s)\n", bus->bus_id, buf);
     184#endif
     185}
     186
     187static void ct_io_apic_entry(struct __io_apic_entry *ioa)
     188{
     189        /* This I/O APIC is marked unusable */
     190        if ((ioa->io_apic_flags & 1) == 0)
     191                return;
     192       
     193        if (io_apic_cnt++ > 0) {
     194                /*
     195                 * Multiple I/O APICs are currently not supported.
     196                 */
     197                return;
     198        }
     199       
     200        io_apic = (uint32_t *) (uintptr_t) ioa->io_apic;
     201}
     202
     203static void ct_io_intr_entry(struct __io_intr_entry *iointr
     204    __attribute__((unused)))
     205{
     206#ifdef MPSCT_VERBOSE
     207        printf("MPS: ");
     208       
     209        switch (iointr->intr_type) {
     210        case 0:
     211                printf("INT");
     212                break;
     213        case 1:
     214                printf("NMI");
     215                break;
     216        case 2:
     217                printf("SMI");
     218                break;
     219        case 3:
     220                printf("ExtINT");
     221                break;
     222        }
     223       
     224        printf(", ");
     225       
     226        switch (iointr->poel & 3) {
     227        case 0:
     228                printf("bus-like");
     229                break;
     230        case 1:
     231                printf("active high");
     232                break;
     233        case 2:
     234                printf("reserved");
     235                break;
     236        case 3:
     237                printf("active low");
     238                break;
     239        }
     240       
     241        printf(", ");
     242       
     243        switch ((iointr->poel >> 2) & 3) {
     244        case 0:
     245                printf("bus-like");
     246                break;
     247        case 1:
     248                printf("edge-triggered");
     249                break;
     250        case 2:
     251                printf("reserved");
     252                break;
     253        case 3:
     254                printf("level-triggered");
     255                break;
     256        }
     257       
     258        printf(", bus=%" PRIu8 " irq=%" PRIu8 " io_apic=%" PRIu8" pin=%"
     259            PRIu8 "\n", iointr->src_bus_id, iointr->src_bus_irq,
     260            iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
     261#endif
     262}
     263
     264static void ct_l_intr_entry(struct __l_intr_entry *lintr
     265    __attribute__((unused)))
     266{
     267#ifdef MPSCT_VERBOSE
     268        printf("MPS: ");
     269       
     270        switch (lintr->intr_type) {
     271        case 0:
     272                printf("INT");
     273                break;
     274        case 1:
     275                printf("NMI");
     276                break;
     277        case 2:
     278                printf("SMI");
     279                break;
     280        case 3:
     281                printf("ExtINT");
     282                break;
     283        }
     284       
     285        printf(", ");
     286       
     287        switch (lintr->poel & 3) {
     288        case 0:
     289                printf("bus-like");
     290                break;
     291        case 1:
     292                printf("active high");
     293                break;
     294        case 2:
     295                printf("reserved");
     296                break;
     297        case 3:
     298                printf("active low");
     299                break;
     300        }
     301       
     302        printf(", ");
     303       
     304        switch ((lintr->poel >> 2) & 3) {
     305        case 0:
     306                printf("bus-like");
     307                break;
     308        case 1:
     309                printf("edge-triggered");
     310                break;
     311        case 2:
     312                printf("reserved");
     313                break;
     314        case 3:
     315                printf("level-triggered");
     316                break;
     317        }
     318       
     319        printf(", bus=%" PRIu8 " irq=%" PRIu8 " l_apic=%" PRIu8" pin=%"
     320            PRIu8 "\n", lintr->src_bus_id, lintr->src_bus_irq,
     321            lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
     322#endif
     323}
     324
     325static void ct_extended_entries(void)
     326{
     327        uint8_t *ext = (uint8_t *) ct + ct->base_table_length;
     328        uint8_t *cur;
     329       
     330        for (cur = ext; cur < ext + ct->ext_table_length;
     331            cur += cur[CT_EXT_ENTRY_LEN]) {
     332                switch (cur[CT_EXT_ENTRY_TYPE]) {
     333                default:
     334                        printf("MPS: Skipping MP Configuration Table extended "
     335                            "entry type %" PRIu8 "\n", cur[CT_EXT_ENTRY_TYPE]);
    186336                }
    187337        }
    188 
    189         return;
    190        
    191 fs_found:
    192         printf("%p: MPS Floating Pointer Structure\n", fs);
    193 
    194         if (fs->config_type == 0 && fs->configuration_table) {
    195                 if (fs->mpfib2 >> 7) {
    196                         printf("%s: PIC mode not supported\n", __func__);
    197                         return;
    198                 }
    199 
    200                 ct = (struct mps_ct *)PA2KA((uintptr_t)fs->configuration_table);
    201                 config.cpu_count = configure_via_ct();
    202         }
    203         else
    204                 config.cpu_count = configure_via_default(fs->config_type);
    205 
    206         return;
    207 }
    208 
    209 int configure_via_ct(void)
    210 {
    211         uint8_t *cur;
    212         unsigned int i, cnt;
    213                
     338}
     339
     340static void configure_via_ct(void)
     341{
    214342        if (ct->signature != CT_SIGNATURE) {
    215                 printf("%s: bad ct->signature\n", __func__);
    216                 return 1;
    217         }
     343                printf("MPS: Wrong ct->signature\n");
     344                return;
     345        }
     346       
    218347        if (!mps_ct_check()) {
    219                 printf("%s: bad ct checksum\n", __func__);
    220                 return 1;
    221         }
     348                printf("MPS: Wrong ct checksum\n");
     349                return;
     350        }
     351       
    222352        if (ct->oem_table) {
    223                 printf("%s: ct->oem_table not supported\n", __func__);
    224                 return 1;
    225         }
    226        
    227         l_apic = (uint32_t *)(uintptr_t)ct->l_apic;
    228 
    229         cnt = 0;
    230         cur = &ct->base_table[0];
     353                printf("MPS: ct->oem_table not supported\n");
     354                return;
     355        }
     356       
     357        l_apic = (uint32_t *) (uintptr_t) ct->l_apic;
     358       
     359        uint8_t *cur = &ct->base_table[0];
     360        uint16_t i;
     361       
    231362        for (i = 0; i < ct->entry_count; i++) {
    232363                switch (*cur) {
    233                 /* Processor entry */
    234                 case 0:
     364                case 0:  /* Processor entry */
    235365                        processor_entries = processor_entries ?
    236366                            processor_entries :
    237367                            (struct __processor_entry *) cur;
    238368                        processor_entry_cnt++;
    239                         cnt += ct_processor_entry((struct __processor_entry *)
    240                             cur);
     369                        ct_processor_entry((struct __processor_entry *) cur);
    241370                        cur += 20;
    242371                        break;
    243 
    244                 /* Bus entry */
    245                 case 1:
     372                case 1:  /* Bus entry */
    246373                        bus_entries = bus_entries ?
    247374                            bus_entries : (struct __bus_entry *) cur;
     
    250377                        cur += 8;
    251378                        break;
    252                                
    253                 /* I/O Apic */
    254                 case 2:
     379                case 2:  /* I/O APIC */
    255380                        io_apic_entries = io_apic_entries ?
    256381                            io_apic_entries : (struct __io_apic_entry *) cur;
    257                                 io_apic_entry_cnt++;
     382                        io_apic_entry_cnt++;
    258383                        ct_io_apic_entry((struct __io_apic_entry *) cur);
    259384                        cur += 8;
    260385                        break;
    261                                
    262                 /* I/O Interrupt Assignment */
    263                 case 3:
     386                case 3:  /* I/O Interrupt Assignment */
    264387                        io_intr_entries = io_intr_entries ?
    265388                            io_intr_entries : (struct __io_intr_entry *) cur;
     
    268391                        cur += 8;
    269392                        break;
    270 
    271                 /* Local Interrupt Assignment */
    272                 case 4:
     393                case 4:  /* Local Interrupt Assignment */
    273394                        l_intr_entries = l_intr_entries ?
    274395                            l_intr_entries : (struct __l_intr_entry *) cur;
     
    277398                        cur += 8;
    278399                        break;
    279 
    280400                default:
    281401                        /*
    282402                         * Something is wrong. Fallback to UP mode.
    283403                         */
    284 
    285                         printf("%s: ct badness\n", __func__);
    286                         return 1;
     404                        printf("MPS: ct badness %" PRIu8 "\n", *cur);
     405                        return;
    287406                }
    288407        }
     
    292411         */
    293412        ct_extended_entries();
    294         return cnt;
    295 }
    296 
    297 int configure_via_default(uint8_t n __attribute__((unused)))
     413}
     414
     415static void configure_via_default(uint8_t n __attribute__((unused)))
    298416{
    299417        /*
    300418         * Not yet implemented.
    301419         */
    302         printf("%s: not supported\n", __func__);
    303         return 1;
    304 }
    305 
    306 
    307 int ct_processor_entry(struct __processor_entry *pr __attribute__((unused)))
    308 {
     420        printf("MPS: Default configuration not supported\n");
     421}
     422
     423void mps_init(void)
     424{
     425        uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) };
     426        unsigned int i;
     427        unsigned int j;
     428        unsigned int length[2] = { 1024, 64 * 1024 };
     429       
    309430        /*
    310          * Ignore processors which are not marked enabled.
     431         * Find MP Floating Pointer Structure
     432         *  1a. search first 1K of EBDA
     433         *  1b. if EBDA is undefined, search last 1K of base memory
     434         *  2.  search 64K starting at 0xf0000
    311435         */
    312         if ((pr->cpu_flags & (1 << 0)) == 0)
    313                 return 0;
    314        
    315         apic_id_mask |= (1 << pr->l_apic_id);
    316         return 1;
    317 }
    318 
    319 void ct_bus_entry(struct __bus_entry *bus __attribute__((unused)))
    320 {
    321 #ifdef MPSCT_VERBOSE
    322         char buf[7];
    323         memcpy((void *) buf, (void *) bus->bus_type, 6);
    324         buf[6] = 0;
    325         printf("bus%d: %s\n", bus->bus_id, buf);
    326 #endif
    327 }
    328 
    329 void ct_io_apic_entry(struct __io_apic_entry *ioa)
    330 {
    331         static unsigned int io_apic_count = 0;
    332 
    333         /* this ioapic is marked unusable */
    334         if ((ioa->io_apic_flags & 1) == 0)
    335                 return;
    336        
    337         if (io_apic_count++ > 0) {
    338                 /*
    339                  * Multiple IO APIC's are currently not supported.
    340                  */
    341                 return;
    342         }
    343        
    344         io_apic = (uint32_t *)(uintptr_t)ioa->io_apic;
    345 }
    346 
    347 //#define MPSCT_VERBOSE
    348 void ct_io_intr_entry(struct __io_intr_entry *iointr __attribute__((unused)))
    349 {
    350 #ifdef MPSCT_VERBOSE
    351         switch (iointr->intr_type) {
    352         case 0:
    353                 printf("INT");
    354                 break;
    355         case 1:
    356                 printf("NMI");
    357                 break;
    358         case 2:
    359                 printf("SMI");
    360                 break;
    361         case 3:
    362                 printf("ExtINT");
    363                 break;
    364         }
    365         putchar(',');
    366         switch (iointr->poel & 3) {
    367         case 0:
    368                 printf("bus-like");
    369                 break;
    370         case 1:
    371                 printf("active high");
    372                 break;
    373         case 2:
    374                 printf("reserved");
    375                 break;
    376         case 3:
    377                 printf("active low");
    378                 break;
    379         }
    380         putchar(',');
    381         switch ((iointr->poel >> 2) & 3) {
    382         case 0:
    383                 printf("bus-like");
    384                 break;
    385         case 1:
    386                 printf("edge-triggered");
    387                 break;
    388         case 2:
    389                 printf("reserved");
    390                 break;
    391         case 3:
    392                 printf("level-triggered");
    393                 break;
    394         }
    395         putchar(',');
    396         printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
    397         putchar(',');
    398         printf("io_apic%d,pin%d", iointr->dst_io_apic_id,
    399             iointr->dst_io_apic_pin);
    400         putchar('\n'); 
    401 #endif
    402 }
    403 
    404 void ct_l_intr_entry(struct __l_intr_entry *lintr __attribute__((unused)))
    405 {
    406 #ifdef MPSCT_VERBOSE
    407         switch (lintr->intr_type) {
    408         case 0:
    409             printf("INT");
    410             break;
    411         case 1:
    412             printf("NMI");
    413             break;
    414         case 2:
    415             printf("SMI");
    416             break;
    417         case 3:
    418             printf("ExtINT");
    419             break;
    420         }
    421         putchar(',');
    422         switch (lintr->poel & 3) {
    423         case 0:
    424             printf("bus-like");
    425             break;
    426         case 1:
    427             printf("active high");
    428             break;
    429         case 2:
    430             printf("reserved");
    431             break;
    432         case 3:
    433             printf("active low");
    434             break;
    435         }
    436         putchar(',');
    437         switch ((lintr->poel >> 2) & 3) {
    438         case 0:
    439             printf("bus-like");
    440             break;
    441         case 1:
    442             printf("edge-triggered");
    443             break;
    444         case 2:
    445             printf("reserved");
    446             break;
    447         case 3:
    448             printf("level-triggered");
    449             break;
    450         }
    451         putchar(',');
    452         printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
    453         putchar(',');
    454         printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
    455         putchar('\n');
    456 #endif
    457 }
    458 
    459 void ct_extended_entries(void)
    460 {
    461         uint8_t *ext = (uint8_t *) ct + ct->base_table_length;
    462         uint8_t *cur;
    463 
    464         for (cur = ext; cur < ext + ct->ext_table_length;
    465             cur += cur[CT_EXT_ENTRY_LEN]) {
    466                 switch (cur[CT_EXT_ENTRY_TYPE]) {
    467                 default:
    468                         printf("%p: skipping MP Configuration Table extended "
    469                             "entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]);
    470                         break;
     436       
     437        addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024);
     438        for (i = 0; i < 2; i++) {
     439                for (j = 0; j < length[i]; j += 16) {
     440                        if ((*((uint32_t *) &addr[i][j]) ==
     441                            FS_SIGNATURE) && (mps_fs_check(&addr[i][j]))) {
     442                                fs = (struct mps_fs *) &addr[i][j];
     443                                goto fs_found;
     444                        }
    471445                }
    472446        }
    473 }
    474 
    475 int mps_irq_to_pin(unsigned int irq)
    476 {
    477         unsigned int i;
    478        
    479         for (i = 0; i < io_intr_entry_cnt; i++) {
    480                 if (io_intr_entries[i].src_bus_irq == irq &&
    481                     io_intr_entries[i].intr_type == 0)
    482                         return io_intr_entries[i].dst_io_apic_pin;
    483         }
    484        
    485         return -1;
     447       
     448        return;
     449       
     450fs_found:
     451        printf("%p: MPS Floating Pointer Structure\n", fs);
     452       
     453        if ((fs->config_type == 0) && (fs->configuration_table)) {
     454                if (fs->mpfib2 >> 7) {
     455                        printf("MPS: PIC mode not supported\n");
     456                        return;
     457                }
     458               
     459                ct = (struct mps_ct *) PA2KA((uintptr_t) fs->configuration_table);
     460                configure_via_ct();
     461        } else
     462                configure_via_default(fs->config_type);
     463       
     464        if (processor_entry_cnt > 0)
     465                config.cpu_count = processor_entry_cnt;
    486466}
    487467
  • kernel/arch/ia32/src/smp/smp.c

    r9a21f9d rfe32163  
    6262void smp_init(void)
    6363{
    64         uintptr_t l_apic_address, io_apic_address;
    65 
     64        uintptr_t l_apic_address;
     65        uintptr_t io_apic_address;
     66       
    6667        if (acpi_madt) {
    6768                acpi_madt_parse();
    6869                ops = &madt_config_operations;
    6970        }
     71       
    7072        if (config.cpu_count == 1) {
    7173                mps_init();
    7274                ops = &mps_config_operations;
    7375        }
    74 
     76       
    7577        l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
    7678            FRAME_ATOMIC | FRAME_KA);
    7779        if (!l_apic_address)
    7880                panic("Cannot allocate address for l_apic.");
    79 
     81       
    8082        io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
    8183            FRAME_ATOMIC | FRAME_KA);
    8284        if (!io_apic_address)
    8385                panic("Cannot allocate address for io_apic.");
    84 
     86       
    8587        if (config.cpu_count > 1) {
    8688                page_table_lock(AS_KERNEL, true);
     
    9092                    (uintptr_t) io_apic, PAGE_NOT_CACHEABLE | PAGE_WRITE);
    9193                page_table_unlock(AS_KERNEL, true);
    92                                  
     94               
    9395                l_apic = (uint32_t *) l_apic_address;
    9496                io_apic = (uint32_t *) io_apic_address;
     
    108110       
    109111        ASSERT(ops != NULL);
    110 
     112       
    111113        /*
    112114         * We need to access data in frame 0.
    113115         * We boldly make use of kernel address space mapping.
    114116         */
    115 
     117       
    116118        /*
    117119         * Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot()
    118120         */
    119121        *((uint16_t *) (PA2KA(0x467 + 0))) =
    120             (uint16_t) (((uintptr_t) ap_boot) >> 4);    /* segment */
    121         *((uint16_t *) (PA2KA(0x467 + 2))) = 0;         /* offset */
     122            (uint16_t) (((uintptr_t) ap_boot) >> 4);  /* segment */
     123        *((uint16_t *) (PA2KA(0x467 + 2))) = 0;       /* offset */
    122124       
    123125        /*
     
    125127         * BIOS will not do the POST after the INIT signal.
    126128         */
    127         pio_write_8((ioport8_t *)0x70, 0xf);
    128         pio_write_8((ioport8_t *)0x71, 0xa);
    129 
     129        pio_write_8((ioport8_t *) 0x70, 0xf);
     130        pio_write_8((ioport8_t *) 0x71, 0xa);
     131       
    130132        pic_disable_irqs(0xffff);
    131133        apic_init();
    132134       
    133135        uint8_t apic = l_apic_id();
    134 
    135         for (i = 0; i < ops->cpu_count(); i++) {
    136                 descriptor_t *gdt_new;
    137                
     136       
     137        for (i = 0; i < config.cpu_count; i++) {
    138138                /*
    139139                 * Skip processors marked unusable.
     
    141141                if (!ops->cpu_enabled(i))
    142142                        continue;
    143 
     143               
    144144                /*
    145145                 * The bootstrap processor is already up.
     
    147147                if (ops->cpu_bootstrap(i))
    148148                        continue;
    149 
     149               
    150150                if (ops->cpu_apic_id(i) == apic) {
    151151                        printf("%s: bad processor entry #%u, will not send IPI "
     
    162162                 * the memory subsystem
    163163                 */
    164                 gdt_new = (descriptor_t *) malloc(GDT_ITEMS *
    165                     sizeof(descriptor_t), FRAME_ATOMIC);
     164                descriptor_t *gdt_new =
     165                    (descriptor_t *) malloc(GDT_ITEMS * sizeof(descriptor_t),
     166                    FRAME_ATOMIC);
    166167                if (!gdt_new)
    167168                        panic("Cannot allocate memory for GDT.");
    168 
     169               
    169170                memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(descriptor_t));
    170171                memsetb(&gdt_new[TSS_DES], sizeof(descriptor_t), 0);
     
    172173                protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new);
    173174                gdtr.base = (uintptr_t) gdt_new;
    174 
     175               
    175176                if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) {
    176177                        /*
     
    181182                        if (waitq_sleep_timeout(&ap_completion_wq, 1000000,
    182183                            SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) {
    183                                 unsigned int cpu = (config.cpu_active > i) ?
    184                                     config.cpu_active : i;
    185184                                printf("%s: waiting for cpu%u (APIC ID = %d) "
    186                                     "timed out\n", __FUNCTION__, cpu,
     185                                    "timed out\n", __FUNCTION__, i,
    187186                                    ops->cpu_apic_id(i));
    188187                        }
  • kernel/genarch/src/acpi/madt.c

    r9a21f9d rfe32163  
    2727 */
    2828
    29 /** @addtogroup genarch 
     29/** @addtogroup genarch
    3030 * @{
    3131 */
    3232/**
    3333 * @file
    34  * @brief       Multiple APIC Description Table (MADT) parsing.
     34 * @brief Multiple APIC Description Table (MADT) parsing.
    3535 */
    3636
     
    5252#ifdef CONFIG_SMP
    5353
    54 /** Standard ISA IRQ map; can be overriden by Interrupt Source Override entries of MADT. */
    55 int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    56 
    57 static void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index);
    58 static void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index);
    59 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index);
    60 static int madt_cmp(void * a, void * b);
     54/**
     55 * Standard ISA IRQ map; can be overriden by
     56 * Interrupt Source Override entries of MADT.
     57 */
     58static int isa_irq_map[] =
     59    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    6160
    6261struct madt_l_apic *madt_l_apic_entries = NULL;
    6362struct madt_io_apic *madt_io_apic_entries = NULL;
    6463
    65 size_t madt_l_apic_entry_index = 0;
    66 size_t madt_io_apic_entry_index = 0;
    67 size_t madt_l_apic_entry_cnt = 0;
    68 size_t madt_io_apic_entry_cnt = 0;
    69 size_t cpu_count = 0;
    70 
    71 struct madt_apic_header * * madt_entries_index = NULL;
    72 unsigned int madt_entries_index_cnt = 0;
     64static size_t madt_l_apic_entry_index = 0;
     65static size_t madt_io_apic_entry_index = 0;
     66static size_t madt_l_apic_entry_cnt = 0;
     67static size_t madt_io_apic_entry_cnt = 0;
     68
     69static struct madt_apic_header **madt_entries_index = NULL;
    7370
    7471const char *entry[] = {
     
    8481};
    8582
    86 /*
    87  * ACPI MADT Implementation of SMP configuration interface.
    88  */
    89 static size_t madt_cpu_count(void);
    90 static bool madt_cpu_enabled(size_t i);
    91 static bool madt_cpu_bootstrap(size_t i);
    92 static uint8_t madt_cpu_apic_id(size_t i);
    93 static int madt_irq_to_pin(unsigned int irq);
    94 
     83static uint8_t madt_cpu_apic_id(size_t i)
     84{
     85        ASSERT(i < madt_l_apic_entry_cnt);
     86       
     87        return ((struct madt_l_apic *)
     88            madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
     89}
     90
     91static bool madt_cpu_enabled(size_t i)
     92{
     93        ASSERT(i < madt_l_apic_entry_cnt);
     94       
     95        /*
     96         * FIXME: The current local APIC driver limits usable
     97         * APIC IDs to 8.
     98         *
     99         */
     100        if (madt_cpu_apic_id(i) > 7)
     101                return false;
     102       
     103        return ((struct madt_l_apic *)
     104            madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
     105}
     106
     107static bool madt_cpu_bootstrap(size_t i)
     108{
     109        ASSERT(i < madt_l_apic_entry_cnt);
     110       
     111        return ((struct madt_l_apic *)
     112            madt_entries_index[madt_l_apic_entry_index + i])->apic_id ==
     113            l_apic_id();
     114}
     115
     116static int madt_irq_to_pin(unsigned int irq)
     117{
     118        ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
     119       
     120        return isa_irq_map[irq];
     121}
     122
     123/** ACPI MADT Implementation of SMP configuration interface.
     124 *
     125 */
    95126struct smp_config_operations madt_config_operations = {
    96         .cpu_count = madt_cpu_count,
    97127        .cpu_enabled = madt_cpu_enabled,
    98128        .cpu_bootstrap = madt_cpu_bootstrap,
     
    101131};
    102132
    103 size_t madt_cpu_count(void)
    104 {
    105         return madt_l_apic_entry_cnt;
    106 }
    107 
    108 bool madt_cpu_enabled(size_t i)
    109 {
    110         ASSERT(i < madt_l_apic_entry_cnt);
    111         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
    112 
    113 }
    114 
    115 bool madt_cpu_bootstrap(size_t i)
    116 {
    117         ASSERT(i < madt_l_apic_entry_cnt);
    118         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
    119 }
    120 
    121 uint8_t madt_cpu_apic_id(size_t i)
    122 {
    123         ASSERT(i < madt_l_apic_entry_cnt);
    124         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
    125 }
    126 
    127 int madt_irq_to_pin(unsigned int irq)
    128 {
    129         ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
    130         return isa_irq_map[irq];
    131 }
    132 
    133 int madt_cmp(void * a, void * b)
    134 {
    135         return
    136                 (((struct madt_apic_header *) a)->type > ((struct madt_apic_header *) b)->type) ?
    137                 1 :
    138                 ((((struct madt_apic_header *) a)->type < ((struct madt_apic_header *) b)->type) ? -1 : 0);
    139 }
    140        
    141 void acpi_madt_parse(void)
    142 {
    143         struct madt_apic_header *end = (struct madt_apic_header *) (((uint8_t *) acpi_madt) + acpi_madt->header.length);
    144         struct madt_apic_header *h;
    145        
    146         l_apic = (uint32_t *) (unative_t) acpi_madt->l_apic_address;
    147 
    148         /* calculate madt entries */
    149         for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
    150                 madt_entries_index_cnt++;
    151         }
    152 
    153         /* create madt apic entries index array */
    154         madt_entries_index = (struct madt_apic_header * *) malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *), FRAME_ATOMIC);
    155         if (!madt_entries_index)
    156                 panic("Memory allocation error.");
    157 
    158         uint32_t index = 0;
    159 
    160         for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
    161                 madt_entries_index[index++] = h;
    162         }
    163 
    164         /* Quicksort MADT index structure */
    165         qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t), &madt_cmp);
    166 
    167         /* Parse MADT entries */
    168         if (madt_entries_index_cnt > 0) {       
    169                 for (index = 0; index < madt_entries_index_cnt - 1; index++) {
    170                         h = madt_entries_index[index];
    171                         switch (h->type) {
    172                                 case MADT_L_APIC:
    173                                         madt_l_apic_entry((struct madt_l_apic *) h, index);
    174                                         break;
    175                                 case MADT_IO_APIC:
    176                                         madt_io_apic_entry((struct madt_io_apic *) h, index);
    177                                         break;
    178                                 case MADT_INTR_SRC_OVRD:
    179                                         madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) h, index);
    180                                         break;
    181                                 case MADT_NMI_SRC:
    182                                 case MADT_L_APIC_NMI:
    183                                 case MADT_L_APIC_ADDR_OVRD:
    184                                 case MADT_IO_SAPIC:
    185                                 case MADT_L_SAPIC:
    186                                 case MADT_PLATFORM_INTR_SRC:
    187                                         printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type);
    188                                         break;
    189        
    190                                 default:
    191                                         if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
    192                                                 printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type);
    193                                         }
    194                                         if (h->type >= MADT_RESERVED_OEM_BEGIN) {
    195                                                 printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type);
    196                                         }
    197                                         break;
    198                         }
    199                 }
    200         }
    201 
    202         if (cpu_count)
    203                 config.cpu_count = cpu_count;
    204 }
    205  
    206 
    207 void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index)
    208 {
    209         if (!madt_l_apic_entry_cnt++) {
    210                 madt_l_apic_entry_index = index;
    211         }
    212                
     133static int madt_cmp(void *a, void *b)
     134{
     135        uint8_t typea = ((struct madt_apic_header *) a)->type;
     136        uint8_t typeb = ((struct madt_apic_header *) b)->type;
     137       
     138        if (typea > typeb)
     139                return 1;
     140       
     141        if (typea < typeb)
     142                return -1;
     143       
     144        return 0;
     145}
     146
     147static void madt_l_apic_entry(struct madt_l_apic *la, size_t i)
     148{
     149        if (!madt_l_apic_entry_cnt++)
     150                madt_l_apic_entry_index = i;
     151       
    213152        if (!(la->flags & 0x1)) {
    214153                /* Processor is unusable, skip it. */
     
    216155        }
    217156       
    218         cpu_count++;   
    219         apic_id_mask |= 1<<la->apic_id;
    220 }
    221 
    222 void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index)
     157        apic_id_mask |= 1 << la->apic_id;
     158}
     159
     160static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
    223161{
    224162        if (!madt_io_apic_entry_cnt++) {
    225                 /* remember index of the first io apic entry */
    226                 madt_io_apic_entry_index = index;
     163                /* Remember index of the first io apic entry */
     164                madt_io_apic_entry_index = i;
    227165                io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
    228166        } else {
    229                 /* currently not supported */
    230                 return;
     167                /* Currently not supported */
    231168        }
    232169}
    233170
    234 void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
     171static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
     172    size_t i)
    235173{
    236174        ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
    237         printf("MADT: ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8 ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
    238                 entry[override->header.type], override->bus, override->source,
    239                 override->global_int, override->flags);
     175       
     176        printf("MADT: Ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8
     177            ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
     178            entry[override->header.type], override->bus, override->source,
     179            override->global_int, override->flags);
     180}
     181
     182void acpi_madt_parse(void)
     183{
     184        struct madt_apic_header *end = (struct madt_apic_header *)
     185            (((uint8_t *) acpi_madt) + acpi_madt->header.length);
     186        struct madt_apic_header *hdr;
     187       
     188        l_apic = (uint32_t *) (unative_t) acpi_madt->l_apic_address;
     189       
     190        /* Count MADT entries */
     191        unsigned int madt_entries_index_cnt = 0;
     192        for (hdr = &acpi_madt->apic_header[0]; hdr < end;
     193            hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
     194                madt_entries_index_cnt++;
     195       
     196        /* Create MADT APIC entries index array */
     197        madt_entries_index = (struct madt_apic_header **)
     198            malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header **),
     199            FRAME_ATOMIC);
     200        if (!madt_entries_index)
     201                panic("Memory allocation error.");
     202       
     203        size_t i = 0;
     204       
     205        for (hdr = &acpi_madt->apic_header[0]; hdr < end;
     206            hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
     207                madt_entries_index[i++] = hdr;
     208       
     209        /* Sort MADT index structure */
     210        qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t),
     211            &madt_cmp);
     212       
     213        /* Parse MADT entries */
     214        for (i = 0; i < madt_entries_index_cnt; i++) {
     215                hdr = madt_entries_index[i];
     216               
     217                switch (hdr->type) {
     218                case MADT_L_APIC:
     219                        madt_l_apic_entry((struct madt_l_apic *) hdr, i);
     220                        break;
     221                case MADT_IO_APIC:
     222                        madt_io_apic_entry((struct madt_io_apic *) hdr, i);
     223                break;
     224                case MADT_INTR_SRC_OVRD:
     225                        madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) hdr, i);
     226                        break;
     227                case MADT_NMI_SRC:
     228                case MADT_L_APIC_NMI:
     229                case MADT_L_APIC_ADDR_OVRD:
     230                case MADT_IO_SAPIC:
     231                case MADT_L_SAPIC:
     232                case MADT_PLATFORM_INTR_SRC:
     233                        printf("MADT: Skipping %s entry (type=%" PRIu8 ")\n",
     234                            entry[hdr->type], hdr->type);
     235                        break;
     236                default:
     237                        if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN)
     238                            && (hdr->type <= MADT_RESERVED_SKIP_END))
     239                                printf("MADT: Skipping reserved entry (type=%" PRIu8 ")\n",
     240                                    hdr->type);
     241                               
     242                        if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
     243                                printf("MADT: Skipping OEM entry (type=%" PRIu8 ")\n",
     244                                    hdr->type);
     245                       
     246                        break;
     247                }
     248        }
     249       
     250        if (madt_l_apic_entry_cnt > 0)
     251                config.cpu_count = madt_l_apic_entry_cnt;
    240252}
    241253
  • kernel/generic/src/smp/ipi.c

    r9a21f9d rfe32163  
    4747 * @param ipi Message to broadcast.
    4848 *
    49  * @bug The decision whether to actually send the IPI must be based
    50  *      on a different criterion. The current version has
    51  *      problems when some of the detected CPUs are marked
    52  *      disabled in machine configuration.
    5349 */
    5450void ipi_broadcast(int ipi)
     
    6056         */
    6157       
    62         if ((config.cpu_active > 1) && (config.cpu_active == config.cpu_count))
     58        if (config.cpu_count > 1)
    6359                ipi_broadcast_arch(ipi);
    6460}
Note: See TracChangeset for help on using the changeset viewer.