Ignore:
File:
1 edited

Legend:

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

    rd99c1d2 r0a79ad9  
    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 mps_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 mps_cpu_enabled(size_t i)
     82{
     83        ASSERT(i < processor_entry_cnt);
     84       
     85        /*
     86         * FIXME: The current local APIC driver limits usable
     87         * CPU IDs to 8.
     88         *
     89         */
     90        if (i > 7)
     91                return false;
     92       
     93        return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
     94}
     95
     96static bool mps_cpu_bootstrap(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,
    97         .cpu_enabled = is_cpu_enabled,
    98         .cpu_bootstrap = is_bsp,
    99         .cpu_apic_id = get_cpu_apic_id,
     120        .cpu_enabled = mps_cpu_enabled,
     121        .cpu_bootstrap = mps_cpu_bootstrap,
     122        .cpu_apic_id = mps_cpu_apic_id,
    100123        .irq_to_pin = mps_irq_to_pin
    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
Note: See TracChangeset for help on using the changeset viewer.